Pods, services, deployments... what do I use when?

By: Scott Coulton, Microsoft Developer Advocate, CNCF Ambassador, and Docker Captain

When you first start your Kubernetes journey, the first thing you need to learn is how to deploy an application. There are multiple resource types that you can use to do this which include: pods, deployments and services.  In this blog post we will first explain what each resource type does and then when and why you would use that resource type. The first type we will use is pods.

Pods

A pod is the lowest unit of an application in Kubernetes. Now, before we move on, we need to get one thing straight — and that is a pod is not equal to a container in the Docker world. A pod can be made up of multiple containers.  If you have come from a pure Docker background, this can be hard to wrap your head around. If a pod can have more than one container, how does it work? There are some limits we need to be aware of. A pod has the following:

  • A single IP address
  • Share localhost
  • A shared IPC space
  • A shared network port range
  • Shared volumes

The containers in a pod talk to each other via local host, whereas pod-to-pod communication is done via services. Pods are a great way for you to deploy an application, but there is some limitation to the pod resource type. A pod is a single entity, and if it fails, it cannot restart itself; this won’t suit most use cases, as we want our applications to be highly available. Don’t worry, Kubernetes has this issue solved, and we will look at how to tackle high availability further on in the post.

Services

If we want to have connectivity to our pods, we will need to create a service.  In Kubernetes, a service is a network abstraction over a set of pods. This allows for the traffic to be load balanced for failures. A service allows Kubernetes to set a single DNS record for the pods. As we mentioned earlier, each pod has a separate IP address. With the service resource type, you would usually define a selector like the example below:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp

In addition to this, kube-proxy also creates a virtual IP in the cluster to access the service. This virtual IP then routes to the pod IPs. If the pod IPs change or new pods are deployed, the service resource type will track the change and update the internal routing on your behalf.

A picture containing screenshot

Description automatically generated

Replication controller

Now in the pod section of the post, we discovered that pods are mortal, and if they die, that is the end of them. What if you want to have three versions of the same pod running for availability?

Enter the replication controller.

The main responsibility for the replication controller is to prevent against failure, and it sits above the pod resource type and controls it. Let’s look at an example. I want to deploy 4 of my pod x, this time I would create a replica set. A replica set has a defined number of pods that needs to be running, in this case 4. If one of the pods fails or dies, the replication controller will start a new pod for me and again, I will have 4 of pod x running. So, this functionality looks after the issue we mentioned earlier about pods being mortal. Now, a replica set sounds like we have everything we need, right? What about the lifecycle of the pods? Say we want a new version, how do we upgrade the pods without downtime? A replication controller does not look after this.

Deployments

So, we have learnt about pods, services, replica sets, and, now the last piece of the puzzle: deployments.

The deployment resource type sits above a replica set and can manipulate them. Why would we want to manipulate a replica set? Replica sets are all or nothing. If you need to do an upgrade, you need to replace the replica set. This action will cause downtime to your application.

One of the main benefits of Kubernetes is high availability. Deployments give us the functionality to do upgrades without downtime. As you do in a replica set, you specify the number of pods you would like to run. Once you trigger an update a deployment will do a rolling upgrade on the pods, all while making sure the upgrade is successful on the pod before moving to the next one. This is awesome!

So, this sounds like we have what we need to deploy and upgrade our application on Kubernetes. But what happens if we rollout a new version of our application and something goes wrong? Deployments have us covered there as well, as we can just as easily rollback a deployment. There is one caveat to this: if you are using a pvc (persistent volume claim) and have written something to the claim. That will not be rolled back. The other thing to remember is that deployments control replica sets and replica sets control pods; this means that when you use a deployment resource type, you can't forget that you still need a service to access it.

A close up of a map

Description automatically generated

In a production environment the recommendation would be to use deployments for our applications within Kubernetes.  

In saying that, I still think it's important knowledge to have in your tool box to understand how deployments work and the other resource types that it controls.

About: Scott Coulton

Scott Coulton is a Developer Advocate, CNCF Ambassador, and Docker Captain with 10 years of experience as a software engineer in the managed services and hosting space. He has extensive experience in architecture and rolling out distributed compute systems and network solutions for national and multinational companies with a wide variety of technologies, including Azure, Kubernetes, Puppet, Docker, Cisco, VMware, Microsoft, and Linux. His design strengths are in cloud computing, automation, and security space.

Twitter: https://twitter.com/scottcoulton
LinkedIn: https://au.linkedin.com/in/scott-coulton-22864813
Github: https://github.com/scotty-c

Show Comments