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,106 @@
# Assignment
The Nautilus DevOps team has already deployed a ReplicaSet to host an application that requires a highly available infrastructure. Your task is to expose the application running in the existing ReplicaSet by creating a Kubernetes NodePort Service.
Follow the specifications below to create the Service and ensure the application pods are accessible:
A ReplicaSet named httpd-replicaset is already running in the cluster.
The pods managed by the ReplicaSet use the following labels:
Assign labels app as httpd_app, and type as front-end.
Create a NodePort Service named httpd-service to expose the application.
Set the NodePort to 30080.
Expose port 80 of the application.
Note: Do not delete or modify the configuration of the deployed ReplicaSet application.
# Solution
# Kubernetes NodePort Service — `httpd-service`
A NodePort Service that exposes the pods already managed by the `httpd-replicaset`, matched
by their labels. Applied inline via a heredoc — no manifest file on disk, and the ReplicaSet
is left untouched.
## Apply (heredoc → kubectl)
```bash
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Service
metadata:
name: httpd-service
spec:
type: NodePort
selector:
app: httpd_app
type: front-end
ports:
- port: 80
targetPort: 80
nodePort: 30080
EOF
```
## How it works
### The heredoc apply pattern
- **`kubectl apply -f -`** reads from **stdin**; nothing written to disk.
- **`<<'EOF'` (delimiter quoted)** disables shell expansion — the right default for k8s YAML.
### A Service finds pods by label selector
A Service has no direct link to the ReplicaSet — it targets **pods** whose labels match its
`selector`. This is the crux of the task:
- **`selector: {app: httpd_app, type: front-end}`** — must exactly match the labels on the
pods the ReplicaSet manages. Any pod carrying **both** labels becomes an endpoint of this
Service, regardless of what created it. Since the ReplicaSet stamps its pods with these
labels, the Service automatically picks them up. A mismatched selector would yield a Service
with **zero endpoints** — it'd exist but route nowhere.
This is also why we don't touch the ReplicaSet: the Service attaches by label, so exposing the
app needs no change to the existing workload at all.
### NodePort and the port fields
`type: NodePort` opens a port on **every node** that forwards to the Service, which in turn
load-balances across the matching pods. The three port fields each mean something distinct:
| Field | Meaning |
|-------|---------|
| `port: 80` | The port the **Service** itself listens on (its ClusterIP:80). |
| `targetPort: 80` | The port on the **pod/container** traffic is forwarded to — Apache's port 80. |
| `nodePort: 30080` | The port opened on **each node's** IP for external access. |
So the path is: `<node-ip>:30080` → Service `:80` → pod `:80`. `30080` is inside the valid
NodePort range (`3000032767`), so the API accepts it.
### Why all three ports are set explicitly
`targetPort` defaults to `port` if omitted (both 80 here, so it'd work either way), and
`nodePort` would be auto-assigned from the range if omitted — but the task pins it to `30080`,
so it's set explicitly. Being explicit also makes the manifest self-documenting.
## Verify
```bash
# Service created as NodePort with the right ports
kubectl get service httpd-service
# Endpoints populated = selector matched the ReplicaSet's pods (this is the key check)
kubectl get endpoints httpd-service
# Confirm it reaches the app (from a node or the jump-host)
curl -s http://<node-ip>:30080 | head -n 5
```
Expected — `httpd-service` of type `NodePort` showing `80:30080/TCP`, and
`kubectl get endpoints httpd-service` listing one IP per matching pod. If endpoints is empty,
the selector doesn't match the pods' labels — recheck them with
`kubectl get pods --show-labels`.