Modernize the Kubernetes guestbook example
Fixes
MODIFY
kubernetes-ts-guestbook/index.ts
kubernetes-ts-guestbook/index.ts
import * as pulumi from "@pulumi/pulumi";
import * as k8s from "@pulumi/kubernetes";
+import * as util from "./util";
-// REDIS MASTER
+// Minikube does not implement services of type `LoadBalancer`; require the user to specify if we're
+// running on minikube, and if so, create only services of type ClusterIP.
+let config = new pulumi.Config("guestbook");
+let isMinikube = config.require("isMinikube");
-let redisMasterLabels = { app: "redis", tier: "backend", role: "master"};
-let redisMasterService = new k8s.core.v1.Service("redis-master", {
- metadata: {
- name: "redis-master",
- labels: redisMasterLabels,
- },
- spec: {
- ports: [{ port: 6379, targetPort: 6379 }],
- selector: redisMasterLabels,
- },
-});
-let redisMasterDeployment = new k8s.apps.v1.Deployment("redis-master", {
- metadata: {
- name: "redis-master",
- },
- spec: {
- selector: {
- matchLabels: redisMasterLabels
- },
- replicas: 1,
- template: {
- metadata: {
- labels: redisMasterLabels,
- },
- spec: {
- containers: [{
+//
+// REDIS MASTER.
+//
+
+let redisMasterDeployment = util.deployContainer("redis-master", 1, {
name: "master",
image: "k8s.gcr.io/redis:e2e",
- resources: {
- requests: {
- cpu: "100m",
- memory: "100Mi",
- },
- },
- ports: [{
- containerPort: 6379,
- }],
- }],
- },
- },
- },
+ resources: { requests: { cpu: "100m", memory: "100Mi" } },
+ ports: [{ containerPort: 6379 }]
});
-
-// REDIS SLAVE
-let redisSlaveLabels = { app: "redis", tier: "backend", role: "slave" };
-let redisSlaveService = new k8s.core.v1.Service("redis-slave", {
+let redisMasterService = new k8s.core.v1.Service("redis-master", {
metadata: {
- name: "redis-slave",
- labels: redisSlaveLabels,
+ labels: redisMasterDeployment.metadata.apply(meta => meta.labels)
},
spec: {
ports: [{ port: 6379, targetPort: 6379 }],
- selector: redisSlaveLabels,
- },
+ selector: redisMasterDeployment.spec.apply(spec => spec.template.metadata.labels)
+ }
});
-let redisSlaveDeployment = new k8s.apps.v1.Deployment("redis-slave", {
- metadata: {
- name: "redis-slave",
- },
- spec: {
- selector: {
- matchLabels: redisSlaveLabels
- },
- replicas: 1,
- template: {
- metadata: {
- labels: redisSlaveLabels,
- },
- spec: {
- containers: [{
+
+//
+// REDIS SLAVE.
+//
+
+let redisSlaveDeployment = util.deployContainer("redis-slave", 1, {
name: "slave",
image: "gcr.io/google_samples/gb-redisslave:v1",
- resources: {
- requests: {
- cpu: "100m",
- memory: "100Mi",
- },
- },
- env: [{
- name: "GET_HOSTS_FROM",
- value: "dns",
+ resources: { requests: { cpu: "100m", memory: "100Mi" } },
// If your cluster config does not include a dns service, then to instead access an environment
- // variable to find the master service's host, comment out the 'value: dns' line above, and
- // uncomment the line below:
- // value: "env"
- }],
- ports: [{
- containerPort: 6379,
- }],
- }],
- },
- },
- },
+ // variable to find the master service's host, change `value: "dns"` to read `value: "env"`.
+ env: [{ name: "GET_HOSTS_FROM", value: "dns" }],
+ ports: [{ containerPort: 6379 }]
});
-
-// FRONTEND
-let frontendLabels = { app: "guestbook", tier: "frontend" };
-let frontendService = new k8s.core.v1.Service("frontend", {
- metadata: {
- name: "frontend",
- labels: frontendLabels,
- },
+let redisSlaveService = new k8s.core.v1.Service("redis-slave", {
+ metadata: { labels: redisSlaveDeployment.metadata.apply(meta => meta.labels) },
spec: {
- // If your cluster does not support `LoadBalancer` (such as on minikube), comment out the it, uncomment the
- // following to automatically create an external load-balanced IP for the frontend service.
- type: "LoadBalancer",
- ports: [{ port: 80 }],
- selector: frontendLabels,
- },
+ ports: [{ port: 6379, targetPort: 6379 }],
+ selector: redisSlaveDeployment.spec.apply(spec => spec.template.metadata.labels)
+ }
});
-let frontendDeployment = new k8s.apps.v1.Deployment("frontend", {
- metadata: {
- name: "frontend",
- },
- spec: {
- selector: {
- matchLabels: frontendLabels
- },
- replicas: 3,
- template: {
- metadata: {
- labels: frontendLabels,
- },
- spec: {
- containers: [{
+
+//
+// FRONTEND
+//
+
+let frontendDeployment = util.deployContainer("frontend", 3, {
name: "php-redis",
image: "gcr.io/google-samples/gb-frontend:v4",
- resources: {
- requests: {
- cpu: "100m",
- memory: "100Mi",
- },
- },
- env: [{
- name: "GET_HOSTS_FROM",
- value: "dns",
+ resources: { requests: { cpu: "100m", memory: "100Mi" } },
// If your cluster config does not include a dns service, then to instead access an environment
- // variable to find the master service's host, comment out the 'value: dns' line above, and
- // uncomment the line below:
- // value: "env"
- }],
- ports: [{
- containerPort: 80,
- }],
- }],
- },
- },
- },
+ // variable to find the master service's host, change `value: "dns"` to read `value: "env"`.
+ env: [{ name: "GET_HOSTS_FROM", value: "dns" /* value: "env"*/ }],
+ ports: [{ containerPort: 80 }]
+});
+let frontendService = new k8s.core.v1.Service("frontend", {
+ metadata: { labels: frontendDeployment.metadata.apply(meta => meta.labels) },
+ spec: {
+ type: isMinikube === "true" ? "ClusterIP" : "LoadBalancer",
+ ports: [{ port: 80 }],
+ selector: frontendDeployment.spec.apply(spec => spec.template.metadata.labels)
+ }
});
+
+// Export the frontend IP.
+export let frontendIp: pulumi.Output<string>;
+if (isMinikube === "true") {
+ frontendIp = frontendService.spec.apply(spec => spec.clusterIP);
+} else {
+ frontendIp = frontendService.status.apply(status => status.loadBalancer.ingress[0].ip);
+}

MODIFY
kubernetes-ts-guestbook/package.json
kubernetes-ts-guestbook/package.json
{
"name": "guestbook",
"version": "0.1.0",
- "main": "bin/index.js",
- "typings": "bin/index.d.ts",
- "scripts": {
- "build": "tsc"
- },
"devDependencies": {
"@types/node": "^9.3.0",
"typescript": "^2.5.3"
},
"dependencies": {
- "@pulumi/kubernetes": "^0.14.0",
- "@pulumi/pulumi": "^0.14.0"
+ "@pulumi/kubernetes": "^0.15.0",
+ "@pulumi/pulumi": "^0.15.0"
},
"license": "MIT"
}

ADD
kubernetes-ts-guestbook/util.ts
+import * as k8s from "@pulumi/kubernetes";
+
+export function deployContainer(name: string, replicas: number, container: any) {
+ const labels = { app: name };
+ return new k8s.apps.v1beta1.Deployment(name, {
+ spec: {
+ selector: { matchLabels: labels },
+ replicas: replicas,
+ template: {
+ metadata: { labels: labels },
+ spec: { containers: [container] }
+ }
+ }
+ });
+}

Modernize the Kubernetes guestbook example

Fixes #115.