2
2
3
3
![ ] ( images/automate_all_the_things.webp ) <!-- .element: style="float: right; width: 40%;" -->
4
4
5
- XXX version control because YAML is text
5
+ Handle Ops stuff like a developer would
6
6
7
- XXX separate instance for testing
7
+ Everything in version control...
8
8
9
- XXX PR/MR for Ops changes
9
+ ...because YAML is text
10
10
11
- XXX automated tests
11
+ Use branches for stages (e.g. dev, qa, live)
12
+
13
+ Pipeline to deploy to stages
14
+
15
+ Integrate changes using pull/merge requests
16
+
17
+ Add automated tests to pipeline
18
+
19
+ Changes are pushed into Kubernetes cluster
12
20
13
21
---
14
22
15
23
## Cluster access 1/
16
24
17
25
Different approches to access the cluster from a pipeline
18
26
27
+ ![ ] ( 120_kubernetes/ci_cd/inside.drawio.svg ) <!-- .element: style="float: right; width: 20%; margin-top: 1em;" -->
28
+
19
29
### Inside cluster
20
30
21
31
Pipeline runs inside the target cluster
22
32
23
- ![ ] ( 120_kubernetes/ci_cd/inside.drawio.svg ) <!-- .element: style="width: 50%;" -->
24
-
25
33
Direct API access with RBAC
26
34
27
- ### Demo
35
+ ![ ] ( 120_kubernetes/ci_cd/side-by-side.drawio.svg ) <!-- .element: style="float: right; width: 20%; margin-top: 1em;" -->
28
36
29
- XXX
37
+ ### Next to cluster
30
38
31
- ---
39
+ Pipeline runs somewhere else...
32
40
33
- ## Cluster access 2/2
41
+ ...or does not have direct access to Kubernetes API
34
42
35
- Different approches to access the cluster from a pipeline
43
+ Pipeline fetches (encrypted) kubeconfig
36
44
37
- ### Next to cluster
45
+ ---
38
46
39
- Pipeline runs somewhere else...
47
+ ## Useful tools
40
48
41
- ...or does not have direct access to Kubernetes API
49
+ Validate YAML using ` yamllint ` [ ] ( https://github.com/adrienverge/yamllint )
42
50
43
- ![ ] ( 120_kubernetes/ci_cd/side-by-side.drawio.svg ) <!-- .element: style="width: 50%;" -->
51
+ ``` bash
52
+ helm template my-ntpd ../helm/ntpd/ > ntpd.yaml
53
+ yamllint ntpd.yaml
54
+ cat << EOF >.yamllint
55
+ rules:
56
+ indentation:
57
+ indent-sequences: consistent
58
+ EOF
59
+ yamllint ntpd.yaml
60
+ ```
44
61
45
- Pipeline fetches (encrypted) kubeconfig
62
+ Validate against official schemas using ` kubeval ` [ ] ( https://github.com/instrumenta/kubeval ) :
46
63
47
- ### Demo
64
+ ``` bash
65
+ kubeval ntpd.yaml
66
+ ```
48
67
49
- XXX
68
+ Static analysis using ` kube-linter ` [ ] ( https://github.com/stackrox/kube-linter )
69
+
70
+ ``` bash
71
+ kube-linter lint ntpd.yaml
72
+ kube-linter lint ../helm/ntpd/
73
+ kube-linter checks list
74
+ ```
50
75
51
76
---
52
77
@@ -121,8 +146,6 @@ Resource requests are important for scheduling
121
146
122
147
Limits are important for eviction
123
148
124
- XXX usage
125
-
126
149
### You want ` (requests == limits) `
127
150
128
151
Pods will not be evicted...
@@ -162,7 +185,10 @@ Next pipeline run will fail because resource already exists
162
185
Instead create resource definition on-the-fly:
163
186
164
187
``` bash
165
- kubectl create secret --dry-run=client \
188
+ kubectl create secret generic foo \
189
+ --from-literal=bar=baz \
190
+ --dry-run=client \
191
+ --output=yaml \
166
192
| kubectl apply -f -
167
193
```
168
194
@@ -179,8 +205,17 @@ Do not use sleep after apply, scale, delete
179
205
Let ` kubectl ` do the waiting:
180
206
181
207
``` bash
182
- kubectl wait --for=condition=ready pod/foo
183
- kubectl rollout status deployment bar --timeout=15m
208
+ helm upgrade --install my-nginx bitnami/nginx \
209
+ --set service.type=ClusterIP
210
+ kubectl rollout status deployment my-nginx --timeout=15m
211
+ kubectl wait pods \
212
+ --for=condition=ready \
213
+ --selector app.kubernetes.io/instance=my-nginx
214
+ ```
215
+
216
+ Works for jobs as well:
217
+
218
+ ``` bash
184
219
kubectl wait --for=condition=complete job/baz
185
220
```
186
221
@@ -195,13 +230,22 @@ Finding the pod name is error prone
195
230
Filter by label:
196
231
197
232
``` bash
198
- kubectl delete pod --selector app=foo,component=db
233
+ helm upgrade --install my-nginx bitnami/nginx \
234
+ --set service.type=ClusterIP \
235
+ --set replicaCount=2
236
+ kubectl delete pod --selector app.kubernetes.io/instance=my-nginx
237
+ ```
238
+
239
+ Show logs of the first pod of a deployment:
240
+
241
+ ``` bash
242
+ kubectl logs deployment/my-nginx
199
243
```
200
244
201
- Show logs of a deployment with a single pod :
245
+ Show logs of multiple pods at once with stern [ ] ( https://github.com/stern/stern ) :
202
246
203
247
``` bash
204
- kubectl logs deployment/foo
248
+ stern --selector app.kubernetes.io/instance=my-nginx
205
249
```
206
250
207
251
---
@@ -215,15 +259,24 @@ When a pod is broken, it can be investigated
215
259
Remove a label to exclude it from ` ReplicaSet ` , ` Deployment ` , ` Service `
216
260
217
261
``` bash
218
- kubectl label pod foo-12345 app-
262
+ helm upgrade --install my-nginx bitnami/nginx \
263
+ --set service.type=ClusterIP \
264
+ --set replicaCount=2
265
+ kubectl get pods -l app.kubernetes.io/instance=my-nginx -o name \
266
+ | head -n 1 \
267
+ | xargs -I{} kubectl label {} app.kubernetes.io/instance-
219
268
```
220
269
221
270
` ReplicaSet ` replaces missing pod
222
271
223
- Pod ` foo-12345 ` can be investigated
224
-
225
272
Remove after troubleshooting
226
273
274
+ ``` bash
275
+ kubectl logs --selector ' !app.kubernetes.io/instance'
276
+ kubectl delete pod \
277
+ -l ' app.kubernetes.io/name=nginx,!app.kubernetes.io/instance'
278
+ ```
279
+
227
280
---
228
281
229
282
## Lessons Learnt 5/
@@ -267,13 +320,3 @@ Doing updates regularly is easier
267
320
Automerge for patches can help stay on top of things
268
321
269
322
Automated tests help decide whether an update is safe
270
-
271
- ---
272
-
273
- ## Lessons Learnt 7/7
274
-
275
- ### Image tags
276
-
277
- XXX immutable tags
278
-
279
- XXX version pinning
0 commit comments