Kubernetes: Create, Update, and Destroy
This tutorial shows you how to use Pulumi to write and manage a Kubernetes application through it’s lifecycle. We will use the Pulumi Kubernetes TypeScript SDK to write the Kubernetes applications, and the Pulumi CLI to create, update, and destroy resources on the Kubernetes cluster.
Along the way, we will get a taste for several of Pulumi’s features for visualizing and understanding how an update will impact the application running in the cluster.
For example, in the gif below, we can see how updating one resource (in this case, a ConfigMap) “ripples through” the rest of the application, causing other resources to be updated, as well.
Topics:
- Prerequisites
- Provisioning a Kubernetes application
- Using Pulumi’s notion of “stack outputs”
- Using Pulumi’s diff facilities to understand how a change affects an application
- Updating an application

Prerequisites
IMPORTANT: This tutorial expects that you have provisioned a Kubernetes cluster and have an active kubeconfig file.
- Install Node.js.
- Install a package manager for Node.js, such as npm or Yarn.
- Install the Pulumi CLI.
Provisioning a Kubernetes application
We’re going to provision one of Pulumi’s example applications. We’ll dig into the code when we modify it later.
This application will:
- Create a container running nginx (an open source web server).
- Create a ConfigMapwith an configuration file that configures nginx to proxy traffic topulumi.github.io.
- Mount that configuration data into the nginx container.
- Expose the nginx container to the internet using a Service.
To provision the application, we need to:
- Run - pulumi new.- $ mkdir test-pulumi && cd test-pulumi # Clones the application into the current directory, and begins provisioning it in the active # context of your kubeconfig file. $ pulumi new https://github.com/pulumi/examples/tree/master/kubernetes-ts-configmap-rollout
- Answer the questions prompted by - pulumi new. This will bring up a CLI prompt that looks like the following, asking you questions to get you started. It is ok to accept default values for all questions except- isMinikube, where it is important to answer- false.- IMPORTANT: If you are using minikube, Docker for Mac, or any other compute provider that can’t allocate a load balancer, you can answer - true, but you won’t be able to bring up the service in your browser without using something like- kubectl port-forward. 
- Accept the update. After all the questions are answered, you should see a prompt like the following, asking if you’d like to proceed with the update. You can opt to view the diff, if you like, but we’ll also do this later when we update the application. - Resources: + 4 to create Do you want to perform this update? yes > no details
Once all this is complete, Pulumi will begin provisioning the application. It should look something like the following gif, though it will be slightly different, depending on the name you’ve given your stack.
There are several things to notice here:
- Resources are provisioned in a specific order. We can see from the output that the - ConfigMapis provisioned first, the- Deploymentsecond, and the- Servicethird.- As we will see in the following sections, Pulumi keeps track of resources as a graph. We will also see that this allows Pulumi to tell us how a change to one resource will affect other resources. 
- We get intermediate status updates as resources provision. As the - Servicerolls out, for example, we can see distinct stages in the initialization.
These two things will be important in the next sections.

Using Pulumi’s notion of “stack outputs”
It’s worth noting briefly that Pulumi provides convenient tooling for “exporting” values of initialized resources.
This application exports frontendIp, which is the IP address of the load balancer that the
underlying compute provider provisioned when you started the service. You can view it with the following command:
$ pulumi stack output frontendIp
35.247.60.31
If you paste this IP into your browser, you should see that it’s redirected you to the Pulumi homepage. Alternatively, you can run this:
$ curl -sL $(pulumi stack output frontendIp):80 | grep -C 1 "<title>"
    <title>Pulumi. Serverless // Containers // Infrastructure // Cloud // DevOps</title>
Using Pulumi’s diff facilities to understand how a change affects an application
In this section, we’ll re-configure nginx to point at google.com by changing the data in the
ConfigMap.
This is one of the “gotchas” of Kubernetes – by default kubectl will not trigger a rollout among
the containers that reference a ConfigMap when its data will change. Instead, the kubelet silently, transparently syncs the data to the containers after the TTL expires.
In this section, we will see that Pulumi plans a safe update of the ConfigMap. It will:
- Create a new ConfigMapwith a new name and the new data.
- Update the PodTemplateof theDeploymentto point at the newConfigMap. This update triggers theDeploymentcontroller to try to roll out a new set of containers with mounts that contain this new data.
- Only once that succeeds, delete the old ConfigMap.
Here are the steps to make this change:
- Find the configuration data we need to change. In index.ts we can see the definition of the - ConfigMap:- // nginx Configuration data to proxy traffic to `pulumi.github.io`. Read from // `default.conf` file. const nginxConfig = new k8s.core.v1.ConfigMap(appName, { metadata: { labels: appLabels }, data: { "default.conf": fs.readFileSync("default.conf").toString() }, });- This indicates that the - ConfigMapis reading the- default.conffile using- fs.readFileSync.
- Change the configuration file. If you’re on macOS, you can run: - $ sed -i bak "s/pulumi.github.io/google.com/g" default.conf- If you’re running a platform that does not support - sed, paste the following into your- default.conffile:- upstream node { server google.com; } server { listen 80; server_name _; root /usr/share/nginx/html; location / { proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header Host google.com; proxy_pass http://node; proxy_redirect off; port_in_redirect off; } }
- Get a high-level view of the changes with - pulumi preview. It should look something like the picture below. As we mentioned before, we can see that Pulumi plans to explicitly trigger a rollout in the- Deploymentby replacing the- ConfigMap. This is in contrast to- kubectl, which will silently sync the new version of the file to the containers. 
- Get a more detailed view of the changes with - pulumi preview --diff.. It will look conceptually something like the following gif (though this gif is a different app). 
Updating an application
Once we’re confident this is what we want, we can run the update:
- Run - pulumi up.- $ pulumi up- The output should look something like this.  
- Verify the rollout worked. You can do this by pasting the URL into the browser (be sure to disable the cache), or by running the following: - $ curl -sL $(pulumi stack output frontendIp) | grep -o "<title>Google</title>" <title>Google</title>
Destroying an application
Once we’re done with the application, it’s possible to destroy it using:
$ pulumi destroy