Overview of Kubernetes
Let’s get to it!
It is possible that you may have heard about Pods, Deployments, Configmaps, and the like. If you haven’t, then you are about to! :smile:
Note: the examples we reference here can also be found in the examples sudirectory.
Pods
By now we know that Kubernetes is a “Production-Grade Container Scheduling and Management”. Now, we have to figure out what to put in containers…
Containers are designed for you to run 1 process in them. They are not entire machines! They should not ron daemonized applications, you shouldn’t have nginx sending over reuests to your web app, or anything of the sort. You get one process so use it wisely!
However, you may need to have multiple processes working together. Have you heard of Istio, Linkerd, or any of the other tens of service meshes? What they do, is that they run a sidecar container with your “application”. This sidecar container may handle networking, telemetry, what have you. Thus you get to focus on your app and the othe container that runs with your app will help you out (no need to bake additional logic into your application).
To enable this pattern, Kubernetes packages one or more containers in a Pod.
(If you are familiar with ECS/Fargate you may have workedwith tasks).
The most common way of running thins in Kubernetes is by using YAML. Time for an example! Let’s run a container that uses ubuntu 18.04:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- image: ubuntu:18.04
name: bash
args:
- "sleep"
- "999"
Now, create the pod!
kubectl apply -f examples/pod.yaml
You can look at the pod by running
kubectl get pods
and delete it by running
kubectl delete -f examples/pod.yaml
ReplicaSets
tl;dr: pods package applications.
Another thing you may see or hear every now and then are ReplicaSets.
ReplicaSets help you scale your app.
ReplicaSets have a similar structure to Pods:
apiVersion: ...
kind: ...
metadata:
...
spec:
replicas: N
selector:
matchLabels:
...
template:
The apiVersion, kind, metadata, and spec are in almost all Kuberentes
resources, so this you will see most of the time.
Within the spec field, however you see some new fields:
replicas: specifies the number of replicas of a given pod that you want to run.selector.matchLabels: like many objects in Kubernetes, ReplicaSets are managed by a Kubernetes component (a “controller”). This controller is an application, and this application finds pods through “labels” (labels are attached to Kubernetes resources, they are essentially more metadata). So in theselector.matchLabelsfield you tell Kubernetes how the Pods for this ReplicaSet will be labeled.template: this is where you specify the pod template (or pod spec!!) that the replicaset is to use to create pods!
Let’s now create a replicaset that runs 2 replicas of the pod in the previous section. The replicaset definition will now look like this:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: my-rs
spec:
replicas: 2
selector:
matchLabels:
app: ubuntu
template:
metadata:
labels:
app: ubuntu
spec:
containers:
- image: ubuntu:18.04
name: bash
args:
- "sleep"
- "999"
Create it
kubectl apply -f examples/rs.yaml
Inspect it
kubectl get replicasets
Inspect its pods
kubectl get pods --show-labels
And delete it
kubectl delete -f examples/rs.yaml
Deployments
tl;dr pods package applications and replicasets allow you to scale your pods.
Deployments are where it is at! :rocket: Deployments are an abstraction on top of ReplicaSets; Deployments manage ReplicaSets! So for the most part, you want to be writing Deployments instead of ReplicaSets.
We previously mentioned that replicasets manage pod replicas. Well, deployments manage replicasets!
There are many features that Deployments bring to the table but the number one is the ability to manage version updates. what if you want to bump your app to its latest version? If you already have a deployment running, then that deployment will have a replicaset, and that replicaset will be “managing” some pods. If you now update your deployment to use a new container image version then the deployment will create a new replicaset, and this new replicaset will then create pods based on the newer version. As the new pods come to live, the old replicaset will slowly decresed its desired replica count, thus killing the old pods until we replace all the old pods with ones running the latest version.
And now time for another example! A deployment looks very much like a replicaset. You can compare this to our previous example:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deploy
spec:
replicas: 1
selector:
matchLabels:
app: ubuntu
template:
metadata:
labels:
app: ubuntu
spec:
containers:
- image: ubuntu:18.04
name: bash
args:
- "sleep"
- "999"
You can create the deployment
kubectl apply -f examples/deploy.yaml
You can inspect the deployment
kubectl get deployments
You can inspect its replicaset
kubectl get replicasets --show-labels
Its pods
kubectl get pods --show-labels
and to clean it up
kubectl delete -f examples/deploy.yaml