docs: add Kubernetes CKS study notes

This commit is contained in:
2026-08-04 23:18:45 +02:00
parent a6ee7a2b07
commit 91a1849009
57 changed files with 8313 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
# Assignment
Nautilus developers need access to the last 24 hours of logs so that they can trace issues and bugs. Therefore, we need to ship the access and error logs for the web server to a log-aggregation service. Following the separation of concerns principle, we implement the Sidecar pattern by deploying a second container that ships the error and access logs from nginx. Nginx does one thing, and it does it well - serving web pages. The second container also specializes in its task - shipping logs. Since containers are running on the same Pod, we can use a shared emptyDir volume to read and write logs.
Create a pod named webserver.
Create an emptyDir volume named shared-logs.
Create a regular container in the webserver pod from the nginx:latest image named nginx-container, and an init container from the ubuntu:latest image named sidecar-container.
Add the following command to the sidecar-container "sh","-c","while true; do cat /var/log/nginx/access.log /var/log/nginx/error.log; sleep 30; done"
Mount the shared-logs volume in both containers at /var/log/nginx. Ensure all containers are in a running state.
Note: The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster.
# Solution
# Kubernetes Sidecar Logging Pod — `webserver`
An nginx container plus a log-shipping `sidecar-container`, sharing an `emptyDir` volume at
`/var/log/nginx`. The sidecar is defined as a **native sidecar** (an init container with
`restartPolicy: Always`) so it keeps running without blocking the pod. Applied inline via a
heredoc — no manifest file on disk.
## Apply (heredoc → kubectl)
```bash
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: webserver
spec:
volumes:
- name: shared-logs
emptyDir: {}
initContainers:
- name: sidecar-container
image: ubuntu:latest
restartPolicy: Always
command:
- sh
- -c
- "while true; do cat /var/log/nginx/access.log /var/log/nginx/error.log; sleep 30; done"
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
containers:
- name: nginx-container
image: nginx:latest
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
EOF
```
## How it works
### The catch: "init container" that must keep running
The task calls `sidecar-container` an **init container**, gives it an infinite
`while true` loop, and requires **all containers to be running**. Those are contradictory for a
*classic* init container: a normal init container must run to **completion** before the main
container starts. An init container with `while true` never completes, so the pod would hang in
`Init:0/1` forever and nginx would never start.
### The resolution: a native sidecar
Kubernetes 1.28+ supports **native sidecar containers** — an entry under `initContainers` that
carries **`restartPolicy: Always`**. That one field changes the semantics:
- it's still declared under `initContainers` (satisfying "init container"),
- but with `restartPolicy: Always`, Kubernetes **starts it and moves on** without waiting for it
to complete, and **keeps it running** for the pod's lifetime alongside the main container.
So nginx starts normally, the sidecar runs continuously tailing the logs, and the pod reaches a
fully `Running` state — meeting both "init container" and "all containers running." This is
exactly the sidecar pattern the task describes, implemented the modern, native way.
### The shared volume
- **`shared-logs` (`emptyDir`)** is declared once and mounted at **`/var/log/nginx` in both
containers**. nginx writes `access.log` and `error.log` there (its default log directory);
the sidecar reads from the same path because it's the same underlying storage. This is the
"read and write logs via a shared emptyDir" mechanism the task calls for — separation of
concerns: nginx serves, the sidecar ships logs, they meet only at the shared volume.
### The sidecar command
`sh -c "while true; do cat .../access.log .../error.log; sleep 30; done"` continuously dumps the
two log files every 30 seconds (standing in for shipping them to an aggregator). The infinite
loop is what requires the native-sidecar treatment above — without `restartPolicy: Always` under
`initContainers`, this loop would block the pod.
> Note: nginx creates `access.log`/`error.log` on first request; until then the sidecar's `cat`
> may print "No such file or directory" to its own stdout, which is harmless — it keeps looping.
## Verify
```bash
# Pod fully up: nginx running AND the native sidecar running
kubectl get pod webserver
# Confirm the sidecar is an init container with restartPolicy: Always
kubectl get pod webserver \
-o jsonpath='{.spec.initContainers[0].name}{" restartPolicy="}{.spec.initContainers[0].restartPolicy}{"\n"}'
# Both mounts point at /var/log/nginx
kubectl get pod webserver \
-o jsonpath='{range .spec.containers[*]}{.name}{" "}{.volumeMounts[0].mountPath}{"\n"}{end}'
```
Expected — `webserver` `Running` with the nginx container ready; the jsonpath printing
`sidecar-container restartPolicy=Always`; and the mount path `/var/log/nginx` on the containers.
> If the pod sits in `Init:0/1`, the sidecar is being treated as a **classic** init container —
> the `restartPolicy: Always` line is missing or the cluster predates native sidecars (needs
> Kubernetes 1.28+). Confirm the field made it into the spec with the second command above.