Skip to main content

App Rollout via Data Change in Amazon S3

A simple Deployment obtaining data from S3

This example lives in the pulumi/examples repository. Check out just this directory to use it:

Get started with this example
git clone --filter=blob:none --sparse https://github.com/pulumi/examples pulumi-examples
git -C pulumi-examples sparse-checkout set kubernetes-ts-s3-rollout
cd pulumi-examples/kubernetes-ts-s3-rollout

This example is similar in principle to the ConfigMap-based rollout example, except a rollout is triggered any time the data in S3 changes.

Like the ConfigMap-based example, this one uses nginx to reverse-proxy traffic to pulumi.github.io. The nginx configuration is contained in the file default.conf in this directory; this program reads that file and puts it into an S3 bucket. Hence, changing data in that file will cause register as a change in the S3 bucket’s data, which will trigger a rollout of the nginx Deployment.

Running the App#

Follow the steps in Pulumi Installation and Setup and Configuring Pulumi Kubernetes to get setup with Pulumi and Kubernetes.

Install dependencies:

Terminal window
npm install

Create a new stack:

Terminal window
pulumi stack init
Enter a stack name: s3-kube

Perform the deployment:

Terminal window
pulumi up
Updating stack 's3-kube'
Performing changes:
Type Name Status Info
+ pulumi:pulumi:Stack data-from-s3-s3-kube created
+ ├─ aws:s3:Bucket nginx-configs created
+ ├─ aws:s3:BucketPolicy bucketPolicy created
+ ├─ aws:s3:BucketObject default.conf created
+ ├─ kubernetes:apps:Deployment nginx created
+ └─ kubernetes:core:Service nginx created
---outputs:---
defaultConfUrl: "nginx-configs-4b9ea08.s3.amazonaws.com/default.conf"
frontendIp : "35.224.120.207"
info: 6 changes performed:
+ 6 resources created
Update duration: 1m21.870672089s
Permalink: https://app.pulumi.com/hausdorff/s3-kube/updates/1

We can see here in the ---outputs:--- section that our proxy was allocated a public IP, in this case 35.224.120.207". It is exported with a stack output variable, frontendIp. We can use curl and grep to retrieve the <title> of the site the proxy points at.

Terminal window
curl -sL $(pulumi stack output frontendIp):80 | grep -C 1 "<title>"
<title>Pulumi. Serverless // Containers // Infrastructure // Cloud // DevOps</title>

Now, open default.conf and change .node.server and .server.location.proxy_set_header to point at google.com. If you’re on macOS you can run sed -i bak "s/pulumi.github.io/google.com/g" default.conf

The result should look like this:

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;
}
}

Running preview now shows that this change will cause us to replace the S3 bucket with a new one containing the new data, and subsequently trigger a rollout in the Deployment.

NOTE: This rollout is safe! Pulumi executes this plan with the following steps:

  1. Create a new S3 bucket with a new name and the new data.
  2. Update the PodTemplate of the Deployment to point at the new S3 bucket. This update triggers the Deployment controller to try to roll out a new set of containers with mounts that contain this new data.
  3. Only once that succeeds, delete the old S3 bucket.
Terminal window
Previewing update of stack 's3-kube'
Type Name Status Info
* pulumi:pulumi:Stack configmap-rollout-configmap-rollout-dev no change
+- ├─ kubernetes:core:ConfigMap nginx replace changes: ~ data,metadata
~ └─ kubernetes:apps:Deployment nginx update changes: ~ spec
info: 2 changes previewed:
~ 1 resource to update
+-1 resource to replace
2 resources unchanged

Running pulumi up would actually attempt to achieve these results.

Now, if we curl the IP address once more, we see that it points at google.com!

Note: minikube does not support type LoadBalancer; if you are deploying to minikube, make sure to run kubectl port-forward svc/frontend 8080:80 to forward the cluster port to the local machine and access the service via localhost:8080.

Terminal window
curl -sL $(pulumi stack output frontendIp) | grep -o "<title>Google</title>"
<title>Google</title>

Related

The infrastructure as code platform for any cloud.