Project

General

Profile

The ungleich kubernetes infrastructure » History » Version 213

Nico Schottelius, 06/25/2024 07:10 PM

1 22 Nico Schottelius
h1. The ungleich kubernetes infrastructure and ungleich kubernetes manual
2 1 Nico Schottelius
3 3 Nico Schottelius
{{toc}}
4
5 1 Nico Schottelius
h2. Status
6
7 211 Nico Schottelius
This document is **production**.
8
This document is the ungleich kubernetes infrastructure overview as well as the ungleich kubernetes manual.
9 1 Nico Schottelius
10 10 Nico Schottelius
h2. k8s clusters
11
12 123 Nico Schottelius
| Cluster            | Purpose/Setup     | Maintainer | Master(s)                     | argo                                                   | v4 http proxy | last verified |
13
| c0.k8s.ooo         | Dev               | -          | UNUSED                        |                                                        |               |    2021-10-05 |
14
| c1.k8s.ooo         | retired           |            | -                             |                                                        |               |    2022-03-15 |
15
| c2.k8s.ooo         | Dev p7 HW         | Nico       | server47 server53 server54    | "argo":https://argocd-server.argocd.svc.c2.k8s.ooo     |               |    2021-10-05 |
16
| c3.k8s.ooo         | retired           | -          | -                             |                                                        |               |    2021-10-05 |
17
| c4.k8s.ooo         | Dev2 p7 HW        | Jin-Guk    | server52 server53 server54    |                                                        |               |             - |
18
| c5.k8s.ooo         | retired           |            | -                             |                                                        |               |    2022-03-15 |
19
| c6.k8s.ooo         | Dev p6 VM Jin-Guk | Jin-Guk    |                               |                                                        |               |               |
20
| [[p5.k8s.ooo]]     | production        |            | server34 server36 server38    | "argo":https://argocd-server.argocd.svc.p5.k8s.ooo     | -             |               |
21
| [[p5-cow.k8s.ooo]] | production        | Nico       | server47 server51 server55    | "argo":https://argocd-server.argocd.svc.p5-cow.k8s.ooo |               |    2022-08-27 |
22
| [[p6.k8s.ooo]]     | production        |            | server67 server69 server71    | "argo":https://argocd-server.argocd.svc.p6.k8s.ooo     | 147.78.194.13 |    2021-10-05 |
23 184 Nico Schottelius
| [[p6-cow.k8s.ooo]] | production        |            | server134 server135 server136 | "argo":https://argocd-server.argocd.svc.p6in10.k8s.ooo | ?             |    2023-05-17 |
24 177 Nico Schottelius
| [[p10.k8s.ooo]]    | production        |            | server131 server132 server133 | "argo":https://argocd-server.argocd.svc.p10.k8s.ooo    | 147.78.194.12 |    2021-10-05 |
25 123 Nico Schottelius
| [[k8s.ge.nau.so]]  | development       |            | server107 server108 server109 | "argo":https://argocd-server.argocd.svc.k8s.ge.nau.so  |               |               |
26
| [[dev.k8s.ooo]]    | development       |            | server110 server111 server112 | "argo":https://argocd-server.argocd.svc.dev.k8s.ooo    | -             |    2022-07-08 |
27 164 Nico Schottelius
| [[r1r2p15k8sooo|r1.p15.k8s.ooo]] | production | Nico | server120 | | | 2022-10-30 |
28
| [[r1r2p15k8sooo|r2.p15.k8s.ooo]] | production | Nico | server121 | | | 2022-09-06 |
29 162 Nico Schottelius
| [[r1r2p10k8sooo|r1.p10.k8s.ooo]] | production | Nico | server122 | | | 2022-10-30 |
30
| [[r1r2p10k8sooo|r2.p10.k8s.ooo]] | production | Nico | server123 | | | 2022-10-15 |
31
| [[r1r2p5k8sooo|r1.p5.k8s.ooo]] | production | Nico | server137 | | | 2022-10-30 |
32
| [[r1r2p5k8sooo|r2.p5.k8s.ooo]] | production | Nico | server138 | | | 2022-10-30 |
33
| [[r1r2p6k8sooo|r1.p6.k8s.ooo]] | production | Nico | server139 | | | 2022-10-30 |
34
| [[r1r2p6k8sooo|r2.p6.k8s.ooo]] | production | Nico | server140 | | | 2022-10-30 |
35 21 Nico Schottelius
36 1 Nico Schottelius
h2. General architecture and components overview
37
38
* All k8s clusters are IPv6 only
39
* We use BGP peering to propagate podcidr and serviceCidr networks to our infrastructure
40
* The main public testing repository is "ungleich-k8s":https://code.ungleich.ch/ungleich-public/ungleich-k8s
41 18 Nico Schottelius
** Private configurations are found in the **k8s-config** repository
42 1 Nico Schottelius
43
h3. Cluster types
44
45 28 Nico Schottelius
| **Type/Feature**            | **Development**                | **Production**         |
46
| Min No. nodes               | 3 (1 master, 3 worker)         | 5 (3 master, 3 worker) |
47
| Recommended minimum         | 4 (dedicated master, 3 worker) | 8 (3 master, 5 worker) |
48
| Separation of control plane | optional                       | recommended            |
49
| Persistent storage          | required                       | required               |
50
| Number of storage monitors  | 3                              | 5                      |
51 1 Nico Schottelius
52 43 Nico Schottelius
h2. General k8s operations
53 1 Nico Schottelius
54 46 Nico Schottelius
h3. Cheat sheet / external great references
55
56
* "kubectl cheatsheet":https://kubernetes.io/docs/reference/kubectl/cheatsheet/
57
58 117 Nico Schottelius
h3. Allowing to schedule work on the control plane / removing node taints
59 69 Nico Schottelius
60
* Mostly for single node / test / development clusters
61
* Just remove the master taint as follows
62
63
<pre>
64
kubectl taint nodes --all node-role.kubernetes.io/master-
65 118 Nico Schottelius
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
66 69 Nico Schottelius
</pre>
67 1 Nico Schottelius
68 117 Nico Schottelius
You can check the node taints using @kubectl describe node ...@
69 69 Nico Schottelius
70 208 Nico Schottelius
h3. Adding taints
71
72
* For instance to limit nodes to specific customers
73
74
<pre>
75
kubectl taint nodes serverXX customer=CUSTOMERNAME:NoSchedule
76
</pre>
77
78 44 Nico Schottelius
h3. Get the cluster admin.conf
79
80
* On the masters of each cluster you can find the file @/etc/kubernetes/admin.conf@
81
* To be able to administrate the cluster you can copy the admin.conf to your local machine
82
* Multi cluster debugging can very easy if you name the config ~/cX-admin.conf (see example below)
83
84
<pre>
85
% scp root@server47.place7.ungleich.ch:/etc/kubernetes/admin.conf ~/c2-admin.conf
86
% export KUBECONFIG=~/c2-admin.conf    
87
% kubectl get nodes
88
NAME       STATUS                     ROLES                  AGE   VERSION
89
server47   Ready                      control-plane,master   82d   v1.22.0
90
server48   Ready                      control-plane,master   82d   v1.22.0
91
server49   Ready                      <none>                 82d   v1.22.0
92
server50   Ready                      <none>                 82d   v1.22.0
93
server59   Ready                      control-plane,master   82d   v1.22.0
94
server60   Ready,SchedulingDisabled   <none>                 82d   v1.22.0
95
server61   Ready                      <none>                 82d   v1.22.0
96
server62   Ready                      <none>                 82d   v1.22.0               
97
</pre>
98
99 18 Nico Schottelius
h3. Installing a new k8s cluster
100 8 Nico Schottelius
101 9 Nico Schottelius
* Decide on the cluster name (usually *cX.k8s.ooo*), X counting upwards
102 28 Nico Schottelius
** Using pXX.k8s.ooo for production clusters of placeXX
103 9 Nico Schottelius
* Use cdist to configure the nodes with requirements like crio
104
* Decide between single or multi node control plane setups (see below)
105 28 Nico Schottelius
** Single control plane suitable for development clusters
106 9 Nico Schottelius
107 28 Nico Schottelius
Typical init procedure:
108 9 Nico Schottelius
109 206 Nico Schottelius
h4. Single control plane:
110
111
<pre>
112
kubeadm init --config bootstrap/XXX/kubeadm.yaml
113
</pre>
114
115
h4. Multi control plane (HA):
116
117
<pre>
118
kubeadm init --config bootstrap/XXX/kubeadm.yaml --upload-certs
119
</pre>
120
121 10 Nico Schottelius
122 29 Nico Schottelius
h3. Deleting a pod that is hanging in terminating state
123
124
<pre>
125
kubectl delete pod <PODNAME> --grace-period=0 --force --namespace <NAMESPACE>
126
</pre>
127
128
(from https://stackoverflow.com/questions/35453792/pods-stuck-in-terminating-status)
129
130 42 Nico Schottelius
h3. Listing nodes of a cluster
131
132
<pre>
133
[15:05] bridge:~% kubectl get nodes
134
NAME       STATUS   ROLES                  AGE   VERSION
135
server22   Ready    <none>                 52d   v1.22.0
136
server23   Ready    <none>                 52d   v1.22.2
137
server24   Ready    <none>                 52d   v1.22.0
138
server25   Ready    <none>                 52d   v1.22.0
139
server26   Ready    <none>                 52d   v1.22.0
140
server27   Ready    <none>                 52d   v1.22.0
141
server63   Ready    control-plane,master   52d   v1.22.0
142
server64   Ready    <none>                 52d   v1.22.0
143
server65   Ready    control-plane,master   52d   v1.22.0
144
server66   Ready    <none>                 52d   v1.22.0
145
server83   Ready    control-plane,master   52d   v1.22.0
146
server84   Ready    <none>                 52d   v1.22.0
147
server85   Ready    <none>                 52d   v1.22.0
148
server86   Ready    <none>                 52d   v1.22.0
149
</pre>
150
151 41 Nico Schottelius
h3. Removing / draining a node
152
153
Usually @kubectl drain server@ should do the job, but sometimes we need to be more aggressive:
154
155 1 Nico Schottelius
<pre>
156 103 Nico Schottelius
kubectl drain --delete-emptydir-data --ignore-daemonsets serverXX
157 42 Nico Schottelius
</pre>
158
159
h3. Readding a node after draining
160
161
<pre>
162
kubectl uncordon serverXX
163 1 Nico Schottelius
</pre>
164 43 Nico Schottelius
165 50 Nico Schottelius
h3. (Re-)joining worker nodes after creating the cluster
166 49 Nico Schottelius
167
* We need to have an up-to-date token
168
* We use different join commands for the workers and control plane nodes
169
170
Generating the join command on an existing control plane node:
171
172
<pre>
173
kubeadm token create --print-join-command
174
</pre>
175
176 50 Nico Schottelius
h3. (Re-)joining control plane nodes after creating the cluster
177 1 Nico Schottelius
178 50 Nico Schottelius
* We generate the token again
179
* We upload the certificates
180
* We need to combine/create the join command for the control plane node
181
182
Example session:
183
184
<pre>
185
% kubeadm token create --print-join-command
186
kubeadm join p10-api.k8s.ooo:6443 --token xmff4i.ABC --discovery-token-ca-cert-hash sha256:longhash 
187
188
% kubeadm init phase upload-certs --upload-certs
189
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
190
[upload-certs] Using certificate key:
191
CERTKEY
192
193
# Then we use these two outputs on the joining node:
194
195
kubeadm join p10-api.k8s.ooo:6443 --token xmff4i.ABC --discovery-token-ca-cert-hash sha256:longhash --control-plane --certificate-key CERTKEY
196
</pre>
197
198
Commands to be used on a control plane node:
199
200
<pre>
201
kubeadm token create --print-join-command
202
kubeadm init phase upload-certs --upload-certs
203
</pre>
204
205
Commands to be used on the joining node:
206
207
<pre>
208
JOINCOMMAND --control-plane --certificate-key CERTKEY
209
</pre>
210 49 Nico Schottelius
211 51 Nico Schottelius
SEE ALSO
212
213
* https://stackoverflow.com/questions/63936268/how-to-generate-kubeadm-token-for-secondary-control-plane-nodes
214
* https://blog.scottlowe.org/2019/08/15/reconstructing-the-join-command-for-kubeadm/
215
216 53 Nico Schottelius
h3. How to fix etcd does not start when rejoining a kubernetes cluster as a control plane
217 52 Nico Schottelius
218
If during the above step etcd does not come up, @kubeadm join@ can hang as follows:
219
220
<pre>
221
[control-plane] Creating static Pod manifest for "kube-apiserver"                                                              
222
[control-plane] Creating static Pod manifest for "kube-controller-manager"                                                     
223
[control-plane] Creating static Pod manifest for "kube-scheduler"                                                              
224
[check-etcd] Checking that the etcd cluster is healthy                                                                         
225
error execution phase check-etcd: etcd cluster is not healthy: failed to dial endpoint https://[2a0a:e5c0:10:1:225:b3ff:fe20:37
226
8a]:2379 with maintenance client: context deadline exceeded                                                                    
227
To see the stack trace of this error execute with --v=5 or higher         
228
</pre>
229
230
Then the problem is likely that the etcd server is still a member of the cluster. We first need to remove it from the etcd cluster and then the join works.
231
232
To fix this we do:
233
234
* Find a working etcd pod
235
* Find the etcd members / member list
236
* Remove the etcd member that we want to re-join the cluster
237
238
239
<pre>
240
# Find the etcd pods
241
kubectl -n kube-system get pods -l component=etcd,tier=control-plane
242
243
# Get the list of etcd servers with the member id 
244
kubectl exec -n kube-system -ti ETCDPODNAME -- etcdctl --endpoints '[::1]:2379' --cacert /etc/kubernetes/pki/etcd/ca.crt --cert  /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key member list
245
246
# Remove the member
247
kubectl exec -n kube-system -ti ETCDPODNAME -- etcdctl --endpoints '[::1]:2379' --cacert /etc/kubernetes/pki/etcd/ca.crt --cert  /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key member remove MEMBERID
248
</pre>
249
250
Sample session:
251
252
<pre>
253
[10:48] line:~% kubectl -n kube-system get pods -l component=etcd,tier=control-plane
254
NAME            READY   STATUS    RESTARTS     AGE
255
etcd-server63   1/1     Running   0            3m11s
256
etcd-server65   1/1     Running   3            7d2h
257
etcd-server83   1/1     Running   8 (6d ago)   7d2h
258
[10:48] line:~% kubectl exec -n kube-system -ti etcd-server65 -- etcdctl --endpoints '[::1]:2379' --cacert /etc/kubernetes/pki/etcd/ca.crt --cert  /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key member list
259
356891cd676df6e4, started, server65, https://[2a0a:e5c0:10:1:225:b3ff:fe20:375c]:2380, https://[2a0a:e5c0:10:1:225:b3ff:fe20:375c]:2379, false
260
371b8a07185dee7e, started, server63, https://[2a0a:e5c0:10:1:225:b3ff:fe20:378a]:2380, https://[2a0a:e5c0:10:1:225:b3ff:fe20:378a]:2379, false
261
5942bc58307f8af9, started, server83, https://[2a0a:e5c0:10:1:3e4a:92ff:fe79:bb98]:2380, https://[2a0a:e5c0:10:1:3e4a:92ff:fe79:bb98]:2379, false
262
263
[10:48] line:~% kubectl exec -n kube-system -ti etcd-server65 -- etcdctl --endpoints '[::1]:2379' --cacert /etc/kubernetes/pki/etcd/ca.crt --cert  /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key member remove 371b8a07185dee7e
264
Member 371b8a07185dee7e removed from cluster e3c0805f592a8f77
265 1 Nico Schottelius
266
</pre>
267
268
SEE ALSO
269
270
* We found the solution using https://stackoverflow.com/questions/67921552/re-installed-node-cannot-join-kubernetes-cluster
271 56 Nico Schottelius
272 213 Nico Schottelius
h4. Updating the members
273
274
1) get alive member
275
276
<pre>
277
% kubectl -n kube-system get pods -l component=etcd,tier=control-plane
278
NAME            READY   STATUS    RESTARTS   AGE
279
etcd-server67   1/1     Running   1          185d
280
etcd-server69   1/1     Running   1          185d
281
etcd-server71   1/1     Running   2          185d
282
[20:57] sun:~% 
283
</pre>
284
285
2) get member list
286
287
* in this case via crictl, as the api does not work correctly anymore
288
289
<pre>
290
291
292
</pre>
293
294
295
3) update
296
297
<pre>
298
etcdctl member update MEMBERID  --peer-urls=https://[...]:2380
299
300
301
</pre>
302
303 147 Nico Schottelius
h3. Node labels (adding, showing, removing)
304
305
Listing the labels:
306
307
<pre>
308
kubectl get nodes --show-labels
309
</pre>
310
311
Adding labels:
312
313
<pre>
314
kubectl label nodes LIST-OF-NODES label1=value1 
315
316
</pre>
317
318
For instance:
319
320
<pre>
321
kubectl label nodes router2 router3 hosttype=router 
322
</pre>
323
324
Selecting nodes in pods:
325
326
<pre>
327
apiVersion: v1
328
kind: Pod
329
...
330
spec:
331
  nodeSelector:
332
    hosttype: router
333
</pre>
334
335 148 Nico Schottelius
Removing labels by adding a minus at the end of the label name:
336
337
<pre>
338
kubectl label node <nodename> <labelname>-
339
</pre>
340
341
For instance:
342
343
<pre>
344
kubectl label nodes router2 router3 hosttype- 
345
</pre>
346
347 147 Nico Schottelius
SEE ALSO
348 1 Nico Schottelius
349 148 Nico Schottelius
* https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/
350
* https://stackoverflow.com/questions/34067979/how-to-delete-a-node-label-by-command-and-api
351 147 Nico Schottelius
352 199 Nico Schottelius
h3. Listing all pods on a node
353
354
<pre>
355
kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=serverXX
356
</pre>
357
358
Found on https://stackoverflow.com/questions/62000559/how-to-list-all-the-pods-running-in-a-particular-worker-node-by-executing-a-comm
359
360 101 Nico Schottelius
h3. Hardware Maintenance using ungleich-hardware
361
362
Use the following manifest and replace the HOST with the actual host:
363
364
<pre>
365
apiVersion: v1
366
kind: Pod
367
metadata:
368
  name: ungleich-hardware-HOST
369
spec:
370
  containers:
371
  - name: ungleich-hardware
372
    image: ungleich/ungleich-hardware:0.0.5
373
    args:
374
    - sleep
375
    - "1000000"
376
    volumeMounts:
377
      - mountPath: /dev
378
        name: dev
379
    securityContext:
380
      privileged: true
381
  nodeSelector:
382
    kubernetes.io/hostname: "HOST"
383
384
  volumes:
385
    - name: dev
386
      hostPath:
387
        path: /dev
388
</pre>
389
390 102 Nico Schottelius
Also see: [[The_ungleich_hardware_maintenance_guide]]
391
392 105 Nico Schottelius
h3. Triggering a cronjob / creating a job from a cronjob
393 104 Nico Schottelius
394
To test a cronjob, we can create a job from a cronjob:
395
396
<pre>
397
kubectl create job --from=cronjob/volume2-daily-backup volume2-manual
398
</pre>
399
400
This creates a job volume2-manual based on the cronjob  volume2-daily
401
402 112 Nico Schottelius
h3. su-ing into a user that has nologin shell set
403
404
Many times users are having nologin as their shell inside the container. To be able to execute maintenance commands within the
405
container, we can use @su -s /bin/sh@ like this:
406
407
<pre>
408
su -s /bin/sh -c '/path/to/your/script' testuser
409
</pre>
410
411
Found on https://serverfault.com/questions/351046/how-to-run-command-as-user-who-has-usr-sbin-nologin-as-shell
412
413 113 Nico Schottelius
h3. How to print a secret value
414
415
Assuming you want the "password" item from a secret, use:
416
417
<pre>
418
kubectl get secret SECRETNAME -o jsonpath="{.data.password}" | base64 -d; echo "" 
419
</pre>
420
421 209 Nico Schottelius
h3. Fixing the "ImageInspectError"
422
423
If you see this problem:
424
425
<pre>
426
# kubectl get pods
427
NAME                                                       READY   STATUS                   RESTARTS   AGE
428
bird-router-server137-bird-767f65bb47-g4xsh                0/1     Init:ImageInspectError   0          77d
429
bird-router-server137-openvpn-server120-5c987b7ffb-cn9xf   0/1     ImageInspectError        1          159d
430
bird-router-server137-unbound-5c6f5d4bb6-cxbpr             0/1     ImageInspectError        1          159d
431
</pre>
432
433
Fixes so far:
434
435
* correct registries.conf
436
437 212 Nico Schottelius
h3. Automatic cleanup of images
438
439
* options to kubelet
440
441
<pre>
442
  --image-gc-high-threshold=90: The percent of disk usage after which image garbage collection is always run. Default: 90%
443
  --image-gc-low-threshold=80: The percent of disk usage before which image garbage collection is never run. Lowest disk usage to garbage collect to. Default: 80%
444
</pre>
445 209 Nico Schottelius
446 173 Nico Schottelius
h3. How to upgrade a kubernetes cluster
447 172 Nico Schottelius
448
h4. General
449
450
* Should be done every X months to stay up-to-date
451
** X probably something like 3-6
452
* kubeadm based clusters
453
* Needs specific kubeadm versions for upgrade
454
* Follow instructions on https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
455 190 Nico Schottelius
* Finding releases: https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG
456 172 Nico Schottelius
457
h4. Getting a specific kubeadm or kubelet version
458
459
<pre>
460 190 Nico Schottelius
RELEASE=v1.22.17
461
RELEASE=v1.23.17
462 181 Nico Schottelius
RELEASE=v1.24.9
463 1 Nico Schottelius
RELEASE=v1.25.9
464
RELEASE=v1.26.6
465 190 Nico Schottelius
RELEASE=v1.27.2
466
467 187 Nico Schottelius
ARCH=amd64
468 172 Nico Schottelius
469
curl -L --remote-name-all https://dl.k8s.io/release/${RELEASE}/bin/linux/${ARCH}/{kubeadm,kubelet}
470 182 Nico Schottelius
chmod u+x kubeadm kubelet
471 172 Nico Schottelius
</pre>
472
473
h4. Steps
474
475
* kubeadm upgrade plan
476
** On one control plane node
477
* kubeadm upgrade apply vXX.YY.ZZ
478
** On one control plane node
479 189 Nico Schottelius
* kubeadm upgrade node
480
** On all other control plane nodes
481
** On all worker nodes afterwards
482
483 172 Nico Schottelius
484 173 Nico Schottelius
Repeat for all control planes nodes. The upgrade kubelet on all other nodes via package manager.
485 172 Nico Schottelius
486 193 Nico Schottelius
h4. Upgrading to 1.22.17
487 1 Nico Schottelius
488 193 Nico Schottelius
* https://v1-22.docs.kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
489 194 Nico Schottelius
* Need to create a kubeadm config map
490 198 Nico Schottelius
** f.i. using the following
491
** @/usr/local/bin/kubeadm-v1.22.17   upgrade --config kubeadm.yaml --ignore-preflight-errors=CoreDNSUnsupportedPlugins,CoreDNSMigration apply -y v1.22.17@
492 193 Nico Schottelius
* Done for p6 on 2023-10-04
493
494
h4. Upgrading to 1.23.17
495
496
* https://v1-23.docs.kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
497
* No special notes
498
* Done for p6 on 2023-10-04
499
500
h4. Upgrading to 1.24.17
501
502
* https://v1-24.docs.kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
503
* No special notes
504
* Done for p6 on 2023-10-04
505
506
h4. Upgrading to 1.25.14
507
508
* https://v1-24.docs.kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
509
* No special notes
510
* Done for p6 on 2023-10-04
511
512
h4. Upgrading to 1.26.9
513
514 1 Nico Schottelius
* https://v1-26.docs.kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
515 193 Nico Schottelius
* No special notes
516
* Done for p6 on 2023-10-04
517 188 Nico Schottelius
518 196 Nico Schottelius
h4. Upgrading to 1.27
519 186 Nico Schottelius
520 192 Nico Schottelius
* https://v1-27.docs.kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
521 186 Nico Schottelius
* kubelet will not start anymore
522
* reason: @"command failed" err="failed to parse kubelet flag: unknown flag: --container-runtime"@
523
* /var/lib/kubelet/kubeadm-flags.env contains that parameter
524
* remove it, start kubelet
525 192 Nico Schottelius
526 197 Nico Schottelius
h4. Upgrading to 1.28
527 192 Nico Schottelius
528
* https://v1-28.docs.kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
529 186 Nico Schottelius
530 210 Nico Schottelius
h4. Upgrading to 1.29
531
532
* Done for many clusters around 2024-01-10
533
* Unsure if it was properly released
534
* https://v1-29.docs.kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
535
536 186 Nico Schottelius
h4. Upgrade to crio 1.27: missing crun
537
538
Error message
539
540
<pre>
541
level=fatal msg="validating runtime config: runtime validation: \"crun\" not found in $PATH: exec: \"crun\": executable file not found in $PATH"
542
</pre>
543
544
Fix:
545
546
<pre>
547
apk add crun
548
</pre>
549
550 157 Nico Schottelius
h2. Reference CNI
551
552
* Mainly "stupid", but effective plugins
553
* Main documentation on https://www.cni.dev/plugins/current/
554 158 Nico Schottelius
* Plugins
555
** bridge
556
*** Can create the bridge on the host
557
*** But seems not to be able to add host interfaces to it as well
558
*** Has support for vlan tags
559
** vlan
560
*** creates vlan tagged sub interface on the host
561 160 Nico Schottelius
*** "It's a 1:1 mapping (i.e. no bridge in between)":https://github.com/k8snetworkplumbingwg/multus-cni/issues/569
562 158 Nico Schottelius
** host-device
563
*** moves the interface from the host into the container
564
*** very easy for physical connections to containers
565 159 Nico Schottelius
** ipvlan
566
*** "virtualisation" of a host device
567
*** routing based on IP
568
*** Same MAC for everyone
569
*** Cannot reach the master interface
570
** maclvan
571
*** With mac addresses
572
*** Supports various modes (to be checked)
573
** ptp ("point to point")
574
*** Creates a host device and connects it to the container
575
** win*
576 158 Nico Schottelius
*** Windows implementations
577 157 Nico Schottelius
578 62 Nico Schottelius
h2. Calico CNI
579
580
h3. Calico Installation
581
582
* We install "calico using helm":https://docs.projectcalico.org/getting-started/kubernetes/helm
583
* This has the following advantages:
584
** Easy to upgrade
585
** Does not require os to configure IPv6/dual stack settings as the tigera operator figures out things on its own
586
587
Usually plain calico can be installed directly using:
588
589
<pre>
590 174 Nico Schottelius
VERSION=v3.25.0
591 149 Nico Schottelius
592 1 Nico Schottelius
helm repo add projectcalico https://docs.projectcalico.org/charts
593 167 Nico Schottelius
helm repo update
594 124 Nico Schottelius
helm upgrade --install --namespace tigera calico projectcalico/tigera-operator --version $VERSION --create-namespace
595 1 Nico Schottelius
</pre>
596 92 Nico Schottelius
597
* Check the tags on https://github.com/projectcalico/calico/tags for the latest release
598 62 Nico Schottelius
599
h3. Installing calicoctl
600
601 115 Nico Schottelius
* General installation instructions, including binary download: https://projectcalico.docs.tigera.io/maintenance/clis/calicoctl/install
602
603 62 Nico Schottelius
To be able to manage and configure calico, we need to 
604
"install calicoctl (we choose the version as a pod)":https://docs.projectcalico.org/getting-started/clis/calicoctl/install#install-calicoctl-as-a-kubernetes-pod
605
606
<pre>
607
kubectl apply -f https://docs.projectcalico.org/manifests/calicoctl.yaml
608
</pre>
609
610 93 Nico Schottelius
Or version specific:
611
612
<pre>
613
kubectl apply -f https://github.com/projectcalico/calico/blob/v3.20.4/manifests/calicoctl.yaml
614 97 Nico Schottelius
615
# For 3.22
616
kubectl apply -f https://projectcalico.docs.tigera.io/archive/v3.22/manifests/calicoctl.yaml
617 93 Nico Schottelius
</pre>
618
619 70 Nico Schottelius
And making it easier accessible by alias:
620
621
<pre>
622
alias calicoctl="kubectl exec -i -n kube-system calicoctl -- /calicoctl"
623
</pre>
624
625 62 Nico Schottelius
h3. Calico configuration
626
627 63 Nico Schottelius
By default our k8s clusters "BGP peer":https://docs.projectcalico.org/networking/bgp
628
with an upstream router to propagate podcidr and servicecidr.
629 62 Nico Schottelius
630
Default settings in our infrastructure:
631
632
* We use a full-mesh using the @nodeToNodeMeshEnabled: true@ option
633
* We keep the original next hop so that *only* the server with the pod is announcing it (instead of ecmp)
634 1 Nico Schottelius
* We use private ASNs for k8s clusters
635 63 Nico Schottelius
* We do *not* use any overlay
636 62 Nico Schottelius
637
After installing calico and calicoctl the last step of the installation is usually:
638
639 1 Nico Schottelius
<pre>
640 79 Nico Schottelius
calicoctl create -f - < calico-bgp.yaml
641 62 Nico Schottelius
</pre>
642
643
644
A sample BGP configuration:
645
646
<pre>
647
---
648
apiVersion: projectcalico.org/v3
649
kind: BGPConfiguration
650
metadata:
651
  name: default
652
spec:
653
  logSeverityScreen: Info
654
  nodeToNodeMeshEnabled: true
655
  asNumber: 65534
656
  serviceClusterIPs:
657
  - cidr: 2a0a:e5c0:10:3::/108
658
  serviceExternalIPs:
659
  - cidr: 2a0a:e5c0:10:3::/108
660
---
661
apiVersion: projectcalico.org/v3
662
kind: BGPPeer
663
metadata:
664
  name: router1-place10
665
spec:
666
  peerIP: 2a0a:e5c0:10:1::50
667
  asNumber: 213081
668
  keepOriginalNextHop: true
669
</pre>
670
671 126 Nico Schottelius
h2. Cilium CNI (experimental)
672
673 137 Nico Schottelius
h3. Status
674
675 138 Nico Schottelius
*NO WORKING CILIUM CONFIGURATION FOR IPV6 only modes*
676 137 Nico Schottelius
677 146 Nico Schottelius
h3. Latest error
678
679
It seems cilium does not run on IPv6 only hosts:
680
681
<pre>
682
level=info msg="Validating configured node address ranges" subsys=daemon
683
level=fatal msg="postinit failed" error="external IPv4 node address could not be derived, please configure via --ipv4-node" subsys=daemon
684
level=info msg="Starting IP identity watcher" subsys=ipcache
685
</pre>
686
687
It crashes after that log entry
688
689 128 Nico Schottelius
h3. BGP configuration
690
691
* The cilium-operator will not start without a correct configmap being present beforehand (see error message below)
692
* Creating the bgp config beforehand as a configmap is thus required.
693
694
The error one gets without the configmap present:
695
696
Pods are hanging with:
697
698
<pre>
699
cilium-bpqm6                       0/1     Init:0/4            0             9s
700
cilium-operator-5947d94f7f-5bmh2   0/1     ContainerCreating   0             9s
701
</pre>
702
703
The error message in the cilium-*perator is:
704
705
<pre>
706
Events:
707
  Type     Reason       Age                From               Message
708
  ----     ------       ----               ----               -------
709
  Normal   Scheduled    80s                default-scheduler  Successfully assigned kube-system/cilium-operator-5947d94f7f-lqcsp to server56
710
  Warning  FailedMount  16s (x8 over 80s)  kubelet            MountVolume.SetUp failed for volume "bgp-config-path" : configmap "bgp-config" not found
711
</pre>
712
713
A correct bgp config looks like this:
714
715
<pre>
716
apiVersion: v1
717
kind: ConfigMap
718
metadata:
719
  name: bgp-config
720
  namespace: kube-system
721
data:
722
  config.yaml: |
723
    peers:
724
      - peer-address: 2a0a:e5c0::46
725
        peer-asn: 209898
726
        my-asn: 65533
727
      - peer-address: 2a0a:e5c0::47
728
        peer-asn: 209898
729
        my-asn: 65533
730
    address-pools:
731
      - name: default
732
        protocol: bgp
733
        addresses:
734
          - 2a0a:e5c0:0:14::/64
735
</pre>
736 127 Nico Schottelius
737
h3. Installation
738 130 Nico Schottelius
739 127 Nico Schottelius
Adding the repo
740 1 Nico Schottelius
<pre>
741 127 Nico Schottelius
742 129 Nico Schottelius
helm repo add cilium https://helm.cilium.io/
743 130 Nico Schottelius
helm repo update
744
</pre>
745 129 Nico Schottelius
746 135 Nico Schottelius
Installing + configuring cilium
747 129 Nico Schottelius
<pre>
748 130 Nico Schottelius
ipv6pool=2a0a:e5c0:0:14::/112
749 1 Nico Schottelius
750 146 Nico Schottelius
version=1.12.2
751 129 Nico Schottelius
752
helm upgrade --install cilium cilium/cilium --version $version \
753 1 Nico Schottelius
  --namespace kube-system \
754
  --set ipv4.enabled=false \
755
  --set ipv6.enabled=true \
756 146 Nico Schottelius
  --set enableIPv6Masquerade=false \
757
  --set bgpControlPlane.enabled=true 
758 1 Nico Schottelius
759 146 Nico Schottelius
#  --set ipam.operator.clusterPoolIPv6PodCIDRList=$ipv6pool
760
761
# Old style bgp?
762 136 Nico Schottelius
#   --set bgp.enabled=true --set bgp.announce.podCIDR=true \
763 127 Nico Schottelius
764
# Show possible configuration options
765
helm show values cilium/cilium
766
767 1 Nico Schottelius
</pre>
768 132 Nico Schottelius
769
Using a /64 for ipam.operator.clusterPoolIPv6PodCIDRList fails with:
770
771
<pre>
772
level=fatal msg="Unable to init cluster-pool allocator" error="unable to initialize IPv6 allocator New CIDR set failed; the node CIDR size is too big" subsys=cilium-operator-generic
773
</pre>
774
775 126 Nico Schottelius
776 1 Nico Schottelius
See also https://github.com/cilium/cilium/issues/20756
777 135 Nico Schottelius
778
Seems a /112 is actually working.
779
780
h3. Kernel modules
781
782
Cilium requires the following modules to be loaded on the host (not loaded by default):
783
784
<pre>
785 1 Nico Schottelius
modprobe  ip6table_raw
786
modprobe  ip6table_filter
787
</pre>
788 146 Nico Schottelius
789
h3. Interesting helm flags
790
791
* autoDirectNodeRoutes
792
* bgpControlPlane.enabled = true
793
794
h3. SEE ALSO
795
796
* https://docs.cilium.io/en/v1.12/helm-reference/
797 133 Nico Schottelius
798 179 Nico Schottelius
h2. Multus
799 168 Nico Schottelius
800
* https://github.com/k8snetworkplumbingwg/multus-cni
801
* Installing a deployment w/ CRDs
802 150 Nico Schottelius
803 169 Nico Schottelius
<pre>
804 176 Nico Schottelius
VERSION=v4.0.1
805 169 Nico Schottelius
806 170 Nico Schottelius
kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/${VERSION}/deployments/multus-daemonset-crio.yml
807
</pre>
808 169 Nico Schottelius
809 191 Nico Schottelius
h2. ArgoCD
810 56 Nico Schottelius
811 60 Nico Schottelius
h3. Argocd Installation
812 1 Nico Schottelius
813 116 Nico Schottelius
* See https://argo-cd.readthedocs.io/en/stable/
814
815 60 Nico Schottelius
As there is no configuration management present yet, argocd is installed using
816
817 1 Nico Schottelius
<pre>
818 60 Nico Schottelius
kubectl create namespace argocd
819 1 Nico Schottelius
820
# OR: latest stable
821
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
822
823 191 Nico Schottelius
# OR Specific Version
824
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.3.2/manifests/install.yaml
825 56 Nico Schottelius
826 191 Nico Schottelius
827
</pre>
828 1 Nico Schottelius
829 60 Nico Schottelius
h3. Get the argocd credentials
830
831
<pre>
832
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo ""
833
</pre>
834 52 Nico Schottelius
835 87 Nico Schottelius
h3. Accessing argocd
836
837
In regular IPv6 clusters:
838
839
* Navigate to https://argocd-server.argocd.CLUSTERDOMAIN
840
841
In legacy IPv4 clusters
842
843
<pre>
844
kubectl --namespace argocd port-forward svc/argocd-server 8080:80
845
</pre>
846
847 88 Nico Schottelius
* Navigate to https://localhost:8080
848
849 68 Nico Schottelius
h3. Using the argocd webhook to trigger changes
850 67 Nico Schottelius
851
* To trigger changes post json https://argocd.example.com/api/webhook
852
853 72 Nico Schottelius
h3. Deploying an application
854
855
* Applications are deployed via git towards gitea (code.ungleich.ch) and then pulled by argo
856 73 Nico Schottelius
* Always include the *redmine-url* pointing to the (customer) ticket
857
** Also add the support-url if it exists
858 72 Nico Schottelius
859
Application sample
860
861
<pre>
862
apiVersion: argoproj.io/v1alpha1
863
kind: Application
864
metadata:
865
  name: gitea-CUSTOMER
866
  namespace: argocd
867
spec:
868
  destination:
869
    namespace: default
870
    server: 'https://kubernetes.default.svc'
871
  source:
872
    path: apps/prod/gitea
873
    repoURL: 'https://code.ungleich.ch/ungleich-intern/k8s-config.git'
874
    targetRevision: HEAD
875
    helm:
876
      parameters:
877
        - name: storage.data.storageClass
878
          value: rook-ceph-block-hdd
879
        - name: storage.data.size
880
          value: 200Gi
881
        - name: storage.db.storageClass
882
          value: rook-ceph-block-ssd
883
        - name: storage.db.size
884
          value: 10Gi
885
        - name: storage.letsencrypt.storageClass
886
          value: rook-ceph-block-hdd
887
        - name: storage.letsencrypt.size
888
          value: 50Mi
889
        - name: letsencryptStaging
890
          value: 'no'
891
        - name: fqdn
892
          value: 'code.verua.online'
893
  project: default
894
  syncPolicy:
895
    automated:
896
      prune: true
897
      selfHeal: true
898
  info:
899
    - name: 'redmine-url'
900
      value: 'https://redmine.ungleich.ch/issues/ISSUEID'
901
    - name: 'support-url'
902
      value: 'https://support.ungleich.ch/Ticket/Display.html?id=TICKETID'
903
</pre>
904
905 80 Nico Schottelius
h2. Helm related operations and conventions
906 55 Nico Schottelius
907 61 Nico Schottelius
We use helm charts extensively.
908
909
* In production, they are managed via argocd
910
* In development, helm chart can de developed and deployed manually using the helm utility.
911
912 55 Nico Schottelius
h3. Installing a helm chart
913
914
One can use the usual pattern of
915
916
<pre>
917
helm install <releasename> <chartdirectory>
918
</pre>
919
920
However often you want to reinstall/update when testing helm charts. The following pattern is "better", because it allows you to reinstall, if it is already installed:
921
922
<pre>
923
helm upgrade --install <releasename> <chartdirectory>
924 1 Nico Schottelius
</pre>
925 80 Nico Schottelius
926
h3. Naming services and deployments in helm charts [Application labels]
927
928
* We always have {{ .Release.Name }} to identify the current "instance"
929
* Deployments:
930
** use @app: <what it is>@, f.i. @app: nginx@, @app: postgres@, ...
931 81 Nico Schottelius
* See more about standard labels on
932
** https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
933
** https://helm.sh/docs/chart_best_practices/labels/
934 55 Nico Schottelius
935 151 Nico Schottelius
h3. Show all versions of a helm chart
936
937
<pre>
938
helm search repo -l repo/chart
939
</pre>
940
941
For example:
942
943
<pre>
944
% helm search repo -l projectcalico/tigera-operator 
945
NAME                         	CHART VERSION	APP VERSION	DESCRIPTION                            
946
projectcalico/tigera-operator	v3.23.3      	v3.23.3    	Installs the Tigera operator for Calico
947
projectcalico/tigera-operator	v3.23.2      	v3.23.2    	Installs the Tigera operator for Calico
948
....
949
</pre>
950
951 152 Nico Schottelius
h3. Show possible values of a chart
952
953
<pre>
954
helm show values <repo/chart>
955
</pre>
956
957
Example:
958
959
<pre>
960
helm show values ingress-nginx/ingress-nginx
961
</pre>
962
963 207 Nico Schottelius
h3. Show all possible charts in a repo
964
965
<pre>
966
helm search repo REPO
967
</pre>
968
969 178 Nico Schottelius
h3. Download a chart
970
971
For instance for checking it out locally. Use:
972
973
<pre>
974
helm pull <repo/chart>
975
</pre>
976 152 Nico Schottelius
977 139 Nico Schottelius
h2. Rook + Ceph
978
979
h3. Installation
980
981
* Usually directly via argocd
982
983 71 Nico Schottelius
h3. Executing ceph commands
984
985
Using the ceph-tools pod as follows:
986
987
<pre>
988
kubectl exec -n rook-ceph -ti $(kubectl -n rook-ceph get pods -l app=rook-ceph-tools -o jsonpath='{.items[*].metadata.name}') -- ceph -s
989
</pre>
990
991 43 Nico Schottelius
h3. Inspecting the logs of a specific server
992
993
<pre>
994
# Get the related pods
995
kubectl -n rook-ceph get pods -l app=rook-ceph-osd-prepare 
996
...
997
998
# Inspect the logs of a specific pod
999
kubectl -n rook-ceph logs -f rook-ceph-osd-prepare-server23--1-444qx
1000
1001 71 Nico Schottelius
</pre>
1002
1003
h3. Inspecting the logs of the rook-ceph-operator
1004
1005
<pre>
1006
kubectl -n rook-ceph logs -f -l app=rook-ceph-operator
1007 43 Nico Schottelius
</pre>
1008
1009 200 Nico Schottelius
h3. (Temporarily) Disabling the rook-operation
1010
1011
* first disabling the sync in argocd
1012
* then scale it down
1013
1014
<pre>
1015
kubectl -n rook-ceph scale deployment rook-ceph-operator --replicas=0
1016
</pre>
1017
1018
When done with the work/maintenance, re-enable sync in argocd.
1019
The following command is thus strictly speaking not required, as argocd will fix it on its own:
1020
1021
<pre>
1022
kubectl -n rook-ceph scale deployment rook-ceph-operator --replicas=1
1023
</pre>
1024
1025 121 Nico Schottelius
h3. Restarting the rook operator
1026
1027
<pre>
1028
kubectl -n rook-ceph delete pods  -l app=rook-ceph-operator
1029
</pre>
1030
1031 43 Nico Schottelius
h3. Triggering server prepare / adding new osds
1032
1033
The rook-ceph-operator triggers/watches/creates pods to maintain hosts. To trigger a full "re scan", simply delete that pod:
1034
1035
<pre>
1036
kubectl -n rook-ceph delete pods -l app=rook-ceph-operator
1037
</pre>
1038
1039
This will cause all the @rook-ceph-osd-prepare-..@ jobs to be recreated and thus OSDs to be created, if new disks have been added.
1040
1041
h3. Removing an OSD
1042
1043
* See "Ceph OSD Management":https://rook.io/docs/rook/v1.7/ceph-osd-mgmt.html
1044 77 Nico Schottelius
* More specifically: https://github.com/rook/rook/blob/release-1.7/cluster/examples/kubernetes/ceph/osd-purge.yaml
1045 99 Nico Schottelius
* Then delete the related deployment
1046 41 Nico Schottelius
1047 98 Nico Schottelius
Set osd id in the osd-purge.yaml and apply it. OSD should be down before.
1048
1049
<pre>
1050
apiVersion: batch/v1
1051
kind: Job
1052
metadata:
1053
  name: rook-ceph-purge-osd
1054
  namespace: rook-ceph # namespace:cluster
1055
  labels:
1056
    app: rook-ceph-purge-osd
1057
spec:
1058
  template:
1059
    metadata:
1060
      labels:
1061
        app: rook-ceph-purge-osd
1062
    spec:
1063
      serviceAccountName: rook-ceph-purge-osd
1064
      containers:
1065
        - name: osd-removal
1066
          image: rook/ceph:master
1067
          # TODO: Insert the OSD ID in the last parameter that is to be removed
1068
          # The OSD IDs are a comma-separated list. For example: "0" or "0,2".
1069
          # If you want to preserve the OSD PVCs, set `--preserve-pvc true`.
1070
          #
1071
          # A --force-osd-removal option is available if the OSD should be destroyed even though the
1072
          # removal could lead to data loss.
1073
          args:
1074
            - "ceph"
1075
            - "osd"
1076
            - "remove"
1077
            - "--preserve-pvc"
1078
            - "false"
1079
            - "--force-osd-removal"
1080
            - "false"
1081
            - "--osd-ids"
1082
            - "SETTHEOSDIDHERE"
1083
          env:
1084
            - name: POD_NAMESPACE
1085
              valueFrom:
1086
                fieldRef:
1087
                  fieldPath: metadata.namespace
1088
            - name: ROOK_MON_ENDPOINTS
1089
              valueFrom:
1090
                configMapKeyRef:
1091
                  key: data
1092
                  name: rook-ceph-mon-endpoints
1093
            - name: ROOK_CEPH_USERNAME
1094
              valueFrom:
1095
                secretKeyRef:
1096
                  key: ceph-username
1097
                  name: rook-ceph-mon
1098
            - name: ROOK_CEPH_SECRET
1099
              valueFrom:
1100
                secretKeyRef:
1101
                  key: ceph-secret
1102
                  name: rook-ceph-mon
1103
            - name: ROOK_CONFIG_DIR
1104
              value: /var/lib/rook
1105
            - name: ROOK_CEPH_CONFIG_OVERRIDE
1106
              value: /etc/rook/config/override.conf
1107
            - name: ROOK_FSID
1108
              valueFrom:
1109
                secretKeyRef:
1110
                  key: fsid
1111
                  name: rook-ceph-mon
1112
            - name: ROOK_LOG_LEVEL
1113
              value: DEBUG
1114
          volumeMounts:
1115
            - mountPath: /etc/ceph
1116
              name: ceph-conf-emptydir
1117
            - mountPath: /var/lib/rook
1118
              name: rook-config
1119
      volumes:
1120
        - emptyDir: {}
1121
          name: ceph-conf-emptydir
1122
        - emptyDir: {}
1123
          name: rook-config
1124
      restartPolicy: Never
1125
1126
1127 99 Nico Schottelius
</pre>
1128
1129 1 Nico Schottelius
Deleting the deployment:
1130
1131
<pre>
1132
[18:05] bridge:~% kubectl -n rook-ceph delete deployment rook-ceph-osd-6
1133 99 Nico Schottelius
deployment.apps "rook-ceph-osd-6" deleted
1134
</pre>
1135 185 Nico Schottelius
1136
h3. Placement of mons/osds/etc.
1137
1138
See https://rook.io/docs/rook/v1.11/CRDs/Cluster/ceph-cluster-crd/#placement-configuration-settings
1139 98 Nico Schottelius
1140 145 Nico Schottelius
h2. Ingress + Cert Manager
1141
1142
* We deploy "nginx-ingress":https://docs.nginx.com/nginx-ingress-controller/ to get an ingress
1143
* we deploy "cert-manager":https://cert-manager.io/ to handle certificates
1144
* We independently deploy @ClusterIssuer@ to allow the cert-manager app to deploy and the issuer to be created once the CRDs from cert manager are in place
1145
1146
h3. IPv4 reachability 
1147
1148
The ingress is by default IPv6 only. To make it reachable from the IPv4 world, get its IPv6 address and configure a NAT64 mapping in Jool.
1149
1150
Steps:
1151
1152
h4. Get the ingress IPv6 address
1153
1154
Use @kubectl -n ingress-nginx get svc ingress-nginx-controller -o jsonpath='{.spec.clusterIP}'; echo ''@
1155
1156
Example:
1157
1158
<pre>
1159
kubectl -n ingress-nginx get svc ingress-nginx-controller -o jsonpath='{.spec.clusterIP}'; echo ''
1160
2a0a:e5c0:10:1b::ce11
1161
</pre>
1162
1163
h4. Add NAT64 mapping
1164
1165
* Update the __dcl_jool_siit cdist type
1166
* Record the two IPs (IPv6 and IPv4)
1167
* Configure all routers
1168
1169
1170
h4. Add DNS record
1171
1172
To use the ingress capable as a CNAME destination, create an "ingress" DNS record, such as:
1173
1174
<pre>
1175
; k8s ingress for dev
1176
dev-ingress                 AAAA 2a0a:e5c0:10:1b::ce11
1177
dev-ingress                 A 147.78.194.23
1178
1179
</pre> 
1180
1181
h4. Add supporting wildcard DNS
1182
1183
If you plan to add various sites under a specific domain, we can add a wildcard DNS entry, such as *.k8s-dev.django-hosting.ch:
1184
1185
<pre>
1186
*.k8s-dev         CNAME dev-ingress.ungleich.ch.
1187
</pre>
1188
1189 76 Nico Schottelius
h2. Harbor
1190
1191 175 Nico Schottelius
* We user "Harbor":https://goharbor.io/ as an image registry for our own images. Internal app reference: apps/prod/harbor.
1192
* The admin password is in the password store, it is Harbor12345 by default
1193 76 Nico Schottelius
* At the moment harbor only authenticates against the internal ldap tree
1194
1195
h3. LDAP configuration
1196
1197
* The url needs to be ldaps://...
1198
* uid = uid
1199
* rest standard
1200 75 Nico Schottelius
1201 89 Nico Schottelius
h2. Monitoring / Prometheus
1202
1203 90 Nico Schottelius
* Via "kube-prometheus":https://github.com/prometheus-operator/kube-prometheus/
1204 89 Nico Schottelius
1205 91 Nico Schottelius
Access via ...
1206
1207
* http://prometheus-k8s.monitoring.svc:9090
1208
* http://grafana.monitoring.svc:3000
1209
* http://alertmanager.monitoring.svc:9093
1210
1211
1212 100 Nico Schottelius
h3. Prometheus Options
1213
1214
* "helm/kube-prometheus-stack":https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack
1215
** Includes dashboards and co.
1216
* "manifest based kube-prometheus":https://github.com/prometheus-operator/kube-prometheus
1217
** Includes dashboards and co.
1218
* "Prometheus Operator (mainly CRD manifest":https://github.com/prometheus-operator/prometheus-operator
1219
1220 171 Nico Schottelius
h3. Grafana default password
1221
1222
* If not changed: @prom-operator@
1223
1224 82 Nico Schottelius
h2. Nextcloud
1225
1226 85 Nico Schottelius
h3. How to get the nextcloud credentials 
1227 84 Nico Schottelius
1228
* The initial username is set to "nextcloud"
1229
* The password is autogenerated and saved in a kubernetes secret
1230
1231
<pre>
1232 85 Nico Schottelius
kubectl get secret RELEASENAME-nextcloud -o jsonpath="{.data.PASSWORD}" | base64 -d; echo "" 
1233 84 Nico Schottelius
</pre>
1234
1235 83 Nico Schottelius
h3. How to fix "Access through untrusted domain"
1236
1237 82 Nico Schottelius
* Nextcloud stores the initial domain configuration
1238 1 Nico Schottelius
* If the FQDN is changed, it will show the error message "Access through untrusted domain"
1239 82 Nico Schottelius
* To fix, edit /var/www/html/config/config.php and correct the domain
1240 1 Nico Schottelius
* Then delete the pods
1241 165 Nico Schottelius
1242
h3. Running occ commands inside the nextcloud container
1243
1244
* Find the pod in the right namespace
1245
1246
Exec:
1247
1248
<pre>
1249
su www-data -s /bin/sh -c ./occ
1250
</pre>
1251
1252
* -s /bin/sh is needed as the default shell is set to /bin/false
1253
1254 166 Nico Schottelius
h4. Rescanning files
1255 165 Nico Schottelius
1256 166 Nico Schottelius
* If files have been added without nextcloud's knowledge
1257
1258
<pre>
1259
su www-data -s /bin/sh -c "./occ files:scan --all"
1260
</pre>
1261 82 Nico Schottelius
1262 201 Nico Schottelius
h2. Sealed Secrets
1263
1264 202 Jin-Guk Kwon
* install kubeseal
1265 1 Nico Schottelius
1266 202 Jin-Guk Kwon
<pre>
1267
KUBESEAL_VERSION='0.23.0'
1268
wget "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION:?}/kubeseal-${KUBESEAL_VERSION:?}-linux-amd64.tar.gz" 
1269
tar -xvzf kubeseal-${KUBESEAL_VERSION:?}-linux-amd64.tar.gz kubeseal
1270
sudo install -m 755 kubeseal /usr/local/bin/kubeseal
1271
</pre>
1272
1273
* create key for sealed-secret
1274
1275
<pre>
1276
kubeseal --fetch-cert > /tmp/public-key-cert.pem
1277
</pre>
1278
1279
* create the secret
1280
1281
<pre>
1282 203 Jin-Guk Kwon
ex)
1283 202 Jin-Guk Kwon
apiVersion: v1
1284
kind: Secret
1285
metadata:
1286
  name: Release.Name-postgres-config
1287
  annotations:
1288
    secret-generator.v1.mittwald.de/autogenerate: POSTGRES_PASSWORD
1289
    hosting: Release.Name
1290
  labels:
1291
    app.kubernetes.io/instance: Release.Name
1292
    app.kubernetes.io/component: postgres
1293
stringData:
1294
  POSTGRES_USER: postgresUser
1295
  POSTGRES_DB: postgresDBName
1296
  POSTGRES_INITDB_ARGS: "--no-locale --encoding=UTF8"
1297
</pre>
1298
1299
* convert secret.yaml to sealed-secret.yaml
1300
1301
<pre>
1302
kubeseal -n <namespace> --cert=/tmp/public-key-cert.pem --format=yaml < ./secret.yaml  > ./sealed-secret.yaml
1303
</pre>
1304
1305
* use sealed-secret.yaml on helm-chart directory
1306 201 Nico Schottelius
1307 205 Jin-Guk Kwon
* refer ticket : #11989 , #12120
1308 204 Jin-Guk Kwon
1309 1 Nico Schottelius
h2. Infrastructure versions
1310 35 Nico Schottelius
1311 57 Nico Schottelius
h3. ungleich kubernetes infrastructure v5 (2021-10)
1312 1 Nico Schottelius
1313 57 Nico Schottelius
Clusters are configured / setup in this order:
1314
1315
* Bootstrap via kubeadm
1316 59 Nico Schottelius
* "Networking via calico + BGP (non ECMP) using helm":https://docs.projectcalico.org/getting-started/kubernetes/helm
1317
* "ArgoCD for CD":https://argo-cd.readthedocs.io/en/stable/
1318
** "rook for storage via argocd":https://rook.io/
1319 58 Nico Schottelius
** haproxy for in IPv6-cluster-IPv4-to-IPv6 proxy via argocd
1320
** "kubernetes-secret-generator for in cluster secrets":https://github.com/mittwald/kubernetes-secret-generator
1321
** "ungleich-certbot managing certs and nginx":https://hub.docker.com/repository/docker/ungleich/ungleich-certbot
1322
1323 57 Nico Schottelius
1324
h3. ungleich kubernetes infrastructure v4 (2021-09)
1325
1326 54 Nico Schottelius
* rook is configured via manifests instead of using the rook-ceph-cluster helm chart
1327 1 Nico Schottelius
* The rook operator is still being installed via helm
1328 35 Nico Schottelius
1329 57 Nico Schottelius
h3. ungleich kubernetes infrastructure v3 (2021-07)
1330 1 Nico Schottelius
1331 10 Nico Schottelius
* rook is now installed via helm via argocd instead of directly via manifests
1332 28 Nico Schottelius
1333 57 Nico Schottelius
h3. ungleich kubernetes infrastructure v2 (2021-05)
1334 28 Nico Schottelius
1335
* Replaced fluxv2 from ungleich k8s v1 with argocd
1336 1 Nico Schottelius
** argocd can apply helm templates directly without needing to go through Chart releases
1337 28 Nico Schottelius
* We are also using argoflow for build flows
1338
* Planned to add "kaniko":https://github.com/GoogleContainerTools/kaniko for image building
1339
1340 57 Nico Schottelius
h3. ungleich kubernetes infrastructure v1 (2021-01)
1341 28 Nico Schottelius
1342
We are using the following components:
1343
1344
* "Calico as a CNI":https://www.projectcalico.org/ with BGP, IPv6 only, no encapsulation
1345
** Needed for basic networking
1346
* "kubernetes-secret-generator":https://github.com/mittwald/kubernetes-secret-generator for creating secrets
1347
** Needed so that secrets are not stored in the git repository, but only in the cluster
1348
* "ungleich-certbot":https://hub.docker.com/repository/docker/ungleich/ungleich-certbot
1349
** Needed to get letsencrypt certificates for services
1350
* "rook with ceph rbd + cephfs":https://rook.io/ for storage
1351
** rbd for almost everything, *ReadWriteOnce*
1352
** cephfs for smaller things, multi access *ReadWriteMany*
1353
** Needed for providing persistent storage
1354
* "flux v2":https://fluxcd.io/
1355
** Needed to manage resources automatically