Kubernetes is a powerful open-source container management system that enables you to run multiple containers on the same machine. Kubernetes also provides a way to create and manage replica sets, which can provide redundancy for your applications. Kubernetes is an important part of the modern software development process and can be used in both large-scale deployments and small-scale applications.


Kubernetes is not known for being approachable. To master Kubernetes, you need to understand how its abstractions fit together. Kubernetes comes with dozens of resource types which you can use within your applications. Let’s look at the roles of the most frequently used resources.

Pods

If there’s one Kubernetes term to learn, it’s “Pod.” Pods are the fundamental compute unit used by Kubernetes. They host your running containers. For this reason, it’s common to liken a pod to an instance of a Docker container.

This likeness isn’t exact as a single Kubernetes pod may have multiple containers running within it. Pods are better seen as a “group” of containers that have a shared execution context. The Pod’s environment is isolated; the individual container environments within are further sub-isolated.

Containers in a pod are always scheduled onto the same Kubernetes node. They’ll run on the same physical machine and can share storage and network resources.

The above manifest would manually create a single Pod. The Pod would run a container using the my-image:latest image.

You don’t normally manage Pods directly in Kubernetes. Pods are created as a consequence of adding other resources, such as a Deployment (see below). You should treat your Pods as ephemeral units. Kubernetes has control over the Pod and could reschedule it to another node if cluster resources become constrained.

Replica Sets

Replica Sets (usually written as ReplicaSets, without a space) are another abstraction layer on top of Pods. ReplicaSets guarantee that there will be a specific number of identical Pods running at any given time.

When using ReplicaSets, you get to enforce a minimum number of Pods for your application. You specify the number of Pods that should be run concurrently. Kubernetes then schedules enough Pods to meet the minimum availability you define. Remember that each Pod may consist of multiple running containers, depending on how your application is configured.

When a Pod is created by a ReplicaSet, Kubernetes updates the Pod’s metadata.ownerReferences field to include the ReplicaSet’s identity. The ReplicaSet can then establish the Pods it controls, so it knows whether the minimum availability target has been met.

ReplicaSets have a replicas field that defines the number of Pods to run. Change this value and apply the updated ReplicaSet manifest to your cluster to have Kubernetes reschedule your Pods to match the new replica count.

This detail highlights an important point about ReplicaSets: Kubernetes only guarantees the number of running Pods will eventually match the replica count you’ve specified. If you change the replica count, there will be a period of time where more or fewer Pods are running than your manifest indicates. The ReplicaSet will create or delete Pods until the desired number are operational.

The manifest above would run three replicas of the my-image:latest container image using a ReplicaSet. You could change the number of replicas by updating the value in the manifest and re-applying it (kubectl apply -f my-manifest.yml).

Deployments

While ReplicaSets make it easier to work with Pods, they too are rarely used directly. Deployments are an abstraction atop ReplicaSets. You usually create a deployment when adding a new workload into a cluster.

Deployment resources enable declarative updates of Pods and ReplicaSets. They let you perform rolling updates of ReplicaSets, where Pods are rescheduled without any service downtime. The Pods and ReplicaSets are replaced individually, allowing old and new versions to briefly coexist.

The need for Deployments arose out of Kubernetes’ historical approach to replicas. ReplicaSets evolved out of Replication Controllers. Replication Controllers offered functionality similar to ReplicaSets but with built-in scaling support.

Replication Controllers did not offer declarative scaling though. You had to manually use kubectl rolling-update to scale the replicas without downtime. This was at odds with the declarative manifest-based approach of other Kubernetes resources.

Compared to ReplicaSets, the primary advantage of Deployments is their support for rolling updates. Changing the number of replicas in a ReplicaSet does not guarantee any number of Pods will remain in any given state during the rollout. With a Deployment, you can be sure your application will continue handling traffic, even if the Deployment hasn’t yet completed.

Today, Kubernetes advises using Deployments to represent your workloads. Your Deployments will run and scale ReplicaSets automatically; ReplicaSets will in turn manage your Pods. You can perform a rolling update of a Deployment by updating the replicas field in its manifest. Kubernetes will then ensure your application remains available throughout the change, allowing new and old Pods to temporarily co-exist.

The manifest above would create a Deployment consisting of three replicas, each running the my-image:latest container image. Changing the replicas value would trigger a rolling update of the underlying ReplicaSets and Pods.

Other Kinds of Resource

The three types of resource we’ve looked at are the most common objects you’ll encounter when working with Kubernetes. They are used to configure your application’s workloads and manage your containers.

You’ll need to use other kinds of resource type as you work more with Kubernetes. ConfigMaps and Secrets let you inject configuration into your Pods, enabling them to access outside values. Volumes and Persistent Volumes provide Pods with a shared writable filesystem that can be used to store data, instead of the default ephemeral storage that’s lost when the Pod exits.

A further set of resources help to manage your workload’s networking options. Services allow you to expose a set of Pods as a single network service with one IP address. Ingresses let you expose services externally. They route traffic into your cluster to a destination service based on attributes like hostname, port and URL path.

Finally, there’s meta-resources that describe your cluster. Namespaces are used to isolate individual workloads, preventing name collisions. You should usually create a new namespace for each of your independent workloads. Nodes are a kind of resource which represent the physical machines running your Pods. Each Node will usually host multiple Pods. Kubernetes works out how to schedule workloads based on the availability of each Node and the constraints you enforce.

You can view the full resource list for your cluster by running kubectl api-resources. In addition to the built-in resources, workloads can add their own Custom Resource Definitions (CRDs) which let you create new kinds of object. Kubernetes automatically provides API endpoints for Custom Resource Definitions.

Conclusion

Learning Kubernetes means getting acquainted with new abstractions and terminologies. While this makes for a broad API surface area, each Kubernetes object has a relatively narrow purpose.

You’ll often be able to stick with the high-level abstractions such as Deployments. You shouldn’t need to micro-manage fundamental resource types, like Pods, unless you have complex requirements that can’t be solved with Deployments and ReplicaSets alone.