In previous articles, we presented Kubernetes. We also explained how to install it. But before passing to using Kubernetes, we have first to learn how to create Kubernetes with YAML files through this Introduction to YAML.
YAML Basics
It’s difficult to ignore YAML if you’re doing anything related to Kubernetes. YAML, which stands for Yet Another Markup Language, or YAML Ain’t Markup Language is a human-readable text-based format for stating configuration-type information.
Using YAML for Kubernetes configurations gives you a number of advantages, including:
- Convenience: You’ll no longer have to specify all of your parameters to the command line.
- Maintenance: YAML files can be added to source control to track changes
- Flexibility: You can create much more complex structures using YAML.
YAML is a kind of JSON, which means that any valid JSON file is also a valid YAML file. So, if you know JSON and you are only going to write your own YAML, it would be easy for you.
Luckily, there are only two types of structures you need to know about in YAML:
- Lists
- Maps
You may have maps of lists and lists of maps, but if you understand these two structures, you’re all set: they are all you need to get started through this introduction to YAML.
YAML Maps
Let’s start with YAML maps. Maps let you associate name-value pairs, which is necessary when you’re trying to set up configuration information. Let’s take an example a YAML file that starts like this:
--- apiVersion: v1 kind: Pod
The first line is a separator and it’s optional unless you want to define multiple structures in a single file. From there, we have two values, v1 and Pod, mapped to 2 keys, apiVersion and kind.
The equivalent of the file above as JSON is:
{ "apiVersion": "v1", "kind": "Pod" }
Notice that in the YAML version, the quotation marks are optional: the processor can decide that you’re looking at a string based on the formatting.
We can specify more complicated structures by creating a key that maps to another map, rather than a string like this:
--- apiVersion: v1 kind: Pod metadata: name: my-website labels: app: web
In this case, we have a key, metadata, which has as a value a map with 2 more keys which are name and labels. The labels key itself has a map as a value. You can nest these two as far as you want.
YAML knows how all of these elements relate to each other because we’ve specified the lines. In this example I’ve used 2 spaces, but the number of spaces doesn’t matter as long as it’s 1 or more, and as long as you’re keeping the same spacing for the element of the same level. For example, name and labels are at the same level, so the processor knows they’re both part of the same map; it also knows that app is a value for labels because it’s indented further.
One other thing is to NEVER use tabs in a YAML file.
So if we turn this into JSON, it would look like this:
{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "my-website", "labels": { "app": "web" } }
Now let’s take a look at lists.
YAML lists
YAML lists are just a sequence of objects. For example:
args: - sleep - "10" - message - "Hello there!"
If we turn this into JSON, we will get the following form:
{ "args": ["sleep", "100", "message", " Hello there!" }
The good thing here is that the members of a list can be maps themselves:
For example:
--- apiVersion: v1 kind: Pod metadata: name: my-website labels: app: web spec: containers: - name: front-end image: nginx ports: - containerPort: 80 - name: my-rss-reader image: nickchase/rss-php-nginx:v1 ports: - containerPort: 88
So, as you can see here, we created a list of container “objects”, each one of them is consisted of a name, an image, and a list of ports. Each list item under ports is a map that lists the containerPort and its value.
Moving to its equivalent:
{ “apiVersion”: “v1”, “kind”: “Pod”, “metadata”: { “name”: “my-website”, “labels”: { “app”: “web” } }, “spec”: { “containers”: [{ “name”: “front-end”, “image”: “nginx”, “ports”: [{ “containerPort”: “80” }] }, { “name”: “my-rss-reader”, “image”: “nickchase/rss-php-nginx:v1”, “ports”: [{ “containerPort”: “88” }] }] } }
So esentially, no matter what structure you want to build, you can do it with those two maps and lists.
So, let’s move to an example and build our first Pod.
Creating a Pod using YAML
In our previous example, we created a simple Pod using YAML, here is the YAML content:
--- apiVersion: v1 kind: Pod metadata: name: mywebapp labels: role: webserver-role app: nginx spec: containers: - name: webserver image: nginx ports: - containerPort:80 - name: database-server image: mysql-3.6 ports: - containerPort:3306 volumes: - name: webserverr-storage emptyDir: {}
- Taking it apart a piece at a time, we firstly start with the API version: and here it has just the value v1.
- Next, we’re specifying that we want to create a Pod; we instead specify a Deployment, Job, Service, and so on, depending on the resource we’re trying to create.
- Later, we specify the metadata: and Here we’re stating the name of the Pod, as well as the label we will use to identify the pod to Kubernetes.
- Finally, we will specify the actual objects that the pod have. The spec property contains containers, storage volumes, or other components that Kubernetes requests to know about, as well as properties like whether to restart the container if it fails. You will specify a full list of Kubernetes Pod properties in the Kubernetes API specification.
You can create the pod with the following command:
kubectl create -f pod.yaml
Creating a Deployment using YAML
Before creating the deployment, you should remember as well that the deployment itself is a set of resources to be managed as one unit. And also remember that one reason to use Kubernetes is for redundancy of the resources, mainly through via replicas and replicasets. So one of the things we should specify in a deployment is the number of the replicas under the “spec” key. The main specifications to include while defining a deployment via YAML are apiVersion, kind, metadata, and spec.
Here is an example for Creating a Kubernetes deployment via YAML:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchlabels: app: nginx template: metadata labels: app: nginx spec: containers: - name: webserver image: nginx ports: - containerPort:80 - name: database-server image: mysql-3.6 ports: - containerPort:3306
From the YAML file above, we have specified the following statements:
- this deployment should always have exactly 3 running replicas.
- Because deployments are sets of objects, we have to specify what objects of this deployment under the template part: the specification ensures that we are creating only the correct pods for this deployment. And for that, we used the “selector.matchlabels” specification. In this case, only those pods that match the desired label (which is app:nginx) will be included in this deployment.
- We created 2 pods in this deployment which are webserver and database-server: Their specs are also included here.
You can create the deployment with the following command:
kubectl create -f deployment.yaml
Creating a Service using YAML
After defining the pods and the deployment to create those pods, we need a way to access pod-set even if the pods themselves are recreated or lost. And this should be transparent to any application or other pods trying to access this pod-set. And to do so, we will use a Kubernetes service:
Here is an example of service definition in Kubernetes in YAML:
apiVersion: v1 kind: Service metadata: name: nginx-service labels: app: nginx spec: ports: - nodePort: 30500 port: 80 protocol: TCP targetPort: 80 selector: app: nginx type: NodePort
From the YAML file above, we have specified the following statements:
- The service name is “nginx-service” with a selector that has the app: nginx label to match and identify the pods in Nginx deployment. Since the deployment and the pods have the exact same label, all incoming requests to this service will be automatically routed to the Nginx deployment.
- This service is of type NodePort and it points to the Nginx deployment. Using NodePort, we can access the Nginx service on all Kubernetes nodes via port 30500.
You can create the service with the following command:
kubectl create -f service.yaml
Just as with deployments and pods, services have many more specifications you can define for services.
Thought this tutorial, we have presented an introduction to YAML to create different Kubernetes. We will have the chance to describe them further in the coming articles.