If you work in the software development world, you have surely heard of Kubernetes. But what exactly is it, and why has it become the de-facto standard for managing containerized applications? This guide will take you from the basics to the fundamental concepts, with practical examples and diagrams to help you understand.
Before Kubernetes: A Bit of History
To understand why Kubernetes is so revolutionary, let's take a step back.
- Traditional Deployment: Initially, applications were run on physical servers. This approach was expensive, difficult to scale, and prone to resource conflicts.
- Virtualized Deployment: Then came Virtual Machines (VMs). VMs allowed multiple isolated applications to run on the same hardware, improving resource utilization and security. However, each VM runs an entire operating system, consuming a lot of resources.
- Containerized Deployment: Containers (like Docker) are the next evolution. They share the same host operating system but run isolated processes. They are lightweight, fast to start, and portable.
Containers solved the portability problem but created another one: how to manage hundreds (or thousands) of containers in a production environment? How to ensure they are always running, can communicate with each other, and scale based on load?
This is where Kubernetes comes in.
What is Kubernetes?
Kubernetes (often abbreviated as K8s) is an open-source platform for container orchestration. In simple terms, it automates the deployment, scaling, and management of containerized applications. Created by Google and now maintained by the Cloud Native Computing Foundation (CNCF), Kubernetes has become the go-to tool for anyone working with microservices at scale.
The Architecture of a Kubernetes Cluster
A Kubernetes environment is called a cluster. A cluster is composed of a set of machines, called nodes, that run our applications. The architecture is divided into two main parts: the Control Plane and the Worker Nodes.
Control Plane
The Control Plane is the "brain" of the cluster. It makes global decisions (like scheduling) and detects and responds to cluster events. Its main components are:
- API Server (
kube-apiserver
): It is the gateway to the cluster. It exposes the Kubernetes API, which is used by users (viakubectl
), cluster components, and external tools to communicate. - etcd: A consistent and highly available key-value database. It stores all cluster data, representing the desired and current state of the system.
- Scheduler (
kube-scheduler
): Assigns newly created Pods to an available Worker Node, taking into account resource requirements, policies, and other constraints. - Controller Manager (
kube-controller-manager
): Runs controllers, which are control loops that watch the state of the cluster and work to bring it to the desired state. For example, theNode Controller
manages nodes, while theReplication Controller
ensures that the correct number of Pods are running.
Worker Node
Worker Nodes are the machines (physical or virtual) where the applications are actually run. Each node is managed by the Control Plane and contains the following components:
- Kubelet: An agent that runs on each node. It ensures that the containers described in the Pods are running and healthy.
- Kube-proxy: A network proxy that manages network rules on the nodes. It allows network communication to the Pods from network sessions inside or outside the cluster.
- Container Runtime: The software responsible for running containers. Docker is the most famous, but Kubernetes also supports other runtimes like
containerd
andCRI-O
.
Fundamental Kubernetes Objects
In Kubernetes, everything is represented by objects. These objects are "records of intent": once you create an object, Kubernetes constantly works to ensure that it exists and matches the desired state.
Here are the most important ones:
Pod
The Pod is the smallest execution unit in Kubernetes. It represents one or more containers that are run together on the same node, sharing resources like the network and storage.
Generally, you run only one container per Pod, but in advanced scenarios (like "sidecar containers" for logging or monitoring), you can have more.
You almost never create Pods directly. You use higher-level abstractions like Deployments.
Deployment
A Deployment is the object you will use most often. It describes the desired state for a group of identical Pods. The Deployment controller is responsible for:
- Creating and managing a ReplicaSet (another object that ensures a specific number of replicas of a Pod are always running).
- Scaling the number of Pods up or down.
- Managing application updates in a controlled manner (e.g., Rolling Update), without downtime.
Here is an example YAML file for a Deployment that runs 3 replicas of an NGINX server:
# nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
Service
Pods in Kubernetes are ephemeral: they can be created and destroyed at any time. Each Pod has its own IP address, but this IP is not stable. So, how do we reliably expose our application?
With a Service. A Service is an abstraction that defines a logical set of Pods and a policy for accessing them. It provides a stable access point (a virtual IP address and a DNS name) for a group of Pods.
The Service uses a selector
based on labels
to find the Pods to which it should forward traffic.
Here is how to create a Service for our NGINX Deployment:
# nginx-service.yaml apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 type: ClusterIP # Default - exposes the service only within the cluster
There are different types of Services:
ClusterIP
: Exposes the service on a cluster-internal IP (default).NodePort
: Exposes the service on a static port on each Worker Node.LoadBalancer
: Creates an external load balancer in the cloud provider (e.g., AWS, GCP) and assigns a public IP to the service.
Ingress
A LoadBalancer
Service is great, but creating one for each service can be expensive. To expose multiple HTTP/HTTPS services to the outside world, you use an Ingress.
An Ingress acts as an "intelligent router" for external traffic. It allows you to define routing rules based on host (e.g., api.mysite.com
) or path (e.g., mysite.com/api
).
Here is an example of an Ingress:
# example-ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress spec: rules: - host: mysite.com http: paths: - path: /api pathType: Prefix backend: service: name: api-service port: number: 8080 - path: /ui pathType: Prefix backend: service: name: ui-service port: number: 3000
Other Useful Objects
- Namespace: Allows you to create "virtual clusters" inside a physical cluster. Useful for isolating environments (e.g.,
development
,staging
,production
) or teams. - ConfigMap and Secret: To manage configuration data and secrets (like passwords or API keys) decoupled from the container image.
- StatefulSet: Similar to a Deployment, but specific for stateful applications (like databases) that require stable network identities and persistent storage.
- PersistentVolume (PV) and PersistentVolumeClaim (PVC): To manage persistent storage in the cluster.
Conclusion
Kubernetes is an incredibly powerful tool, but its learning curve can be steep. This guide has only scratched the surface, but we hope it has given you a solid understanding of the basic concepts.
What to do now?
- Experiment locally: Install Minikube or Kind to create a Kubernetes cluster on your computer.
- Use
kubectl
: Familiarize yourself with thekubectl
command, your main tool for interacting with the cluster. Try creating the NGINX Deployment and Service from this article. - Explore the official tutorials: The Kubernetes documentation is a fantastic resource full of examples.
Container orchestration is a fundamental skill in the cloud-native world, and mastering Kubernetes will open up a world of possibilities. Have fun!