How YOU actually use Kubernetes, starring YAML files
Follow me on Twitter, happy to take your suggestions on topics or improvements /Chris
I've described concepts such as Minkube, Pods, Nodes, Services and more over the course of four articles. Although educational you are likely to use Kubernetes in a different way than how I been showing you so far, you are likely to use YAML files
YAML files are files that let us define a configuration of whatever it may be.
YAML as in Y A M L, aka Y M C A? 😃
No, not like that, more YAML as in Camel
Oh ok, tell me more
YAML actually stands for "YAML Ain't Markup Language" even though it from the beginning stood for Yet Another Markup Language. The reason for changing its meaning was to make clear its purpose as data-oriented, rather than document markup.
Yep, you got it, it's a recursive definition. It's also called a human-readable data serialization language.
Thanks for the history lesson, what about its role in Kubernetes?
As we said before we've been showing you Kubernetes usage by using the command line and that ain't quite how people use it.
Let me guess I use YAML files
Right, every single thing you can describe and deploy to Kubernetes can be described as a YAML file. It's actually simpler that way as well. But before we talk about specific Kubernetes usage we need to know some basics about the YAML files, so to understand the file when we are looking at it
I'm gonna need coffee for this right?
Resources
This article isn't really part of a series but I have written other parts on it. If you are completely new I recommend reading part I first below
Part I - from the beginning, Part I, Basics, Deployment and Minikube In this part, we cover why Kubernetes, some history and some basic concepts like deploying, Nodes, Pods.
Part II - introducing Services and Labeling In this part, we deepen our knowledge on Pods and Nodes. We also introduce Services and labeling using labels to query our artifacts.
Part III - Scaling In this part, we look at scaling using desired state. We specify how many Pods we want and let Kubernetes do the heavy lifting in terms of ensuring that your Pods are scaled up to the desired number but also maintaining it by using something called self-healing.
Part IV - Auto scaling This is how you likely will carry out scaling in Kubernetes by looking at CPU usage
Below is some more resource that I recommend you have a look at when Kubernetes is starting to click:
- Horizontal Pod Auto scale This describes in detail how everything works. On a flow as well as API level
- Free Azure Account If you want to try out AKS, Azure Kubernetes Service, you will need a free Azure account
- Kubernetes.io One of the best resources to learn about Kubernetes is at this official Kubernetes site by Google.
- Kubernetes overview An overview of Kubernetes, all its parts and how it works
- Kubernetes in the Cloud Do you feel you know everything about Kubernetes already and just want to learn how to use a managed service? Then this link is for you
- Documentation on AKS, Azure Kubernetes Service Azure Kubernetes Service, a managed Kubernetes
- Best practices on AKS You already know AKS and want to learn how to use it better?
The YAML format
What do we need to know about the format to be able to work with it? Well, YAML is a superset of JSON which makes a JSON file a valid YAML file. That's an interesting piece of information but really want to know is the structures used within namely:
- Maps
- Lists
Ok, show me
Maps
Let's start with creating a file, let's call it config.yaml
:
---
version: 1
name: some value
2
3
This above right here contains some useful insights on the YAML format. The ---
is called a separator and is optional unless we have more than one structure in the file. What we see after that is version
and name
. The key is separated by its value with :
.
This is supposed to be a superset of JSON right, aren't we missing double quotations?
Ah, sharp eyes, double quotations ""
are actually optional. Why write more than you have to right? So the above corresponds to the following in JSON:
{
"version": "1",
"name": "some value"
}
2
3
4
The above is a map, but one of the keys in your Map can point to a map in turn, like the below example:
---
version: 1
name: some value,
address:
street: One Microsoft Way
city: Redmond
country: USA
2
3
4
5
6
7
Lists
Ok then, let's look at our next format lists. Consider the following example:
version: 1
todos:
- shop
- clean
- do math
- write essay
2
3
4
5
6
todos
in this case is the list type and this would correspond to the following in JSON:
"version": "1",
"todos": ["shop", "clean", "do match", "write essay"]
2
What about list items that are maps?
That's simple:
created: 2019-01-01
items:
- quantity: 2
price: 10
discounts:
- id: 1
displayName: 10% off
- id: 111
displayName: Holiday Sale
2
3
4
5
6
7
8
9
The above would correspond to the following JSON:
{
"created": "2019-01-01",
"items": [{
"quantity": 2,
"price" : 111,
"discounts": [{
"id": 1,
"displayName": "10% off"
}, {
"id": 111,
"displayName": "Holiday Sale"
}]
}]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
I get it, I think. What about Kubernetes?
Oh, one more thing before we turn all Kubernetes. Tabs = NOT cool. Spaces are what you use but be consistent, if you start using 2 spaces, usee that throughout.
YAML In Kubernetes
Most of the things you can deploy to a Cluster in Kubernetes can be described as a YAML file. There are some obvious advantages to that:
- Saving your fingers: No more typing long constructs on the command line
- Source control: YAML files can be stored in source control and thereby we can track changes
- Flexibility: You’ll be able to create much more complex structures using YAML than you can on the command line
So what are we going to describe in YAML then? We will not only describe but deploy the following:
- Pod, Pod is the smallest possible deployable unit. I know know, you usually don't deploy just a Pod, for the sake of practice lets do it this once
- Deployment, this is more on the level of what we would want to deploy. It gives us the ability to defines replicas among other things
Describe and deploy a Pod
Lets build up YAML file for a Pod gradually and finish off by deploying to the Cluster. Ok, here we go:
—--
apiVersion: v1
kind: Pod
2
3
We start by specifying an apiVersion
. Then we continue with specifying kind: Pod
. Now this one is important. This can be many different types like a Deployment or a Service for example, Pod it is.
Metadata The next part of our file is the metadata part. Here we give it a name and also a label:
metadata:
name: My Pod
labels:
app: web
2
3
4
Specification
Now we come to the part where we describe the parts that make up the Pod.
spec:
containers:
- name: first-app
image: gcr.io/google-samples/kubernetes-bootcamp:v1
ports:
- containerPort: 8080
2
3
4
5
6
All put together our pod.yaml
file should now look like this:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: web
spec:
containers:
- name: first-app
image: gcr.io/google-samples/kubernetes-bootcamp:v1
ports:
- containerPort: 8080
2
3
4
5
6
7
8
9
10
11
12
Deploying our POD YAML
At this point we want to deploy it to a cluster. So we will talk to our old friend again, minikube
and kubectl
.
Sometimes my minikube
is a bit slow so I restart it with the command minikube start
. Once that command has finished running let's check the pod situation with:
kubectl get pods
It should list all the Pods that are currently up and running:
As you can see above we have done a fair bit of experimenting in the past and created all sorts of Pods, this will obviously look different for you.
Thereafter let's take our pod.yaml
file and create a Pod from it. To do that we run the command:
kubectl create -f pod.yaml
Which simply means create a Pod from a file -f
, with file name pod.yaml
. The result of this command is:
The result of the command implies we got a Pod created, let's rerun our pods listing command:
kubectl get pods
This time around our new Pod is up and running. But of course, deploying just a Pod like this is no good. The reason is that Pods are mortal, if it goes down, its gone. No service will bring it up again.
So why even show it?
It might be educational to show how you can create an artifact from a file but from a Kubernetes standpoint, it's not using all the wonderful services that could keep it alive if something happens. After all, that's why we have Kubernetes, for the resilience.
Therefore, let's look at a deployment next.
Before we continue let's clean up after ourselves with:
kubectl delete pods my-pod
This trigger something called a graceful termination, which is the recommended way of doing things. If you are impatient though you can force delete it with the following command:
kubectl delete pods my-pod --grace-period=0 --force
We of course delete the graceful way so after a while we get this:
Were you to run kubectl get pods
our pod is now gone. All our app data, gone, vamose.
I get it, take it easy, I won't create Pods directly, can we continue?
Deployment
Ok then, deployments, the right way of doing things.
We will use something called a ReplicationController
. Now, this is technically an older concept that is gradually being replaced by Deployment
s which are a high-level concept managing the deployment of ReplicaSets
. There are issues on dashboard support and other things still, which makes all these similar concepts hang around to confuse us a bit more 😉 Bottom line is its ok to use these older concepts for still some time.
This time around we will define a new type of object, a so-called ReplicationController
. Now, this is a deployment that not only points out what image to deploy to a Pod but also how many Pods we want any given point, a so-called desired state. Let's have a look at the file, starting from the top:
apiVersion: v1
kind: ReplicationController
metadata:
name: my-rc
2
3
4
We define the kind
as of type ReplicationController
instead of Pod
and we go on to name it in the metadata as my-rc
. Now let's head down to the specification part:
spec:
replicas: 5
selector:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: my-first-app
image: gcr.io/google-samples/kubernetes-bootcamp:v1
ports:
- containerPort: 8080
2
3
4
5
6
7
8
9
10
11
12
13
14
The really interesting part here is replicas
, the number of Pods and the rest of it is mainly us pointing out the same image again.
The specification looks slightly different at the top level, as it is a ReplicationController but the inner spec
is what we are used to, pointing out the image, port and other things. Let's see the full file that we name rc.yaml
:
apiVersion: v1
kind: ReplicationController
metadata:
name: my-rc
spec:
replicas: 5
selector:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: my-first-app
image: gcr.io/google-samples/kubernetes-bootcamp:v1
ports:
- containerPort: 8080
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
We create the above deployment based on the file by typing:
kubectl create -f rc.yaml
Above we see that our replication controller is created.
Lets list all our pods right now and make sure we get as many pods as expected:
kubectl get pods
Looking at the above listing we see that we have 5 replicas, 5 instances of our Pod. We could try and delete one and see what happens:
kubectl delete pods my-rc-wx6h7
It tells us the above Pod is deleted so we wait for the graceful deletion to finish and then we list our Pods again and this is what we get:
As you can see above, our specific Pod is deleted but it's being replaced by another one, the number of replicas is intact, Kubernetes is doing its job
So how do we bring it down, garlic, a stake?
Let's start by listing all replication controllers:
kubernetes get replicationcontroller
Now there are two way we can bring it down, garlic or deletion 😉
Yea yea very funny, deletion, tell me more bored
It's as simple as typing
kubectl delete replicationcontroller [name of replication controller]
What happens if you do the above is that it will not only delete the replication controller but the all the pods with it, so-called cascading delete. If you just want the replication controller gone you can specify --cascade=false
. We want it all gone so we just type:
kubectl delete my-rc
That should remove all of it. If we run kubectl get replicationcontroller
it should be gone. Let's run kubectl get pods
and make sure the pods are gone too.
Let's take away the other replication controller as well, it's been hanging around my system for far too long:
kubectl delete replicationcontroller my-rc
Quickly hit:
kubectl get pods
and you will be able to see the Pods being terminated:
Summary
In this article, we talked about the file format YAML, what it is, how it works. We also discussed how we should be using YAML files to configure our Kubernetes experience. Furthermore, we showed how to deploy Pods but also ReplicationControllers
. Hopefully, this was educational and gave you a taste on what real Kubernetes management looks like.