Kubernetes Overview, Part One
Kubernetes is an open-source system for managing containerized applications across multiple hosts in a cluster.
Kubernetes provides mechanisms for application deployment, scheduling, updating, maintenance, and scaling. A key feature of Kubernetes is that it actively manages the containers to ensure the state of the cluster continually matches the user's intentions.
Kubernetes enables you to respond quickly to customer demand by scaling or rolling out new features. It also allows you to make maximal use of your hardware.
- Lean: lightweight, simple, accessible
- Portable: public, private, hybrid, multi cloud
- Extensible: modular, pluggable, hookable, composable, toolable
- Self-healing: auto-placement, auto-restart, auto-replication
Kubernetes builds on a decade and a half of experience at Google running production workloads at scale, combined with best-of-breed ideas and practices from the community.
In this miniseries, we’ll cover Kubernetes from the ground up.
Let’s start with the basic components.
kubectl utility lets you interface with the Kubernetes cluster manager. For example, you can add and delete nodes, pods, replication controllers, and services. You can also check their status, and so on.
For more information, see the documentation.
A cluster is a set of physical or virtual machines (or both) combined with other infrastructure resources used by Kubernetes to run your applications.
In the following diagram, we can see how a heterogeneous set of user-specified containers are neatly and automatically packed into the available nodes by Kubernetes.
We can get basic information about the cluster with the
Here's an example:
The Kubernetes control plane is split into a set of components. These components work together to provide a unified view of the cluster.
All persistent state data is stored an etcd cluster. This provides a distributed way to store configuration data reliably.
The master services are the set of main Kubernetes control services, usually running on one server. If high availability is needed, they can be run on a multiple servers behind a load balancer.
The master services are as follows:
The API server is the central management point of the entire cluster, and allows the admin to configure Kubernetes workloads and organizational units. The API server is also responsible for making sure etcd and the service details of deployed containers are in agreement.
In other words, the API server validates and configures (on command) the data for pods, services, and replication controllers. It also assigns pods to nodes and synchronizes pod information with service configuration.
The controller manager service handles the replication processes defined by individual replication tasks. The details of these operations are written to etcd, which the controller manager watches for changes. When a change is seen, the controller manager reads the information and implements the replication procedure that fulfills the desired state, e.g. scaling the application group up or down.
In other words, the controller manager watches etcd for replication tasks and uses the API to enforce the desired state.
The scheduler assigns workloads to specific nodes in the cluster. It does this by reading in the workload operating requirements, analyzing the current environment (i.e. the health and operational details of the individual nodes in the cluster), and then placing the workload on a suitable node, or nodes.
A node (sometimes called a worker node) is a physical or virtual machine running Kubernetes services, onto which pods can be scheduled.
Nodes are managed by the control plane.
These Kubernetes services usually run on each node:
The kubelet daemon is the primary agent that runs on each node. The kubelet daemon watches the master API server and ensures the appropriate local containers are started, remain healthy, and continue to run.
The kube-proxy daemon runs on each node as a simple network proxy and load balancer for the services on that node.
You can get a list of nodes by running:
Kubernetes defines its constructs through configuration files (called manifests) which can be either YAML or JSON.
A namespace is like a prefix to the name of a resource. Namespaces help different projects, environments (e.g. dev and production), teams, or customers share the same cluster. It does this by preventing name collisions.
Namespace can be created with a manifest file.
Create a file called
development-ns.yaml and put this in:
Then you can create the new namespace by running:
And to list existing namespaces, run:
For more information about namespaces, see the documentation.
Pods are a collocated group of application containers with shared volumes.
Pods are the smallest deployable units that can be created, scheduled, and managed with Kubernetes. Pods can be created individually. As pods do not have a managed lifecycle, if they die, they will not be recreated. For that reason, it is recommended that you use a replication controller (which we cover later) even if you are creating a single pod.
The applications in the pod all use the same network namespace, IP address, and port space. And they can find and communicate with each other using
localhost. Each pod has an IP address in a flat shared networking namespace that has full communication with other physical computers and containers across the network.
Let's create a simple pod definition for a single nginx web container.
Create a file named
nginx.yaml, and put this in it:
In this file:
Nameis the name you give to your container
imageis the Docker image name you want to use
containerPortexposes the specified container port so we can connect to the nginx server at the pod’s IP address
By default, the entrypoint defined in the image is what will run. With our nginx image, that command runs nginx.
Let’s create the pod by running:
Easy as that!
You can check this worked by running:
Bingo. Here, we can see the nginx pod we created. It's one minute old.
We can also check the resources for our running pod:
And we can delete our pod:
See, it worked:
For more information about Pods, see the documentation.
Replication controllers manage the lifecycle of pods. They insure a specified number of specific pods are running at any given time. They do this by creating or deleting pods as required. For this reason, it's recommended you use a replication controller even if you are creating a single pod.
Let’s create the replication controller for our previously used nginx pod.
nginxrc.yaml file, and put this in it:
Now create the replication controller from that file:
We can see how many replicas we have:
And we can easily scale pods:
And check it worked:
Here we see the replication controller has scaled from one to three pod replicas.
The replication controller will now ensure that number of replicas will be run at all times.
Here's how our replication controller functions:
As you can see, it knows there are three pods with the label
nginx. And it watches over those pods, ready to recreate one if necessary.
For more information about replication controllers, see the documentation.
Services provide a single stable name and address for a set of pods. They act as basic load balancers.
Most pods are designed to be long-running, but once the single process dies, the pod dies with it. If it dies, the replication controller replaces it with a new pod. Every pod gets its own dedicated IP address, which allows containers to have the same port, even if they're sharing the same host. But every time pod is started by the replication controller, the pod gets a new IP address.
This is where services really help. A service is attached to a replication controller. Each service gets assigned a virtual IP address, which remains constant. As long as we know the service IP address, the service itself will keep track of the pods created by the replication controller, and will distribute requests to them.
Let's create a service for our
my-nginx replication controller.
Create a file called
nginxsvc.yaml, and put this in:
Now, we can create our service by running:
And check it worked:
Because every node in a Kubernetes cluster runs a kube-proxy, the kube-proxy watches the Kubernetes API server for the addition and removal of services. For each new service, kube-proxy opens a (randomly chosen) port on the local node. Any connections made to that port are proxied to one of the corresponding backend pods.
Here's how our
nginxsvc service functions:
As you can see, incoming requests to HTTP port 80 arrive at the
nginxsvc service and are proxied to one of the three
For more information about services, see the documentation.
Labels are used to organize and select groups of objects based on key-value pairs.
They are used by every Kubernetes component. For example: the replication controller uses them for service discovery.
Let’s see how labels are used to connect the replication controller
my-nginx with the
my-nginx replication controller config includes this:
app label is set to
That label is used by our
nginxsvc service config:
This label then functions to connect the service to the replication controller.
You can see which selector a service is using like so:
For more information about Labels, see the documentation.
In part one of this Kubernetes miniseries, we looked at kubectl, clusters, the control plane, namespaces, pods, services, replication controllers, and labels.
In part two, we’ll look at volumes, secrets, rolling updates, and Helm.