├── README.md ├── apps ├── configmap-rollout │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── default.conf │ ├── images │ │ ├── rollout.cast │ │ └── rollout.gif │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── cronjob │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── daemonset │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── deployment-secret │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── job │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── pod-sidecar │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── statefulset │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json └── wordpress │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── aws ├── 01-identity │ ├── .gitignore │ ├── Pulumi.yaml │ ├── README.md │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── 02-managed-infra │ ├── Pulumi.yaml │ ├── README.md │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── 03-cluster-configuration │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── iam.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── 04-cluster-services │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── 05-app-services │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json └── 06-apps │ └── build-deploy-container │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── node-app │ ├── .dockerignore │ ├── Dockerfile │ └── app │ │ ├── index.html │ │ ├── index.js │ │ └── package.json │ ├── package.json │ └── tsconfig.json ├── azure ├── 01-identity │ ├── Pulumi.yaml │ ├── README.md │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── 02-managed-infra │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── 03-cluster-configuration │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── 04-cluster-services │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── 05-app-services │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── mongoHelpers.ts │ ├── package.json │ └── tsconfig.json ├── 06-apps │ └── build-deploy-container │ │ ├── Pulumi.yaml │ │ ├── README.md │ │ ├── config.ts │ │ ├── index.ts │ │ ├── node-app │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ └── app │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ └── package.json │ │ ├── package.json │ │ └── tsconfig.json ├── identity │ └── yarn.lock └── infrastructure │ └── yarn.lock ├── gcp ├── 01-identity │ ├── .gitignore │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── util.ts ├── 02-managed-infra │ ├── .gitignore │ ├── Pulumi.yaml │ ├── README.md │ ├── index.ts │ └── package.json ├── 03-cluster-configuration │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── 04-cluster-services │ └── README.md ├── 05-app-services │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json └── 06-apps │ └── build-deploy-container │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── node-app │ ├── .dockerignore │ ├── Dockerfile │ └── app │ │ ├── index.html │ │ ├── index.js │ │ └── package.json │ ├── package.json │ └── tsconfig.json ├── general-app-services └── nginx-ingress-controller │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── general-cluster-services └── datadog-daemonset │ ├── Pulumi.yaml │ ├── README.md │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── images └── cake.svg └── orig ├── README.md ├── aws ├── identity │ ├── README.md │ ├── examples │ │ └── eks-admin │ │ │ ├── Pulumi.yaml │ │ │ ├── index.ts │ │ │ ├── package.json │ │ │ └── util.ts │ ├── index.ts │ ├── lib │ │ ├── baseline.ts │ │ ├── common.ts │ │ ├── groups.ts │ │ └── policies.ts │ ├── package.json │ └── yarn.lock └── infrastructure │ ├── Pulumi.yaml │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── scripts │ └── deploy-with-ci-user.sh ├── azure ├── identity │ ├── .gitignore │ ├── Pulumi.yaml │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── yarn.lock └── infrastructure │ ├── .gitignore │ ├── Pulumi.yaml │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── yarn.lock ├── docs ├── 00-prerequisites.md ├── 01-architecture.md ├── 02-identity.md ├── 03-infrastructure.md ├── 04-app.md └── images │ ├── app.png │ ├── identity.png │ ├── infrastructure.png │ └── kube-arch.png ├── gcp ├── identity │ ├── .gitignore │ ├── Pulumi.yaml │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── util.ts └── infrastructure │ ├── .gitignore │ ├── Pulumi.yaml │ ├── config.ts │ ├── index.ts │ ├── package.json │ └── scripts │ └── login-to-ci-service-account.sh ├── services ├── .gitignore ├── scripts │ ├── get-kubeconfig.sh │ └── login-to-ci-service-account.sh └── wordpress │ ├── .gitignore │ ├── Pulumi.yaml │ ├── config.ts │ ├── index.ts │ └── package.json ├── tsconfig.json └── tslint.json /README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Guides 2 | 3 | [Pulumi Crosswalk for Kubernetes][crosswalk-k8s] is a collection of industry standard 4 | best-practices for managing Kubernetes, and its infrastructure in production. 5 | 6 | This guide is for provisioning and configuring production-grade Kubernetes 7 | clusters, and deploying workloads into the clusters. 8 | 9 | If you are just getting started with Pulumi and Kubernetes, the 10 | [Get Started][k8s-get-started] guide is a better place to start. 11 | 12 | 13 | 14 | The cloud provider stacks to deploy. 15 | 16 | | AWS | Azure | GCP | 17 | |---|---|---| 18 | | [Identity](./aws/01-identity) | [Identity](./azure/01-identity) | [Identity](./gcp/01-identity) | 19 | | [Managed Infrastructure](./aws/02-managed-infra) | [Managed Infrastructure](./azure/02-managed-infra) | [Managed Infrastructure](./gcp/02-managed-infra) | 20 | | [Cluster Configuration](./aws/03-cluster-configuration) | [Cluster Configuration](./azure/03-cluster-configuration) | [Cluster Configuration](./gcp/03-cluster-configuration) | 21 | | [Deploy Cluster Services](./aws/04-cluster-services) | [Deploy Cluster Services](./azure/04-cluster-services) | [Deploy Cluster Services](./gcp/04-cluster-services) | 22 | | [Deploy App Services](./aws/05-app-services) | [Deploy App Services](./azure/05-app-services) | [Deploy App Services](./gcp/05-app-services) | 23 | | [Deploy Apps](./aws/06-apps) | [Deploy Apps](./azure/06-apps) | [Deploy Apps](./gcp/06-apps) | 24 | 25 | The Kubernetes stacks that can be deployed on all clouds: 26 | 27 | * [General Cluster Services](./general-cluster-services) 28 | * [General App Services](./general-app-services) 29 | * [Apps](./apps) 30 | 31 | [crosswalk-k8s]: https://pulumi.com/docs/guides/crosswalk/kubernetes 32 | [k8s-get-started]: https://pulumi.com/docs/get-started/kubernetes 33 | -------------------------------------------------------------------------------- /apps/configmap-rollout/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-configmap-rollout 2 | description: A Deployment that mounts a ConfigMap; updating the data in the ConfigMap triggers a rollout of the Deployment 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /apps/configmap-rollout/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | }; 23 | -------------------------------------------------------------------------------- /apps/configmap-rollout/default.conf: -------------------------------------------------------------------------------- 1 | upstream node { 2 | server pulumi.github.io; 3 | } 4 | server { 5 | listen 80; 6 | server_name _; 7 | root /usr/share/nginx/html; 8 | location / { 9 | proxy_set_header X-Real-IP \$remote_addr; 10 | proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; 11 | proxy_set_header Host pulumi.github.io; 12 | proxy_pass http://node; 13 | proxy_redirect off; 14 | port_in_redirect off; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /apps/configmap-rollout/images/rollout.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/kubernetes-guides/a29612928c8082516bac34eb4b57ed2a3cdde9df/apps/configmap-rollout/images/rollout.gif -------------------------------------------------------------------------------- /apps/configmap-rollout/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. All rights reserved. 2 | 3 | import * as k8s from "@pulumi/kubernetes"; 4 | import * as fs from "fs"; 5 | import { config } from "./config"; 6 | 7 | const provider = new k8s.Provider("provider", { 8 | kubeconfig: config.kubeconfig, 9 | namespace: config.appsNamespaceName, 10 | }); 11 | 12 | const appName = "nginx"; 13 | const appLabels = { app: appName }; 14 | 15 | // nginx Configuration data to proxy traffic to `pulumi.github.io`. Read from 16 | // `default.conf` file. 17 | const nginxConfig = new k8s.core.v1.ConfigMap(appName, { 18 | metadata: { labels: appLabels }, 19 | data: { "default.conf": fs.readFileSync("default.conf").toString() }, 20 | }, { provider: provider }); 21 | const nginxConfigName = nginxConfig.metadata.name; 22 | 23 | // Deploy 1 nginx replica, mounting the configuration data into the nginx 24 | // container. 25 | const nginx = new k8s.apps.v1.Deployment(appName, { 26 | metadata: { labels: appLabels }, 27 | spec: { 28 | selector: { 29 | matchLabels: appLabels, 30 | }, 31 | replicas: 1, 32 | template: { 33 | metadata: { labels: appLabels }, 34 | spec: { 35 | containers: [ 36 | { 37 | image: "nginx:1.13.6-alpine", 38 | name: "nginx", 39 | volumeMounts: [{ name: "nginx-configs", mountPath: "/etc/nginx/conf.d" }], 40 | }, 41 | ], 42 | volumes: [{ name: "nginx-configs", configMap: { name: nginxConfigName } }], 43 | }, 44 | }, 45 | }, 46 | }, { provider: provider }); 47 | 48 | // Expose proxy to the public Internet. 49 | const frontend = new k8s.core.v1.Service(appName, { 50 | metadata: { labels: nginx.spec.template.metadata.labels }, 51 | spec: { 52 | type: "LoadBalancer", 53 | ports: [{ port: 80, targetPort: 80, protocol: "TCP" }], 54 | selector: appLabels, 55 | }, 56 | }, { provider: provider }); 57 | 58 | // Export the frontend IP. 59 | export const frontendIp = frontend.status.loadBalancer.ingress[0].ip; 60 | -------------------------------------------------------------------------------- /apps/configmap-rollout/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-apps-configmap-rollout", 3 | "devDependencies": { 4 | "@types/node": "^8.0.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/pulumi": "latest", 8 | "@pulumi/kubernetes": "latest" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /apps/configmap-rollout/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "experimentalDecorators": true, 9 | "pretty": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "strictNullChecks": true 15 | }, 16 | "files": [ 17 | "index.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/cronjob/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-cronjob 2 | description: Show how to create a CronJob 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /apps/cronjob/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/apps/cronjob/README.md) 2 | 3 | # CronJob 4 | 5 | Create a CronJob that runs a Pod on a schedule. 6 | 7 | ## Deploying the App 8 | 9 | To deploy your infrastructure, follow the below steps. 10 | 11 | ### Prerequisites 12 | 13 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 14 | 15 | ### Steps 16 | 17 | After cloning this repo, from this working directory, run these commands: 18 | 19 | 1. Install the required Node.js packages: 20 | 21 | ```bash 22 | $ npm install 23 | ``` 24 | 25 | 2. Create a new stack, which is an isolated deployment target for this example: 26 | 27 | ```bash 28 | $ pulumi stack init 29 | ``` 30 | 31 | 3. Update the stack. 32 | 33 | ```bash 34 | $ pulumi up 35 | ``` 36 | 37 | 4. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 38 | 39 | ```bash 40 | $ pulumi destroy --yes 41 | $ pulumi stack rm --yes 42 | ``` 43 | -------------------------------------------------------------------------------- /apps/cronjob/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | }; 23 | -------------------------------------------------------------------------------- /apps/cronjob/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. All rights reserved. 2 | 3 | import * as k8s from "@pulumi/kubernetes"; 4 | import { config } from "./config"; 5 | 6 | const provider = new k8s.Provider("provider", { 7 | kubeconfig: config.kubeconfig, 8 | namespace: config.appsNamespaceName, 9 | }); 10 | 11 | // Create an example CronJob. 12 | const exampleCronJob = new k8s.batch.v1beta1.CronJob("example-cronjob", { 13 | spec: { 14 | schedule: "*/1 * * * *", 15 | jobTemplate: { 16 | spec: { 17 | template: { 18 | spec: { 19 | containers: [ 20 | { 21 | name: "hello", 22 | image: "busybox", 23 | args: ["/bin/sh", "-c", "date; echo Hello from the Kubernetes cluster"], 24 | } 25 | ], 26 | restartPolicy: "OnFailure" 27 | } 28 | } 29 | } 30 | }, 31 | } 32 | }, { provider: provider }); 33 | -------------------------------------------------------------------------------- /apps/cronjob/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-apps-cronjob", 3 | "devDependencies": { 4 | "@types/node": "^8.0.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/pulumi": "latest", 8 | "@pulumi/kubernetes": "latest" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /apps/cronjob/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "experimentalDecorators": true, 9 | "pretty": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "strictNullChecks": true 15 | }, 16 | "files": [ 17 | "index.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/daemonset/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-daemonset 2 | description: Show how to create a DaemonSet 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /apps/daemonset/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/apps/daemonset/README.md) 2 | 3 | # DaemonSet 4 | 5 | Create a DaemonSet that deploys a Pod to each worker node. 6 | 7 | ## Deploying the App 8 | 9 | To deploy your infrastructure, follow the below steps. 10 | 11 | ### Prerequisites 12 | 13 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 14 | 15 | ### Steps 16 | 17 | After cloning this repo, from this working directory, run these commands: 18 | 19 | 1. Install the required Node.js packages: 20 | 21 | ```bash 22 | $ npm install 23 | ``` 24 | 25 | 2. Create a new stack, which is an isolated deployment target for this example: 26 | 27 | ```bash 28 | $ pulumi stack init 29 | ``` 30 | 31 | 3. Update the stack. 32 | 33 | ```bash 34 | $ pulumi up 35 | ``` 36 | 37 | 4. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 38 | 39 | ```bash 40 | $ pulumi destroy --yes 41 | $ pulumi stack rm --yes 42 | ``` 43 | -------------------------------------------------------------------------------- /apps/daemonset/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | }; 23 | -------------------------------------------------------------------------------- /apps/daemonset/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. All rights reserved. 2 | 3 | import * as k8s from "@pulumi/kubernetes"; 4 | import { config } from "./config"; 5 | 6 | const provider = new k8s.Provider("provider", { 7 | kubeconfig: config.kubeconfig, 8 | namespace: config.appsNamespaceName, 9 | }); 10 | 11 | // Create a DaemonSet that deploys nginx to each worker node. 12 | const appName = "nginx"; 13 | const appLabels = { app: appName }; 14 | const nginx = new k8s.apps.v1.DaemonSet(appName, { 15 | metadata: { labels: appLabels }, 16 | spec: { 17 | selector: { 18 | matchLabels: appLabels, 19 | }, 20 | template: { 21 | metadata: { labels: appLabels }, 22 | spec: { 23 | containers: [ 24 | { 25 | image: "nginx", 26 | name: "nginx", 27 | }, 28 | ], 29 | }, 30 | }, 31 | }, 32 | }, { provider: provider }); 33 | -------------------------------------------------------------------------------- /apps/daemonset/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-apps-daemonset", 3 | "devDependencies": { 4 | "@types/node": "^8.0.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/pulumi": "latest", 8 | "@pulumi/kubernetes": "latest" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /apps/daemonset/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "experimentalDecorators": true, 9 | "pretty": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "strictNullChecks": true 15 | }, 16 | "files": [ 17 | "index.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/deployment-secret/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-deployment-secret 2 | description: A Deployment that references a secret value as an environment variable. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /apps/deployment-secret/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/apps/deployment-secret/README.md) 2 | 3 | # Deployment Secret 4 | 5 | Inject database credentials into a Deployment as environment variables. 6 | 7 | ## Deploying the App 8 | 9 | To deploy your infrastructure, follow the below steps. 10 | 11 | ### Prerequisites 12 | 13 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 14 | 15 | ### Steps 16 | 17 | After cloning this repo, from this working directory, run these commands: 18 | 19 | 1. Install the required Node.js packages: 20 | 21 | ```bash 22 | $ npm install 23 | ``` 24 | 25 | 2. Create a new stack, which is an isolated deployment target for this example: 26 | 27 | ```bash 28 | $ pulumi stack init 29 | ``` 30 | 31 | 3. Update the stack. 32 | 33 | ```bash 34 | $ pulumi up 35 | ``` 36 | 37 | 4. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 38 | 39 | ```bash 40 | $ pulumi destroy --yes 41 | $ pulumi stack rm --yes 42 | ``` 43 | -------------------------------------------------------------------------------- /apps/deployment-secret/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | 23 | // Misc 24 | databaseUsername: "admin", 25 | databasePassword: "supersecurepassword123", 26 | }; 27 | -------------------------------------------------------------------------------- /apps/deployment-secret/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. All rights reserved. 2 | 3 | import * as k8s from "@pulumi/kubernetes"; 4 | import * as kx from "@pulumi/kubernetesx"; 5 | import { config } from "./config"; 6 | 7 | const provider = new k8s.Provider("provider", { 8 | kubeconfig: config.kubeconfig, 9 | namespace: config.appsNamespaceName, 10 | }); 11 | 12 | // Create a Secret with the database credentials. 13 | const databaseSecret = new k8s.core.v1.Secret("db-secret", { 14 | stringData: { 15 | "database-username": config.databaseUsername, 16 | "database-password": config.databasePassword, 17 | } 18 | }, { provider: provider }); 19 | 20 | // Create a Deployment that uses the database credentials as environment variables. 21 | const appName = "nginx"; 22 | const appLabels = { app: appName }; 23 | const nginx = new k8s.apps.v1.Deployment(appName, { 24 | metadata: { labels: appLabels }, 25 | spec: { 26 | selector: { 27 | matchLabels: appLabels, 28 | }, 29 | replicas: 1, 30 | template: { 31 | metadata: { labels: appLabels }, 32 | spec: { 33 | containers: [ 34 | { 35 | image: "nginx", 36 | name: "nginx", 37 | env: [ 38 | { 39 | name: "DATABASE_USERNAME", 40 | valueFrom: { 41 | secretKeyRef: { 42 | name: databaseSecret.metadata.name, 43 | key: "database-username" 44 | } 45 | } 46 | }, 47 | { 48 | name: "DATABASE_PASSWORD", 49 | valueFrom: { 50 | secretKeyRef: { 51 | name: databaseSecret.metadata.name, 52 | key: "database-password" 53 | } 54 | } 55 | } 56 | ] 57 | }, 58 | ], 59 | }, 60 | }, 61 | }, 62 | }, { provider: provider }); 63 | 64 | // 65 | // Example using KX 66 | // 67 | 68 | // Create a KX Secret with the database credentials. 69 | const databaseSecretKx = new kx.Secret("db-secret", { 70 | stringData: { 71 | "database-username": config.databaseUsername, 72 | "database-password": config.databasePassword, 73 | } 74 | }, { provider: provider }); 75 | 76 | // Define the Pod to deploy. 77 | const nginxPB = new kx.PodBuilder({ 78 | containers: [{ 79 | image: "nginx", 80 | env: { 81 | "DATABASE_USERNAME": databaseSecretKx.asEnvValue("database-username"), 82 | "DATABASE_PASSWORD": databaseSecretKx.asEnvValue("database-password"), 83 | } 84 | }] 85 | }); 86 | 87 | // Create a KX Deployment from the KX PodBuilder by transforming it into a DeploymentSpec. 88 | // The deployment uses the database credentials as environment variables. 89 | const nginxKx = new kx.Deployment(appName, { 90 | spec: nginxPB.asDeploymentSpec({replicas: 1}) 91 | }, { provider: provider }); 92 | -------------------------------------------------------------------------------- /apps/deployment-secret/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-apps-deployment-secret", 3 | "devDependencies": { 4 | "@types/node": "^8.0.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/pulumi": "latest", 8 | "@pulumi/kubernetes": "latest", 9 | "@pulumi/kubernetesx": "latest" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /apps/deployment-secret/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "experimentalDecorators": true, 9 | "pretty": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "strictNullChecks": true 15 | }, 16 | "files": [ 17 | "index.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/job/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-job 2 | description: Show how to create a Job 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /apps/job/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/apps/job/README.md) 2 | 3 | # Job 4 | 5 | Create a Job that successfully runs to completion. 6 | 7 | ## Deploying the App 8 | 9 | To deploy your infrastructure, follow the below steps. 10 | 11 | ### Prerequisites 12 | 13 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 14 | 15 | ### Steps 16 | 17 | After cloning this repo, from this working directory, run these commands: 18 | 19 | 1. Install the required Node.js packages: 20 | 21 | ```bash 22 | $ npm install 23 | ``` 24 | 25 | 2. Create a new stack, which is an isolated deployment target for this example: 26 | 27 | ```bash 28 | $ pulumi stack init 29 | ``` 30 | 31 | 3. Update the stack. 32 | 33 | ```bash 34 | $ pulumi up 35 | ``` 36 | 37 | 4. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 38 | 39 | ```bash 40 | $ pulumi destroy --yes 41 | $ pulumi stack rm --yes 42 | ``` 43 | -------------------------------------------------------------------------------- /apps/job/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | }; 23 | -------------------------------------------------------------------------------- /apps/job/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. All rights reserved. 2 | 3 | import * as k8s from "@pulumi/kubernetes"; 4 | import * as kx from "@pulumi/kubernetesx"; 5 | import { config } from "./config"; 6 | 7 | const provider = new k8s.Provider("provider", { 8 | kubeconfig: config.kubeconfig, 9 | namespace: config.appsNamespaceName, 10 | }); 11 | 12 | // Create an example Job. 13 | const exampleJob = new k8s.batch.v1.Job("example-job", { 14 | spec: { 15 | template: { 16 | spec: { 17 | containers: [ 18 | { 19 | name: "pi", 20 | image: "perl", 21 | command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"], 22 | } 23 | ], 24 | restartPolicy: "Never" 25 | } 26 | }, 27 | } 28 | }, { provider: provider }); 29 | 30 | // Example using kx. 31 | 32 | // Create the PodBuilder for the Job. 33 | const pb = new kx.PodBuilder({ 34 | containers: [{ 35 | name: "pi", 36 | image: "perl", 37 | command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"], 38 | }], 39 | restartPolicy: "Never", 40 | }); 41 | 42 | // Create a Job using the Pod defined by the PodBuilder. 43 | const exampleJobKx = new kx.Job("example-job-kx", { 44 | spec: pb.asJobSpec(), 45 | }, { provider: provider }); 46 | -------------------------------------------------------------------------------- /apps/job/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-apps-job", 3 | "devDependencies": { 4 | "@types/node": "^8.0.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/pulumi": "latest", 8 | "@pulumi/kubernetes": "latest", 9 | "@pulumi/kubernetesx": "^0.1.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /apps/job/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "experimentalDecorators": true, 9 | "pretty": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "strictNullChecks": true 15 | }, 16 | "files": [ 17 | "index.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/pod-sidecar/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-pod-sidecar 2 | description: Create a Pod with a Sidecar container. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /apps/pod-sidecar/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/apps/pod-sidecar/README.md) 2 | 3 | # Pod with a Sidecar 4 | 5 | Create a NGINX Pod with a Debian container sidecar. 6 | 7 | ## Deploying the App 8 | 9 | To deploy your infrastructure, follow the below steps. 10 | 11 | ### Prerequisites 12 | 13 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 14 | 15 | ### Steps 16 | 17 | After cloning this repo, from this working directory, run these commands: 18 | 19 | 1. Install the required Node.js packages: 20 | 21 | ```bash 22 | $ npm install 23 | ``` 24 | 25 | 2. Create a new stack, which is an isolated deployment target for this example: 26 | 27 | ```bash 28 | $ pulumi stack init 29 | ``` 30 | 31 | 3. Update the stack. 32 | 33 | ```bash 34 | $ pulumi up 35 | ``` 36 | 37 | 4. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 38 | 39 | ```bash 40 | $ pulumi destroy --yes 41 | $ pulumi stack rm --yes 42 | ``` 43 | -------------------------------------------------------------------------------- /apps/pod-sidecar/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | }; 23 | -------------------------------------------------------------------------------- /apps/pod-sidecar/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. All rights reserved. 2 | 3 | import * as k8s from "@pulumi/kubernetes"; 4 | import { config } from "./config"; 5 | 6 | const provider = new k8s.Provider("provider", { 7 | kubeconfig: config.kubeconfig, 8 | namespace: config.appsNamespaceName, 9 | }); 10 | 11 | // Create an example Pod with a Sidecar. 12 | const pod = new k8s.core.v1.Pod("example", { 13 | spec: { 14 | restartPolicy: "Never", 15 | volumes: [ 16 | {name: "shared-data", emptyDir: {}}, 17 | ], 18 | containers: [ 19 | { 20 | name: "nginx", 21 | image: "nginx", 22 | resources: {requests: {cpu: "50m", memory: "50Mi"}}, 23 | volumeMounts: [ 24 | { name: "shared-data", mountPath: "/usr/share/nginx/html"}, 25 | ], 26 | }, 27 | { 28 | name: "debian-container", 29 | image: "debian", 30 | resources: {requests: {cpu: "50m", memory: "50Mi"}}, 31 | volumeMounts: [ 32 | { name: "shared-data", mountPath: "/pod-data"}, 33 | ], 34 | command: [ "/bin/bash"], 35 | args: ["-c", "echo Hello from the Debian container > /pod-data/index.html ; sleep infinity"], 36 | } 37 | ], 38 | } 39 | }, { provider: provider }); 40 | -------------------------------------------------------------------------------- /apps/pod-sidecar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-apps-job", 3 | "devDependencies": { 4 | "@types/node": "^8.0.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/pulumi": "latest", 8 | "@pulumi/kubernetes": "latest" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /apps/pod-sidecar/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "experimentalDecorators": true, 9 | "pretty": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "strictNullChecks": true 15 | }, 16 | "files": [ 17 | "index.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/statefulset/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-statefulset 2 | description: Show how to create a StatefulSet 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /apps/statefulset/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/apps/statefulset/README.md) 2 | 3 | # StatefulSet 4 | 5 | This example deploys MariaDB as a StatefulSet. 6 | 7 | ## Deploying the App 8 | 9 | To deploy your infrastructure, follow the below steps. 10 | 11 | ### Prerequisites 12 | 13 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 14 | 15 | ### Steps 16 | 17 | After cloning this repo, from this working directory, run these commands: 18 | 19 | 1. Install the required Node.js packages: 20 | 21 | ```bash 22 | $ npm install 23 | ``` 24 | 25 | 2. Create a new stack, which is an isolated deployment target for this example: 26 | 27 | ```bash 28 | $ pulumi stack init 29 | ``` 30 | 31 | 3. Update the stack. 32 | 33 | ```bash 34 | $ pulumi up 35 | ``` 36 | 37 | 4. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 38 | 39 | ```bash 40 | $ pulumi destroy --yes 41 | $ pulumi stack rm --yes 42 | ``` 43 | -------------------------------------------------------------------------------- /apps/statefulset/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | }; 23 | -------------------------------------------------------------------------------- /apps/statefulset/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-apps-statefulset", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/kubernetes": "latest", 9 | "@pulumi/pulumi": "latest", 10 | "@pulumi/random": "latest" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /apps/statefulset/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /apps/wordpress/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-wordpress 2 | description: Deploy wordpress. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /apps/wordpress/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/apps/wordpress/README.md) 2 | 3 | # Deploy Wordpress 4 | 5 | This example deploys wordpress. 6 | 7 | ## Deploying the App 8 | 9 | To deploy your infrastructure, follow the below steps. 10 | 11 | ### Prerequisites 12 | 13 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 14 | 15 | ### Steps 16 | 17 | After cloning this repo, from this working directory, run these commands: 18 | 19 | 1. Install the required Node.js packages: 20 | 21 | ```bash 22 | $ npm install 23 | ``` 24 | 25 | 2. Create a new stack, which is an isolated deployment target for this example: 26 | 27 | ```bash 28 | $ pulumi stack init 29 | ``` 30 | 31 | 3. Update the stack. 32 | 33 | ```bash 34 | $ pulumi up 35 | ``` 36 | 37 | 4. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 38 | 39 | ```bash 40 | $ pulumi destroy --yes 41 | $ pulumi stack rm --yes 42 | ``` 43 | -------------------------------------------------------------------------------- /apps/wordpress/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | }; 23 | -------------------------------------------------------------------------------- /apps/wordpress/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-apps-wordpress", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/kubernetes": "latest", 9 | "@pulumi/pulumi": "latest", 10 | "@pulumi/random": "latest" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /apps/wordpress/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /aws/01-identity/.gitignore: -------------------------------------------------------------------------------- 1 | /.pulumi/ 2 | /.vscode/ 3 | bin/ 4 | node_modules/ 5 | *.pyc 6 | .Python 7 | include/ 8 | lib/ 9 | yarn.lock 10 | yarn-error.log 11 | package-lock.json 12 | Pulumi.*.yaml 13 | .idea/ 14 | *.iml 15 | 16 | infra-ci-client-secret.json 17 | k8s-app-dev-ci-client-secret.json 18 | -------------------------------------------------------------------------------- /aws/01-identity/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-aws-identity 2 | description: Creates an identity stack for an AWS EKS cluster and its users. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /aws/01-identity/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/aws/01-identity/README.md) 2 | 3 | # Identity - AWS 4 | 5 | Create the Identity resources to deploy EKS. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/identity) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Configure the stack. 35 | 36 | ```bash 37 | $ pulumi config set aws:region us-west-2 38 | ``` 39 | 40 | 1. Update the stack. 41 | 42 | ```bash 43 | $ pulumi up 44 | ``` 45 | 46 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 47 | 48 | ```bash 49 | $ pulumi destroy --yes 50 | $ pulumi stack rm --yes 51 | ``` 52 | -------------------------------------------------------------------------------- /aws/01-identity/index.ts: -------------------------------------------------------------------------------- 1 | import * as aws from "@pulumi/aws"; 2 | import * as pulumi from "@pulumi/pulumi"; 3 | 4 | // The managed policies EKS requires of nodegroups join a cluster. 5 | const nodegroupManagedPolicyArns: string[] = [ 6 | "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy", 7 | "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy", 8 | "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", 9 | ]; 10 | 11 | // Create the EKS cluster admins role. 12 | const adminsName = "admins"; 13 | const adminsIamRole = new aws.iam.Role(`${adminsName}-eksClusterAdmin`, { 14 | assumeRolePolicy: aws.getCallerIdentity().then(id => 15 | aws.iam.assumeRolePolicyForPrincipal({"AWS": `arn:aws:iam::${id.accountId}:root`})) 16 | }) 17 | export const adminsIamRoleArn = adminsIamRole.arn; 18 | const adminsIamRolePolicy = new aws.iam.RolePolicy(`${adminsName}-eksClusterAdminPolicy`, { 19 | role: adminsIamRole, 20 | policy: { 21 | Version: "2012-10-17", 22 | Statement: [ 23 | { Effect: "Allow", Action: ["eks:*", "ec2:DescribeImages"], Resource: "*", }, 24 | { Effect: "Allow", Action: "iam:PassRole", Resource: "*"}, 25 | ], 26 | }, 27 | }, 28 | { parent: adminsIamRole }, 29 | ); 30 | 31 | // Create the EKS cluster developers role. 32 | const devName = "devs"; 33 | const devsIamRole = new aws.iam.Role(`${devName}-eksClusterDeveloper`, { 34 | assumeRolePolicy: aws.getCallerIdentity().then(id => 35 | aws.iam.assumeRolePolicyForPrincipal({"AWS": `arn:aws:iam::${id.accountId}:root`})) 36 | }) 37 | export const devsIamRoleArn = devsIamRole.arn; 38 | 39 | // Create the standard node group worker role and attach the required policies. 40 | const stdName = "standardNodeGroup"; 41 | const stdNodegroupIamRole = new aws.iam.Role(`${stdName}-eksClusterWorkerNode`, { 42 | assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({"Service": "ec2.amazonaws.com"}) 43 | }) 44 | attachPoliciesToRole(stdName, stdNodegroupIamRole, nodegroupManagedPolicyArns); 45 | export const stdNodegroupIamRoleArn = stdNodegroupIamRole.arn; 46 | 47 | // Create the performant node group worker role and attach the required policies. 48 | const perfName = "performanceNodeGroup"; 49 | const perfNodegroupIamRole = new aws.iam.Role(`${perfName}-eksClusterWorkerNode`, { 50 | assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({"Service": "ec2.amazonaws.com"}) 51 | }) 52 | attachPoliciesToRole(perfName, perfNodegroupIamRole, nodegroupManagedPolicyArns); 53 | export const perfNodegroupIamRoleArn = perfNodegroupIamRole.arn; 54 | 55 | // Attach policies to a role. 56 | function attachPoliciesToRole(name: string, role: aws.iam.Role, policyArns: string[]) { 57 | for (const policyArn of policyArns) { 58 | new aws.iam.RolePolicyAttachment(`${name}-${policyArn.split('/')[1]}`, 59 | { policyArn: policyArn, role: role }, 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /aws/01-identity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-aws-identity", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/aws": "latest", 9 | "@pulumi/pulumi": "latest" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /aws/01-identity/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /aws/02-managed-infra/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-aws-infra 2 | description: Creates an managed infrastructure stack for an AWS EKS cluster. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /aws/02-managed-infra/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/aws/02-managed-infra/README.md) 2 | 3 | # Managed Infrastructure - AWS 4 | 5 | Create the Managed Infrastructure resources to deploy EKS. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/managed-infra) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Configure the stack. 35 | 36 | ```bash 37 | $ pulumi config set aws:region us-west-2 38 | ``` 39 | 40 | 1. Update the stack. 41 | 42 | ```bash 43 | $ pulumi up 44 | ``` 45 | 46 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 47 | 48 | ```bash 49 | $ pulumi destroy --yes 50 | $ pulumi stack rm --yes 51 | ``` 52 | -------------------------------------------------------------------------------- /aws/02-managed-infra/index.ts: -------------------------------------------------------------------------------- 1 | import * as awsx from "@pulumi/awsx"; 2 | 3 | // Create a new VPC with custom settings. 4 | const vpcName = "eksVpc"; 5 | const vpc = new awsx.ec2.Vpc(vpcName, { 6 | cidrBlock: "172.16.0.0/16", 7 | numberOfAvailabilityZones: "all", 8 | tags: { "Name": vpcName }, 9 | }); 10 | 11 | // Export the VPC resource IDs. 12 | export const vpcId = vpc.id; 13 | export const publicSubnetIds = vpc.publicSubnetIds; 14 | export const privateSubnetIds = vpc.privateSubnetIds; 15 | 16 | /* 17 | // Use the default VPC 18 | const defaultVpc = awsx.ec2.Vpc.getDefault(); 19 | 20 | // Export the VPC resource IDs. 21 | export const defaultVpcId = defaultVpc.id; 22 | export const defaultPublicSubnetIds = defaultVpc.publicSubnetIds; 23 | export const defaultPrivateSubnetIds = defaultVpc.privateSubnetIds; 24 | */ 25 | 26 | /* 27 | // Use an existing VPC, subnets, and gateways. 28 | const existingVpc = awsx.ec2.Vpc.fromExistingIds("existingVpc", { 29 | vpcId: "vpc-00000000000000000", 30 | publicSubnetIds: ["subnet-00000000000000000", "subnet-11111111111111111"], 31 | privateSubnetIds: ["subnet-22222222222222222", "subnet-33333333333333333"], 32 | internetGatewayId: "igw-00000000000000000", 33 | natGatewayIds: ["nat-00000000000000000", "nat-11111111111111111"], 34 | }) 35 | 36 | // Export the VPC resource IDs. 37 | export const existingVpcId = existingVpc.id; 38 | export const existingPublicSubnetIds = existingVpc.publicSubnetIds; 39 | export const existingPrivateSubnetIds = existingVpc.privateSubnetIds; 40 | */ 41 | -------------------------------------------------------------------------------- /aws/02-managed-infra/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-aws-infra", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/awsx": "latest", 9 | "@pulumi/pulumi": "latest" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /aws/02-managed-infra/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /aws/03-cluster-configuration/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-aws-cluster 2 | description: Creates an EKS cluster using best-practices. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /aws/03-cluster-configuration/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/aws/03-cluster-configuration/README.md) 2 | 3 | # Cluster Configuration - AWS 4 | 5 | Create the EKS Cluster and Kubernetes Defaults. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/control-plane) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Collect any stack configuration references to configure the stack in the 35 | next step. 36 | 37 | To get the Pulumi Stack Reference of a dependent stack, reference it in the 38 | config using the format: `//` e.g. `myUser/myProject/dev01` 39 | 40 | You can retrieve the Stack's reference name by running `pulumi stack ls` in 41 | the stack, and extracting it's stack URI. 42 | 43 | The stack reference for the example below is: `myUser/k8s-aws-identity/dev-1573587501` 44 | 45 | ```bash 46 | user@pulumi:~/pulumi/kubernetes-guides/aws/01-identity$ pul stack ls 47 | NAME LAST UPDATE RESOURCE COUNT URL 48 | dev-1573587501* 4 minutes ago 13 https://app.pulumi.com/myUser/k8s-aws-identity/dev-1573587501 49 | ``` 50 | 51 | 1. Configure the stack. 52 | 53 | ```bash 54 | $ pulumi config set aws:region us-west-2 55 | $ pulumi config set k8s-aws-cluster:identityStackRef myUser/k8s-aws-identity/dev-1573589109 56 | $ pulumi config set k8s-aws-cluster:infraStackRef myUser/k8s-aws-infra/dev-1573589378 57 | ``` 58 | 59 | 1. Update the stack. 60 | 61 | ```bash 62 | $ pulumi up 63 | ``` 64 | 65 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 66 | 67 | ```bash 68 | $ pulumi destroy --yes 69 | $ pulumi stack rm --yes 70 | ``` 71 | -------------------------------------------------------------------------------- /aws/03-cluster-configuration/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const identityStackRef = new pulumi.StackReference(pulumiConfig.require("identityStackRef")); 8 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 9 | 10 | export const config = { 11 | // Identity 12 | adminsIamRoleArn: identityStackRef.getOutput("adminsIamRoleArn"), 13 | devsIamRoleArn : identityStackRef.getOutput("devsIamRoleArn"), 14 | stdNodegroupIamRoleArn : identityStackRef.getOutput("stdNodegroupIamRoleArn"), 15 | perfNodegroupIamRoleArn: identityStackRef.getOutput("perfNodegroupIamRoleArn"), 16 | 17 | // Infrastructure / Networking 18 | vpcId: infraStackRef.getOutput("vpcId"), 19 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 20 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 21 | 22 | /* 23 | defaultVpcId: infraStackRef.getOutput("defaultVpcId"), 24 | defaultPublicSubnetIds: infraStackRef.getOutput("defaultPublicSubnetIds"), 25 | defaultPrivateSubnetIds: infraStackRef.getOutput("defaultPrivateSubnetIds"), 26 | */ 27 | 28 | /* 29 | existingVpcId: infraStackRef.getOutput("existingVpcId"), 30 | existingPublicSubnetIds: infraStackRef.getOutput("existingPublicSubnetIds"), 31 | existingPrivateSubnetIds: infraStackRef.getOutput("existingPrivateSubnetIds"), 32 | */ 33 | }; 34 | -------------------------------------------------------------------------------- /aws/03-cluster-configuration/iam.ts: -------------------------------------------------------------------------------- 1 | import * as aws from "@pulumi/aws"; 2 | 3 | // Creates a collection of IAM instance profiles from the given roles. 4 | export function createInstanceProfiles(name: string, roles: aws.iam.Role[]): aws.iam.InstanceProfile[] { 5 | const profiles: aws.iam.InstanceProfile[] = []; 6 | 7 | for (let i = 0; i < roles.length; i++) { 8 | const role = roles[i]; 9 | profiles.push(new aws.iam.InstanceProfile(`${name}-instanceProfile-${i}`, {role: role})); 10 | } 11 | 12 | return profiles; 13 | } 14 | -------------------------------------------------------------------------------- /aws/03-cluster-configuration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-aws-cluster", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/aws": "latest", 9 | "@pulumi/kubernetes": "latest", 10 | "@pulumi/pulumi": "latest", 11 | "@pulumi/eks": "latest" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /aws/03-cluster-configuration/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /aws/04-cluster-services/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-aws-cluster-svcs 2 | description: Deploys common EKS cluster services. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /aws/04-cluster-services/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/aws/04-cluster-services/README.md) 2 | 3 | # Cluster Services - AWS 4 | 5 | Deploy Cluster Services in the EKS Cluster. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/cluster-services) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Collect any stack configuration references to configure the stack in the 35 | next step. 36 | 37 | To get the Pulumi Stack Reference of a dependent stack, reference it in the 38 | config using the format: `//` e.g. `myUser/myProject/dev01` 39 | 40 | You can retrieve the Stack's reference name by running `pulumi stack ls` in 41 | the stack, and extracting it's stack URI. 42 | 43 | The stack reference for the example below is: `myUser/k8s-aws-identity/dev-1573587501` 44 | 45 | ```bash 46 | user@pulumi:~/pulumi/kubernetes-guides/aws/01-identity$ pul stack ls 47 | NAME LAST UPDATE RESOURCE COUNT URL 48 | dev-1573587501* 4 minutes ago 13 https://app.pulumi.com/myUser/k8s-aws-identity/dev-1573587501 49 | ``` 50 | 51 | 1. Configure the stack. 52 | 53 | ```bash 54 | $ pulumi config set aws:region us-west-2 55 | $ pulumi config set k8s-aws-cluster-svcs:identityStackRef myUser/k8s-aws-identity/dev-1573589109 56 | $ pulumi config set k8s-aws-cluster-svcs:clusterStackRef myUser/k8s-aws-cluster/dev-1571780002 57 | ``` 58 | 59 | 1. Update the stack. 60 | 61 | ```bash 62 | $ pulumi up 63 | ``` 64 | 65 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 66 | 67 | ```bash 68 | $ pulumi destroy --yes 69 | $ pulumi stack rm --yes 70 | ``` 71 | -------------------------------------------------------------------------------- /aws/04-cluster-services/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const identityStackRef = new pulumi.StackReference(pulumiConfig.require("identityStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Identity 12 | stdNodegroupIamRoleArn : identityStackRef.getOutput("stdNodegroupIamRoleArn"), 13 | perfNodegroupIamRoleArn: identityStackRef.getOutput("perfNodegroupIamRoleArn"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 19 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 20 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 21 | }; 22 | -------------------------------------------------------------------------------- /aws/04-cluster-services/index.ts: -------------------------------------------------------------------------------- 1 | import * as aws from "@pulumi/aws"; 2 | import * as k8s from "@pulumi/kubernetes"; 3 | import * as pulumi from "@pulumi/pulumi"; 4 | import { config } from "./config"; 5 | 6 | const projectName = pulumi.getProject(); 7 | 8 | export const stdNodegroupIamRoleArn = config.stdNodegroupIamRoleArn 9 | export const perfNodegroupIamRoleArn = config.perfNodegroupIamRoleArn 10 | const stdNodegroupIamRoleName = stdNodegroupIamRoleArn.apply(s => s.split("/")).apply(s => s[1]) 11 | const perfNodegroupIamRoleName = perfNodegroupIamRoleArn.apply(s => s.split("/")).apply(s => s[1]) 12 | export const clusterName = config.clusterName 13 | 14 | // Create a new IAM Policy for fluentd-cloudwatch to manage CloudWatch Logs. 15 | const name = "fluentd-cloudwatch"; 16 | const fluentdCloudWatchPolicy = new aws.iam.Policy(name, 17 | { 18 | description: "Allows fluentd-cloudwatch to work with CloudWatch Logs.", 19 | policy: JSON.stringify( 20 | { 21 | Version: "2012-10-17", 22 | Statement: [{Effect: "Allow", Action: ["logs:*"], Resource: ["arn:aws:logs:*:*:*"]}] 23 | } 24 | ) 25 | }, 26 | ); 27 | 28 | // Attach CloudWatch Logs policies to a role. 29 | function attachLogPolicies(name: string, arn: pulumi.Input) { 30 | new aws.iam.RolePolicyAttachment(name, 31 | { policyArn: fluentdCloudWatchPolicy.arn, role: arn}, 32 | ); 33 | } 34 | 35 | attachLogPolicies("stdRpa", stdNodegroupIamRoleName); 36 | attachLogPolicies("perfRpa", perfNodegroupIamRoleName); 37 | 38 | // Deploy fluentd using the Helm chart. 39 | const provider = new k8s.Provider("provider", {kubeconfig: config.kubeconfig}); 40 | const fluentdCloudWatchLogGroup = new aws.cloudwatch.LogGroup(name); 41 | export let fluentdCloudWatchLogGroupName = fluentdCloudWatchLogGroup.name; 42 | const fluentdCloudwatch = new k8s.helm.v2.Chart(name, 43 | { 44 | namespace: config.clusterSvcsNamespaceName, 45 | chart: "fluentd-cloudwatch", 46 | version: "0.11.0", 47 | fetchOpts: { 48 | repo: "https://kubernetes-charts-incubator.storage.googleapis.com/", 49 | }, 50 | values: { 51 | extraVars: [ "{ name: FLUENT_UID, value: '0' }" ], 52 | rbac: {create: true}, 53 | awsRegion: aws.config.region, 54 | logGroupName: fluentdCloudWatchLogGroup.name, 55 | }, 56 | transformations: [ 57 | (obj: any) => { 58 | // Do transformations on the YAML to set the namespace 59 | if (obj.metadata) { 60 | obj.metadata.namespace = config.clusterSvcsNamespaceName; 61 | } 62 | }, 63 | ], 64 | }, 65 | {providers: { kubernetes: provider }}, 66 | ); 67 | -------------------------------------------------------------------------------- /aws/04-cluster-services/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-aws-cluster-svcs", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/aws": "latest", 9 | "@pulumi/kubernetes": "latest", 10 | "@pulumi/pulumi": "latest" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /aws/04-cluster-services/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /aws/05-app-services/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-aws-apps-svcs 2 | description: Deploys common EKS app services. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /aws/05-app-services/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/aws/05-app-services/README.md) 2 | 3 | # App Services - AWS 4 | 5 | Deploy App Services in the EKS Cluster. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/app-services) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Collect any stack configuration references to configure the stack in the 35 | next step. 36 | 37 | To get the Pulumi Stack Reference of a dependent stack, reference it in the 38 | config using the format: `//` e.g. `myUser/myProject/dev01` 39 | 40 | You can retrieve the Stack's reference name by running `pulumi stack ls` in 41 | the stack, and extracting it's stack URI. 42 | 43 | The stack reference for the example below is: `myUser/k8s-aws-identity/dev-1573587501` 44 | 45 | ```bash 46 | user@pulumi:~/pulumi/kubernetes-guides/aws/01-identity$ pul stack ls 47 | NAME LAST UPDATE RESOURCE COUNT URL 48 | dev-1573587501* 4 minutes ago 13 https://app.pulumi.com/myUser/k8s-aws-identity/dev-1573587501 49 | ``` 50 | 51 | 1. Configure the stack. 52 | 53 | ```bash 54 | $ pulumi config set aws:region us-west-2 55 | $ pulumi config set k8s-aws-apps-svcs:infraStackRef myUser/k8s-aws-infra/dev-1573589378 && \ 56 | $ pulumi config set k8s-aws-apps-svcs:clusterStackRef myUser/k8s-aws-cluster/dev-1571780002 57 | ``` 58 | 59 | 1. Update the stack. 60 | 61 | ```bash 62 | $ pulumi up 63 | ``` 64 | 65 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 66 | 67 | ```bash 68 | $ pulumi destroy --yes 69 | $ pulumi stack rm --yes 70 | ``` 71 | -------------------------------------------------------------------------------- /aws/05-app-services/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | }; 23 | -------------------------------------------------------------------------------- /aws/05-app-services/index.ts: -------------------------------------------------------------------------------- 1 | import * as aws from "@pulumi/aws"; 2 | import * as k8s from "@pulumi/kubernetes"; 3 | import * as pulumi from "@pulumi/pulumi"; 4 | import * as random from "@pulumi/random"; 5 | import { config } from "./config"; 6 | 7 | const projectName = pulumi.getProject(); 8 | 9 | const privateSubnetIds = config.privateSubnetIds; 10 | const securityGroupIds = config.securityGroupIds; 11 | const clusterName = config.clusterName; 12 | 13 | // Generate a strong password for the Postgres DB. 14 | const password = new random.RandomPassword(`${projectName}-password`, { 15 | length: 16, 16 | overrideSpecial: "_%@", 17 | special: true, 18 | }).result; 19 | 20 | // Create a Postgres DB instance of RDS. 21 | const dbSubnets = new aws.rds.SubnetGroup(`${projectName}-subnets`, { 22 | subnetIds: privateSubnetIds 23 | }); 24 | const db = new aws.rds.Instance("postgresdb", { 25 | engine: "postgres", 26 | instanceClass: "db.t2.micro", 27 | allocatedStorage: 20, 28 | dbSubnetGroupName: dbSubnets.id, 29 | vpcSecurityGroupIds: securityGroupIds, 30 | name: "testdb", 31 | username: "alice", 32 | password: password, 33 | skipFinalSnapshot: true, 34 | }); 35 | 36 | // Create a Secret from the DB connection information. 37 | const provider = new k8s.Provider("provider", {kubeconfig: config.kubeconfig}); 38 | const dbConn = new k8s.core.v1.Secret("postgres-db-conn", 39 | { 40 | data: { 41 | host: db.address.apply(addr => Buffer.from(addr).toString("base64")), 42 | port: db.port.apply(port => Buffer.of(port).toString("base64")), 43 | username: db.username.apply(user => Buffer.from(user).toString("base64")), 44 | password: password.apply(pass => Buffer.from(pass).toString("base64")), 45 | }, 46 | }, 47 | {provider: provider}, 48 | ); 49 | 50 | // Create a Redis instance. 51 | const cacheSubnets = new aws.elasticache.SubnetGroup(`${projectName}-cache-subnets`, { 52 | subnetIds: privateSubnetIds, 53 | }); 54 | const cacheCluster = new aws.elasticache.Cluster("cachecluster", { 55 | engine: "redis", 56 | nodeType: "cache.t2.micro", 57 | numCacheNodes: 1, 58 | subnetGroupName: cacheSubnets.id, 59 | securityGroupIds: securityGroupIds, 60 | }); 61 | 62 | // Create a ConfigMap from the cache connection information. 63 | const cacheConn = new k8s.core.v1.ConfigMap("postgres-db-conn", 64 | { 65 | data: { 66 | host: cacheCluster.cacheNodes[0].address.apply(addr => Buffer.from(addr).toString("base64")), 67 | }, 68 | }, 69 | {provider: provider}, 70 | ); 71 | -------------------------------------------------------------------------------- /aws/05-app-services/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-aws-apps-svcs", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/aws": "latest", 9 | "@pulumi/kubernetes": "latest", 10 | "@pulumi/random": "latest", 11 | "@pulumi/pulumi": "latest" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /aws/05-app-services/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /aws/06-apps/build-deploy-container/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-deploy-container 2 | description: Build and push image to private registry and create a Deployment from it. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /aws/06-apps/build-deploy-container/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/aws/06-apps/build-deploy-container/README.md) 2 | 3 | # Build container image and push to private registry on AWS 4 | 5 | This example builds a container image of a simple Node app and pushes the image 6 | to a private registry on ECR. The image is used to create a Kubernetes 7 | Deployment. 8 | 9 | ## Deploying the App 10 | 11 | To deploy your infrastructure, follow the below steps. 12 | 13 | ### Prerequisites 14 | 15 | 1. [Install Pulumi](https://www.pulumi.com/docs/get-started/install/) 16 | 1. [Install Node.js 8.11.3](https://nodejs.org/en/download/) 17 | 1. [Install Docker](https://docs.docker.com/v17.09/engine/installation/) 18 | 1. [Configure AWS Credentials](https://www.pulumi.com/docs/intro/cloud-providers/aws/setup/) 19 | 1. [Configure access to a Kubernetes cluster](https://kubernetes.io/docs/setup/) 20 | 21 | ### Steps 22 | 23 | After cloning this repo, from this working directory, run these commands: 24 | 25 | 1. Install the required Node.js packages: 26 | 27 | ```bash 28 | $ npm install 29 | ``` 30 | 31 | 2. Create a new stack, which is an isolated deployment target for this example: 32 | 33 | ```bash 34 | $ pulumi stack init 35 | ``` 36 | 37 | 3. Set the required configuration variables for this program: 38 | 39 | ```bash 40 | $ pulumi config set aws:region us-west-2 # Any valid AWS region here. 41 | ``` 42 | 43 | Note that you can choose different regions here. 44 | 45 | 4. Bring up the stack, which will create the cloud resources, build and push the image to the private registry, 46 | and then create a Deployment using that image. 47 | 48 | ```bash 49 | $ pulumi up 50 | ``` 51 | 52 | 5. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 53 | 54 | ```bash 55 | $ pulumi destroy --yes 56 | $ pulumi stack rm --yes 57 | ``` 58 | -------------------------------------------------------------------------------- /aws/06-apps/build-deploy-container/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | }; 23 | -------------------------------------------------------------------------------- /aws/06-apps/build-deploy-container/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as awsx from "@pulumi/awsx"; 16 | import * as k8s from "@pulumi/kubernetes"; 17 | import * as kx from "@pulumi/kubernetesx"; 18 | import { config } from "./config"; 19 | 20 | // Create a new VPC with custom settings. 21 | const vpcName = "eksVpc"; 22 | const vpc = new awsx.ec2.Vpc(vpcName, { 23 | cidrBlock: "172.16.0.0/16", 24 | tags: { "Name": vpcName }, 25 | }); 26 | 27 | // Export the VPC resource IDs. 28 | export const vpcId = vpc.vpcId; 29 | export const publicSubnetIds = vpc.publicSubnetIds; 30 | export const privateSubnetIds = vpc.privateSubnetIds; 31 | 32 | // Create a repository. 33 | const repo = new awsx.ecr.Repository("repo", { 34 | forceDelete: true, 35 | }); 36 | 37 | // Build a Docker image from a local Dockerfile context in the 38 | // './node-app' directory, and push it to the registry. 39 | const customImage = "node-app"; 40 | const appImage = new awsx.ecr.Image("image", { 41 | repositoryUrl: repo.url, 42 | path: `./${customImage}`, 43 | }); 44 | 45 | // Create a k8s provider. 46 | const provider = new k8s.Provider("provider", { 47 | kubeconfig: config.kubeconfig, 48 | namespace: config.appsNamespaceName, 49 | }); 50 | 51 | // Create a Deployment of the built container. 52 | const appLabels = { app: customImage }; 53 | const appDeployment = new k8s.apps.v1.Deployment("app", { 54 | spec: { 55 | selector: { matchLabels: appLabels }, 56 | replicas: 1, 57 | template: { 58 | metadata: { labels: appLabels }, 59 | spec: { 60 | containers: [{ 61 | name: customImage, 62 | image: appImage.imageUri, 63 | ports: [{name: "http", containerPort: 80}], 64 | }], 65 | } 66 | }, 67 | } 68 | }, { provider: provider }); 69 | 70 | // 71 | // Example using kx. 72 | // 73 | 74 | // Define the Pod for the Deployment. 75 | const pb = new kx.PodBuilder({ 76 | containers: [{ 77 | image: appImage.imageUri, 78 | ports: { "http": 80 }, 79 | }], 80 | }); 81 | 82 | // Create a Deployment of the Pod defined by the PodBuilder. 83 | const appDeploymentKx = new kx.Deployment("app-kx", { 84 | spec: pb.asDeploymentSpec(), 85 | }, { provider: provider }); 86 | -------------------------------------------------------------------------------- /aws/06-apps/build-deploy-container/node-app/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /aws/06-apps/build-deploy-container/node-app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8.9.3-alpine 2 | RUN mkdir -p /usr/src/app 3 | COPY ./app/* /usr/src/app/ 4 | WORKDIR /usr/src/app 5 | RUN npm install 6 | CMD node /usr/src/app/index.js 7 | -------------------------------------------------------------------------------- /aws/06-apps/build-deploy-container/node-app/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello, world!

4 | 5 | 6 | -------------------------------------------------------------------------------- /aws/06-apps/build-deploy-container/node-app/app/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const morgan = require('morgan'); 3 | 4 | const app = express(); 5 | app.use(morgan('combined')); 6 | 7 | app.get('/', (req, res) => { 8 | res.sendFile(__dirname + '/index.html') 9 | }); 10 | 11 | var listener = app.listen(process.env.PORT || 80, function() { 12 | console.log('listening on port ' + listener.address().port); 13 | }); -------------------------------------------------------------------------------- /aws/06-apps/build-deploy-container/node-app/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-helloworld", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": { 7 | "express": "^4.14.0", 8 | "morgan": "^1.8.2" 9 | }, 10 | "devDependencies": {}, 11 | "author": "" 12 | } 13 | -------------------------------------------------------------------------------- /aws/06-apps/build-deploy-container/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-aws-apps-deploy-container", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/awsx": "latest", 9 | "@pulumi/docker": "latest", 10 | "@pulumi/kubernetes": "latest", 11 | "@pulumi/kubernetesx": "^0.1.0", 12 | "@pulumi/pulumi": "latest" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /aws/06-apps/build-deploy-container/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /azure/01-identity/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-az-identity 2 | description: Creates an identity stack for an AKS cluster and its users. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /azure/01-identity/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/azure/01-identity/README.md) 2 | 3 | # Identity - Azure 4 | 5 | Create the Identity resources to deploy AKS. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/identity) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Configure the stack. 35 | 36 | ```bash 37 | $ pulumi config set azure:location westus2 38 | ``` 39 | 40 | 1. Update the stack. 41 | 42 | ```bash 43 | $ pulumi up 44 | ``` 45 | 46 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 47 | 48 | ```bash 49 | $ pulumi destroy --yes 50 | $ pulumi stack rm --yes 51 | ``` 52 | -------------------------------------------------------------------------------- /azure/01-identity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-az-identity", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/azure": "latest", 9 | "@pulumi/azuread": "latest", 10 | "@pulumi/random": "latest", 11 | "@pulumi/pulumi": "latest" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /azure/01-identity/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /azure/02-managed-infra/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-az-infra 2 | description: Creates a managed infrastructure stack for an AKS cluster. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /azure/02-managed-infra/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/azure/02-managed-infra/README.md) 2 | 3 | # Managed Infrastructure - Azure 4 | 5 | Create the Managed Infrastructure resources to deploy AKS. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/managed-infra) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Collect any stack configuration references to configure the stack in the 35 | next step. 36 | 37 | To get the Pulumi Stack Reference of a dependent stack, reference it in the 38 | config using the format: `//` e.g. `myUser/myProject/dev01` 39 | 40 | You can retrieve the Stack's reference name by running `pulumi stack ls` in 41 | the stack, and extracting it's stack URI. 42 | 43 | The stack reference for the example below is: `myUser/k8s-az-identity/dev-1573587501` 44 | 45 | ```bash 46 | user@pulumi:~/pulumi/kubernetes-guides/azure/01-identity$ pul stack ls 47 | NAME LAST UPDATE RESOURCE COUNT URL 48 | dev-1573587501* 4 minutes ago 13 https://app.pulumi.com/myUser/k8s-az-identity/dev-1573587501 49 | ``` 50 | 51 | 1. Configure the stack. 52 | 53 | ```bash 54 | $ pulumi config set azure:location westus2 55 | $ pulumi config set k8s-az-infra:identityStackRef myUser/k8s-az-identity/dev-1573591216 56 | ``` 57 | 58 | 1. Update the stack. 59 | 60 | ```bash 61 | $ pulumi up 62 | ``` 63 | 64 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 65 | 66 | ```bash 67 | $ pulumi destroy --yes 68 | $ pulumi stack rm --yes 69 | ``` 70 | -------------------------------------------------------------------------------- /azure/02-managed-infra/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | const pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const identityStackRef = new pulumi.StackReference(pulumiConfig.require("identityStackRef")); 8 | 9 | export const config = { 10 | // Resource Group 11 | resourceGroupName: identityStackRef.getOutput("resourceGroupName"), 12 | }; 13 | -------------------------------------------------------------------------------- /azure/02-managed-infra/index.ts: -------------------------------------------------------------------------------- 1 | import * as azure from "@pulumi/azure"; 2 | import * as pulumi from "@pulumi/pulumi"; 3 | import { config } from "./config"; 4 | 5 | const name = pulumi.getProject(); 6 | 7 | // Create a Virtual Network for the cluster 8 | const vnet = new azure.network.VirtualNetwork(name, { 9 | resourceGroupName: config.resourceGroupName, 10 | addressSpaces: ["10.2.0.0/16"], 11 | }); 12 | 13 | // Create a Subnet for the cluster 14 | const subnet = new azure.network.Subnet(name, { 15 | resourceGroupName: config.resourceGroupName, 16 | virtualNetworkName: vnet.name, 17 | addressPrefix: "10.2.1.0/24", 18 | }); 19 | 20 | // Log and Monitoring workspace 21 | const loganalytics = new azure.operationalinsights.AnalyticsWorkspace(name, { 22 | resourceGroupName: config.resourceGroupName, 23 | sku: "PerGB2018", 24 | retentionInDays: 30, 25 | }); 26 | 27 | // Export outputs for other stacks 28 | export const subnetId = subnet.id; 29 | export const logAnalyticsWorkspaceId = loganalytics.id; 30 | -------------------------------------------------------------------------------- /azure/02-managed-infra/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-az-infra", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/azure": "latest", 9 | "@pulumi/pulumi": "latest" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /azure/02-managed-infra/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "config.ts", 23 | "index.ts" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /azure/03-cluster-configuration/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-az-cluster 2 | description: Creates an Azure cluster using best-practices. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /azure/03-cluster-configuration/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/azure/03-cluster-configuration/README.md) 2 | 3 | # Cluster Configuration - Azure 4 | 5 | Create the AKS Cluster and Kubernetes Defaults. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/control-plane) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Collect any stack configuration references to configure the stack in the 35 | next step. 36 | 37 | To get the Pulumi Stack Reference of a dependent stack, reference it in the 38 | config using the format: `//` e.g. `myUser/myProject/dev01` 39 | 40 | You can retrieve the Stack's reference name by running `pulumi stack ls` in 41 | the stack, and extracting it's stack URI. 42 | 43 | The stack reference for the example below is: `myUser/k8s-az-identity/dev-1573587501` 44 | 45 | ```bash 46 | user@pulumi:~/pulumi/kubernetes-guides/azure/01-identity$ pul stack ls 47 | NAME LAST UPDATE RESOURCE COUNT URL 48 | dev-1573587501* 4 minutes ago 13 https://app.pulumi.com/myUser/k8s-az-identity/dev-1573587501 49 | ``` 50 | 51 | 1. Configure the stack. 52 | 53 | ```bash 54 | $ pulumi config set azure:location westus2 55 | $ pulumi config set k8s-az-cluster:identityStackRef metral/k8s-az-identity/dev-1573591216 56 | $ pulumi config set k8s-az-cluster:infraStackRef metral/k8s-az-infra/dev-1573591518 57 | ``` 58 | 59 | 1. Update the stack. 60 | 61 | ```bash 62 | $ pulumi up 63 | ``` 64 | 65 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 66 | 67 | ```bash 68 | $ pulumi destroy --yes 69 | $ pulumi stack rm --yes 70 | ``` 71 | -------------------------------------------------------------------------------- /azure/03-cluster-configuration/config.ts: -------------------------------------------------------------------------------- 1 | import * as azure from "@pulumi/azure"; 2 | import * as pulumi from "@pulumi/pulumi"; 3 | 4 | const pulumiConfig = new pulumi.Config(); 5 | 6 | // Existing Pulumi stack reference in the format: 7 | // // e.g. "myUser/myProject/dev" 8 | 9 | const identityStackRef = new pulumi.StackReference(pulumiConfig.require("identityStackRef")); 10 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 11 | 12 | export const config = { 13 | // Resource Group 14 | resourceGroupName: identityStackRef.getOutput("resourceGroupName"), 15 | 16 | // Identity 17 | adServerAppId: identityStackRef.getOutput("adServerAppId"), 18 | adServerAppSecret: identityStackRef.getOutput("adServerAppSecret"), 19 | adClientAppId: identityStackRef.getOutput("adClientAppId"), 20 | adClientAppSecret: identityStackRef.getOutput("adClientAppSecret"), 21 | adGroupAdmins: identityStackRef.getOutput("adGroupAdmins"), 22 | adGroupDevs: identityStackRef.getOutput("adGroupDevs"), 23 | 24 | // Infrastructure / Networking 25 | subnetId: infraStackRef.getOutput("subnetId"), 26 | logAnalyticsWorkspaceId: infraStackRef.getOutput("logAnalyticsWorkspaceId"), 27 | }; 28 | -------------------------------------------------------------------------------- /azure/03-cluster-configuration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-az-cluster", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/azure": "latest", 9 | "@pulumi/tls": "latest", 10 | "@pulumi/kubernetes": "latest", 11 | "@pulumi/pulumi": "latest" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /azure/03-cluster-configuration/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "config.ts", 23 | "index.ts" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /azure/04-cluster-services/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-az-cl-svcs 2 | description: Creates Azure Cluster Services for an AKS cluster. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /azure/04-cluster-services/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/azure/04-cluster-services/README.md) 2 | 3 | # Cluster Services - Azure 4 | 5 | Deploy Cluster Services in the AKS cluster. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/cluster-services) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Collect any stack configuration references to configure the stack in the 35 | next step. 36 | 37 | To get the Pulumi Stack Reference of a dependent stack, reference it in the 38 | config using the format: `//` e.g. `myUser/myProject/dev01` 39 | 40 | You can retrieve the Stack's reference name by running `pulumi stack ls` in 41 | the stack, and extracting it's stack URI. 42 | 43 | The stack reference for the example below is: `myUser/k8s-az-identity/dev-1573587501` 44 | 45 | ```bash 46 | user@pulumi:~/pulumi/kubernetes-guides/azure/01-identity$ pul stack ls 47 | NAME LAST UPDATE RESOURCE COUNT URL 48 | dev-1573587501* 4 minutes ago 13 https://app.pulumi.com/myUser/k8s-az-identity/dev-1573587501 49 | ``` 50 | 51 | 1. Configure the stack. 52 | 53 | ```bash 54 | $ pulumi config set azure:location westus2 55 | $ pulumi config set k8s-az-cl-svcs:infraStackRef myUser/k8s-az-infra/dev-1573591518 56 | $ pulumi config set k8s-az-cl-svcs:clusterStackRef myUser/k8s-az-cluster/dev-1573591790 57 | ``` 58 | 59 | 1. Update the stack. 60 | 61 | ```bash 62 | $ pulumi up 63 | ``` 64 | 65 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 66 | 67 | ```bash 68 | $ pulumi destroy --yes 69 | $ pulumi stack rm --yes 70 | ``` 71 | -------------------------------------------------------------------------------- /azure/04-cluster-services/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | const pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infrastructure 12 | logAnalyticsWorkspaceId: infraStackRef.getOutput("logAnalyticsWorkspaceId"), 13 | 14 | // AKS Cluster 15 | clusterId: clusterStackRef.getOutput("clusterId"), 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | }; 18 | -------------------------------------------------------------------------------- /azure/04-cluster-services/index.ts: -------------------------------------------------------------------------------- 1 | import * as azure from "@pulumi/azure"; 2 | import * as pulumi from "@pulumi/pulumi"; 3 | import { config } from "./config"; 4 | 5 | const name = pulumi.getProject(); 6 | 7 | // Enable the Monitoring Diagonostic control plane component logs and AllMetrics 8 | const azMonitoringDiagnostic = new azure.monitoring.DiagnosticSetting(name, { 9 | logAnalyticsWorkspaceId: config.logAnalyticsWorkspaceId, 10 | targetResourceId: config.clusterId, 11 | logs: ["kube-apiserver", "kube-controller-manager", "kube-scheduler", "kube-audit", "cluster-autoscaler"] 12 | .map(category => ({ 13 | category, 14 | enabled : true, 15 | retentionPolicy: { enabled: true }, 16 | })), 17 | metrics: [{ 18 | category: "AllMetrics", 19 | retentionPolicy: { enabled: true }, 20 | }], 21 | }); 22 | -------------------------------------------------------------------------------- /azure/04-cluster-services/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-az-cl-svcs", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/azure": "latest", 9 | "@pulumi/pulumi": "latest" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /azure/04-cluster-services/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "config.ts", 23 | "index.ts" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /azure/05-app-services/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-az-apps-svcs 2 | description: Creates Application Services for an AKS cluster. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /azure/05-app-services/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/azure/05-app-services/README.md) 2 | 3 | # App Services - Azure 4 | 5 | Deploy App Services in the AKS cluster. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/app-services) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Collect any stack configuration references to configure the stack in the 35 | next step. 36 | 37 | To get the Pulumi Stack Reference of a dependent stack, reference it in the 38 | config using the format: `//` e.g. `myUser/myProject/dev01` 39 | 40 | You can retrieve the Stack's reference name by running `pulumi stack ls` in 41 | the stack, and extracting it's stack URI. 42 | 43 | The stack reference for the example below is: `myUser/k8s-az-identity/dev-1573587501` 44 | 45 | ```bash 46 | user@pulumi:~/pulumi/kubernetes-guides/azure/01-identity$ pul stack ls 47 | NAME LAST UPDATE RESOURCE COUNT URL 48 | dev-1573587501* 4 minutes ago 13 https://app.pulumi.com/myUser/k8s-az-identity/dev-1573587501 49 | ``` 50 | 51 | 1. Configure the stack. 52 | 53 | ```bash 54 | $ pulumi config set azure:location westus2 55 | $ pulumi config set k8s-az-apps-svcs:identityStackRef myUser/k8s-az-infra/dev-1573591518 && \ 56 | $ pulumi config set k8s-az-cl-svcs:infraStackRef myUser/k8s-az-infra/dev-1573591518 57 | $ pulumi config set k8s-az-cl-svcs:clusterStackRef myUser/k8s-az-cluster/dev-1573591790 58 | ``` 59 | 60 | 1. Update the stack. 61 | 62 | ```bash 63 | $ pulumi up 64 | ``` 65 | 66 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 67 | 68 | ```bash 69 | $ pulumi destroy --yes 70 | $ pulumi stack rm --yes 71 | ``` 72 | -------------------------------------------------------------------------------- /azure/05-app-services/config.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. All rights reserved. 2 | 3 | import * as pulumi from "@pulumi/pulumi"; 4 | 5 | const pulumiConfig = new pulumi.Config(); 6 | 7 | // Existing Pulumi stack reference in the format: 8 | // // e.g. "myUser/myProject/dev" 9 | 10 | const identityStackRef = new pulumi.StackReference(pulumiConfig.require("identityStackRef")); 11 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 12 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 13 | 14 | export const config = { 15 | // Resource Group 16 | resourceGroupName: identityStackRef.getOutput("resourceGroupName"), 17 | 18 | // Identity 19 | adApplicationId: identityStackRef.getOutput("adApplicationId"), 20 | adSpPassword: identityStackRef.getOutput("adSpPassword"), 21 | 22 | // Infrastructure / Networking 23 | subnetId: infraStackRef.getOutput("subnetId"), 24 | logAnalyticsWorkspaceId: infraStackRef.getOutput("logAnalyticsWorkspaceId"), 25 | 26 | // AKS Cluster 27 | clusterId: clusterStackRef.getOutput("clusterId"), 28 | kubeconfig: clusterStackRef.getOutput("kubeconfigAdmin"), 29 | clusterName: clusterStackRef.getOutput("clusterName"), 30 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 31 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 32 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 33 | }; 34 | -------------------------------------------------------------------------------- /azure/05-app-services/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. All rights reserved. 2 | 3 | import * as azure from "@pulumi/azure"; 4 | import * as k8s from "@pulumi/kubernetes"; 5 | import * as pulumi from "@pulumi/pulumi"; 6 | 7 | import { config } from "./config"; 8 | import * as mongoHelpers from "./mongoHelpers"; 9 | 10 | const name = pulumi.getProject(); 11 | 12 | // Define a separate resource group for app services. 13 | const resourceGroup = new azure.core.ResourceGroup(name); 14 | 15 | // Create a MongoDB-flavored instance of CosmosDB. 16 | const cosmosdb = new azure.cosmosdb.Account("k8s-az-mongodb", { 17 | resourceGroupName: resourceGroup.name, 18 | kind: "MongoDB", 19 | consistencyPolicy: { 20 | consistencyLevel: "Session", 21 | }, 22 | offerType: "Standard", 23 | geoLocations: [ 24 | { location: resourceGroup.location, failoverPriority: 0 }, 25 | ], 26 | }); 27 | 28 | // A k8s provider instance of the cluster. 29 | const provider = new k8s.Provider(`${name}-aks`, { 30 | kubeconfig: config.kubeconfig, 31 | }); 32 | 33 | // Create secret from MongoDB connection string. 34 | const mongoConnStrings = new k8s.core.v1.Secret( 35 | "mongo-secrets", 36 | { 37 | metadata: { name: "mongo-secrets", namespace: config.appsNamespaceName}, 38 | data: mongoHelpers.parseConnString(cosmosdb.connectionStrings), 39 | }, 40 | { provider }, 41 | ); 42 | -------------------------------------------------------------------------------- /azure/05-app-services/mongoHelpers.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. All rights reserved. 2 | 3 | import * as pulumi from "@pulumi/pulumi"; 4 | 5 | export function parseConnString( 6 | conns: pulumi.Output, 7 | ): pulumi.Output<{ [key: string]: string }> { 8 | // Per the official docs[1], the format of this connection string is: 9 | // 10 | // mongodb://username:password@host:port/[database]?ssl=true 11 | // 12 | // Where these could have the following values: 13 | // 14 | // { 15 | // username: "cosmosdb93a4133a", 16 | // password: "23maXrWsrzZ1LmPe4w6XNGRJJTHsqGZPDTjyVQNbPaw119KCoCNpStH0DQms5MKdyAecisBM9uWbpV7lUnyNeQ==", 17 | // host: "cosmosdb93a4133a.documents.azure.com", 18 | // port: "10255", 19 | // database: "mydatabase" 20 | // } 21 | // 22 | // There are a few subtleties involved in getting the Bitnami node Chart to actually be able to 23 | // use this: 24 | // 25 | // 1. The `database` field is optional, we default to `test`, as the API expects. 26 | // 2. The node Chart expects the components of this connection string to be parsed and 27 | // presented in files in a `Secret`. The CosmosDb API doesn't natively expose this, so we 28 | // must parse it ourselves. 29 | // 3. The node Chart uses mongoose to speak the MongoDB wire protocol to CosmosDB. Mongoose 30 | // fails to parse base64-encoded passwords because it doesn't like the `=` character. This 31 | // means we have to (1) URI-encode the password component ourselves, and (2) base64-encode 32 | // that URI-encoded password, because this is the format Kubernetes expects. 33 | // 34 | // [1]: https://docs.microsoft.com/en-us/azure/cosmos-db/connect-mongodb-account 35 | 36 | function toBase64(s: string): string { 37 | return Buffer.from(s).toString("base64"); 38 | } 39 | 40 | return conns.apply(conns => { 41 | const conn = conns[0]; 42 | const noProtocol = conn.replace(/^mongodb\:\/\//, ""); 43 | const [username, rest1, rest2] = noProtocol.split(":", 3); 44 | const [password, host] = rest1.split("@", 2); 45 | const [port, rest3] = rest2.split("/", 2); 46 | const database = rest3.replace(/\?ssl=true$/, ""); 47 | return { 48 | host: toBase64(host), 49 | port: toBase64(port), 50 | username: toBase64(username), 51 | password: toBase64(encodeURIComponent(password)), 52 | database: toBase64(database === "" ? "test" : database), 53 | }; 54 | }); 55 | } 56 | -------------------------------------------------------------------------------- /azure/05-app-services/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-az-app-svcs", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/azure": "latest", 9 | "@pulumi/kubernetes": "latest", 10 | "@pulumi/pulumi": "latest" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /azure/05-app-services/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "config.ts", 23 | "index.ts", 24 | "mongoHelpers.ts" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /azure/06-apps/build-deploy-container/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-deploy-container 2 | description: Build and push image to private registry and create a Deployment from it. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /azure/06-apps/build-deploy-container/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/azure/06-apps/build-deploy-container/README.md) 2 | 3 | # Build container image and push to private registry on Azure 4 | 5 | This example builds a container image of a simple Node app and pushes the image 6 | to a private registry on Azure. The image is used to create a Kubernetes 7 | Deployment. 8 | 9 | ## Deploying the App 10 | 11 | To deploy your infrastructure, follow the below steps. 12 | 13 | ### Prerequisites 14 | 15 | 1. [Install Pulumi](https://www.pulumi.com/docs/get-started/install/) 16 | 1. [Install Node.js 8.11.3](https://nodejs.org/en/download/) 17 | 1. [Install Docker](https://docs.docker.com/v17.09/engine/installation/) 18 | 1. [Configure Azure Credentials](https://www.pulumi.com/docs/intro/cloud-providers/azure/setup/) 19 | 1. [Configure access to a Kubernetes cluster](https://kubernetes.io/docs/setup/) 20 | 21 | ### Steps 22 | 23 | After cloning this repo, from this working directory, run these commands: 24 | 25 | 1. Install the required Node.js packages: 26 | 27 | ```bash 28 | $ npm install 29 | ``` 30 | 31 | 2. Create a new stack, which is an isolated deployment target for this example: 32 | 33 | ```bash 34 | $ pulumi stack init 35 | ``` 36 | 37 | 3. Set the required configuration variables for this program: 38 | 39 | ```bash 40 | $ pulumi config set azure:location westus2 # Any valid Azure location here. 41 | ``` 42 | 43 | Note that you can choose different regions here. 44 | 45 | 4. Bring up the stack, which will create the cloud resources, build and push the image to the private registry, 46 | and then create a Deployment using that image. 47 | 48 | ```bash 49 | $ pulumi up 50 | ``` 51 | 52 | 5. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 53 | 54 | ```bash 55 | $ pulumi destroy --yes 56 | $ pulumi stack rm --yes 57 | ``` 58 | -------------------------------------------------------------------------------- /azure/06-apps/build-deploy-container/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | }; 23 | -------------------------------------------------------------------------------- /azure/06-apps/build-deploy-container/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as azure from "@pulumi/azure"; 16 | import * as docker from "@pulumi/docker"; 17 | import * as k8s from "@pulumi/kubernetes"; 18 | import * as kx from "@pulumi/kubernetesx"; 19 | import * as pulumi from "@pulumi/pulumi"; 20 | import { config } from "./config"; 21 | 22 | // Create an Azure Resource Group 23 | const resourceGroup = new azure.core.ResourceGroup("samples"); 24 | 25 | // Create a registry in ACR. 26 | const registry = new azure.containerservice.Registry("myregistry", { 27 | resourceGroupName: resourceGroup.name, 28 | sku: "Basic", 29 | adminEnabled: true, 30 | }); 31 | 32 | // Build a Docker image from a local Dockerfile context in the 33 | // './node-app' directory, and push it to the registry. 34 | const customImage = "node-app"; 35 | const appImage = new docker.Image(customImage, { 36 | imageName: pulumi.interpolate`${registry.loginServer}/${customImage}:v1.0.0`, 37 | build: { 38 | context: `./${customImage}`, 39 | }, 40 | registry: { 41 | server: registry.loginServer, 42 | username: registry.adminUsername, 43 | password: registry.adminPassword, 44 | }, 45 | }); 46 | 47 | // Create a k8s provider. 48 | const provider = new k8s.Provider("provider", { 49 | kubeconfig: config.kubeconfig, 50 | namespace: config.appsNamespaceName, 51 | }); 52 | 53 | // Create a Deployment of the built container. 54 | const appLabels = { app: customImage }; 55 | const appDeployment = new k8s.apps.v1.Deployment("app", { 56 | spec: { 57 | selector: { matchLabels: appLabels }, 58 | replicas: 1, 59 | template: { 60 | metadata: { labels: appLabels }, 61 | spec: { 62 | containers: [{ 63 | name: customImage, 64 | image: appImage.imageName, 65 | ports: [{name: "http", containerPort: 80}], 66 | }], 67 | } 68 | }, 69 | } 70 | }, { provider: provider }); 71 | 72 | // 73 | // Example using kx. 74 | // 75 | 76 | // Define the Pod for the Deployment. 77 | const pb = new kx.PodBuilder({ 78 | containers: [{ 79 | image: appImage.imageName, 80 | ports: { "http": 80 }, 81 | }], 82 | }); 83 | 84 | // Create a Deployment of the Pod defined by the PodBuilder. 85 | const appDeploymentKx = new kx.Deployment("app-kx", { 86 | spec: pb.asDeploymentSpec(), 87 | }, { provider: provider }); 88 | -------------------------------------------------------------------------------- /azure/06-apps/build-deploy-container/node-app/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /azure/06-apps/build-deploy-container/node-app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8.9.3-alpine 2 | RUN mkdir -p /usr/src/app 3 | COPY ./app/* /usr/src/app/ 4 | WORKDIR /usr/src/app 5 | RUN npm install 6 | CMD node /usr/src/app/index.js 7 | -------------------------------------------------------------------------------- /azure/06-apps/build-deploy-container/node-app/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello, world!

4 | 5 | 6 | -------------------------------------------------------------------------------- /azure/06-apps/build-deploy-container/node-app/app/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const morgan = require('morgan'); 3 | 4 | const app = express(); 5 | app.use(morgan('combined')); 6 | 7 | app.get('/', (req, res) => { 8 | res.sendFile(__dirname + '/index.html') 9 | }); 10 | 11 | var listener = app.listen(process.env.PORT || 80, function() { 12 | console.log('listening on port ' + listener.address().port); 13 | }); -------------------------------------------------------------------------------- /azure/06-apps/build-deploy-container/node-app/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-helloworld", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": { 7 | "express": "^4.14.0", 8 | "morgan": "^1.8.2" 9 | }, 10 | "devDependencies": {}, 11 | "author": "" 12 | } 13 | -------------------------------------------------------------------------------- /azure/06-apps/build-deploy-container/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-azure-apps-deploy-container", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/azure": "latest", 9 | "@pulumi/docker": "latest", 10 | "@pulumi/kubernetes": "latest", 11 | "@pulumi/kubernetesx": "^0.1.0", 12 | "@pulumi/pulumi": "latest" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /azure/06-apps/build-deploy-container/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /gcp/01-identity/.gitignore: -------------------------------------------------------------------------------- 1 | /.pulumi/ 2 | /.vscode/ 3 | bin/ 4 | node_modules/ 5 | *.pyc 6 | .Python 7 | include/ 8 | lib/ 9 | yarn.lock 10 | yarn-error.log 11 | package-lock.json 12 | Pulumi.*.yaml 13 | .idea/ 14 | *.iml 15 | 16 | infra-ci-client-secret.json 17 | k8s-app-dev-ci-client-secret.json 18 | -------------------------------------------------------------------------------- /gcp/01-identity/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-gcp-identity 2 | description: Creates an identity stack for an GKE cluster and its users. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /gcp/01-identity/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/gcp/01-identity/README.md) 2 | 3 | # Identity - GCP 4 | 5 | Create the Identity resources to deploy GKE. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/identity) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Configure the stack. 35 | 36 | ```bash 37 | $ pulumi config set gcp:zone us-west1-a 38 | $ pulumi config set gcp:project 39 | ``` 40 | 41 | 1. Update the stack. 42 | 43 | ```bash 44 | $ pulumi up 45 | ``` 46 | 47 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 48 | 49 | ```bash 50 | $ pulumi destroy --yes 51 | $ pulumi stack rm --yes 52 | ``` 53 | -------------------------------------------------------------------------------- /gcp/01-identity/config.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { Config } from "@pulumi/pulumi"; 16 | 17 | // 18 | // GCP-specific config. 19 | // 20 | 21 | // project is the GCP project you are going to deploy to. 22 | export const project = new Config("gcp").require("project"); 23 | -------------------------------------------------------------------------------- /gcp/01-identity/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as gcp from "@pulumi/gcp"; 16 | import * as config from "./config"; 17 | import * as util from "./util"; 18 | 19 | // Create the GKE cluster admins ServiceAccount. 20 | const adminsName = "admins"; 21 | export const adminsAccountId = `k8s-${adminsName}`; 22 | const adminsIamServiceAccount = new gcp.serviceAccount.Account(adminsName, { 23 | project: config.project, 24 | accountId: adminsAccountId, 25 | displayName: "Kubernetes Admins", 26 | }); 27 | 28 | // Bind the admin ServiceAccount to be a GKE cluster admin. 29 | util.bindToRole(`${adminsName}-k8s`, adminsIamServiceAccount, { 30 | project: config.project, 31 | roles: ["roles/container.admin", "roles/container.clusterAdmin", "roles/container.developer"], 32 | }); 33 | 34 | // Bind the admin ServiceAccount to be a CloudSQL admin. 35 | util.bindToRole(`${adminsName}-cloudsql`, adminsIamServiceAccount, { 36 | project: config.project, 37 | roles: ["roles/cloudsql.admin"], 38 | }); 39 | 40 | // Export the admins ServiceAccount key. 41 | const adminsIamServiceAccountKey = util.createServiceAccountKey(`${adminsName}Key`, adminsIamServiceAccount); 42 | 43 | // Export the admins ServiceAccount client secret to authenticate as this service account. 44 | export const adminsIamServiceAccountSecret = util.clientSecret(adminsIamServiceAccountKey); 45 | 46 | // Create the GKE cluster developers ServiceAccount. 47 | const devsName = "devs"; 48 | export const devsAccountId = `k8s-${devsName}`; 49 | const devsIamServiceAccount = new gcp.serviceAccount.Account(devsName, { 50 | project: config.project, 51 | accountId: devsAccountId, 52 | displayName: "Kubernetes Developers", 53 | }); 54 | 55 | 56 | // Bind the devs ServiceAccount to be a GKE cluster developer. 57 | util.bindToRole(`${devsName}-k8s`, devsIamServiceAccount, { 58 | project: config.project, 59 | roles: ["roles/container.developer"], 60 | }); 61 | 62 | // Export the devs ServiceAccount key. 63 | const devsIamServiceAccountKey = util.createServiceAccountKey(`${devsName}Key`, devsIamServiceAccount); 64 | 65 | // Export the devs ServiceAccount client secret to authenticate as this service account. 66 | export const devsIamServiceAccountSecret = util.clientSecret(devsIamServiceAccountKey); 67 | 68 | // Export the project name for downstream stacks. 69 | export const project = config.project; 70 | -------------------------------------------------------------------------------- /gcp/01-identity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-gcp-identity", 3 | "devDependencies": { 4 | "@types/node": "latest" 5 | }, 6 | "dependencies": { 7 | "@pulumi/gcp": "latest", 8 | "@pulumi/pulumi": "latest" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /gcp/01-identity/util.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as pulumi from "@pulumi/pulumi"; 16 | import * as gcp from "@pulumi/gcp"; 17 | 18 | export function bindToRole( 19 | name: string, 20 | sa: gcp.serviceAccount.Account, 21 | args: { project: pulumi.Input; roles: string[]}) 22 | { 23 | args.roles.forEach((role, index) => { 24 | new gcp.projects.IAMMember(`${name}-${index}`, { 25 | project: args.project, 26 | role: role, 27 | member: sa.email.apply(email => `serviceAccount:${email}`), 28 | }); 29 | }) 30 | } 31 | 32 | export function createServiceAccountKey(name: string, sa: gcp.serviceAccount.Account): gcp.serviceAccount.Key { 33 | return new gcp.serviceAccount.Key(name, { serviceAccountId: sa.name }); 34 | } 35 | 36 | export function clientSecret(key: gcp.serviceAccount.Key): pulumi.Output { 37 | return key.privateKey.apply(key => JSON.parse(Buffer.from(key, "base64").toString("ascii"))); 38 | } 39 | -------------------------------------------------------------------------------- /gcp/02-managed-infra/.gitignore: -------------------------------------------------------------------------------- 1 | /.pulumi/ 2 | /.vscode/ 3 | bin/ 4 | node_modules/ 5 | *.pyc 6 | .Python 7 | include/ 8 | lib/ 9 | yarn.lock 10 | yarn-error.log 11 | package-lock.json 12 | Pulumi.*.yaml 13 | .idea/ 14 | *.iml 15 | 16 | infra-ci-client-secret.json 17 | k8s-app-dev-ci-client-secret.json 18 | -------------------------------------------------------------------------------- /gcp/02-managed-infra/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-gcp-infra 2 | description: Creates an managed infrastructure stack for an GCP GKE cluster. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /gcp/02-managed-infra/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/gcp/02-managed-infra/README.md) 2 | 3 | # Managed Infrastructure - GCP 4 | 5 | Create the Managed Infrastructure resources to deploy GKE. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/managed-infra) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Configure the stack. 35 | 36 | ```bash 37 | $ pulumi config set gcp:zone us-west1-a 38 | $ pulumi config set gcp:project 39 | ``` 40 | 41 | 1. Update the stack. 42 | 43 | ```bash 44 | $ pulumi up 45 | ``` 46 | 47 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 48 | 49 | ```bash 50 | $ pulumi destroy --yes 51 | $ pulumi stack rm --yes 52 | ``` 53 | -------------------------------------------------------------------------------- /gcp/02-managed-infra/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as pulumi from "@pulumi/pulumi"; 16 | import * as gcp from "@pulumi/gcp"; 17 | import * as k8s from "@pulumi/kubernetes"; 18 | import * as random from "@pulumi/random"; 19 | 20 | const projectName = pulumi.getProject(); 21 | 22 | // Create a new network. 23 | const network = new gcp.compute.Network(projectName, { 24 | autoCreateSubnetworks: false, 25 | }); 26 | export const networkName = network.name; 27 | 28 | // Create a new subnet. 29 | const subnet = new gcp.compute.Subnetwork(projectName, { 30 | ipCidrRange: "10.0.0.0/24", 31 | network: network.name, 32 | secondaryIpRanges: [{ rangeName: "pods", ipCidrRange: "10.1.0.0/16" }], 33 | }); 34 | export const subnetworkName = subnet.name; 35 | -------------------------------------------------------------------------------- /gcp/02-managed-infra/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-gcp-infra", 3 | "devDependencies": { 4 | "@types/node": "latest" 5 | }, 6 | "peerDependencies": { 7 | "@pulumi/gke": "latest" 8 | }, 9 | "dependencies": { 10 | "@pulumi/gcp": "latest", 11 | "@pulumi/kubernetes": "latest", 12 | "@pulumi/pulumi": "latest", 13 | "@pulumi/random": "latest" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /gcp/03-cluster-configuration/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-gke-cluster 2 | description: Creates a GKE cluster using best-practices. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /gcp/03-cluster-configuration/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/gcp/03-cluster-configuration/README.md) 2 | 3 | # Cluster Configuration - GCP 4 | 5 | Create the GKE Cluster and Kubernetes Defaults. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/control-plane) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Collect any stack configuration references to configure the stack in the 35 | next step. 36 | 37 | To get the Pulumi Stack Reference of a dependent stack, reference it in the 38 | config using the format: `//` e.g. `myUser/myProject/dev01` 39 | 40 | You can retrieve the Stack's reference name by running `pulumi stack ls` in 41 | the stack, and extracting it's stack URI. 42 | 43 | The stack reference for the example below is: `myUser/k8s-gcp-identity/dev-1573587501` 44 | 45 | ```bash 46 | user@pulumi:~/pulumi/kubernetes-guides/gcp/01-identity$ pul stack ls 47 | NAME LAST UPDATE RESOURCE COUNT URL 48 | dev-1573587501* 4 minutes ago 13 https://app.pulumi.com/myUser/k8s-gcp-identity/dev-1573587501 49 | ``` 50 | 51 | 1. Configure the stack. 52 | 53 | ```bash 54 | $ pulumi config set gcp:zone us-west1-a 55 | $ pulumi config set gcp:project 56 | $ pulumi config set k8s-gke-cluster:identityStackRef myUser/k8s-gcp-identity/dev-1573589109 57 | $ pulumi config set k8s-gke-cluster:infraStackRef myUser/k8s-gcp-infra/dev-1573589378 58 | ``` 59 | 60 | 1. Update the stack. 61 | 62 | ```bash 63 | $ pulumi up 64 | ``` 65 | 66 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 67 | 68 | ```bash 69 | $ pulumi destroy --yes 70 | $ pulumi stack rm --yes 71 | ``` 72 | -------------------------------------------------------------------------------- /gcp/03-cluster-configuration/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | const identityStackName = new pulumi.StackReference(pulumiConfig.require("identityStackName")); 6 | const infraStackName = new pulumi.StackReference(pulumiConfig.require("infraStackName")); 7 | 8 | export const config = { 9 | adminsIamServiceAccountSecret: identityStackName.requireOutput("adminsIamServiceAccountSecret"), 10 | devsIamServiceAccountSecret: identityStackName.requireOutput("devsIamServiceAccountSecret"), 11 | project: identityStackName.requireOutput("project"), 12 | adminsAccountId: identityStackName.requireOutput("adminsAccountId"), 13 | devsAccountId: identityStackName.requireOutput("devsAccountId"), 14 | networkName: infraStackName.requireOutput("networkName"), 15 | subnetworkName: infraStackName.requireOutput("subnetworkName"), 16 | }; 17 | -------------------------------------------------------------------------------- /gcp/03-cluster-configuration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-gke-cluster", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest", 6 | "@types/which": "latest" 7 | }, 8 | "dependencies": { 9 | "@pulumi/kubernetes": "latest", 10 | "@pulumi/gcp": "latest", 11 | "@pulumi/pulumi": "latest", 12 | "@pulumi/random": "latest" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gcp/03-cluster-configuration/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /gcp/04-cluster-services/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/kubernetes-guides/a29612928c8082516bac34eb4b57ed2a3cdde9df/gcp/04-cluster-services/README.md -------------------------------------------------------------------------------- /gcp/05-app-services/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-gke-apps-svcs 2 | description: Deploys common GKE app services. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /gcp/05-app-services/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/gcp/05-app-services/README.md) 2 | 3 | # App Services - GCP 4 | 5 | Deploy App Services in the GKE Cluster. 6 | 7 | Check out the [Crosswalk Guide](https://www.pulumi.com/docs/guides/crosswalk/kubernetes/app-services) 8 | on this stack for more details. 9 | 10 | ## Deploying the Stack 11 | 12 | To deploy your infrastructure, follow the below steps. 13 | 14 | ### Prerequisites 15 | 16 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 17 | 18 | ### Steps 19 | 20 | After cloning this repo, from this working directory, run these commands: 21 | 22 | 1. Install the required Node.js packages: 23 | 24 | ```bash 25 | $ npm install 26 | ``` 27 | 28 | 1. Create a new stack, which is an isolated deployment target for this example: 29 | 30 | ```bash 31 | $ pulumi stack init 32 | ``` 33 | 34 | 1. Collect any stack configuration references to configure the stack in the 35 | next step. 36 | 37 | To get the Pulumi Stack Reference of a dependent stack, reference it in the 38 | config using the format: `//` e.g. `myUser/myProject/dev01` 39 | 40 | You can retrieve the Stack's reference name by running `pulumi stack ls` in 41 | the stack, and extracting it's stack URI. 42 | 43 | The stack reference for the example below is: `myUser/k8s-gcp-identity/dev-1573587501` 44 | 45 | ```bash 46 | user@pulumi:~/pulumi/kubernetes-guides/gcp/01-identity$ pul stack ls 47 | NAME LAST UPDATE RESOURCE COUNT URL 48 | dev-1573587501* 4 minutes ago 13 https://app.pulumi.com/myUser/k8s-gcp-identity/dev-1573587501 49 | ``` 50 | 51 | 1. Configure the stack. 52 | 53 | ```bash 54 | $ pulumi config set gcp:zone us-west1-a 55 | $ pulumi config set gcp:project 56 | $ pulumi config set k8s-gke-apps-svcs:identityStackRef myUser/k8s-gcp-identity/dev-1573589109 57 | $ pulumi config set k8s-gke-apps-svcs:clusterStackRef myUser/k8s-gke-cluster/dev-1573601751 58 | ``` 59 | 60 | 1. Update the stack. 61 | 62 | ```bash 63 | $ pulumi up 64 | ``` 65 | 66 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 67 | 68 | ```bash 69 | $ pulumi destroy --yes 70 | $ pulumi stack rm --yes 71 | ``` 72 | -------------------------------------------------------------------------------- /gcp/05-app-services/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const identityStackRef = new pulumi.StackReference(pulumiConfig.require("identityStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | project: identityStackRef.requireOutput("project"), 12 | 13 | // Cluster 14 | kubeconfig: clusterStackRef.requireOutput("kubeconfig"), 15 | clusterName: clusterStackRef.getOutput("clusterName"), 16 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 17 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 18 | }; 19 | -------------------------------------------------------------------------------- /gcp/05-app-services/index.ts: -------------------------------------------------------------------------------- 1 | import * as gcp from "@pulumi/gcp"; 2 | import * as k8s from "@pulumi/kubernetes"; 3 | import * as pulumi from "@pulumi/pulumi"; 4 | import * as random from "@pulumi/random"; 5 | import { config } from "./config"; 6 | 7 | const projectName = pulumi.getProject(); 8 | 9 | // const privateSubnetIds = config.privateSubnetIds; 10 | // const securityGroupIds = config.securityGroupIds; 11 | const clusterName = config.clusterName; 12 | 13 | // Generate a strong password for the Postgres DB. 14 | const postgresDbPassword = new random.RandomString( 15 | `${projectName}-db-password`, 16 | { 17 | length: 20, 18 | special: true, 19 | }, 20 | { additionalSecretOutputs: ["result"] }, 21 | ).result; 22 | 23 | // Create a Postgres DB instance. 24 | const db = new gcp.sql.DatabaseInstance("postgresdb", { 25 | project: config.project, 26 | region: "us-west1", 27 | databaseVersion: "POSTGRES_9_6", 28 | settings: { tier: "db-f1-micro" }, 29 | }); 30 | 31 | // Configure a new SQL user. 32 | const user = new gcp.sql.User("default", { 33 | project: config.project, 34 | instance: db.name, 35 | password: postgresDbPassword, 36 | }); 37 | 38 | // Create a new k8s provider. 39 | const provider = new k8s.Provider("provider", { 40 | kubeconfig: config.kubeconfig, 41 | }); 42 | 43 | // Create a Secret from the DB connection information. 44 | const dbConn = new k8s.core.v1.Secret( 45 | "postgres-db-conn", 46 | { 47 | data: { 48 | host: db.privateIpAddress.apply(addr => Buffer.from(addr).toString("base64")), 49 | port: Buffer.from("5432").toString("base64"), 50 | username: user.name.apply(user => Buffer.from(user).toString("base64")), 51 | password: postgresDbPassword.apply(pass => Buffer.from(pass).toString("base64")), 52 | }, 53 | }, 54 | { provider: provider }, 55 | ); 56 | 57 | // Create a Redis instance. 58 | const cache = new gcp.redis.Instance("redis", { 59 | tier: "STANDARD_HA", 60 | memorySizeGb: 1, 61 | redisVersion: "REDIS_3_2", 62 | }); 63 | 64 | // Create a ConfigMap from the cache connection information. 65 | const cacheConn = new k8s.core.v1.ConfigMap( 66 | "postgres-db-conn", 67 | { 68 | data: { 69 | host: cache.host.apply(addr => Buffer.from(addr).toString("base64")), 70 | }, 71 | }, 72 | { provider: provider }, 73 | ); 74 | -------------------------------------------------------------------------------- /gcp/05-app-services/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-gke-apps-svcs", 3 | "devDependencies": { 4 | "@types/node": "latest", 5 | "typescript": "^3.0.0" 6 | }, 7 | "dependencies": { 8 | "@pulumi/gcp": "latest", 9 | "@pulumi/kubernetes": "latest", 10 | "@pulumi/pulumi": "latest", 11 | "@pulumi/random": "latest" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /gcp/05-app-services/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /gcp/06-apps/build-deploy-container/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-deploy-container 2 | description: Build and push image to private registry and create a Deployment from it. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /gcp/06-apps/build-deploy-container/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/gcp/06-apps/build-deploy-container/README.md) 2 | 3 | # Build container image and push to private registry on GCP 4 | 5 | This example builds a container image of a simple Node app and pushes the image 6 | to a private registry on GCP. The image is used to create a Kubernetes 7 | Deployment. 8 | 9 | ## Deploying the App 10 | 11 | To deploy your infrastructure, follow the below steps. 12 | 13 | ### Prerequisites 14 | 15 | 1. [Install Pulumi](https://www.pulumi.com/docs/get-started/install/) 16 | 1. [Install Node.js 8.11.3](https://nodejs.org/en/download/) 17 | 1. [Install Docker](https://docs.docker.com/v17.09/engine/installation/) 18 | 1. [Configure GCP Credentials](https://www.pulumi.com/docs/intro/cloud-providers/gcp/setup/) 19 | 1. [Configure access to a Kubernetes cluster](https://kubernetes.io/docs/setup/) 20 | 21 | ### Steps 22 | 23 | After cloning this repo, from this working directory, run these commands: 24 | 25 | 1. Install the required Node.js packages: 26 | 27 | ```bash 28 | $ npm install 29 | ``` 30 | 31 | 2. Create a new stack, which is an isolated deployment target for this example: 32 | 33 | ```bash 34 | $ pulumi stack init 35 | ``` 36 | 37 | 3. Set the required configuration variables for this program: 38 | 39 | ```bash 40 | $ pulumi config set gcp:project [your-gcp-project-here] 41 | $ pulumi config set gcp:zone us-west1-a # Any valid GCP zone here. 42 | ``` 43 | 44 | Note that you can choose different zones here. 45 | 46 | 4. Run the following command to authorize Docker to push to the GCR registry: 47 | 48 | ```bash 49 | $ gcloud auth configure-docker 50 | ``` 51 | 52 | 5. Bring up the stack, which will create the cloud resources, build and push the image to the private registry, 53 | and then create a Deployment using that image. 54 | 55 | ```bash 56 | $ pulumi up 57 | ``` 58 | 59 | 6. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 60 | 61 | ```bash 62 | $ pulumi destroy --yes 63 | $ pulumi stack rm --yes 64 | ``` 65 | -------------------------------------------------------------------------------- /gcp/06-apps/build-deploy-container/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | project: infraStackRef.requireOutput("project"), 13 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 14 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 15 | 16 | // Cluster 17 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 18 | clusterName: clusterStackRef.getOutput("clusterName"), 19 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 20 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 21 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 22 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 23 | }; 24 | -------------------------------------------------------------------------------- /gcp/06-apps/build-deploy-container/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as docker from "@pulumi/docker"; 16 | import * as gcp from "@pulumi/gcp"; 17 | import * as k8s from "@pulumi/kubernetes"; 18 | import * as kx from "@pulumi/kubernetesx"; 19 | import * as pulumi from "@pulumi/pulumi"; 20 | import { config } from "./config"; 21 | 22 | // Get the GCP project registry repository. 23 | const registry = gcp.container.getRegistryRepository(); 24 | 25 | // Build a Docker image from a local Dockerfile context in the 26 | // './node-app' directory, and push it to the registry. 27 | const customImage = "node-app"; 28 | const appImage = new docker.Image(customImage, { 29 | imageName: pulumi.interpolate`${registry.repositoryUrl}/${customImage}:v1.0.0`, 30 | build: { 31 | context: `./${customImage}`, 32 | }, 33 | }); 34 | 35 | // Create a k8s provider. 36 | const provider = new k8s.Provider("provider", { 37 | kubeconfig: config.kubeconfig, 38 | namespace: config.appsNamespaceName, 39 | }); 40 | 41 | // Create a Deployment of the built container. 42 | const appLabels = { app: customImage }; 43 | const appDeployment = new k8s.apps.v1.Deployment("app", { 44 | spec: { 45 | selector: { matchLabels: appLabels }, 46 | replicas: 1, 47 | template: { 48 | metadata: { labels: appLabels }, 49 | spec: { 50 | containers: [{ 51 | name: customImage, 52 | image: appImage.imageName, 53 | ports: [{name: "http", containerPort: 80}], 54 | }], 55 | } 56 | }, 57 | } 58 | }, { provider: provider }); 59 | 60 | // 61 | // Example using kx. 62 | // 63 | 64 | // Define the Pod for the Deployment. 65 | const pb = new kx.PodBuilder({ 66 | containers: [{ 67 | image: appImage.imageName, 68 | ports: { "http": 80 }, 69 | }], 70 | }); 71 | 72 | // Create a Deployment of the Pod defined by the PodBuilder. 73 | const appDeploymentKx = new kx.Deployment("app-kx", { 74 | spec: pb.asDeploymentSpec(), 75 | }, { provider: provider }); 76 | -------------------------------------------------------------------------------- /gcp/06-apps/build-deploy-container/node-app/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /gcp/06-apps/build-deploy-container/node-app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8.9.3-alpine 2 | RUN mkdir -p /usr/src/app 3 | COPY ./app/* /usr/src/app/ 4 | WORKDIR /usr/src/app 5 | RUN npm install 6 | CMD node /usr/src/app/index.js 7 | -------------------------------------------------------------------------------- /gcp/06-apps/build-deploy-container/node-app/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello, world!

4 | 5 | 6 | -------------------------------------------------------------------------------- /gcp/06-apps/build-deploy-container/node-app/app/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const morgan = require('morgan'); 3 | 4 | const app = express(); 5 | app.use(morgan('combined')); 6 | 7 | app.get('/', (req, res) => { 8 | res.sendFile(__dirname + '/index.html') 9 | }); 10 | 11 | var listener = app.listen(process.env.PORT || 80, function() { 12 | console.log('listening on port ' + listener.address().port); 13 | }); -------------------------------------------------------------------------------- /gcp/06-apps/build-deploy-container/node-app/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-helloworld", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": { 7 | "express": "^4.14.0", 8 | "morgan": "^1.8.2" 9 | }, 10 | "devDependencies": {}, 11 | "author": "" 12 | } 13 | -------------------------------------------------------------------------------- /gcp/06-apps/build-deploy-container/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-gcp-apps-deploy-container", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/docker": "latest", 9 | "@pulumi/gcp": "latest", 10 | "@pulumi/kubernetes": "latest", 11 | "@pulumi/kubernetesx": "^0.1.0", 12 | "@pulumi/pulumi": "latest" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gcp/06-apps/build-deploy-container/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /general-app-services/nginx-ingress-controller/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-app-svcs-nginx 2 | description: Deploys the NGINX Ingress Controller in the App Services Namespace. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /general-app-services/nginx-ingress-controller/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/general-app-services/nginx-ingress-controller/README.md) 2 | 3 | # NGINX Ingress Controller 4 | 5 | A Deployment of the [NGINX Ingress Controller][k8s-nginx]. 6 | 7 | [k8s-nginx]: https://github.com/kubernetes/ingress-nginx 8 | 9 | ## Deploying the App 10 | 11 | To deploy your infrastructure, follow the below steps. 12 | 13 | ### Prerequisites 14 | 15 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 16 | 17 | ### Steps 18 | 19 | After cloning this repo, from this working directory, run these commands: 20 | 21 | 1. Install the required Node.js packages: 22 | 23 | ```bash 24 | $ npm install 25 | ``` 26 | 27 | 1. Create a new stack, which is an isolated deployment target for this example: 28 | 29 | ```bash 30 | $ pulumi stack init 31 | ``` 32 | 33 | 1. Configure the stack. 34 | 35 | ```bash 36 | $ pulumi config set k8s-aws-apps-svcs-nginx:infraStackRef myUser/k8s--infra/dev-1573589378 37 | $ pulumi config set k8s-aws-apps-svcs-nginx:clusterStackRef myUser/k8s--cluster/dev-1571780002 38 | ``` 39 | 40 | 1. Update the stack. 41 | 42 | ```bash 43 | $ pulumi up 44 | ``` 45 | 46 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 47 | 48 | ```bash 49 | $ pulumi destroy --yes 50 | $ pulumi stack rm --yes 51 | ``` 52 | -------------------------------------------------------------------------------- /general-app-services/nginx-ingress-controller/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const infraStackRef = new pulumi.StackReference(pulumiConfig.require("infraStackRef")); 8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 9 | 10 | export const config = { 11 | // Infra 12 | privateSubnetIds: infraStackRef.getOutput("privateSubnetIds"), 13 | publicSubnetIds: infraStackRef.getOutput("publicSubnetIds"), 14 | 15 | // Cluster 16 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 17 | clusterName: clusterStackRef.getOutput("clusterName"), 18 | securityGroupIds: clusterStackRef.getOutput("securityGroupIds"), 19 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 20 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 21 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 22 | }; 23 | -------------------------------------------------------------------------------- /general-app-services/nginx-ingress-controller/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-app-svcs-nginx", 3 | "devDependencies": { 4 | "typescript": "^3.0.0", 5 | "@types/node": "latest" 6 | }, 7 | "dependencies": { 8 | "@pulumi/aws": "latest", 9 | "@pulumi/kubernetes": "latest", 10 | "@pulumi/random": "latest", 11 | "@pulumi/pulumi": "latest" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /general-app-services/nginx-ingress-controller/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "stripInternal": true, 13 | "experimentalDecorators": true, 14 | "pretty": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "strictNullChecks": true 20 | }, 21 | "files": [ 22 | "index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /general-cluster-services/datadog-daemonset/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: k8s-apps-daemonset-datadog 2 | description: A DaemonSet that deploys DataDog on all nodes. 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /general-cluster-services/datadog-daemonset/README.md: -------------------------------------------------------------------------------- 1 | [![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/kubernetes-guides/blob/master/general-cluster-services/datadog-daemonset/README.md) 2 | 3 | # DataDog DaemonSet 4 | 5 | A DaemonSet that deploys DataDog on all nodes. 6 | 7 | ## Deploying the App 8 | 9 | To deploy your infrastructure, follow the below steps. 10 | 11 | ### Prerequisites 12 | 13 | 1. [Get Started with Kubernetes on Pulumi](https://www.pulumi.com/docs/get-started/kubernetes/) 14 | 15 | ### Steps 16 | 17 | After cloning this repo, from this working directory, run these commands: 18 | 19 | 1. Install the required Node.js packages: 20 | 21 | ```bash 22 | $ npm install 23 | ``` 24 | 25 | 2. Create a new stack, which is an isolated deployment target for this example: 26 | 27 | ```bash 28 | $ pulumi stack init 29 | ``` 30 | 31 | 1. Configure the stack. 32 | 33 | ```bash 34 | $ pulumi config set k8s-apps-daemonset-datadog:clusterStackRef myUser/k8s--cluster/dev-1571780002 35 | $ pulumi config set k8s-apps-daemonset-datadog:datadogApiKey 00000000111111111222222222333333 36 | ``` 37 | 38 | 1. Update the stack. 39 | 40 | ```bash 41 | $ pulumi up 42 | ``` 43 | 44 | 1. Once you've finished experimenting, tear down your stack's resources by destroying and removing it: 45 | 46 | ```bash 47 | $ pulumi destroy --yes 48 | $ pulumi stack rm --yes 49 | ``` 50 | -------------------------------------------------------------------------------- /general-cluster-services/datadog-daemonset/config.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | 3 | let pulumiConfig = new pulumi.Config(); 4 | 5 | // Existing Pulumi stack reference in the format: 6 | // // e.g. "myUser/myProject/dev" 7 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef")); 8 | 9 | export const config = { 10 | // Cluster 11 | kubeconfig: clusterStackRef.getOutput("kubeconfig"), 12 | clusterSvcsNamespaceName: clusterStackRef.getOutput("clusterSvcsNamespaceName"), 13 | appSvcsNamespaceName: clusterStackRef.getOutput("appSvcsNamespaceName"), 14 | appsNamespaceName: clusterStackRef.getOutput("appsNamespaceName"), 15 | 16 | // Misc 17 | datadogApiKey: pulumiConfig.require("datadogApiKey"), 18 | }; 19 | -------------------------------------------------------------------------------- /general-cluster-services/datadog-daemonset/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s-apps-daemonset-datadog", 3 | "devDependencies": { 4 | "@types/node": "^8.0.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/pulumi": "latest", 8 | "@pulumi/kubernetes": "latest" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /general-cluster-services/datadog-daemonset/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "experimentalDecorators": true, 9 | "pretty": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "strictNullChecks": true 15 | }, 16 | "files": [ 17 | "index.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /orig/README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes the Prod Way 2 | 3 | > **NOTE:** This tutorial is still a work in progress! We will remove this message when we are more 4 | > confident in its stability! 5 | 6 | **Kubernetes the Prod Way** is a tutorial, reference architecture, and collection of prod-first code 7 | examples that demonstrate industry best-practices for **using Kubernetes** in contexts where an 8 | **organization of people** must ship **production applications.** 9 | 10 | For example: in an organization, we typically expect identity (_e.g._, [AWS IAM][aws-iam], [GCP 11 | IAM][gcp-iam], [Azure AD][azure-ad]), compute (_e.g._, [EKS][eks], [GKE][gke], [AKS][aks]), storage 12 | (_e.g._, [Aurora][aurora], [Cloud SQL][cloud-sql], [CosmosDB][cosmos-db]), and networking to be 13 | provisioned and "owned" by separate people, and perhaps separate teams. But, when an app team 14 | deploys a service, we expect all of these components to work seamlessly together. 15 | 16 | **Kubernetes the Prod Way** will show you, using batteries-included examples, how to **provision** 17 | and **use** these technologies together in a way that maintains high release velocity, without 18 | sacrificing security, governance, or stability. 19 | 20 | Examples are provided for each of: **AWS, GCP, and Azure.** In the future, we will also provide 21 | examples for common on-prem technology, such as VMWare vSphere. 22 | 23 | ## Target Audience 24 | 25 | This tutorial is aimed at people who are planning to support production applications running on 26 | Kubernetes, particularly those looking for concrete guidance on how to set up infrastructure so that 27 | teams can operate quickly, effectively, and safely. 28 | 29 | ## Contents 30 | 31 | The labs in Kubernetes the Prod Way are built using [Pulumi][pulumi], a tool that allows you to 32 | provision and configure cloud infrastructure, including [Amazon Web Services][aws] (AWS), [Microsoft 33 | Azure][azure], [Google Cloud Platform][gcp] (GCP), and Kubernetes. 34 | 35 | With that said, nearly all of the lessons learned could be applied using other tools as well, and 36 | there is very little that is specific to Pulumi. 37 | 38 | Kubernetes the Prod Way is organized as a series of labs. These labs cover everything from 39 | bootstrapping IAM roles, to provisioning compute, storage, and networking, to deploying applications 40 | on top of Kubernetes. 41 | 42 | * [Prerequisites](./docs/00-prerequisites.md) 43 | * [A Production Architecture for _Teams_](./docs/01-architecture.md) 44 | * [Lab 1: Bootstrapping Identity](./docs/02-identity.md) 45 | * [Lab 2: Provisioning Environments](./docs/03-infrastructure.md) 46 | * [Lab 3: Provisioning Applications](./docs/04-app.md) 47 | * Lab 4: Setting Up CI/CD (coming soon!) 48 | * Lab 5: Configuring Standard Kubernetes Infrastructure (coming soon!) 49 | * Lab 6: Testing your infrastructure (coming soon!) 50 | 51 | 52 | [aws-iam]: https://aws.amazon.com/iam/ 53 | [gcp-iam]: https://cloud.google.com/iam/ 54 | [azure-ad]: https://azure.microsoft.com/en-us/services/active-directory/ 55 | 56 | [eks]: https://aws.amazon.com/eks/ 57 | [gke]: https://cloud.google.com/kubernetes-engine/ 58 | [aks]: https://docs.microsoft.com/en-us/azure/aks/ 59 | 60 | [aurora]: https://aws.amazon.com/rds/aurora/ 61 | [cloud-sql]: https://cloud.google.com/sql/ 62 | [cosmos-db]: https://azure.microsoft.com/en-us/services/cosmos-db/ 63 | 64 | [pulumi]: https://www.pulumi.com/ 65 | 66 | [aws]: https://aws.amazon.com/ 67 | [azure]: https://azure.microsoft.com/en-us/ 68 | [gcp]: https://cloud.google.com/ 69 | -------------------------------------------------------------------------------- /orig/aws/identity/examples/eks-admin/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: identity 2 | description: Identity definitions for production Kubernetes infrastructure 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /orig/aws/identity/examples/eks-admin/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as aws from "@pulumi/aws"; 16 | 17 | import * as iam from "../../"; 18 | import * as util from "./util"; 19 | 20 | const baseline = new iam.BaselineIam("baselineIam", { 21 | groups: { 22 | // Create default EKS admins group. 23 | defineEksAdminsGroup: true, 24 | // Opt out of admin and database admin Groups. 25 | defineAdminsGroup: false, 26 | defineDatabaseAdminsGroup: false, 27 | }, 28 | }); 29 | 30 | // 31 | // User/role for networking CI. Networking admin. 32 | // 33 | 34 | const networkAdminCiUser = new util.BotUser("networkAdminCiUser", { 35 | groupMembership: { groups: [baseline.groups.networkAdmins!.name] }, 36 | }); 37 | const networkAdminCiUserKey = networkAdminCiUser.createAccessKey("networkAdminCiUser"); 38 | 39 | // Export login credentials for CI/CD. 40 | export const networkAdminCiUserAccessKey = { 41 | id: networkAdminCiUserKey.id, 42 | secret: networkAdminCiUserKey.secret, 43 | }; 44 | 45 | // 46 | // EKS management user. Deploys EKS, passes AWS IAM Role ARNs to EKS, so that workloads can be 47 | // correlated to AWS IAM. 48 | // 49 | 50 | const eksAdminCiUser = new util.BotUser("eksAdminCiUser", { 51 | groupMembership: { 52 | groups: [ 53 | // TODO: Remove the "administrator" group when we pull VPC and security policies out and 54 | // manage them separately from the EKS package. 55 | baseline.groups.eksAdmins!.name, 56 | baseline.groups.networkAdmins!.name, // TODO: Revoke network admin. 57 | baseline.groups.useExistingIamRoles!.name, // To use pass role ARNs to k8s RoleBindings. 58 | ], 59 | }, 60 | }); 61 | const eksAdminCiUserKey = eksAdminCiUser.createAccessKey("eksAdminCiUser"); 62 | 63 | export const eksUserCiUserAccessKey = { 64 | id: eksAdminCiUserKey.id, 65 | secret: eksAdminCiUserKey.secret, 66 | }; 67 | 68 | // 69 | // Kubernetes application role. Has access to ECR. 70 | // 71 | 72 | const kubeAppRole = util.newRoleWithPolicies( 73 | "kubeAppRole", 74 | { 75 | description: "Infrastructure management role for CI users", 76 | assumeRolePolicy: eksAdminCiUser.user.arn.apply(util.assumeRolePolicy), 77 | }, 78 | { 79 | ecrPowerUser: aws.iam.AmazonEC2ContainerRegistryPowerUser, 80 | passRole: baseline.policies.useExistingIamRoles!.arn, 81 | }, 82 | ); 83 | export const kubeAppRoleArn = kubeAppRole.arn; 84 | 85 | // 86 | // Export group ARNs. 87 | // 88 | 89 | export const policyArns = baseline.policies.arns(); 90 | export const groupArns = baseline.groups.arns(); 91 | -------------------------------------------------------------------------------- /orig/aws/identity/examples/eks-admin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@types/node": "latest" 4 | }, 5 | "dependencies": { 6 | "@pulumi/aws": "latest", 7 | "@pulumi/pulumi": "latest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /orig/aws/identity/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // 16 | // Exports from `lib/`. 17 | // 18 | 19 | export { EmployeeUser, ContractorUser, BotUser } from "./lib/common"; 20 | export { baselineIamPolicyDocuments, BaselineIamPoliciesOptions } from "./lib/policies"; 21 | export { BaselineIamGroupsOptions } from "./lib/groups"; 22 | export { BaselineIam, BaselineIamOptions } from "./lib/baseline"; 23 | -------------------------------------------------------------------------------- /orig/aws/identity/lib/baseline.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as pulumi from "@pulumi/pulumi"; 16 | 17 | import * as common from "./common"; 18 | import * as groups from "./groups"; 19 | import * as policies from "./policies"; 20 | 21 | export type BaselineIamOptions = { 22 | policies?: policies.BaselineIamPoliciesOptions; 23 | groups?: groups.BaselineIamGroupsOptions; 24 | }; 25 | 26 | export class BaselineIam extends pulumi.ComponentResource { 27 | public readonly policies: policies.BaselineIamPolicies; 28 | public readonly groups: groups.BaselineIamGroups; 29 | 30 | constructor( 31 | name: string, 32 | args: BaselineIamOptions = {}, 33 | opts?: pulumi.ComponentResourceOptions, 34 | ) { 35 | super(`${common.groupName}:index:BaselineIam`, name, args, opts); 36 | 37 | const defineIamPassPolicy = args.policies && args.policies.defineUseExistingIamRolesPolicy; 38 | let defineIamPassGroup = args.groups && args.groups.defineUseExistingIamRolesGroup; 39 | defineIamPassGroup = defineIamPassGroup === undefined ? true : defineIamPassGroup; 40 | 41 | if (defineIamPassGroup === true && defineIamPassPolicy === false) { 42 | throw Error( 43 | "'defineUseExistingIamRolesGroup' can't be true when 'defineUseExistingIamRolesPolicy' is false", 44 | ); 45 | } 46 | 47 | if (defineIamPassGroup === true) { 48 | args.policies = args.policies === undefined ? {} : args.policies; 49 | args.policies.defineUseExistingIamRolesPolicy = true; 50 | } 51 | 52 | this.policies = new policies.BaselineIamPolicies(name, args.policies, { parent: this }); 53 | 54 | const groupsArgs = { 55 | ...args.groups, 56 | useExistingIamRolesPolicy: this.policies.useExistingIamRoles, 57 | }; 58 | this.groups = new groups.BaselineIamGroups(name, groupsArgs, { parent: this }); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /orig/aws/identity/lib/common.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as aws from "@pulumi/aws"; 16 | import * as pulumi from "@pulumi/pulumi"; 17 | 18 | // 19 | // Global statics. 20 | // 21 | 22 | export const groupName = "awsProd"; 23 | 24 | // 25 | // Policy helpers. 26 | // 27 | 28 | export type Policies = { [name: string]: pulumi.Input }; 29 | 30 | // 31 | // User types. 32 | // 33 | 34 | // EmployeeUser represents an AWS IAM User that is a full-time employee. 35 | export class EmployeeUser extends aws.iam.User { 36 | /** 37 | * Create a EmployeeUser resource with the given unique name, arguments, and options. 38 | * 39 | * Because it is useful to quickly distinguish between various types of users, all EmployeeUsers 40 | * are allocated names of the form `employee.${name}`. 41 | * 42 | * @param name The _unique_ name of the resource. 43 | * @param args The arguments to use to populate this resource's properties. 44 | * @param opts A bag of options that control this resource's behavior. 45 | */ 46 | constructor(name: string, args?: aws.iam.UserArgs, opts?: pulumi.CustomResourceOptions) { 47 | super(`employee.${name}`, args, opts); 48 | } 49 | } 50 | 51 | // ContractorUser represents an AWS IAM User that is a contracting employee. 52 | export class ContractorUser extends aws.iam.User { 53 | /** 54 | * Create a ContractorUser resource with the given unique name, arguments, and options. 55 | * 56 | * Because it is useful to quickly distinguish between various types of users, all 57 | * ContractorUsers are allocated names of the form `contractor.${name}`. 58 | * 59 | * @param name The _unique_ name of the resource. 60 | * @param args The arguments to use to populate this resource's properties. 61 | * @param opts A bag of options that control this resource's behavior. 62 | */ 63 | constructor(name: string, args?: aws.iam.UserArgs, opts?: pulumi.CustomResourceOptions) { 64 | super(`contractor.${name}`, args, opts); 65 | } 66 | } 67 | 68 | // BotUser represents an AWS IAM User that is a bot, such as a CI system. 69 | export class BotUser extends aws.iam.User { 70 | /** 71 | * Create a BotUser resource with the given unique name, arguments, and options. 72 | * 73 | * Because it is useful to quickly distinguish between various types of users, all BotUsers are 74 | * allocated names of the form `bot.${name}`. 75 | * 76 | * @param name The _unique_ name of the resource. 77 | * @param args The arguments to use to populate this resource's properties. 78 | * @param opts A bag of options that control this resource's behavior. 79 | */ 80 | constructor(name: string, args?: aws.iam.UserArgs, opts?: pulumi.CustomResourceOptions) { 81 | super(`bot.${name}`, args, opts); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /orig/aws/identity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@types/node": "latest", 4 | "tslint": "^5.11.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/aws": "latest", 8 | "@pulumi/pulumi": "latest" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /orig/aws/infrastructure/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: infrastructure 2 | description: Infrastructure (compute, storage, networking) for production Kubernetes infrastructure 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /orig/aws/infrastructure/config.ts: -------------------------------------------------------------------------------- 1 | import * as aws from "@pulumi/aws"; 2 | import * as eks from "@pulumi/eks"; 3 | import * as pulumi from "@pulumi/pulumi"; 4 | 5 | const config = new pulumi.Config(); 6 | 7 | function getList(name: string): string[] | undefined { 8 | const str = config.get(name); 9 | return str ? str.split(",") : undefined; 10 | } 11 | 12 | /** 13 | * The VPC in which to create infrastructure resources. If left unset, a VPC will be created. 14 | */ 15 | export const vpcId = config.get("vpcId"); 16 | 17 | /** 18 | * The public subnets in the VPC to attach to the EKS cluster and other resources. 19 | */ 20 | export const publicSubnetIds = getList("publicSubnetIds"); 21 | 22 | /** 23 | * The private subnets in the VPC to attach to the EKS cluster and other resources. 24 | */ 25 | export const privateSubnetIds = getList("privateSubnetIds"); 26 | 27 | /** 28 | * When creating a VPC, whether or not to create private and public subnets. Defaults to false. 29 | */ 30 | export const usePrivateSubnets = config.getBoolean("usePrivateSubnets"); 31 | 32 | /** 33 | * When creating a VPC, the number of availability zones in which to create subnets. Defaults to 2. 34 | */ 35 | export const numberOfAvailabilityZones = config.getNumber("numberOfAvailabilityZones"); 36 | 37 | /** 38 | * The instance type for the cluster's worker nodes. Defaults to "t2.medium". 39 | */ 40 | export const instanceType = config.get("instanceType"); 41 | 42 | /** 43 | * The public key (if any) for the cluster's worker nodes. Setting this will enable SSH access to these nodes. 44 | */ 45 | export const publicKey = config.get("publicKey"); 46 | 47 | /** 48 | * The desired capacity of the autoscaling group that manages the cluster's worker nodes. Defaults to 2. 49 | */ 50 | export const desiredCapacity = config.getNumber("desiredCapacity"); 51 | 52 | /** 53 | * The minimum capacity of the autoscaling group that manages the cluster's worker nodes. Defaults to 1. 54 | */ 55 | export const minSize = config.getNumber("minSize"); 56 | 57 | /** 58 | * The maximum capacity of the autoscaling group that manages the cluster's worker nodes. Defaults to 2. 59 | */ 60 | export const maxSize = config.getNumber("maxSize"); 61 | 62 | /** 63 | * The storage class to create. Defaults to "gp2". 64 | */ 65 | export const storageClass = config.get("storageClasses"); 66 | 67 | /** 68 | * The name of the identity stack to use for this cluster. 69 | */ 70 | export const identityStack = config.require("identityStackName"); 71 | -------------------------------------------------------------------------------- /orig/aws/infrastructure/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as awsinfra from "@pulumi/aws-infra"; 16 | import * as eks from "@pulumi/eks"; 17 | import * as pulumi from "@pulumi/pulumi"; 18 | import * as config from "./config"; 19 | 20 | // Create a VPC for the EKS cluster and its nodes if necessary. 21 | let vpcId: pulumi.Input = config.vpcId!; 22 | let publicSubnetIds: pulumi.Input[] = config.publicSubnetIds!; 23 | let privateSubnetIds: pulumi.Input[] = config.privateSubnetIds!; 24 | if (config.vpcId === undefined) { 25 | const network = new awsinfra.Network("network", { 26 | usePrivateSubnets: config.usePrivateSubnets, 27 | numberOfAvailabilityZones: config.numberOfAvailabilityZones, 28 | }); 29 | vpcId = network.vpcId; 30 | publicSubnetIds = network.publicSubnetIds; 31 | privateSubnetIds = config.usePrivateSubnets ? network.subnetIds : undefined; 32 | } 33 | 34 | // Import the identity stack for its roles. 35 | const identityStack = new pulumi.StackReference("identityStack", { name: config.identityStack }); 36 | const kubeAppRole = identityStack.getOutput("kubeAppRoleArn"); 37 | kubeAppRole.apply(role => { 38 | if (role === undefined) { 39 | throw Error(`Stack output ${identityStack}.kubeAppRoleArn is undefined`); 40 | } 41 | }); 42 | 43 | // Create the EKS cluster itself. 44 | const eksCluster = new eks.Cluster("eksCluster", { 45 | vpcId: vpcId, 46 | subnetIds: [...publicSubnetIds, ...(privateSubnetIds || [])], 47 | roleMappings: [ 48 | // TODO: Find a slightly more restrictive permission for this. 49 | { 50 | roleArn: kubeAppRole, 51 | username: kubeAppRole, 52 | groups: ["system:masters"], 53 | }, 54 | ], 55 | instanceType: config.instanceType, 56 | nodePublicKey: config.publicKey, 57 | desiredCapacity: config.desiredCapacity, 58 | minSize: config.minSize, 59 | maxSize: config.maxSize, 60 | storageClasses: config.storageClass, 61 | }); 62 | 63 | export const kubeconfig = eksCluster.kubeconfig; 64 | -------------------------------------------------------------------------------- /orig/aws/infrastructure/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@types/node": "latest" 4 | }, 5 | "dependencies": { 6 | "@pulumi/aws": "latest", 7 | "@pulumi/aws-infra": "latest", 8 | "@pulumi/eks": "latest", 9 | "@pulumi/pulumi": "latest" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /orig/aws/infrastructure/scripts/deploy-with-ci-user.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o errexit -o pipefail 3 | 4 | if [ $# -eq 0 ]; then 5 | echo "Usage: $0 " 6 | echo " First argument should be the name of your AWS identity stack" 7 | exit 1 8 | fi 9 | 10 | # Use EKS management user account. 11 | export AWS_ACCESS_KEY_ID="$(pulumi stack output --stack "$1" eksCiUserAccessKeyId)" 12 | export AWS_SECRET_ACCESS_KEY="$(pulumi stack output --stack "$1" eksCiUserAccessKeySecret)" 13 | 14 | pulumi up --yes 15 | -------------------------------------------------------------------------------- /orig/azure/identity/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /node_modules/ 3 | Pulumi.*.yaml 4 | -------------------------------------------------------------------------------- /orig/azure/identity/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: identity 2 | description: Identity definitions for production Kubernetes infrastructure 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /orig/azure/identity/config.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as pulumi from "@pulumi/pulumi"; 16 | import * as random from "@pulumi/random"; 17 | 18 | const config = new pulumi.Config(); 19 | 20 | // 21 | // AKS-specific config. 22 | // 23 | 24 | export const name = config.get("name") || "aks"; 25 | export const location = config.get("location") || "West US 2"; 26 | export const password = 27 | config.get("password") || 28 | new random.RandomString("password", { 29 | length: 16, 30 | special: true, 31 | }).result; 32 | -------------------------------------------------------------------------------- /orig/azure/identity/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as azure from "@pulumi/azure"; 16 | import * as config from "./config"; 17 | 18 | let resourceGroup = new azure.core.ResourceGroup(config.name, { location: config.location }); 19 | 20 | // Create the AD service principal for the K8s cluster. 21 | let adApp = new azure.ad.Application(`${config.name}-app`); 22 | let adSp = new azure.ad.ServicePrincipal(`${config.name}-sp`, { 23 | applicationId: adApp.applicationId, 24 | }); 25 | let adSpPassword = new azure.ad.ServicePrincipalPassword(`${config.name}-password`, { 26 | servicePrincipalId: adSp.id, 27 | value: config.password, 28 | endDate: "2099-01-01T00:00:00Z", 29 | }); 30 | 31 | // 32 | // Export required properties for downstream stacks. 33 | // 34 | 35 | export const resourceGroupName = resourceGroup.name; 36 | export const applicationID = adApp.applicationId; 37 | export const servicePrincipalPassword = adSpPassword.value; 38 | export const location = config.location; 39 | -------------------------------------------------------------------------------- /orig/azure/identity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@types/node": "latest" 4 | }, 5 | "dependencies": { 6 | "@pulumi/azure": "^0.16.5", 7 | "@pulumi/pulumi": "^0.16.7", 8 | "@pulumi/random": "^0.2.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /orig/azure/infrastructure/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /node_modules/ 3 | Pulumi.*.yaml 4 | -------------------------------------------------------------------------------- /orig/azure/infrastructure/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: infrastructure 2 | description: Infrastructure (compute, storage, networking) for production Kubernetes infrastructure 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /orig/azure/infrastructure/config.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as pulumi from "@pulumi/pulumi"; 16 | 17 | const config = new pulumi.Config(); 18 | 19 | export const identityStackName = config.require("identityStackName"); 20 | const identityStack = new pulumi.StackReference(identityStackName); 21 | // 22 | // Azure-specific config. 23 | // 24 | 25 | export const resourceGroupName = identityStack.getOutput("resourceGroupName"); 26 | export const location = identityStack.getOutput("location"); 27 | export const applicationID = identityStack.getOutput("applicationID"); 28 | export const servicePrincipalPassword = identityStack.getOutput("servicePrincipalPassword"); 29 | 30 | // 31 | // AKS-specific config. 32 | // 33 | 34 | export const nodeCount = config.getNumber("nodeCount") || 2; 35 | export const nodeSize = config.get("nodeSize") || "Standard_D2_v2"; 36 | export const sshPublicKey = config.require("sshPublicKey"); 37 | -------------------------------------------------------------------------------- /orig/azure/infrastructure/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as azure from "@pulumi/azure"; 16 | import * as pulumi from "@pulumi/pulumi"; 17 | import * as config from "./config"; 18 | 19 | // Now allocate an AKS cluster. 20 | const k8sCluster = new azure.containerservice.KubernetesCluster("aksCluster", { 21 | resourceGroupName: config.resourceGroupName, 22 | location: config.location, 23 | agentPoolProfile: { 24 | name: "aksagentpool", 25 | count: config.nodeCount, 26 | vmSize: config.nodeSize, 27 | }, 28 | dnsPrefix: `${pulumi.getStack()}-kube`, 29 | linuxProfile: { 30 | adminUsername: "aksuser", 31 | sshKeys: [ 32 | { 33 | keyData: config.sshPublicKey, 34 | }, 35 | ], 36 | }, 37 | servicePrincipal: { 38 | clientId: config.applicationID, 39 | clientSecret: config.servicePrincipalPassword, 40 | }, 41 | }); 42 | 43 | // 44 | // Export required properties for downstream stacks. 45 | // 46 | 47 | export const kubeconfig = k8sCluster.kubeConfigRaw; 48 | -------------------------------------------------------------------------------- /orig/azure/infrastructure/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@types/node": "latest" 4 | }, 5 | "dependencies": { 6 | "@pulumi/azure": "^0.16.5", 7 | "@pulumi/kubernetes": "^0.18.0", 8 | "@pulumi/pulumi": "^0.16.7" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /orig/docs/00-prerequisites.md: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | 3 | This tutorial leverages [Pulumi][pulumi] and [Node.js][nodejs] to provision and configure 4 | infrastructure on AWS, Azure, or GCP. Pulumi is a platform for building and deploying cloud 5 | infrastructure and applications in your favorite language on any cloud. This particular tutorial is 6 | written in [TypeScript][ts], a strict superset of JavaScript that allows users to add optional type 7 | hints to variables. (Pulumi also supports Python and nothing in principle prevents using that 8 | instead.) 9 | 10 | ## Pulumi CLI 11 | 12 | To begin, you should [install the Pulumi CLI][pulumi-cli]. By default, the Pulumi CLI uses the 13 | Pulumi service to coordinate concurrent updates, so you should also [create an account][pulumi]. 14 | 15 | It is possible to avoid a dependency on the service by using the [local backend][local-backend]. 16 | But, for the purposes of this tutorial, it is much more convenient to use the service, and the 17 | entire tutorial can be completed using only the free tier. 18 | 19 | ## Yarn CLI 20 | 21 | If this is your first time writing a Node.js application, you'll need to install either Yarn or npm, 22 | which are package managers for Node.js applications. You can install it by following [the official 23 | instructions][yarn]. 24 | 25 | ## Cloud Provider CLI 26 | 27 | This tutorial provides code samples for AWS, Azure and GCP. You will need to create an account for 28 | one of those providers, and then install the official CLI. For details, consult our installation 29 | guides: 30 | 31 | * [AWS][aws-setup] 32 | * [Azure][azure-setup] 33 | * [GCP][gcp-setup] 34 | 35 | ## `kubectl`, the Kubernetes CLI 36 | 37 | Pulumi will help to provision cloud resources, including those running on Kubernetes. To interact 38 | with the cluster, it will be useful to install `kubectl`, the official Kubernetes CLI. See official 39 | instructions [here][kubectl]. 40 | 41 | 42 | [pulumi]: https://www.pulumi.com/ 43 | [nodejs]: https://nodejs.org/en/ 44 | [pulumi-cli]: https://pulumi.io/quickstart/install.html 45 | [local-backend]: https://pulumi.io/reference/state.html 46 | [ts]: https://www.typescriptlang.org/ 47 | [yarn]: https://yarnpkg.com/en/docs/install 48 | 49 | [aws-setup]: https://pulumi.io/quickstart/aws/setup.html 50 | [azure-setup]: https://pulumi.io/quickstart/azure/setup.html 51 | [gcp-setup]: https://pulumi.io/quickstart/gcp/setup.html 52 | 53 | [kubectl]: https://kubernetes.io/docs/tasks/tools/install-kubectl/ 54 | -------------------------------------------------------------------------------- /orig/docs/images/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/kubernetes-guides/a29612928c8082516bac34eb4b57ed2a3cdde9df/orig/docs/images/app.png -------------------------------------------------------------------------------- /orig/docs/images/identity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/kubernetes-guides/a29612928c8082516bac34eb4b57ed2a3cdde9df/orig/docs/images/identity.png -------------------------------------------------------------------------------- /orig/docs/images/infrastructure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/kubernetes-guides/a29612928c8082516bac34eb4b57ed2a3cdde9df/orig/docs/images/infrastructure.png -------------------------------------------------------------------------------- /orig/docs/images/kube-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/kubernetes-guides/a29612928c8082516bac34eb4b57ed2a3cdde9df/orig/docs/images/kube-arch.png -------------------------------------------------------------------------------- /orig/gcp/identity/.gitignore: -------------------------------------------------------------------------------- 1 | /.pulumi/ 2 | /.vscode/ 3 | bin/ 4 | node_modules/ 5 | *.pyc 6 | .Python 7 | include/ 8 | lib/ 9 | yarn.lock 10 | yarn-error.log 11 | package-lock.json 12 | Pulumi.*.yaml 13 | .idea/ 14 | *.iml 15 | 16 | infra-ci-client-secret.json 17 | k8s-app-dev-ci-client-secret.json 18 | -------------------------------------------------------------------------------- /orig/gcp/identity/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: identity 2 | description: Identity definitions for production Kubernetes infrastructure 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /orig/gcp/identity/config.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { Config } from "@pulumi/pulumi"; 16 | 17 | // 18 | // GCP-specific config. 19 | // 20 | 21 | // project is the GCP project you are going to deploy to. 22 | export const project = new Config("gcp").require("project"); 23 | -------------------------------------------------------------------------------- /orig/gcp/identity/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as gcp from "@pulumi/gcp"; 16 | 17 | import * as config from "./config"; 18 | import * as util from "./util"; 19 | 20 | // 21 | // Assign infrastructure CI service account Cloud SQL and GKE cluster admin privileges -- i.e., 22 | // privileges to add/delete these things, but not privileges to change apps inside. 23 | // 24 | 25 | const infraCiId = "infraCi"; 26 | 27 | const infraCi = new gcp.serviceAccount.Account(infraCiId, { 28 | project: config.project, 29 | accountId: "infra-ci", 30 | displayName: "Infrastructure CI account", 31 | }); 32 | 33 | const infraCiClusterAdminRole = util.bindToRole(`${infraCiId}ClusterAdmin`, infraCi, { 34 | project: config.project, 35 | role: "roles/container.clusterAdmin", 36 | }); 37 | 38 | const infraCiCloudSqlAdminRole = util.bindToRole(`${infraCiId}CloudSqlAdmin`, infraCi, { 39 | project: config.project, 40 | role: "roles/cloudsql.admin", 41 | }); 42 | 43 | const infraCiKey = util.createCiKey(`${infraCiId}Key`, infraCi); 44 | 45 | // Export client secret so that CI/CD systems can authenticate as this service account. 46 | export const infraCiClientSecret = util.clientSecret(infraCiKey); 47 | 48 | // 49 | // Assign application CI service account container developer privileges -- i.e., privileges to 50 | // change anything in GKE, but not to delete/add GKE clusters. 51 | // 52 | 53 | const k8sAppDevCiId = "k8sAppDev"; 54 | 55 | const k8sAppDevCi = new gcp.serviceAccount.Account(k8sAppDevCiId, { 56 | project: config.project, 57 | accountId: "k8s-app-dev-ci", 58 | displayName: "Infrastructure CI account", 59 | }); 60 | 61 | const k8sAppDevRole = util.bindToRole(k8sAppDevCiId, k8sAppDevCi, { 62 | project: config.project, 63 | role: "roles/container.developer", 64 | }); 65 | 66 | const k8sAppDevCiKey = util.createCiKey(`${k8sAppDevCiId}Key`, k8sAppDevCi); 67 | 68 | // Export client secret so that CI/CD systems can authenticate as this service account. 69 | export const k8sAppDevCiClientSecret = util.clientSecret(k8sAppDevCiKey); 70 | 71 | // 72 | // Export project name for downstream stacks. 73 | // 74 | 75 | export const project = config.project; 76 | -------------------------------------------------------------------------------- /orig/gcp/identity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@types/node": "latest" 4 | }, 5 | "dependencies": { 6 | "@pulumi/gcp": "^0.16.2", 7 | "@pulumi/pulumi": "^0.16.6" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /orig/gcp/identity/util.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as pulumi from "@pulumi/pulumi"; 16 | import * as gcp from "@pulumi/gcp"; 17 | 18 | export function bindToRole( 19 | name: string, 20 | sa: gcp.serviceAccount.Account, 21 | args: { project: pulumi.Input; role: pulumi.Input }, 22 | ): gcp.projects.IAMBinding { 23 | return new gcp.projects.IAMBinding(name, { 24 | project: args.project, 25 | role: args.role, 26 | members: [sa.email.apply(email => `serviceAccount:${email}`)], 27 | }); 28 | } 29 | 30 | export function createCiKey(name: string, sa: gcp.serviceAccount.Account): gcp.serviceAccount.Key { 31 | return new gcp.serviceAccount.Key(name, { serviceAccountId: sa.name }); 32 | } 33 | 34 | export function clientSecret(key: gcp.serviceAccount.Key): pulumi.Output { 35 | return key.privateKey.apply(key => JSON.parse(Buffer.from(key, "base64").toString("ascii"))); 36 | } 37 | -------------------------------------------------------------------------------- /orig/gcp/infrastructure/.gitignore: -------------------------------------------------------------------------------- 1 | /.pulumi/ 2 | /.vscode/ 3 | bin/ 4 | node_modules/ 5 | *.pyc 6 | .Python 7 | include/ 8 | lib/ 9 | yarn.lock 10 | yarn-error.log 11 | package-lock.json 12 | Pulumi.*.yaml 13 | .idea/ 14 | *.iml 15 | 16 | infra-ci-client-secret.json 17 | k8s-app-dev-ci-client-secret.json 18 | -------------------------------------------------------------------------------- /orig/gcp/infrastructure/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: infrastructure 2 | description: Infrastructure (compute, storage, networking) for production Kubernetes infrastructure 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /orig/gcp/infrastructure/config.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as pulumi from "@pulumi/pulumi"; 16 | 17 | const config = new pulumi.Config(); 18 | 19 | export const identityStackName = config.require("identityStackName"); 20 | const identityStack = new pulumi.StackReference(identityStackName); 21 | 22 | // 23 | // GCP-specific config. 24 | // 25 | 26 | // project is the GCP project you are going to deploy to. 27 | export const project = identityStack.getOutput("project"); 28 | 29 | // zone is the zone in which to build the cluster. 30 | export const zone = new pulumi.Config("gcp").get("zone"); 31 | 32 | // 33 | // Kubernetes-specific config. 34 | // 35 | 36 | // envName is the name of the environment represented by this cluster. 37 | export const envName = config.require("envName"); 38 | 39 | // nodeCount is the number of cluster nodes to provision. Defaults to 5 if unspecified. 40 | export const nodeCount = config.getNumber("nodeCount"); 41 | 42 | // nodeMachineType is the machine type to use for cluster nodes. Defaults to n1-standard-1 if unspecified. 43 | // See https://cloud.google.com/compute/docs/machine-types for more details on available machine types. 44 | export const nodeMachineType = config.get("nodeMachineType"); 45 | -------------------------------------------------------------------------------- /orig/gcp/infrastructure/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pulumi/gke", 3 | "devDependencies": { 4 | "@types/node": "latest" 5 | }, 6 | "peerDependencies": { 7 | "@pulumi/gke": "latest" 8 | }, 9 | "dependencies": { 10 | "@pulumi/gcp": "^0.16.2", 11 | "@pulumi/kubernetes": "^0.18.0", 12 | "@pulumi/pulumi": "^0.16.7", 13 | "@pulumi/random": "^0.2.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /orig/gcp/infrastructure/scripts/login-to-ci-service-account.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o errexit -o pipefail 3 | 4 | if [ $# -eq 0 ]; then 5 | echo "Usage: $0 " 6 | echo " First argument should be the name of your GCP identity stack" 7 | exit 1 8 | fi 9 | 10 | pulumi stack output infraCiClientSecret --stack "$1" > infra-ci-client-secret.json 11 | gcloud auth activate-service-account --key-file infra-ci-client-secret.json 12 | rm infra-ci-client-secret.json 13 | -------------------------------------------------------------------------------- /orig/services/.gitignore: -------------------------------------------------------------------------------- 1 | kubeconfig.yaml 2 | -------------------------------------------------------------------------------- /orig/services/scripts/get-kubeconfig.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o errexit -o pipefail 3 | 4 | if [ $# -eq 0 ]; then 5 | echo "Usage: $0 " 6 | echo " First argument should be the name of your GCP infrastructure stack" 7 | exit 1 8 | fi 9 | 10 | pulumi stack output kubeconfig --stack "$1" > kubeconfig.yaml 11 | -------------------------------------------------------------------------------- /orig/services/scripts/login-to-ci-service-account.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o errexit -o pipefail 3 | 4 | if [ $# -eq 0 ]; then 5 | echo "Usage: $0 " 6 | echo " First argument should be the name of your GCP identity stack" 7 | exit 1 8 | fi 9 | 10 | pulumi stack output k8sAppDevCiClientSecret --stack "$1" > k8s-app-dev-ci-client-secret.json 11 | gcloud auth activate-service-account --key-file k8s-app-dev-ci-client-secret.json 12 | rm k8s-app-dev-ci-client-secret.json 13 | -------------------------------------------------------------------------------- /orig/services/wordpress/.gitignore: -------------------------------------------------------------------------------- 1 | /.pulumi/ 2 | /.vscode/ 3 | bin/ 4 | node_modules/ 5 | *.pyc 6 | .Python 7 | include/ 8 | lib/ 9 | yarn.lock 10 | yarn-error.log 11 | package-lock.json 12 | Pulumi.*.yaml 13 | .idea/ 14 | *.iml 15 | 16 | infra-ci-client-secret.json 17 | k8s-app-dev-ci-client-secret.json 18 | -------------------------------------------------------------------------------- /orig/services/wordpress/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: wordpress 2 | description: Wordpress example running on production-ready Kubernetes infrastructure 3 | runtime: nodejs 4 | -------------------------------------------------------------------------------- /orig/services/wordpress/config.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as pulumi from "@pulumi/pulumi"; 16 | import * as k8s from "@pulumi/kubernetes"; 17 | 18 | const config = new pulumi.Config(); 19 | 20 | const infrastructureStackName = config.require("infrastructureStackName"); 21 | const infrastructureStack = new pulumi.StackReference(infrastructureStackName); 22 | 23 | export const k8sProvider = new k8s.Provider(`${infrastructureStackName}`, { 24 | kubeconfig: infrastructureStack.getOutput("kubeconfig"), 25 | }); 26 | -------------------------------------------------------------------------------- /orig/services/wordpress/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019, Pulumi Corporation. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as pulumi from "@pulumi/pulumi"; 16 | import * as k8s from "@pulumi/kubernetes"; 17 | 18 | import * as config from "./config"; 19 | 20 | // Deploy the latest version of the stable/wordpress chart. 21 | const wordpress = new k8s.helm.v2.Chart( 22 | "wpdev", 23 | { 24 | repo: "stable", 25 | version: "2.1.3", 26 | chart: "wordpress", 27 | }, 28 | { providers: { kubernetes: config.k8sProvider } }, 29 | ); 30 | 31 | // Export the public IP for Wordpress. 32 | export const frontendIp = wordpress 33 | .getResourceProperty("v1/Service", "wpdev-wordpress", "status") 34 | .apply(status => status.loadBalancer.ingress[0].ip); 35 | -------------------------------------------------------------------------------- /orig/services/wordpress/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pulumi/gke", 3 | "devDependencies": { 4 | "@types/node": "latest" 5 | }, 6 | "dependencies": { 7 | "@pulumi/kubernetes": "^0.18.0", 8 | "@pulumi/pulumi": "^0.16.7" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /orig/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es6", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "declaration": true, 8 | "sourceMap": false, 9 | "stripInternal": true, 10 | "experimentalDecorators": true, 11 | "pretty": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "noImplicitAny": true, 14 | "noImplicitReturns": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "strictNullChecks": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /orig/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "align": [true, "parameters", "statements"], 4 | "ban": false, 5 | "class-name": true, 6 | "comment-format": [true, "check-space"], 7 | "curly": true, 8 | "eofline": true, 9 | "file-header": [true, "Copyright 2016-2019, Pulumi Corporation."], 10 | "forin": true, 11 | "indent": [true, "spaces"], 12 | "interface-name": false, 13 | "jsdoc-format": false, 14 | "label-position": true, 15 | "member-access": false, 16 | "member-ordering": [true, "variables-before-functions"], 17 | "no-any": false, 18 | "no-arg": true, 19 | "no-bitwise": false, 20 | "no-conditional-assignment": false, 21 | "no-consecutive-blank-lines": false, 22 | "no-console": [true, "debug", "info", "time", "timeEnd", "trace"], 23 | "no-construct": true, 24 | "no-debugger": true, 25 | "no-duplicate-variable": true, 26 | "no-empty": true, 27 | "no-eval": true, 28 | "no-inferrable-types": false, 29 | "no-internal-module": true, 30 | "no-parameter-properties": false, 31 | "no-require-imports": false, 32 | "no-string-literal": false, 33 | "no-switch-case-fall-through": true, 34 | "no-trailing-whitespace": true, 35 | "no-unused-expression": true, 36 | "no-use-before-declare": false, 37 | "no-var-keyword": true, 38 | "no-var-requires": false, 39 | "object-literal-sort-keys": false, 40 | "one-line": [true, "check-open-brace", "check-whitespace"], 41 | "ordered-imports": true, 42 | "prefer-const": true, 43 | "quotemark": [true, "double", "avoid-escape"], 44 | "radix": true, 45 | "semicolon": true, 46 | "switch-default": true, 47 | "trailing-comma": [ 48 | true, 49 | { 50 | "multiline": "always", 51 | "singleline": "never" 52 | } 53 | ], 54 | "triple-equals": [true, "allow-null-check"], 55 | "typedef": [ 56 | false, 57 | "call-signature", 58 | "parameter", 59 | "property-declaration", 60 | "variable-declaration", 61 | "member-variable-declaration" 62 | ], 63 | "typedef-whitespace": [ 64 | true, 65 | { 66 | "call-signature": "nospace", 67 | "index-signature": "nospace", 68 | "parameter": "nospace", 69 | "property-declaration": "nospace", 70 | "variable-declaration": "nospace" 71 | } 72 | ], 73 | "variable-name": [true, "check-format", "allow-leading-underscore", "ban-keywords"], 74 | "whitespace": [ 75 | true, 76 | "check-branch", 77 | "check-decl", 78 | "check-module", 79 | "check-separator", 80 | "check-type" 81 | ] 82 | } 83 | } 84 | --------------------------------------------------------------------------------