Introduction to Kubernetes
Kubernetes, (originally developed by Google), is an open-source container orchestration platform for automating deployments, scaling, and management of containerized applications.
Why use Kubernetes?
Managing a single containerized application is relatively easy, ten containerized applications? Harder, but still doable. What about thousands of containerized applications across multiple servers and environments? Will you be updating, scaling and routing traffic to them one by one?
This is why Kubernetes was created. With Kubernetes, you describe the state that you want, e.g., "run five instances of this application", and it will make the environment match the desired state.
Kubernetes brings many things to the table, among them:
- Automatic recovery: Detects failed containers and restarts or replaces them to minimize downtime;
- Replicas and load balancing: Runs multiple replicas of a service and distributes traffic across them to maintain availability under load or when instances fail.
- Declarative deployments and rollbacks: Applies updates declaratively and can perform rolling updates or roll back to a previous version if problems are detected.
- Scaling: Scales applications horizontally (automatic or manual) to match demand and supports cluster autoscaling for infrastructure capacity.
- Service discovery and stable networking: Provides stable network identities for services and internal service discovery so components can communicate reliably.
- Resource-aware scheduling: Places workloads onto nodes based on resource requests, constraints, affinities, taints/tolerations, and QoS requirements for efficient utilization.
- Configuration and secret management: Separates configuration and secrets from images and injects them securely into running containers.
- Stateful workload support and persistent storage: Manages persistent volumes and stateful sets for databases and other stateful services.
- Self-healing and declarative reconciliation: Continuously reconciles actual cluster state to the declared desired state, maintaining consistency and reducing manual intervention.
You may now be thinking: "I should just use Kubernetes everywhere, right?", and the answer to that is: It depends.
When is Kubernetes a good fit?
Being designed for large container workloads, Kubernetes really shines when you have large scale applications or when you need automated scaling, self-healing, and centralized orchestration across multiple environments.
When is Kubernetes not a good fit?
Kubernetes adds a significant complexity layer and a steep learning curve, operating a cluster requires expertise in various domains such as networking, security and monitoring, Also, running Kubernetes in the cloud can add significant infrastructure and operational costs.
Before choosing Kubernetes, you need to evaluate if its automation and scalability benefits justify the additional complexity.
For small projects, simple monolithic applications, or workloads with straightforward requirements, Kubernetes may be an overcomplicated solution.
How is Kubernetes built?
Kubernetes has a master-worker architecture, i.e. A control plane that makes the decisions while worker nodes run the application workloads.
Together, the control plane and worker nodes form a Kubernetes cluster:
Both the control plane and worker nodes consist of several components, each with a specific responsibility. Rather than a single monolithic process, Kubernetes is a collection of small, focused processes that work together, each one in charge of different things.
This design has a key benefit: if one component fails, the others keep running. The cluster can often self-recover without any manual intervention.
Supported container runtimes
Kubernetes currently supports any container runtime that is OCI compliant. (1)
- Open Container Initiative (OCI) - Open governance structure that defines industry standards around container formats and runtimes. It ensures that container tools and runtimes remain interoperable across the ecosystem.
The CRI, Docker and ContainerD
When Kubernetes was first created, it was primarily designed for orchestrating Docker containers.
As the project grew, other container engines, such as rkt, also sought to integrate with it. In response, Kubernetes introduced the Container Runtime Interface, (CRI), which defines the API that a container runtime must implement in order to work with Kubernetes, while the OCI defines the standards for container images and runtimes.
Predating both standards, Docker did not natively implement the CRI. To maintain compatibility with Docker, Kubernetes introduced dockershim, a compatibility layer that allowed the kubelet to communicate with Docker.
However, Docker is more than just a container engine. It is an ecosystem of tools that includes the Docker CLI, image building tools, authentication utilities, and other related components. Among these, is a container runtime called runc, which is managed by a daemon known as ContainerD.
Docker, however, is more than a container runtime. It is an ecosystem of tools that includes the components such as the Docker CLI, image building tools and authentication utilities.
The Docker Engine uses containerd to manage containers and containerd in turn uses an OCI compatible runtime such as runc to run them.
Because containerd could operate independently of Docker, Kubernetes could communicate with it directly through the CRI instead of going through Docker and dockershim. Maintaining dockershim therefore became unnecessary for clusters that used containerd or another CRI-compliant runtime.
As a result, dockershim was officially deprecated in Kubernetes v1.20 and removed in Kubernetes v1.24.
Today, containerd and other CRI-compliant runtimes, such as CRI-O, are commonly used to run containers in Kubernetes clusters.
Even though Docker is no longer supported as a Kubernetes container runtime, Docker images remain compatible with containerd and other OCI compliant runtimes.