What Kubernetes does
Kubernetes runs containers across a group of machines, called a cluster, and keeps them in the state you declared. You describe what should run, such as which image, how many copies and how traffic reaches them. Kubernetes then starts, restarts and moves containers until the cluster matches that description.
The machines that run your containers are called nodes. A control plane, made up of the API server, a scheduler, controllers and the etcd database, decides what runs where.
You rarely start a container by hand. Instead you create objects through the Kubernetes API, usually by applying YAML files called manifests with kubectl apply.
Desired state and the reconciliation loop
Most Kubernetes objects have a spec, the state you want, and a status, the state the cluster last observed. Controllers run in a loop: they compare the two and take a step to close any gap.
If a Deployment asks for three replicas and the node running one of them fails, Kubernetes sees only two running Pods and creates a replacement. The scheduler assigns the new Pod to a node with enough free CPU and memory, and the kubelet agent on that node starts its containers.
The same loop means a deleted Pod that a Deployment manages is soon replaced. Changes made outside the manifests are overwritten the next time the manifests are applied, so many teams keep manifests in Git and apply them from a pipeline.
The core objects
Most applications on Kubernetes use the same handful of objects.
- A Pod is the smallest unit Kubernetes runs: one or more containers that share an IP address and storage volumes. Pods are disposable, and a replacement Pod gets a new name and a new IP address, so nothing should depend on either.
- A Deployment declares a Pod template and a replica count, and manages rolling updates and rollbacks. You create the Deployment, and the Deployment creates the Pods.
- A Service gives a changing set of Pods one stable virtual IP address and DNS name, choosing the Pods by their labels. The default type, ClusterIP, is reachable only inside the cluster. The LoadBalancer type asks the cloud provider for an external load balancer.
- An Ingress holds HTTP routing rules, by hostname and path, from outside the cluster to Services. It does nothing until an ingress controller is installed. The Ingress API is frozen, and the Kubernetes project recommends its successor, the Gateway API.
- A ConfigMap holds configuration and a Secret holds sensitive values, and both reach containers as environment variables or files. Secrets are only base64-encoded, and etcd stores them unencrypted unless encryption at rest is turned on. Anyone who can create Pods in a namespace can read the Secrets in it.
- A namespace groups objects inside one cluster for naming, access rules and resource quotas. It is not a network boundary: Pods in different namespaces can reach each other unless NetworkPolicies, enforced by the network plugin, block it.
Rolling updates and rollbacks
Changing the image in a Deployment starts a rolling update. Kubernetes creates Pods from the new template a few at a time and removes old ones as the new ones become ready. Two settings set the pace: maxSurge, the extra Pods allowed during the update, and maxUnavailable, the Pods that may be missing. Both default to 25 percent.
If the new Pods never become ready, the rollout stalls and the remaining old Pods keep serving. Kubernetes marks the Deployment as failed after its progress deadline, 10 minutes by default, but it does not roll back on its own.
To go back, run kubectl rollout undo deployment/shop-web, which restores the previous Pod template. The rollback is itself a rolling update, so it follows the same pace and the same probes.
apiVersion: apps/v1
kind: Deployment
metadata:
name: shop-web
spec:
replicas: 3
selector:
matchLabels:
app: shop-web
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: shop-web
spec:
containers:
- name: web
image: registry.example.com/shop:3f9c2a1
ports:
- containerPort: 3000
readinessProbe:
httpGet:
path: /healthz/ready
port: 3000
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz/live
port: 3000
periodSeconds: 10
failureThreshold: 3Readiness, liveness and startup probes
Probes tell Kubernetes when a container is ready for traffic and when it needs a restart. Each probe can be an HTTP request, a TCP connection or a command run inside the container. With maxUnavailable set to 0 in the example above, no old Pod is removed until a new one passes its readiness probe.
- A readiness probe decides whether a Pod receives traffic. While it fails, the Pod is taken out of its Services, and a rollout waits instead of replacing more old Pods.
- A liveness probe decides whether a container is stuck. When it fails a set number of times in a row, the kubelet restarts the container.
- A startup probe holds off the other two until a slow-starting app has finished starting.
- Keep liveness checks to the process itself. A liveness probe that checks the database restarts every Pod at once when the database slows down, turning a slowdown into an outage.
When Kubernetes is more than you need
Kubernetes solves the problems of running many services on many machines, and it brings work of its own. The project ships about three minor versions a year, each with about a year of patch support, so clusters need regular upgrades. Someone also has to manage networking, certificates and access rules, and read the YAML when a rollout fails.
A managed Kubernetes service runs the control plane for you. Your manifests, cluster add-ons and debugging still stay with your team.
For one or two services, a platform that runs containers for you, or a single VM with Docker Compose, is often enough. Kubernetes starts to pay off when you run many services, several teams deploy independently, or workloads have to scale across many machines.