forked from pulumi/examples
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add "triggering a rollout by updating S3" demo
- Loading branch information
Showing
15 changed files
with
641 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
name: data-from-s3 | ||
description: A simple Deployment obtaining data from S3 | ||
runtime: nodejs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
# Kubernetes: Triggering a rollout of an app by changing data in S3 | ||
|
||
This example is similar in principle to the [`ConfigMap`-based rollout example][rollout], 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`. | ||
|
||
![configmapRollout](images/rollout.gif "ConfigMap-induced Rollout") | ||
|
||
## Running the App | ||
|
||
Follow the steps in [Pulumi Installation and Setup](https://docs.pulumi.com/install/) and | ||
[Configuring Pulumi Kubernetes](https://docs.pulumi.com/reference/kubernetes.html#configuration) to | ||
get setup with Pulumi and Kubernetes. | ||
|
||
Install dependencies: | ||
|
||
```sh | ||
npm install | ||
``` | ||
|
||
Create a new stack: | ||
|
||
```sh | ||
$ pulumi stack init | ||
Enter a stack name: s3-kube | ||
``` | ||
|
||
Perform the deployment: | ||
|
||
```sh | ||
$ 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. | ||
|
||
```sh | ||
$ 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: | ||
|
||
```conf | ||
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 https://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. | ||
> 1. 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. | ||
> 1. Only once that succeeds, delete the old S3 bucket. | ||
```sh | ||
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`. | ||
```sh | ||
$ curl -sL $(pulumi stack output frontendIp) | grep -o "<title>Google</title>" | ||
<title>Google</title> | ||
``` | ||
|
||
[rollout]: https://github.com/pulumi/examples/tree/master/kubernetes-ts-configmap-rollout |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import * as fs from "fs"; | ||
|
||
import * as aws from "@pulumi/aws"; | ||
import * as pulumi from "@pulumi/pulumi"; | ||
import * as mime from "mime"; | ||
|
||
// Create a bucket and expose a website index document | ||
let siteBucket = new aws.s3.Bucket("s3-website-bucket", { | ||
website: { | ||
indexDocument: "index.html" | ||
} | ||
}); | ||
|
||
let siteDir = "www"; // directory for content files | ||
|
||
// For each file in the directory, create an S3 object stored in `siteBucket` | ||
for (let item of fs.readdirSync(siteDir)) { | ||
let filePath = require("path").join(siteDir, item); | ||
let object = new aws.s3.BucketObject(item, { | ||
bucket: siteBucket, // reference the s3.Bucket object | ||
source: new pulumi.asset.FileAsset(filePath), // use FileAsset to point to a file | ||
contentType: mime.getType(filePath) || undefined // set the MIME type of the file | ||
}); | ||
} | ||
|
||
// Create an S3 Bucket Policy to allow public read of all objects in bucket | ||
function publicReadPolicyForBucket(bucketName) { | ||
return JSON.stringify({ | ||
Version: "2012-10-17", | ||
Statement: [ | ||
{ | ||
Effect: "Allow", | ||
Principal: "*", | ||
Action: ["s3:GetObject"], | ||
Resource: [ | ||
`arn:aws:s3:::${bucketName}/*` // policy refers to bucket name explicitly | ||
] | ||
} | ||
] | ||
}); | ||
} | ||
|
||
// Set the access policy for the bucket so all objects are readable | ||
let bucketPolicy = new aws.s3.BucketPolicy("bucketPolicy", { | ||
bucket: siteBucket.bucket, // refer to the bucket created earlier | ||
policy: siteBucket.bucket.apply(publicReadPolicyForBucket) // use output property `siteBucket.bucket` | ||
}); | ||
|
||
// Stack exports | ||
export const bucketName = siteBucket.bucket; | ||
export const websiteUrl = siteBucket.websiteEndpoint; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
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 https://node; | ||
proxy_redirect off; | ||
port_in_redirect off; | ||
} | ||
} |
Oops, something went wrong.