Project

General

Profile

The ungleich kubernetes infrastructure » History » Version 118

Nico Schottelius, 07/08/2022 11:20 AM

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 28 Nico Schottelius
This document is **pre-production**.
8
This document is to become 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 111 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
| [[p6.k8s.ooo]]    | production        |            | server67 server69 server71    | "argo":https://argocd-server.argocd.svc.p6.k8s.ooo    | 147.78.194.13 |    2021-10-05 |
22
| [[p10.k8s.ooo]]   | production        |            | server63 server65 server83    | "argo":https://argocd-server.argocd.svc.p10.k8s.ooo   | 147.78.194.12 |    2021-10-05 |
23
| [[k8s.ge.nau.so]] | development       |            | server107 server108 server109 | "argo":https://argocd-server.argocd.svc.k8s.ge.nau.so |               |               |
24 110 Nico Schottelius
25 21 Nico Schottelius
26 1 Nico Schottelius
h2. General architecture and components overview
27
28
* All k8s clusters are IPv6 only
29
* We use BGP peering to propagate podcidr and serviceCidr networks to our infrastructure
30
* The main public testing repository is "ungleich-k8s":https://code.ungleich.ch/ungleich-public/ungleich-k8s
31 18 Nico Schottelius
** Private configurations are found in the **k8s-config** repository
32 1 Nico Schottelius
33
h3. Cluster types
34
35 28 Nico Schottelius
| **Type/Feature**            | **Development**                | **Production**         |
36
| Min No. nodes               | 3 (1 master, 3 worker)         | 5 (3 master, 3 worker) |
37
| Recommended minimum         | 4 (dedicated master, 3 worker) | 8 (3 master, 5 worker) |
38
| Separation of control plane | optional                       | recommended            |
39
| Persistent storage          | required                       | required               |
40
| Number of storage monitors  | 3                              | 5                      |
41 1 Nico Schottelius
42 43 Nico Schottelius
h2. General k8s operations
43 1 Nico Schottelius
44 46 Nico Schottelius
h3. Cheat sheet / external great references
45
46
* "kubectl cheatsheet":https://kubernetes.io/docs/reference/kubectl/cheatsheet/
47
48 117 Nico Schottelius
h3. Allowing to schedule work on the control plane / removing node taints
49 69 Nico Schottelius
50
* Mostly for single node / test / development clusters
51
* Just remove the master taint as follows
52
53
<pre>
54
kubectl taint nodes --all node-role.kubernetes.io/master-
55 118 Nico Schottelius
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
56 69 Nico Schottelius
</pre>
57 1 Nico Schottelius
58 117 Nico Schottelius
You can check the node taints using @kubectl describe node ...@
59 69 Nico Schottelius
60 44 Nico Schottelius
h3. Get the cluster admin.conf
61
62
* On the masters of each cluster you can find the file @/etc/kubernetes/admin.conf@
63
* To be able to administrate the cluster you can copy the admin.conf to your local machine
64
* Multi cluster debugging can very easy if you name the config ~/cX-admin.conf (see example below)
65
66
<pre>
67
% scp root@server47.place7.ungleich.ch:/etc/kubernetes/admin.conf ~/c2-admin.conf
68
% export KUBECONFIG=~/c2-admin.conf    
69
% kubectl get nodes
70
NAME       STATUS                     ROLES                  AGE   VERSION
71
server47   Ready                      control-plane,master   82d   v1.22.0
72
server48   Ready                      control-plane,master   82d   v1.22.0
73
server49   Ready                      <none>                 82d   v1.22.0
74
server50   Ready                      <none>                 82d   v1.22.0
75
server59   Ready                      control-plane,master   82d   v1.22.0
76
server60   Ready,SchedulingDisabled   <none>                 82d   v1.22.0
77
server61   Ready                      <none>                 82d   v1.22.0
78
server62   Ready                      <none>                 82d   v1.22.0               
79
</pre>
80
81 18 Nico Schottelius
h3. Installing a new k8s cluster
82 8 Nico Schottelius
83 9 Nico Schottelius
* Decide on the cluster name (usually *cX.k8s.ooo*), X counting upwards
84 28 Nico Schottelius
** Using pXX.k8s.ooo for production clusters of placeXX
85 9 Nico Schottelius
* Use cdist to configure the nodes with requirements like crio
86
* Decide between single or multi node control plane setups (see below)
87 28 Nico Schottelius
** Single control plane suitable for development clusters
88 9 Nico Schottelius
89 28 Nico Schottelius
Typical init procedure:
90 9 Nico Schottelius
91 28 Nico Schottelius
* Single control plane: @kubeadm init --config bootstrap/XXX/kubeadm.yaml@
92
* Multi control plane (HA): @kubeadm init --config bootstrap/XXX/kubeadm.yaml --upload-certs@
93 10 Nico Schottelius
94 29 Nico Schottelius
h3. Deleting a pod that is hanging in terminating state
95
96
<pre>
97
kubectl delete pod <PODNAME> --grace-period=0 --force --namespace <NAMESPACE>
98
</pre>
99
100
(from https://stackoverflow.com/questions/35453792/pods-stuck-in-terminating-status)
101
102 42 Nico Schottelius
h3. Listing nodes of a cluster
103
104
<pre>
105
[15:05] bridge:~% kubectl get nodes
106
NAME       STATUS   ROLES                  AGE   VERSION
107
server22   Ready    <none>                 52d   v1.22.0
108
server23   Ready    <none>                 52d   v1.22.2
109
server24   Ready    <none>                 52d   v1.22.0
110
server25   Ready    <none>                 52d   v1.22.0
111
server26   Ready    <none>                 52d   v1.22.0
112
server27   Ready    <none>                 52d   v1.22.0
113
server63   Ready    control-plane,master   52d   v1.22.0
114
server64   Ready    <none>                 52d   v1.22.0
115
server65   Ready    control-plane,master   52d   v1.22.0
116
server66   Ready    <none>                 52d   v1.22.0
117
server83   Ready    control-plane,master   52d   v1.22.0
118
server84   Ready    <none>                 52d   v1.22.0
119
server85   Ready    <none>                 52d   v1.22.0
120
server86   Ready    <none>                 52d   v1.22.0
121
</pre>
122
123 41 Nico Schottelius
h3. Removing / draining a node
124
125
Usually @kubectl drain server@ should do the job, but sometimes we need to be more aggressive:
126
127 1 Nico Schottelius
<pre>
128 103 Nico Schottelius
kubectl drain --delete-emptydir-data --ignore-daemonsets serverXX
129 42 Nico Schottelius
</pre>
130
131
h3. Readding a node after draining
132
133
<pre>
134
kubectl uncordon serverXX
135 1 Nico Schottelius
</pre>
136 43 Nico Schottelius
137 50 Nico Schottelius
h3. (Re-)joining worker nodes after creating the cluster
138 49 Nico Schottelius
139
* We need to have an up-to-date token
140
* We use different join commands for the workers and control plane nodes
141
142
Generating the join command on an existing control plane node:
143
144
<pre>
145
kubeadm token create --print-join-command
146
</pre>
147
148 50 Nico Schottelius
h3. (Re-)joining control plane nodes after creating the cluster
149 1 Nico Schottelius
150 50 Nico Schottelius
* We generate the token again
151
* We upload the certificates
152
* We need to combine/create the join command for the control plane node
153
154
Example session:
155
156
<pre>
157
% kubeadm token create --print-join-command
158
kubeadm join p10-api.k8s.ooo:6443 --token xmff4i.ABC --discovery-token-ca-cert-hash sha256:longhash 
159
160
% kubeadm init phase upload-certs --upload-certs
161
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
162
[upload-certs] Using certificate key:
163
CERTKEY
164
165
# Then we use these two outputs on the joining node:
166
167
kubeadm join p10-api.k8s.ooo:6443 --token xmff4i.ABC --discovery-token-ca-cert-hash sha256:longhash --control-plane --certificate-key CERTKEY
168
</pre>
169
170
Commands to be used on a control plane node:
171
172
<pre>
173
kubeadm token create --print-join-command
174
kubeadm init phase upload-certs --upload-certs
175
</pre>
176
177
Commands to be used on the joining node:
178
179
<pre>
180
JOINCOMMAND --control-plane --certificate-key CERTKEY
181
</pre>
182 49 Nico Schottelius
183 51 Nico Schottelius
SEE ALSO
184
185
* https://stackoverflow.com/questions/63936268/how-to-generate-kubeadm-token-for-secondary-control-plane-nodes
186
* https://blog.scottlowe.org/2019/08/15/reconstructing-the-join-command-for-kubeadm/
187
188 53 Nico Schottelius
h3. How to fix etcd does not start when rejoining a kubernetes cluster as a control plane
189 52 Nico Schottelius
190
If during the above step etcd does not come up, @kubeadm join@ can hang as follows:
191
192
<pre>
193
[control-plane] Creating static Pod manifest for "kube-apiserver"                                                              
194
[control-plane] Creating static Pod manifest for "kube-controller-manager"                                                     
195
[control-plane] Creating static Pod manifest for "kube-scheduler"                                                              
196
[check-etcd] Checking that the etcd cluster is healthy                                                                         
197
error execution phase check-etcd: etcd cluster is not healthy: failed to dial endpoint https://[2a0a:e5c0:10:1:225:b3ff:fe20:37
198
8a]:2379 with maintenance client: context deadline exceeded                                                                    
199
To see the stack trace of this error execute with --v=5 or higher         
200
</pre>
201
202
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.
203
204
To fix this we do:
205
206
* Find a working etcd pod
207
* Find the etcd members / member list
208
* Remove the etcd member that we want to re-join the cluster
209
210
211
<pre>
212
# Find the etcd pods
213
kubectl -n kube-system get pods -l component=etcd,tier=control-plane
214
215
# Get the list of etcd servers with the member id 
216
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
217
218
# Remove the member
219
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
220
</pre>
221
222
Sample session:
223
224
<pre>
225
[10:48] line:~% kubectl -n kube-system get pods -l component=etcd,tier=control-plane
226
NAME            READY   STATUS    RESTARTS     AGE
227
etcd-server63   1/1     Running   0            3m11s
228
etcd-server65   1/1     Running   3            7d2h
229
etcd-server83   1/1     Running   8 (6d ago)   7d2h
230
[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
231
356891cd676df6e4, started, server65, https://[2a0a:e5c0:10:1:225:b3ff:fe20:375c]:2380, https://[2a0a:e5c0:10:1:225:b3ff:fe20:375c]:2379, false
232
371b8a07185dee7e, started, server63, https://[2a0a:e5c0:10:1:225:b3ff:fe20:378a]:2380, https://[2a0a:e5c0:10:1:225:b3ff:fe20:378a]:2379, false
233
5942bc58307f8af9, started, server83, https://[2a0a:e5c0:10:1:3e4a:92ff:fe79:bb98]:2380, https://[2a0a:e5c0:10:1:3e4a:92ff:fe79:bb98]:2379, false
234
235
[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
236
Member 371b8a07185dee7e removed from cluster e3c0805f592a8f77
237 1 Nico Schottelius
238
</pre>
239
240
SEE ALSO
241
242
* We found the solution using https://stackoverflow.com/questions/67921552/re-installed-node-cannot-join-kubernetes-cluster
243 56 Nico Schottelius
244 101 Nico Schottelius
h3. Hardware Maintenance using ungleich-hardware
245
246
Use the following manifest and replace the HOST with the actual host:
247
248
<pre>
249
apiVersion: v1
250
kind: Pod
251
metadata:
252
  name: ungleich-hardware-HOST
253
spec:
254
  containers:
255
  - name: ungleich-hardware
256
    image: ungleich/ungleich-hardware:0.0.5
257
    args:
258
    - sleep
259
    - "1000000"
260
    volumeMounts:
261
      - mountPath: /dev
262
        name: dev
263
    securityContext:
264
      privileged: true
265
  nodeSelector:
266
    kubernetes.io/hostname: "HOST"
267
268
  volumes:
269
    - name: dev
270
      hostPath:
271
        path: /dev
272
</pre>
273
274 102 Nico Schottelius
Also see: [[The_ungleich_hardware_maintenance_guide]]
275
276 105 Nico Schottelius
h3. Triggering a cronjob / creating a job from a cronjob
277 104 Nico Schottelius
278
To test a cronjob, we can create a job from a cronjob:
279
280
<pre>
281
kubectl create job --from=cronjob/volume2-daily-backup volume2-manual
282
</pre>
283
284
This creates a job volume2-manual based on the cronjob  volume2-daily
285
286 112 Nico Schottelius
h3. su-ing into a user that has nologin shell set
287
288
Many times users are having nologin as their shell inside the container. To be able to execute maintenance commands within the
289
container, we can use @su -s /bin/sh@ like this:
290
291
<pre>
292
su -s /bin/sh -c '/path/to/your/script' testuser
293
</pre>
294
295
Found on https://serverfault.com/questions/351046/how-to-run-command-as-user-who-has-usr-sbin-nologin-as-shell
296
297 113 Nico Schottelius
h3. How to print a secret value
298
299
Assuming you want the "password" item from a secret, use:
300
301
<pre>
302
kubectl get secret SECRETNAME -o jsonpath="{.data.password}" | base64 -d; echo "" 
303
</pre>
304
305 62 Nico Schottelius
h2. Calico CNI
306
307
h3. Calico Installation
308
309
* We install "calico using helm":https://docs.projectcalico.org/getting-started/kubernetes/helm
310
* This has the following advantages:
311
** Easy to upgrade
312
** Does not require os to configure IPv6/dual stack settings as the tigera operator figures out things on its own
313
314
Usually plain calico can be installed directly using:
315
316
<pre>
317
helm repo add projectcalico https://docs.projectcalico.org/charts
318 114 Jin-Guk Kwon
helm install --namespace tigera calico projectcalico/tigera-operator --version v3.23.2 --create-namespace
319 1 Nico Schottelius
</pre>
320 92 Nico Schottelius
321
* Check the tags on https://github.com/projectcalico/calico/tags for the latest release
322 62 Nico Schottelius
323
h3. Installing calicoctl
324
325 115 Nico Schottelius
* General installation instructions, including binary download: https://projectcalico.docs.tigera.io/maintenance/clis/calicoctl/install
326
327 62 Nico Schottelius
To be able to manage and configure calico, we need to 
328
"install calicoctl (we choose the version as a pod)":https://docs.projectcalico.org/getting-started/clis/calicoctl/install#install-calicoctl-as-a-kubernetes-pod
329
330
<pre>
331
kubectl apply -f https://docs.projectcalico.org/manifests/calicoctl.yaml
332
</pre>
333
334 93 Nico Schottelius
Or version specific:
335
336
<pre>
337
kubectl apply -f https://github.com/projectcalico/calico/blob/v3.20.4/manifests/calicoctl.yaml
338 97 Nico Schottelius
339
# For 3.22
340
kubectl apply -f https://projectcalico.docs.tigera.io/archive/v3.22/manifests/calicoctl.yaml
341 93 Nico Schottelius
</pre>
342
343 70 Nico Schottelius
And making it easier accessible by alias:
344
345
<pre>
346
alias calicoctl="kubectl exec -i -n kube-system calicoctl -- /calicoctl"
347
</pre>
348
349 62 Nico Schottelius
h3. Calico configuration
350
351 63 Nico Schottelius
By default our k8s clusters "BGP peer":https://docs.projectcalico.org/networking/bgp
352
with an upstream router to propagate podcidr and servicecidr.
353 62 Nico Schottelius
354
Default settings in our infrastructure:
355
356
* We use a full-mesh using the @nodeToNodeMeshEnabled: true@ option
357
* We keep the original next hop so that *only* the server with the pod is announcing it (instead of ecmp)
358 1 Nico Schottelius
* We use private ASNs for k8s clusters
359 63 Nico Schottelius
* We do *not* use any overlay
360 62 Nico Schottelius
361
After installing calico and calicoctl the last step of the installation is usually:
362
363 1 Nico Schottelius
<pre>
364 79 Nico Schottelius
calicoctl create -f - < calico-bgp.yaml
365 62 Nico Schottelius
</pre>
366
367
368
A sample BGP configuration:
369
370
<pre>
371
---
372
apiVersion: projectcalico.org/v3
373
kind: BGPConfiguration
374
metadata:
375
  name: default
376
spec:
377
  logSeverityScreen: Info
378
  nodeToNodeMeshEnabled: true
379
  asNumber: 65534
380
  serviceClusterIPs:
381
  - cidr: 2a0a:e5c0:10:3::/108
382
  serviceExternalIPs:
383
  - cidr: 2a0a:e5c0:10:3::/108
384
---
385
apiVersion: projectcalico.org/v3
386
kind: BGPPeer
387
metadata:
388
  name: router1-place10
389
spec:
390
  peerIP: 2a0a:e5c0:10:1::50
391
  asNumber: 213081
392
  keepOriginalNextHop: true
393
</pre>
394
395 64 Nico Schottelius
h2. ArgoCD / ArgoWorkFlow
396 56 Nico Schottelius
397 60 Nico Schottelius
h3. Argocd Installation
398 1 Nico Schottelius
399 116 Nico Schottelius
* See https://argo-cd.readthedocs.io/en/stable/
400
401 60 Nico Schottelius
As there is no configuration management present yet, argocd is installed using
402
403 1 Nico Schottelius
<pre>
404 60 Nico Schottelius
kubectl create namespace argocd
405 86 Nico Schottelius
406 96 Nico Schottelius
# Specific Version
407
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.3.2/manifests/install.yaml
408 86 Nico Schottelius
409
# OR: latest stable
410 60 Nico Schottelius
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
411 56 Nico Schottelius
</pre>
412 1 Nico Schottelius
413 116 Nico Schottelius
414 1 Nico Schottelius
415 60 Nico Schottelius
h3. Get the argocd credentials
416
417
<pre>
418
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo ""
419
</pre>
420 52 Nico Schottelius
421 87 Nico Schottelius
h3. Accessing argocd
422
423
In regular IPv6 clusters:
424
425
* Navigate to https://argocd-server.argocd.CLUSTERDOMAIN
426
427
In legacy IPv4 clusters
428
429
<pre>
430
kubectl --namespace argocd port-forward svc/argocd-server 8080:80
431
</pre>
432
433 88 Nico Schottelius
* Navigate to https://localhost:8080
434
435 68 Nico Schottelius
h3. Using the argocd webhook to trigger changes
436 67 Nico Schottelius
437
* To trigger changes post json https://argocd.example.com/api/webhook
438
439 72 Nico Schottelius
h3. Deploying an application
440
441
* Applications are deployed via git towards gitea (code.ungleich.ch) and then pulled by argo
442 73 Nico Schottelius
* Always include the *redmine-url* pointing to the (customer) ticket
443
** Also add the support-url if it exists
444 72 Nico Schottelius
445
Application sample
446
447
<pre>
448
apiVersion: argoproj.io/v1alpha1
449
kind: Application
450
metadata:
451
  name: gitea-CUSTOMER
452
  namespace: argocd
453
spec:
454
  destination:
455
    namespace: default
456
    server: 'https://kubernetes.default.svc'
457
  source:
458
    path: apps/prod/gitea
459
    repoURL: 'https://code.ungleich.ch/ungleich-intern/k8s-config.git'
460
    targetRevision: HEAD
461
    helm:
462
      parameters:
463
        - name: storage.data.storageClass
464
          value: rook-ceph-block-hdd
465
        - name: storage.data.size
466
          value: 200Gi
467
        - name: storage.db.storageClass
468
          value: rook-ceph-block-ssd
469
        - name: storage.db.size
470
          value: 10Gi
471
        - name: storage.letsencrypt.storageClass
472
          value: rook-ceph-block-hdd
473
        - name: storage.letsencrypt.size
474
          value: 50Mi
475
        - name: letsencryptStaging
476
          value: 'no'
477
        - name: fqdn
478
          value: 'code.verua.online'
479
  project: default
480
  syncPolicy:
481
    automated:
482
      prune: true
483
      selfHeal: true
484
  info:
485
    - name: 'redmine-url'
486
      value: 'https://redmine.ungleich.ch/issues/ISSUEID'
487
    - name: 'support-url'
488
      value: 'https://support.ungleich.ch/Ticket/Display.html?id=TICKETID'
489
</pre>
490
491 80 Nico Schottelius
h2. Helm related operations and conventions
492 55 Nico Schottelius
493 61 Nico Schottelius
We use helm charts extensively.
494
495
* In production, they are managed via argocd
496
* In development, helm chart can de developed and deployed manually using the helm utility.
497
498 55 Nico Schottelius
h3. Installing a helm chart
499
500
One can use the usual pattern of
501
502
<pre>
503
helm install <releasename> <chartdirectory>
504
</pre>
505
506
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:
507
508
<pre>
509
helm upgrade --install <releasename> <chartdirectory>
510 1 Nico Schottelius
</pre>
511 80 Nico Schottelius
512
h3. Naming services and deployments in helm charts [Application labels]
513
514
* We always have {{ .Release.Name }} to identify the current "instance"
515
* Deployments:
516
** use @app: <what it is>@, f.i. @app: nginx@, @app: postgres@, ...
517 81 Nico Schottelius
* See more about standard labels on
518
** https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
519
** https://helm.sh/docs/chart_best_practices/labels/
520 55 Nico Schottelius
521 43 Nico Schottelius
h2. Rook / Ceph Related Operations
522
523 71 Nico Schottelius
h3. Executing ceph commands
524
525
Using the ceph-tools pod as follows:
526
527
<pre>
528
kubectl exec -n rook-ceph -ti $(kubectl -n rook-ceph get pods -l app=rook-ceph-tools -o jsonpath='{.items[*].metadata.name}') -- ceph -s
529
</pre>
530
531 43 Nico Schottelius
h3. Inspecting the logs of a specific server
532
533
<pre>
534
# Get the related pods
535
kubectl -n rook-ceph get pods -l app=rook-ceph-osd-prepare 
536
...
537
538
# Inspect the logs of a specific pod
539
kubectl -n rook-ceph logs -f rook-ceph-osd-prepare-server23--1-444qx
540
541 71 Nico Schottelius
</pre>
542
543
h3. Inspecting the logs of the rook-ceph-operator
544
545
<pre>
546
kubectl -n rook-ceph logs -f -l app=rook-ceph-operator
547 43 Nico Schottelius
</pre>
548
549
h3. Triggering server prepare / adding new osds
550
551
The rook-ceph-operator triggers/watches/creates pods to maintain hosts. To trigger a full "re scan", simply delete that pod:
552
553
<pre>
554
kubectl -n rook-ceph delete pods -l app=rook-ceph-operator
555
</pre>
556
557
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.
558
559
h3. Removing an OSD
560
561
* See "Ceph OSD Management":https://rook.io/docs/rook/v1.7/ceph-osd-mgmt.html
562 77 Nico Schottelius
* More specifically: https://github.com/rook/rook/blob/release-1.7/cluster/examples/kubernetes/ceph/osd-purge.yaml
563 99 Nico Schottelius
* Then delete the related deployment
564 41 Nico Schottelius
565 98 Nico Schottelius
Set osd id in the osd-purge.yaml and apply it. OSD should be down before.
566
567
<pre>
568
apiVersion: batch/v1
569
kind: Job
570
metadata:
571
  name: rook-ceph-purge-osd
572
  namespace: rook-ceph # namespace:cluster
573
  labels:
574
    app: rook-ceph-purge-osd
575
spec:
576
  template:
577
    metadata:
578
      labels:
579
        app: rook-ceph-purge-osd
580
    spec:
581
      serviceAccountName: rook-ceph-purge-osd
582
      containers:
583
        - name: osd-removal
584
          image: rook/ceph:master
585
          # TODO: Insert the OSD ID in the last parameter that is to be removed
586
          # The OSD IDs are a comma-separated list. For example: "0" or "0,2".
587
          # If you want to preserve the OSD PVCs, set `--preserve-pvc true`.
588
          #
589
          # A --force-osd-removal option is available if the OSD should be destroyed even though the
590
          # removal could lead to data loss.
591
          args:
592
            - "ceph"
593
            - "osd"
594
            - "remove"
595
            - "--preserve-pvc"
596
            - "false"
597
            - "--force-osd-removal"
598
            - "false"
599
            - "--osd-ids"
600
            - "SETTHEOSDIDHERE"
601
          env:
602
            - name: POD_NAMESPACE
603
              valueFrom:
604
                fieldRef:
605
                  fieldPath: metadata.namespace
606
            - name: ROOK_MON_ENDPOINTS
607
              valueFrom:
608
                configMapKeyRef:
609
                  key: data
610
                  name: rook-ceph-mon-endpoints
611
            - name: ROOK_CEPH_USERNAME
612
              valueFrom:
613
                secretKeyRef:
614
                  key: ceph-username
615
                  name: rook-ceph-mon
616
            - name: ROOK_CEPH_SECRET
617
              valueFrom:
618
                secretKeyRef:
619
                  key: ceph-secret
620
                  name: rook-ceph-mon
621
            - name: ROOK_CONFIG_DIR
622
              value: /var/lib/rook
623
            - name: ROOK_CEPH_CONFIG_OVERRIDE
624
              value: /etc/rook/config/override.conf
625
            - name: ROOK_FSID
626
              valueFrom:
627
                secretKeyRef:
628
                  key: fsid
629
                  name: rook-ceph-mon
630
            - name: ROOK_LOG_LEVEL
631
              value: DEBUG
632
          volumeMounts:
633
            - mountPath: /etc/ceph
634
              name: ceph-conf-emptydir
635
            - mountPath: /var/lib/rook
636
              name: rook-config
637
      volumes:
638
        - emptyDir: {}
639
          name: ceph-conf-emptydir
640
        - emptyDir: {}
641
          name: rook-config
642
      restartPolicy: Never
643
644
645 99 Nico Schottelius
</pre>
646
647
Deleting the deployment:
648
649
<pre>
650
[18:05] bridge:~% kubectl -n rook-ceph delete deployment rook-ceph-osd-6
651
deployment.apps "rook-ceph-osd-6" deleted
652 98 Nico Schottelius
</pre>
653
654 76 Nico Schottelius
h2. Harbor
655
656
* We user "Harbor":https://goharbor.io/ for caching and as an image registry. Internal app reference: apps/prod/harbor.
657
* The admin password is in the password store, auto generated per cluster
658
* At the moment harbor only authenticates against the internal ldap tree
659
660
h3. LDAP configuration
661
662
* The url needs to be ldaps://...
663
* uid = uid
664
* rest standard
665 75 Nico Schottelius
666 89 Nico Schottelius
h2. Monitoring / Prometheus
667
668 90 Nico Schottelius
* Via "kube-prometheus":https://github.com/prometheus-operator/kube-prometheus/
669 89 Nico Schottelius
670 91 Nico Schottelius
Access via ...
671
672
* http://prometheus-k8s.monitoring.svc:9090
673
* http://grafana.monitoring.svc:3000
674
* http://alertmanager.monitoring.svc:9093
675
676
677 100 Nico Schottelius
h3. Prometheus Options
678
679
* "helm/kube-prometheus-stack":https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack
680
** Includes dashboards and co.
681
* "manifest based kube-prometheus":https://github.com/prometheus-operator/kube-prometheus
682
** Includes dashboards and co.
683
* "Prometheus Operator (mainly CRD manifest":https://github.com/prometheus-operator/prometheus-operator
684
685 91 Nico Schottelius
686 82 Nico Schottelius
h2. Nextcloud
687
688 85 Nico Schottelius
h3. How to get the nextcloud credentials 
689 84 Nico Schottelius
690
* The initial username is set to "nextcloud"
691
* The password is autogenerated and saved in a kubernetes secret
692
693
<pre>
694 85 Nico Schottelius
kubectl get secret RELEASENAME-nextcloud -o jsonpath="{.data.PASSWORD}" | base64 -d; echo "" 
695 84 Nico Schottelius
</pre>
696
697 83 Nico Schottelius
h3. How to fix "Access through untrusted domain"
698
699 82 Nico Schottelius
* Nextcloud stores the initial domain configuration
700 1 Nico Schottelius
* If the FQDN is changed, it will show the error message "Access through untrusted domain"
701 82 Nico Schottelius
* To fix, edit /var/www/html/config/config.php and correct the domain
702 83 Nico Schottelius
* Then delete the pods
703 82 Nico Schottelius
704 1 Nico Schottelius
h2. Infrastructure versions
705 35 Nico Schottelius
706 57 Nico Schottelius
h3. ungleich kubernetes infrastructure v5 (2021-10)
707 1 Nico Schottelius
708 57 Nico Schottelius
Clusters are configured / setup in this order:
709
710
* Bootstrap via kubeadm
711 59 Nico Schottelius
* "Networking via calico + BGP (non ECMP) using helm":https://docs.projectcalico.org/getting-started/kubernetes/helm
712
* "ArgoCD for CD":https://argo-cd.readthedocs.io/en/stable/
713
** "rook for storage via argocd":https://rook.io/
714 58 Nico Schottelius
** haproxy for in IPv6-cluster-IPv4-to-IPv6 proxy via argocd
715
** "kubernetes-secret-generator for in cluster secrets":https://github.com/mittwald/kubernetes-secret-generator
716
** "ungleich-certbot managing certs and nginx":https://hub.docker.com/repository/docker/ungleich/ungleich-certbot
717
718 57 Nico Schottelius
719
h3. ungleich kubernetes infrastructure v4 (2021-09)
720
721 54 Nico Schottelius
* rook is configured via manifests instead of using the rook-ceph-cluster helm chart
722 1 Nico Schottelius
* The rook operator is still being installed via helm
723 35 Nico Schottelius
724 57 Nico Schottelius
h3. ungleich kubernetes infrastructure v3 (2021-07)
725 1 Nico Schottelius
726 10 Nico Schottelius
* rook is now installed via helm via argocd instead of directly via manifests
727 28 Nico Schottelius
728 57 Nico Schottelius
h3. ungleich kubernetes infrastructure v2 (2021-05)
729 28 Nico Schottelius
730
* Replaced fluxv2 from ungleich k8s v1 with argocd
731 1 Nico Schottelius
** argocd can apply helm templates directly without needing to go through Chart releases
732 28 Nico Schottelius
* We are also using argoflow for build flows
733
* Planned to add "kaniko":https://github.com/GoogleContainerTools/kaniko for image building
734
735 57 Nico Schottelius
h3. ungleich kubernetes infrastructure v1 (2021-01)
736 28 Nico Schottelius
737
We are using the following components:
738
739
* "Calico as a CNI":https://www.projectcalico.org/ with BGP, IPv6 only, no encapsulation
740
** Needed for basic networking
741
* "kubernetes-secret-generator":https://github.com/mittwald/kubernetes-secret-generator for creating secrets
742
** Needed so that secrets are not stored in the git repository, but only in the cluster
743
* "ungleich-certbot":https://hub.docker.com/repository/docker/ungleich/ungleich-certbot
744
** Needed to get letsencrypt certificates for services
745
* "rook with ceph rbd + cephfs":https://rook.io/ for storage
746
** rbd for almost everything, *ReadWriteOnce*
747
** cephfs for smaller things, multi access *ReadWriteMany*
748
** Needed for providing persistent storage
749
* "flux v2":https://fluxcd.io/
750
** Needed to manage resources automatically