1. Automating rolling updates for zero-downtime deployments

    TypeScript

    Rolling updates are a strategy for updating the software on your servers with zero downtime. This is accomplished by incrementally updating servers with a new version of the software and slowly rolling this change out across your fleet of servers. By using a managed rolling update strategy, you can achieve zero downtime because only a subset of servers is taken down at any given time. The overall goal is to update your application without interrupting the user experience.

    To demonstrate rolling updates with Pulumi, I will walk you through a Pulumi program that uses a Kubernetes Deployment object to manage the desired state of a set of replicas of a given application container. By defining the strategy field in the Deployment specification, Kubernetes will handle rolling updates to the application. The maxUnavailable field specifies the maximum number of Pods that can be unavailable during the update process, and the maxSurge field specifies the maximum number of additional Pods that can be created above the desired number of Pods.

    Here's a TypeScript Pulumi program that defines a Kubernetes Deployment with a RollingUpdate strategy:

    import * as k8s from "@pulumi/kubernetes"; // A new Kubernetes namespace for our example const ns = new k8s.core.v1.Namespace("app-ns", { metadata: { name: "example-ns" } }); // The application container image const appImage = "nginx:1.19.3"; // For example purposes, we'll use nginx // Define the Kubernetes Deployment const appDeployment = new k8s.apps.v1.Deployment("app-deployment", { metadata: { namespace: ns.metadata.name, }, spec: { replicas: 3, // Amount of desired replicas selector: { matchLabels: { app: "nginx" } }, template: { metadata: { labels: { app: "nginx" } }, spec: { containers: [{ name: "nginx", image: appImage }] } }, strategy: { type: "RollingUpdate", rollingUpdate: { // During an update, the max number of pods that can be unavailable maxUnavailable: 1, // The max number of new pods that can be added above the desired number of pods maxSurge: 1 } } }, }, {dependsOn: ns}); // Export the Deployment name export const deploymentName = appDeployment.metadata.name;

    In the program above, we first import the necessary Pulumi Kubernetes SDK. We create a namespace where our application will reside. It's good practice to namespace your Kubernetes applications, as it provides a unique scope for names and provides a mechanism to attach authorization and policy to a subsection of your cluster.

    We then define the deployment for our application. In this case, it's a simple nginx server, but this would be replaced with your application's image in a real scenario. We define the strategy for updating the pods to be of type RollingUpdate with maxUnavailable and maxSurge options. These options control the rolling update behavior.

    Finally, we export the deployment name, which you can use with other Pulumi programs or connect to other app resources in the same stack.

    This program would be applied by running pulumi up, and Kubernetes would then ensure that the rolling update strategy defined is followed when the deployment’s pod template is modified (e.g., when you change the container image).

    Remember, for this example to work, you need to have

    • Pulumi CLI installed and configured.
    • Access to a Kubernetes cluster (where you have permissions to create resources).
    • Your Pulumi stack configured for the appropriate Kubernetes cluster.

    By changing the appImage to a new version and running pulumi up, you would see a rolling update in action. Pulumi will show you the planned changes before they are applied, and you can confirm them to initiate the rolling update.

    You can also observe the progress directly via Kubernetes tooling, like kubectl rollout status deployment/app-deployment which will give you live feedback on the rolling update process.