Chapter 7 of a local-Kubernetes series: the three manifests you actually need — Namespace, Deployment, Service — and the "aha" that they're glued together by labels and selectors, not hard references.
Key takeaways
-
Namespace = a folder for your resources. Don't dump apps in
default; a dedicated namespace makes cleanup, limits, and isolation easy. Same-namespace access uses the short name (myapp); cross-namespace needs the FQDN (myapp.myapp.svc.cluster.local). -
The object hierarchy:
Deployment → ReplicaSet → Pods. You describe only the Deployment; Kubernetes creates the rest. Pods are ephemeral (new IP on every recreate), so you never address them directly. -
The rule everyone trips on:
spec.selector.matchLabelsmust matchspec.template.metadata.labels. Diverge and Kubernetes rejects the manifest at apply time. - Service (ClusterIP) gives a group of Pods one stable virtual IP + DNS name, reachable only inside the cluster; it tracks which Pods match its selector via EndpointSlices.
-
portvstargetPort:portis what the Service listens on (we use 80);targetPortis the Pod's port (8080). Defaults toportif omitted. -
The single most common bug: the Service's selector doesn't match the Pods' labels →
kubectl describe svcshowsEndpoints: <none>→ the service exists but traffic goes nowhere. One command to diagnose. -
apply(declarative, idempotent) vscreate(imperative, fails if it exists). Alwaysapplyfor Git-tracked manifests.kubectl diff -fbefore applying. -
Keep manifests in Git next to the code (a flat
k8s/folder); reach for Kustomize base+overlays when environments diverge.
Top comments (0)