Recap and cheat sheet
  1. A wraps your container. If the container crashes, the kubelet restarts it in place, in the same Pod (watch the RESTARTS column). A Pod itself is replaced, with a new name and IP, only when it is deleted or its Node is lost.
  2. You don't create Pods by hand: a Deployment keeps the number you want, through a ReplicaSet.
  3. A Deployment's selector cannot be changed after it is created (the error says field is immutable). Change the Pod template labels to match, or delete and recreate the Deployment.
  4. The control plane records what you want; controllers keep fixing the difference. That's the reconciliation loop.
  5. A is one stable name that finds Pods by label. port is what callers use, targetPort is where the container listens.
  6. To test a Service from inside the cluster, run a throwaway Pod that fetches it, or forward a local port to the Service from your own machine.
  7. When something's wrong: get, then describe and read the Events, then compare labels.

Commands to know by heart

kubectl create deployment NAME --image=IMAGE --replicas=N
kubectl scale deployment NAME --replicas=N
kubectl expose deployment NAME --port=80 --target-port=8080
kubectl get pods -o wide --show-labels
kubectl get pods -l app=NAME
kubectl describe pod POD
kubectl delete pod POD
kubectl label pod POD KEY=VALUE
kubectl annotate pod POD KEY=VALUE
kubectl run NAME --image=IMAGE --restart=Never
kubectl run NAME --image=IMAGE --dry-run=client -o yaml > pod.yaml
kubectl run tmp --image=busybox:1.36 --rm -it --restart=Never \
  -- wget -qO- http://shop
kubectl port-forward svc/shop 8080:80
kubectl apply -f FILE.yaml
kubectl create deployment ... --dry-run=client -o yaml > FILE.yaml
kubectl explain deployment.spec

YAML skeletons

apiVersion: apps/v1
kind: Deployment
metadata: { name: shop }
spec:
  replicas: 3
  selector: { matchLabels: { app: shop } }
  template:
    metadata: { labels: { app: shop } }
    spec:
      containers:
        - { name: shop, image: shop:1.0 }
---
apiVersion: v1
kind: Service
metadata: { name: shop }
spec:
  selector: { app: shop }
  ports: [{ port: 80, targetPort: 8080 }]

Next chapter: ConfigMaps, Secrets, and why the Cyclops's Pod is cursed by the gods to repeat CrashLoopBackOff forever, like Sisyphus.