Lab 19 – StatefulSets

Lab 19 – StatefulSets

Cíl: stabilní jména, úložiště na každý pod, řízené pořadí – a překvapení při úklidu. Kapitola: StatefulSets

Lab potřebuje tři PV z labu 18. Ověřte, že jsou Available:

kubectl get pv
kubectl patch pv pv-storage1 -p '{"spec":{"claimRef":null}}' 2>/dev/null
kubectl get pv

Nejdřív headless Service

# 1 –
cd ~
cat > web-headless.yaml <<'YAML'
apiVersion: v1
kind: Service
metadata:
  name: web-headless
spec:
  clusterIP: None            # headless – žádná virtuální IP
  selector:
    app: web-sts
  ports:
    - port: 80
YAML
kubectl apply -f web-headless.yaml
kubectl get svc web-headless      # CLUSTER-IP je "None"

Normální Service pody schová za jednu IP. Headless Service dělá opak: DNS vrátí adresy jednotlivých podů, takže je každá replika adresovatelná jménem. StatefulSet ji vyžaduje.

StatefulSet

# 2 –
cat > web-sts.yaml <<'YAML'
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: web-headless
  replicas: 3
  selector:
    matchLabels:
      app: web-sts
  template:
    metadata:
      labels:
        app: web-sts
    spec:
      containers:
        - name: web
          image: nginx:1.27
          ports:
            - containerPort: 80
          volumeMounts:
            - name: data
              mountPath: /usr/share/nginx/html
          resources:
            requests: { cpu: "20m", memory: "32Mi" }
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteMany"]
        storageClassName: ""
        resources:
          requests:
            storage: 500Mi
YAML
kubectl apply -f web-sts.yaml
kubectl get pods -l app=web-sts -w        # Ctrl-C až všechny tři poběží

Sledujte pořadí: web-0 je Ready dřív, než vznikne web-1, a web-1 dřív než web-2. Deployment by spustil všechny tři naráz; StatefulSet je záměrně sekvenční, protože replika databáze se nemůže připojit ke clusteru, který ještě neběží.

# 3 – jména a úložiště
kubectl get pods -l app=web-sts -o wide
kubectl get pvc
kubectl get pv

Všimněte si jmen PVC: data-web-0, data-web-1, data-web-2 – jméno šablony plus jméno podu. Jeden PVC na repliku, každý navázaný na jeden z vašich NFS PV. Proto tři repliky potřebovaly tři PV.

# 4 – stabilní identita
kubectl exec web-0 -- sh -c 'echo "I am web-0" > /usr/share/nginx/html/index.html'
kubectl exec web-1 -- sh -c 'echo "I am web-1" > /usr/share/nginx/html/index.html'
kubectl delete pod web-0
kubectl get pods -l app=web-sts           # web-0 se vrátí se STEJNÝM jménem
kubectl exec web-0 -- cat /usr/share/nginx/html/index.html   # a stejnými daty

Deployment by vytvořil web-7d9f...-xk2p s prázdným volume. StatefulSet znovu vytvořil web-0 a připojil mu data-web-0.

# 5 – DNS jméno každého podu
kubectl run tmp --image busybox --restart=Never -it --rm -- \
  sh -c 'nslookup web-0.web-headless.default.svc.cluster.local; wget -qO- web-1.web-headless'

<pod>.<service>.<namespace>.svc.cluster.local míří na jednu konkrétní repliku. Takhle se členové databáze hledají navzájem.

# 6 – zmenšení probíhá v opačném pořadí
kubectl scale sts web --replicas=1
kubectl get pods -l app=web-sts           # nejdřív web-2, pak web-1
kubectl get pvc                           # PVC tu pořád jsou

Zmenšení úložiště nemaže. Naškálujte zpátky a web-1 najde svá stará data.

# 7 –
kubectl scale sts web --replicas=2
kubectl exec web-1 -- cat /usr/share/nginx/html/index.html   # "I am web-1"

Úklid – to překvapení

# 8 –
kubectl delete -f web-sts.yaml
kubectl get pvc                            # pořád tady!
kubectl delete pvc data-web-0 data-web-1 data-web-2
kubectl delete -f web-headless.yaml
for p in pv-storage1 pv-storage2 pv-storage3; do
  kubectl patch pv $p -p '{"spec":{"claimRef":null}}'
done
kubectl get pv

Smazání StatefulSetu smaže pody a PVC nechá být. Je to záměr – data jsou smyslem toho objektu – a znamená to, že úklid je vždy ruční druhý krok.