Skip to content

Commit c71546e

Browse files
committed
Add "staged rollout gated by Prometheus" example
1 parent 8e59441 commit c71546e

File tree

8 files changed

+1305
-0
lines changed

8 files changed

+1305
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name: staged-rollout
2+
description: Staged application rollout gated by Prometheus checks
3+
runtime: nodejs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Kubernetes: Staged application rollout gated by Prometheus checks
2+
3+
Demonstrates how to create a staged rollout (from 3-replica canary -> 10-replica staging), gated by
4+
checking that the P90 response time reported by Prometheus is less than some amount. We first deploy
5+
[Prometheus][p8s] using a [Helm][helm] Chart, then deploy a Prometheus-instrumented application
6+
using two `Deployment` objects, with a gated check between them.
7+
8+
The relevant gating code in `index.ts` looks like this:
9+
10+
```typescript
11+
// Canary ring. Replicate instrumented Pod 3 times.
12+
const canary = new k8s.apps.v1beta1.Deployment(
13+
"canary-example-app",
14+
{ spec: { replicas: 1, template: instrumentedPod } },
15+
{ dependsOn: p8sDeployment }
16+
);
17+
18+
// Staging ring. Replicate instrumented Pod 10 times.
19+
const staging = new k8s.apps.v1beta1.Deployment("staging-example-app", {
20+
metadata: {
21+
annotations: {
22+
// Check P90 latency is < 100,000 microseconds. Returns a `Promise<string>` with the P90
23+
// response time. It must resolve correctly before this deployment rolls out. In
24+
// general any `Promise<T>` could go here.
25+
"example.com/p90ResponseTime": util.checkHttpLatency(canary, containerName, {
26+
durationSeconds: 60,
27+
quantile: 0.9,
28+
thresholdMicroseconds: 100000,
29+
prometheusEndpoint: `localhost:${localPort}`,
30+
forwarderHandle: forwarderHandle
31+
})
32+
}
33+
},
34+
spec: { replicas: 1, template: instrumentedPod }
35+
});
36+
```
37+
38+
When the program is run, it will look something like the following (although this is sped up by 8x).
39+
The majority of the time is taken up by deploying Prometheus. Towards the end, at the bottom, you
40+
can see `canary-example-app` and `canary-staging-app` created.
41+
42+
![gatedDeployment](images/gatedDeployment.gif "Deployment gated by Prometheus check")
43+
44+
## Running the App
45+
46+
1. If you haven't already, follow the steps in [Pulumi Installation and Setup][install] and
47+
[Configuring Pulumi Kubernetes][configuration] to get setup with Pulumi and Kubernetes.
48+
49+
1. Now, install dependencies:
50+
51+
```sh
52+
npm install
53+
```
54+
55+
1. Create a new stack:
56+
57+
```sh
58+
$ pulumi stack init
59+
Enter a stack name: staged-rollout
60+
```
61+
62+
1. **IMPORTANT NOTE:** The code in `index.ts` is meant to be run out-of-cluster (_e.g._, on your
63+
local machine). It will thus call `kubectl port-forward` on your behalf so that the Prometheus
64+
service is fowarded to your local machine, which allows this program to poll for metrics. **If
65+
you are running Pulumi in-cluster, you can comment out this part of the example.**
66+
67+
1. Perform the deployment:
68+
69+
```sh
70+
$ pulumi up
71+
Updating stack 'staged-rollout'
72+
Performing changes:
73+
74+
Type Name Status Info
75+
+ pulumi:pulumi:Stack prometheus-staged-rollout
76+
+ ├─ kubernetes:helm.sh:Chart p8s created
77+
+ │ ├─ kubernetes:core:ServiceAccount p8s-prometheus-alertmanager created
78+
+ │ ├─ kubernetes:core:ServiceAccount p8s-prometheus-pushgateway created
79+
+ │ ├─ kubernetes:core:ServiceAccount p8s-prometheus-kube-state-metrics created
80+
+ │ ├─ kubernetes:core:ServiceAccount p8s-prometheus-server created
81+
+ │ ├─ kubernetes:core:ServiceAccount p8s-prometheus-node-exporter created
82+
+ │ ├─ kubernetes:core:ConfigMap p8s-prometheus-alertmanager created
83+
+ │ ├─ kubernetes:rbac.authorization.k8s.io:ClusterRoleBinding p8s-prometheus-server created
84+
+ │ ├─ kubernetes:core:PersistentVolumeClaim p8s-prometheus-server created
85+
+ │ ├─ kubernetes:rbac.authorization.k8s.io:ClusterRoleBinding p8s-prometheus-kube-state-metrics created
86+
+ │ ├─ kubernetes:core:ConfigMap p8s-prometheus-server created
87+
+ │ ├─ kubernetes:core:PersistentVolumeClaim p8s-prometheus-alertmanager created
88+
+ │ ├─ kubernetes:core:Service p8s-prometheus-alertmanager created
89+
+ │ ├─ kubernetes:core:Service p8s-prometheus-kube-state-metrics created
90+
+ │ ├─ kubernetes:core:Service p8s-prometheus-pushgateway created
91+
+ │ ├─ kubernetes:core:Service p8s-prometheus-node-exporter created
92+
+ │ ├─ kubernetes:extensions:Deployment p8s-prometheus-kube-state-metrics created
93+
+ │ ├─ kubernetes:core:Service p8s-prometheus-server created
94+
+ │ ├─ kubernetes:extensions:Deployment p8s-prometheus-pushgateway created
95+
+ │ ├─ kubernetes:rbac.authorization.k8s.io:ClusterRole p8s-prometheus-kube-state-metrics created
96+
+ │ ├─ kubernetes:extensions:DaemonSet p8s-prometheus-node-exporter created
97+
+ │ ├─ kubernetes:extensions:Deployment p8s-prometheus-alertmanager created
98+
+ │ ├─ kubernetes:extensions:Deployment p8s-prometheus-server created
99+
+ │ └─ kubernetes:rbac.authorization.k8s.io:ClusterRole p8s-prometheus-server created
100+
+ ├─ kubernetes:apps:Deployment canary-example-app created
101+
+ └─ kubernetes:apps:Deployment staging-example-app created
102+
103+
Diagnostics:
104+
pulumi:pulumi:Stack: prometheus-test-p8s
105+
info: Checking HTTP metrics
106+
107+
---outputs:---
108+
+ p90ResponseTime: "8221.236"
109+
110+
info: 2 changes performed:
111+
+ 2 resources created
112+
26 resources unchanged
113+
Update duration: 7.362744393s
114+
115+
Permalink: https://app.pulumi.com/hausdorff/test-p8s/updates/1
116+
```
117+
118+
One useful sidenote, we can see here in the `---outputs:---` section that the `p90ResponseTime`
119+
that was computed by the promise is `export`ed, which causes Pulumi to report its value just
120+
before it terminates.
121+
122+
[install]: https://docs.pulumi.com/install/
123+
[configuration]: https://docs.pulumi.com/reference/kubernetes.html#configuration
124+
[p8s]: https://prometheus.io/
125+
[helm]: https://www.helm.sh/

0 commit comments

Comments
 (0)