Project

General

Profile

The ungleich kubernetes infrastructure » History » Version 212

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