Notes02-Core Concepts
Core Concepts
Cluster architecture and the objects you create every day: Pods, ReplicaSets, Deployments, Namespaces, and Services, plus the kubectl forms that build them.
Core Concepts Quick Notes
Cluster shape
A cluster is a control plane plus worker nodes. The control plane decides. Workers run your containers.
kubectl → kube-apiserver → etcd
↑
scheduler, controller-manager, cloud-controller-manager
worker: kubelet → container runtime (CRI) → containers
kube-proxy → Service forwarding rules
- Every change goes through the API server. Controllers, the scheduler, and
kubectlare clients of that API. They do not write to etcd themselves.
Control plane
- kube-apiserver: REST front door. Authenticates the caller, authorizes the verb, runs admission, then persists the object in etcd. It is the only component that talks to etcd.
- etcd: Consistent key-value store. Cluster state lives under the
/registryprefix. Lose etcd and you lose the cluster’s memory. Snapshot a kubeadm member withETCDCTL_API=3 etcdctl snapshot save /opt/etcd-backup.dbagainsthttps://127.0.0.1:2379, using/etc/kubernetes/pki/etcd/ca.crt,server.crt, andserver.key.snapshot restorewrites a new data directory. Point the etcd static Pod’shostPathand--data-dirat that directory and the kubelet restarts etcd. - kube-scheduler: Watches Pods with no
nodeNameand picks a node. It writes the binding back through the API. It does not start containers. - kube-controller-manager: A set of loops that reconcile desired state with actual state: ReplicaSet, Deployment, Node, Job, Namespace, EndpointSlice, ServiceAccount, and others. If a Pod disappears, the replica controller creates a replacement.
- cloud-controller-manager: Cloud-only loops (load balancer Services, node addresses, routes). Absent on a kubeadm cluster with no cloud provider.
On a kubeadm cluster these run as static Pods in kube-system. Their manifests are files on the control-plane node:
/etc/kubernetes/manifests/kube-apiserver.yaml
/etc/kubernetes/manifests/etcd.yaml
/etc/kubernetes/manifests/kube-controller-manager.yaml
/etc/kubernetes/manifests/kube-scheduler.yaml
The kubelet on that node starts them even when the API server is down. That is how the control plane boots.
Worker node
- kubelet: Agent on every node. Watches the API for Pods bound to this node, calls the runtime through CRI, mounts volumes, runs probes, and reports node status.
- Container runtime: containerd is the usual CRI runtime (
cri-ois the other common one). Docker Engine is a separate product. Kubernetes talks to the runtime only through CRI. On the node,crictl psandcrictl logsinspect containers. - kube-proxy: Programs the host so a Service’s virtual IP reaches ready Pods. Modes are
iptables,ipvs, or nftables-based, depending on the cluster. It does not assign Pod IPs. - CNI plugin: Assigns each Pod an IP and connects that network namespace to the node (bridge, route, or overlay). Config lives in
/etc/cni/net.d, binaries in/opt/cni/bin. Afterkubeadm initthe node staysNotReadyuntil a plugin is installed. Pod-to-Pod traffic is the CNI’s job. ClusterIP traffic is kube-proxy’s job, aimed at the Pod IPs the CNI already assigned.
Pods
- What a Pod is: The smallest object the scheduler places. One Pod is one or more containers that share a network namespace, IPC, and volumes, and that share a lifecycle.
- One IP: Containers in the same Pod reach each other on
localhostand must use different ports. Two containers that both bind:80will not start. - Typical shape: One application container. Extra containers share the Pod IP and any volumes you mount into more than one of them.
- Sidecar: Helps the app for the whole Pod lifetime (ships logs from a shared volume, refreshes certificates).
- Adapter: Rewrites the app’s output into the shape the rest of the system expects.
- Ambassador: Proxies outbound calls. The app talks to localhost. The ambassador opens the remote connection.
- Init container: Runs to completion, in list order, before app containers start. The next init starts only after the previous one exits 0. Use one to wait for a dependency, run a migration, or prepare a volume. A failing init retries according to
restartPolicy. App containers stay stopped until every init succeeds.
- Ephemeral: A Pod is not repaired in place. If the node dies, a controller creates a new Pod with a new IP. Stable names and disks belong to higher-level objects (Deployment, StatefulSet, PVC).
- Phases:
Pending(accepted, not running yet),Running,Succeeded,Failed,Unknown.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
containerPort is documentation for humans and for probes. It does not publish the port on the node. A Service does that.
ReplicaSets
- Job: Keep a stable count of Pods that match a selector.
- You rarely create one by hand. A Deployment owns ReplicaSets, one per revision.
- Selector must match the Pod template labels. If it does not, the API rejects the object.
- Orphans: A ReplicaSet adopts existing Pods whose labels match. That is why changing labels on a live Pod can move it between controllers.
kubectl get rs
kubectl scale rs frontend --replicas=4
Deployments
- Job: Declarative updates of a Pod template. Each change creates a new ReplicaSet and shifts replicas according to the strategy.
- RollingUpdate (default): New Pods come up while old ones are removed.
maxUnavailable(often25%) is how many Pods may be down.maxSurge(often25%) is how many extra Pods may exist abovereplicas.kubectl set image deployment/web nginx=nginx:1.28starts a rollout.kubectl rollout status,rollout history, androllout undofollow it. Undo scales the previous ReplicaSet back up. History is kept whilerevisionHistoryLimitis above 0 (default 10). - Recreate: Kill the old Pods, then start the new ones. A gap in availability, used when two versions must not run together.
kubectl create deployment web --image=nginx:1.27 --replicas=3
kubectl get deploy,rs,pods
kubectl scale deployment web --replicas=5
Namespaces
- What they are: A naming and policy boundary inside one cluster. Object names only need to be unique inside the namespace.
- Built-in:
default(where your objects go if you omit-n),kube-system(control plane and addons),kube-public(readable cluster-wide, including unauthenticated in some setups),kube-node-lease(node heartbeats). - Namespaced objects: Pods, Services, Deployments, ConfigMaps, Secrets, Roles, RoleBindings, NetworkPolicies, PVCs.
- Cluster-scoped objects: Nodes, Namespaces, PersistentVolumes, StorageClasses, ClusterRoles, ClusterRoleBindings.
- DNS: A Service named
webinshopisweb.shop.svc.cluster.local. - Not a security boundary by themselves. Isolation needs RBAC and NetworkPolicy. ResourceQuota and LimitRange cap what a namespace may consume.
kubectl create namespace shop
kubectl get pods -n shop
kubectl config set-context --current --namespace=shop
Services
A Service gives a stable virtual IP and DNS name to a changing set of Pods.
Type | What you get | Typical use |
|---|---|---|
ClusterIP | VIP reachable only inside the cluster. Default. | Pod-to-Pod calls |
NodePort | ClusterIP plus a port on every node (default range | Labs, or a load balancer you run yourself |
LoadBalancer | NodePort plus an external load balancer, when a cloud controller exists | North-south traffic on a cloud cluster |
ExternalName | DNS | Alias to a name outside the cluster |
- Selector: Labels that choose member Pods.
kubectl get endpointslicesshows the ready addresses kube-proxy uses. - Empty endpoints: The selector matches nothing, or the Pods are not Ready. Traffic to the ClusterIP is blackholed.
- Headless:
clusterIP: None. DNS returns the Pod IPs directly. Used with StatefulSets. targetPort: Port on the container.port: Port on the Service VIP. They can differ.- kube-proxy installs the forwarding rules. CoreDNS publishes the name. Neither is optional if you want “normal” Service behavior.
kubectl expose deployment web --port=80 --target-port=80 --name=web
kubectl expose deployment web --type=NodePort --port=80 --name=web-ext
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
target-port: 80
Imperative kubectl you will actually type
kubectl run nginx --image=nginx --port=80
kubectl create deployment web --image=nginx:1.27 --replicas=2
kubectl create service clusterip web --tcp=80:80
kubectl create namespace dev
kubectl label pod nginx env=prod --overwrite
kubectl annotate pod nginx owner=platform
kubectl set image deployment/web nginx=nginx:1.28
kubectl delete pod nginx --force --grace-period=0
# correct YAML without applying it
kubectl create deployment web --image=nginx --dry-run=client -o yaml > web.yaml
kubectl apply -f web.yaml
kubectl explain deployment.spec.strategy
kubectl get deploy web -o yaml
kubectl api-resources | head
kubectl runcreates a Pod (older tutorials sometimes imply a Deployment; current kubectl creates a Pod).create deploymentcreates a Deployment. Prefer that when you want replicas and rollouts.--dry-run=client -o yamlis the fastest way to get a valid manifest you can edit (add a volume, a probe, a nodeSelector).
Object model in one line
- Spec: what you asked for.
- Status: what the controllers last observed.
- metadata.labels: used by selectors (Services, ReplicaSets, NetworkPolicies).
- metadata.annotations: arbitrary notes. Selectors ignore them.
- ownerReferences: why a deleted Deployment also deletes its ReplicaSets and Pods (garbage collection).