An Introduction to Kubernetes ☸️

This video features Markus Holtermann at DjangoCon US 2021 in Online.

An Introduction to Kubernetes ☸️
0:23:18
Published October 21, 2021
858 views

You've heard of Kubernetes ☸️. But unless you’ve worked with it or seen it in action, you probably only have a vague idea of what it is. Let me give you an introduction so you can confidently say "I know Kubernetes!"

This talk was presented at: https://2021.djangocon.us/talks/an-introduction-to-kubernetes/

LINKS:
Follow Markus Holtermann 👇
On Twitter: https://twitter.com/m_holtermann
On GitHub: https://github.com/MarkusH
Website: https://markusholtermann.eu

Follow DjangCon US 👇
https://twitter.com/djangocon

Follow DEFNA 👇
https://twitter.com/defnado
https://www.defna.org/

Video production by the speaker and DjangoCon US 2021 Volunteers.

Summary

Kubernetes is a distributed system and container orchestrator that runs workloads in pods across manager and worker nodes, aiming for eventual consistency, recovery from failures, and straightforward scaling. The speaker explains core resources—including namespaces, pods, services, ingresses, ConfigMaps, Secrets, and Deployments—and shows how YAML and kubectl are used to define and manage them. For Django, the practical requirements are to configure allowed hosts, secrets, debug settings, and database access through environment variables, then use a container entrypoint to wait for the database, apply migrations, collect static files, and start Gunicorn.

Key takeaways

  • Kubernetes runs containers inside pods, which are scheduled onto nodes and can be restarted or replaced when failures occur.
  • Deployments manage replicated pods and support rolling updates, while pod and node affinity control where workloads run.
  • Services route traffic to matching pods, and ingresses provide HTTP reverse-proxy routing to services.
  • Namespaces scope resources, while ConfigMaps and Secrets provide reusable application configuration and credentials.
  • A Django container can use an entrypoint to wait for PostgreSQL, run migrations, collect static files, and launch Gunicorn.

Summarised automatically from the transcript.

Transcript

2,698 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:32

Hello everyone, and thank you for tuning in to my introduction to Kubernetes. In an in-person event, I would have started this talk by asking you to raise your hands when you have heard of Kubernetes. I would have continued with a question about who uses Kubernetes. And then I would have hoped that I'm in the right room for the audience. But unfortunately, DjangoCon US 2021 needs to happen online again. So I'm assuming you are here because you want to get to know more about Kubernetes. This talk should be a brief introduction into what Kubernetes is and how it works.

1:18

Not on the low level, but more the part that's interesting to you and me as software developers In the end, I also want to give you all the information that you need in order to deploy your Django project in a Kubernetes cluster. Before I begin, let me briefly introduce myself. Some of you may know me from my engagement in the Django project. Historically, I've primarily contributed to its migration system. Over time, my focus shifted to organizing some Django cons in Europe and Australia. As well as being a member of its operations and security teams. In my day job, I'm a staff engineer and team lead at Microbiolytics.

2:07

I'm responsible for our cloud infrastructure and software. At Microbiolytics, we built hardware and software to analyze chemical liquids and try to revolutionize and modernize the industry in the context of industry 4. 0. So, what is Kubernetes? First and foremost, Kubernetes is a distributed system to run containers. It can not only run Docker containers, but also others. Another term would be orchestrator. However, you can't just run a container. The smallest deployable object in Kubernetes

2:53

is a pod. A pod runs at least one container, and pods ensure that their containers are restarted if needed and desired. Or they vanish when all containers are terminated. I'll go into the bit more detail on pods in a moment. For now, let's look at how you'd communicate with Kubernetes. You generally talk to a REST API that's run on manager nodes. The counterpart to those nodes are worker nodes. Those nodes actually run the pods and thus the containers. You interact with Kubernetes using a command line tool called kubectl or QL or sometimes called kubectl.

3:41

Another property of Kubernetes is its eventual consistency. That means Just because you told Kubernetes to do something, and just because the API responded to you with okay, it doesn't mean it's done. Some operations may take a while. It's also eventually consistent because it can deal with fault, to a degree at least. If a container dies, Kubernetes can restart it. Or when a worker node is offline, Kubernetes will automatically start the containers on other worker nodes. And maybe even it will start a new worker node.

4:27

Let's look at the diagram what Kubernetes could look like on a high level. We'll start with the overall cluster. A cluster is typically standalone. However, you could run multiple clusters that interact with each other through typical network interfacing. Within a cluster, you have nodes. In the chart here, I'm using three. When you run Kubernetes locally on your computer, you typically only have one node But any somewhat serious cluster would have at least th two nodes, or even better, three. This is mostly or actually solely for reliability and redundancy.

5:13

Notes can either be physical bare metal servers or VMs in your cloud provider, such as EC2 instances. In fact, if you are using Kubernetes on any cloud provider, like AKS, EKS, GKS, etc. they use their underlying VMs. And if you want your cluster to survive a data center fire, you would make sure to spread the nodes across different data centers and set up proper network communication between them. Again, the typical cloud provider, they do that for you automatically when you spin up any of their hosted Kubernetes services

6:02

As mentioned earlier, on the nodes we have pods. They are spun up on the nodes that have the required resources available. There either exists just a single instance of a pod, like the one with the pastel yellow background here, or pods exist multiple times. This is, for example, as part of something called a deployment, which starts the same pot multiple times to provide redundancy. For example, the blue and green pods exist two times each, and the orange and red ones three times. For the orange one, something called a pod anti-affinity is defined, in order to prevent the same pod from being run

6:52

more than once per node. This is a good idea to ensure the downtime of one node doesn't cause a disruption to the surface by taking a lot of pots down. In contrast, the red pods do not define a pod anti -affinity, since the same pod is run twice on node 3. Similarly, there's something called pod affinity, which could be set for the green and blue pods to ensure they are run on the same node. A typical use case for this scenario is a lot of network communication between those two pods. And in doing so, you can reduce Internet traffic

7:37

And thus reduce the latency in these network communications. There's also a concept called node affinity, which lets you pin a pod to a specific type of node. For example, if you have some software that uses GPUs for computation, you could have a few expensive nodes with GPUs. and use node affinity to ensure only software is run there that needs to run on this GPU nodes And lastly, let's look into the pods. They can run containers. As mentioned earlier, they run at least one. It's important to remember that all containers within a pod

8:24

run on the same node. Now that that settled, what are the key concepts that you as a developer, engineer, or dev ops person will be exposed to? Generally speaking, in Kubernetes, everything is a resource. We've seen one of them already, pods. A resource consists of a kind, which defines what type of resource you're talking about, and each kind also exists in at least one version. And each resource has some metadata attached, such as its name, a unique identifier, creation timestamp, labels, annotations, and a lot more

9:15

Resources can exist either cluster wide, or they exist within a namespace. Namespaces are a cluster resource as well. They are cluster scoped, which means each namespace can only exist once in a cluster, but ports are namespace scoped, so each port exists once in a namespace. But within different namespaces, the port can exist more than once. You could, for example, create namespaces for development, staging, and production, and then have other resources within those namespaces. After all this theory, let's look at some basic resources.

10:04

Their code and how to use them. I won't be able to give a finite list of bu these building blocks, because I'd never finish writing that list. It's endless. I limit myself to some essential ones. But rest assured there's a ton more I've already mentioned namespaces. They are a key resource because other resources exist on either a cluster level or a namespace level. And what you can see here on the left is a YAML definition of what a namespace resource could look like. The schema is very much the same for all the other resources.

10:50

There's an API version, there's the kind, and some metadata, such as the name. When interacting with Kubernetes, you typically use the command line tool called kubectl as mentioned earlier. For example, to get a list of all namespaces, you would use kubectl get namespaces. You can also create new or update existing resources. The apply command, for example, updates an existing resource or creates a new one if it doesn't exist yet. And you provide it with a file. So if you place the content on the left in a file called kds

11:37

namespace. yaml And use kubectl apply. Kubernetes will create the namespace, which we can see in the list of namespaces once we run kubectl get namespaces again. As already mentioned, there are pods. In our example, we use a container image traffic who am I and name the container who am I. Kubernetes uses the container name to uniquely identify the container within a port. We also define the port that the container exposes and give it the name HTTP. And lastly, we put some labels on the pod.

12:25

We'll use them later to tell Kubernetes where to route network traffic to. Similarly to the namespace, you can use kubectl getPods to get a list of all pods. However Unless you specify the namespace using dash n, Kubernetes is going to use the default namespace Also, did you notice that we defined the namespace in the resource? Well, because of that, we don't need to provide it when we apply the YAML file using kubectl. However, it's still good practice. Great, now that our pod is running, how do we access it? Well

13:11

For that, we need to do some network routing. No worries, you don't need to fiddle around with IP addresses, net masks, and such. The network routing on the level that we are concerned with here happens through a resource type called services. Services bundle traffic on an incoming IP and port and route it to one or more ports, which in turn route it to the corresponding containers. Using the selector, Kubernetes looks up all pods in the same namespace that have the given label. If they define a port HTTP, the service is going to include them in its routing.

13:58

Which means you can scale out your service by deploying more ports we just saw. As long as the label and port match, they are automatically picked up, which makes scaling out or scaling horizontally very very easy. Now, since they're using HTTP here, we also probably want to use something called an ingress definition. Compared to typical deployments, this ingress definition is your reverse proxy. In the example here, we'll be using Nginx. That's the de facto standard in the Kubernetes world. But there's heaps of others as well. For example, traffic.

14:46

In recent Kubernetes versions, the ingress resource has become a bit more complex. But you'll get used to them eventually. When the HTTP request host is example. com, we'll redirect everything underneath a single forward slash to our Who Am I service on port HTTP, so port 8080. In the case of a two-layered application, where your front end is running in a different container than your backend, You could, for example, send each request that starts with slash API to your back-end service, and everything else to your front-end service.

15:31

A concept that has been around for a very long time is the twelve factor app. This means Among eleven other factors, that applications should be configured using environment variables. And we can do that in Kubernetes as well We can either hard code configuration options in port definitions, or using config maps or secrets, which we can then reuse in different pods. There are a few differences between config maps and secrets, but I'm not going into that difference here. That's beyond the scope of this talk. Let's just say the letter is where you store secrets like the secret key and the database URL.

16:20

While config maps contain a value in its clear text, the secrets in val in the secrets file are typically base sixty four encoded. So they are not encrypted, just encoded, so they're still readable. The last Kubernetes resource we're going to look at is a deployment. It's a way to tell Kubernetes to run pods using a given template a certain number of times. What you find here on the one hand side is the replicas, which is set to three in the example. Kubernetes will run three identical pods. We also see a template that defines how a pod should look like.

17:08

Some exceptions aside, you can put everything within the template that's available to the pot resource What you can also see here are two ways to define environment variables in a plot. We define an environment variable sum secret with a value that is read from a Kubernetes secret. And we load the entire config map as environment variables. Every entry, every key in the config map will be the name of an environment variable and the corresponding value, the corresponding value in the environment variable. Once applied, you'll see how Kubernetes spins up three additional pods.

17:53

Their names are somewhat randomly generated. And when you change something in the deployment resource, Kubernetes is going to start new ports. By default, one pod at a time, Kubernetes is starting a new one, waiting for it to be available, and then terminating an old one, until all pods are gone. Well, now that the basics are clear, what do we need to do for Django to work with Kubernetes? It turns out it's only a few things, and only one of them is specific to Kubernetes. Django

18:38

requires you to set a list of allowed hosts. We'll do that using a config map. The first host in this list is probably clear. It's our domain that we want our app to be available on. The second uh value in this allowed hosts is the Kubernetes internal domain name. Using the service name dot namespace name allows you to talk to any service within the cluster, which is pretty neat. Looking at the settings, I've included the ones that are relevant for the deployment in our case. Django will fail to start when no secret key is provided.

19:28

Which is a good thing because then you require and can ensure that we you have actually set a secret key and not accidentally use the secret key that you use for testing. Turning off debug by default is the same good idea. Turn it on when you need it, but have it set to false by default. So by setting an environment variable called debug to the value true, the lowercase string true, we turn on debug. The allowed hosts are string split at a comma as mentioned earlier. And the database settings are retrieved using the wonderful library

20:14

DJ Database URL. In our deployment, we refer to the config maps and secrets in their entirety, and not only key by key. In doing so, we can far more easily reuse the configs, maps, and secrets in other deployments or in other container definitions. Such as when we want to run salary, we need another pot or at least another container where we probably need the same settings. And then there's a bit of a Docker file. I use an entry point script which will be called and defined

20:59

the startup process of the container. The default command is gUnicon though. The entry point, on the other hand, does four things. Firstly, it checks if it can connect to the database. In the Postgres world, there is a pgready command, but that requires specific environments variables to be set. Using Django's db shell is much easier because you can just rely on Django's settings. Secondly, it applies all migrations. This can be quite tricky But proper testing and carefully considering the implications of migrations between two releases make it possible.

21:45

I've used that pattern and have seen it work quite well for a few years now. You can also check out my talk from this year's DjangoCon Europe with more details on this topic and how to deploy migrations and use migrations. Thirdly, we are collecting static files. And lastly, we run the command passed into the container. So by default, gUnicon. But if you want to jump into a Django management command or the Django shell, you can pass in Django admin shell, for example. And that's it.

22:31

I open the talk with the question: what is Kubernetes? And what can I say? This is Kubernetes. Thank you.

Questions this talk answers

What is Kubernetes and how does it work?

Kubernetes is a distributed system and container orchestrator. It runs containers in pods on worker nodes, is controlled through an API and kubectl, and can recover from failed containers or nodes by restarting or rescheduling workloads.

Discussed at 2:07

What is a Kubernetes pod?

A pod is Kubernetes’ smallest deployable object and contains at least one container. Its containers run together on the same node, and the pod manages their lifecycle, including restarting them when appropriate.

Discussed at 2:53

How do Kubernetes services route traffic to pods?

A Service provides a stable incoming IP and port, then selects pods by label and routes traffic to matching named container ports. Adding more matching pods automatically scales the service horizontally.

Discussed at 13:11

What is a Kubernetes Ingress used for?

An Ingress acts like a reverse proxy for HTTP traffic, routing requests based on the host or URL path to Kubernetes Services. It can, for example, send `/api` requests to a backend and other requests to a frontend.

Discussed at 13:58

How do Kubernetes ConfigMaps and Secrets work?

ConfigMaps and Secrets provide reusable configuration through environment variables or pod definitions. ConfigMap values are stored as clear text, while Secret values are typically Base64-encoded rather than encrypted, making Secrets suitable for values such as Django’s secret key and database URL.

Discussed at 15:31

How do Kubernetes Deployments update and scale pods?

A Deployment defines a pod template and the desired replica count, causing Kubernetes to run that many identical pods. When the Deployment changes, Kubernetes performs a rolling update by starting replacement pods, waiting for them to become available, and then terminating old ones.

Discussed at 16:20

What does a Django project need to run in Kubernetes?

Django needs Kubernetes-provided configuration for allowed hosts, a required secret key, disabled debug mode by default, and database settings, usually supplied through ConfigMaps and Secrets. The container entrypoint can wait for the database, apply migrations, collect static files, and then start Gunicorn or another requested Django command.

Discussed at 18:38

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos by Markus Holtermann

More videos from DjangoCon US