Skip to main content

Search the Dev Center

Search tutorials, templates, examples, and more.

Web Application on Kubernetes

The Kubernetes Web Application template scaffolds a Pulumi project that deploys a web application to an existing Kubernetes cluster using Pulumi’s Kubernetes provider. The template creates a new namespace, a ConfigMap with an NGINX configuration, a Deployment to run the application, and a Service that exposes it inside the cluster. The Deployment runs the public nginx image as a placeholder app, so the project deploys end to end out of the box.

Architecture diagram of the Kubernetes Web Application template Kubernetes Cluster Namespace Service Pods Deployment

Before you begin#

For this walkthrough, you'll need:

Create a new project#

Create a new project from the template:

Terminal window
mkdir my-k8s-app; cd my-k8s-app
pulumi new webapp-kubernetes-typescript

The pulumi new command walks you through creating and configuring the new project and stack. A stack is an instance of a project, and you can have many of them (dev, staging, prod), each with its own configuration settings. Depending on the language, you may also be asked for your preferred package manager or toolchain.

This template’s settings include:

KeyDescriptionDefault
namespaceThe Kubernetes namespace to deploy intowebapp
replicasThe number of replicas to deploy1
You can change values like these later with pulumi config set :
Terminal window
pulumi config set namespace <value>
pulumi config set replicas <value>

Review the code#

When setup completes, you’ll see a few files:

  • Pulumi.yaml contains the project name and the language it’s written in.
  • Pulumi.dev.yaml contains the dev stack’s settings, including the values you just entered.
  • index.ts contains the program code that declares your Kubernetes resources.

Take a moment to open them up and have a look. Here’s what’s in index.ts:

index.ts
import * as pulumi from "@pulumi/pulumi";
import * as kubernetes from "@pulumi/kubernetes";
// Get some values from the stack configuration, or use defaults
const config = new pulumi.Config();
const k8sNamespace = config.get("namespace") || "webapp";
const numReplicas = config.getNumber("replicas") || 1;
const appLabels = {
app: "nginx",
};
// Create a new namespace
const webServerNs = new kubernetes.core.v1.Namespace("webserver", {metadata: {
name: k8sNamespace,
}});
// Create a new ConfigMap for the Nginx configuration
const webServerConfig = new kubernetes.core.v1.ConfigMap("webserverconfig", {
metadata: {
namespace: webServerNs.metadata.name,
},
data: {
"nginx.conf": `events { }
http {
server {
listen 80;
root /usr/share/nginx/html;
index index.html index.htm index.nginx-debian.html
server_name _;
location / {
try_files $uri $uri/ =404;
}
}
}
`,
},
});
// Create a new Deployment with a user-specified number of replicas
const webServerDeployment = new kubernetes.apps.v1.Deployment("webserverdeployment", {
metadata: {
namespace: webServerNs.metadata.name,
},
spec: {
selector: {
matchLabels: appLabels,
},
replicas: numReplicas,
template: {
metadata: {
labels: appLabels,
},
spec: {
containers: [{
image: "nginx",
name: "nginx",
volumeMounts: [{
mountPath: "/etc/nginx/nginx.conf",
name: "nginx-conf-volume",
readOnly: true,
subPath: "nginx.conf",
}],
}],
volumes: [{
configMap: {
items: [{
key: "nginx.conf",
path: "nginx.conf",
}],
name: webServerConfig.metadata.name,
},
name: "nginx-conf-volume",
}],
},
},
},
});
// Expose the Deployment as a Kubernetes Service
const webServerService = new kubernetes.core.v1.Service("webserverservice", {
metadata: {
namespace: webServerNs.metadata.name,
},
spec: {
ports: [{
port: 80,
targetPort: 80,
protocol: "TCP",
}],
selector: appLabels,
},
});
// Export some values for use elsewhere
export const deploymentName = webServerDeployment.metadata.name;
export const serviceName = webServerService.metadata.name;

Deploy the project#

The program deploys into the cluster your current kubeconfig context points at. Check which cluster that is before you deploy:

Terminal window
kubectl config current-context

Deploy with pulumi up. It starts with a preview of what it’s about to create and asks before it changes anything. Choose yes to deploy.

Terminal window
pulumi up

Pulumi adds a random suffix to most resource names, so the Deployment webserverdeployment becomes something like webserverdeployment-4f8a2c1d. This is autonaming. It lets you deploy the same program to more than one stack, and lets Pulumi create a replacement before it deletes the old resource, without names colliding. The namespace is the exception: the program gives it the exact name you entered (webapp by default), so a second stack in the same cluster needs a different one.

When it finishes, Pulumi prints the stack’s outputs, values it only knows once the resources exist:

deploymentName

The name of your new Kubernetes Deployment.

serviceName

The name of your new Kubernetes Service.

Read one any time with pulumi stack output <name>, or pass it to another command. This one looks up the Deployment in the webapp namespace (change -n if you entered another). READY shows 1/1 once its pod is running:

Terminal window
kubectl get deployment $(pulumi stack output deploymentName) -n webapp
Need help?

If pulumi up reports that the cluster is unreachable, check which cluster kubectl points to and whether it’s running:

Terminal window
kubectl config current-context
kubectl cluster-info

Restart your local cluster if necessary, or switch to another cluster with kubectl config use-context <CONTEXT_NAME>.

Still stuck? Let us know.

Customize the project#

Projects created with this template expose the following configuration settings:

namespace

The name of the namespace to be created in your existing cluster. Defaults to webapp.

replicas

The number of replicated Pods to be created in your new Deployment. Defaults to 1.

All of these settings are optional and may be adjusted either by editing the stack configuration file directly (by default, Pulumi.dev.yaml) or by changing their values with pulumi config set.

For example, run three pods, then look at the Deployment again; READY shows 3/3:

Terminal window
pulumi config set replicas 3
pulumi up
kubectl get deployment $(pulumi stack output deploymentName) -n webapp

Cleaning up#

You can cleanly destroy the stack and all of its infrastructure with pulumi destroy:

Terminal window
pulumi destroy

Learn more#

Related

The infrastructure as code platform for any cloud.