YAML’s official definition is a “human-friendly, data serialization standard for all programming languages.” YAML’s main advantage over other similar formats like JSON or XML is its human readability. YAML was specifically designed to be easily readable and editable by humans. This makes it ideal for dual human-machine use cases such as log files, configuration files, inter-process messages, and in this case, also for Kubernetes config and definition files. Read more about the rules of YAML syntax here.
In YAML, you only need to know 2 types of structures: lists and maps.
A YAML map is how you define key-value pairs, which is an intuitive and convenient method of creating configurations, such as in Kubernetes (A sample Kubernetes config showing a map is below).
Here, ‘apiVersion’ and ‘kind’ are the keys, and ‘v2.4’ and ‘pod’ are the respective values assigned to these keys. The 3-dashes (—) are used to denote the start of a new YAML file.
apiVersion: v2.4
kind: pod
A YAML list is simply a sequence of objects treated as a unit. For example:
containers:
- name: webserver1
image: nginx:1.6
ports:
- containerPort:80
- name: database-server
image: mysql-3.2
ports:
- containerPort:3306
- name: rss-reader
image: rss-php-nginx:2.8
ports:
- containerPort:86
In the example above, we have a list of 3 items defined in our ‘containers’ key. Each of these 3 items is differently colored for better differentiation. And each item in the list contains a map containing 3 sub-objects: ‘name’, ‘image’, and ‘ports’.
Let’s now take a look at real-world examples of how to create or define Kubernetes objects using YAML. If you first need to re-familiarize yourself with some Kubernetes objects, go back and read this introductory article.
To create a Kubernetes pod with YAML, you first create an empty file, assign it the necessary access permissions, and then define the necessary key-value pairs. The important ones are the apiVersion, the kind (pod), name, and the containers within the pod.
For instance, below is the YAML code to create a pod named mywebapp1 that has 2 containers: One is a web server and the other is a database server. It is also assigned to a specific volume named websvr-storage:
Filename: /k8s/pods/pod1.YAML
apiVersion: v1
kind: Pod
metadata:
name: mywebapp1
labels:
role: webserver-role
app: nginx
spec:
containers:
- name: webserver1
image: nginx:1.6
ports:
- containerPort:80
- name: database-server
image: mysql-3.2
ports:
- containerPort:3306
volumes:
- name: websvr-storage
emptyDir: {}
As you may have guessed, an important key-value here is kind: Pod. You can define many more parameters and values for a pod. For example, you can specify extra parameters to assign CPU resources, configure quality-of-service for a pod, configure service accounts, configure pod initialization, assign a pod to a specific node, and many more tasks as listed in the official Kubernetes documentation.
Remember that in the case of deployment, we are creating a set of resources to be managed as a unit. And also keep in mind that one of the reasons to use Kubernetes is for redundancy of our resources, mainly achieved via replicas and replica sets. Therefore, one of the most common (though not mandatory) specifications in the deployment YAML file is the number of replicas we want, and this is nested under ‘spec’, as detailed in the sample code below. The mandatory specifications to be included when defining our deployment via YAML are apiVersion, kind, metadata, and spec.
Filename: /k8s/deployments/deployment1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment1
labels:
app: nginx
spec:
replicas: 3
selector:
matchlabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: webserver1
image: nginx:1.6
ports:
- containerPort:80
- name: database-server
image: mysql-3.2
ports:
- containerPort:3306
kubectl create -f /k8s/deployments/deployment1.yaml
Now that we have defined our pods and the deployment to create those pods, we need a way of consistently being able to access our 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.
For example, when a user searches from our website’s frontend using HTML, that search request is directed to a set of pods where our database is defined. If the ‘database’ pod goes down and has to be recreated, the frontend should be completely unaware of this. The request should still be acknowledged and fulfilled as usual. And this is achieved by means of Kubernetes services. A service is an abstract way to expose an application running on a set of Pods as a network service.
Let’s take a look at a sample service definition in Kubernetes 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
Note the following:
Just as with deployments and nodes, there are many more specifications you can define for services. Read more about these in the official Kubernetes documentation.
Even though YAML was invented to be more human-readable than other formats like JSON if you need to create tens of YAML manifest files to deploy, manage and upgrade your Kubernetes applications, the friendliness of YAML decreases significantly. Kubernetes requires the manual creation of a large number of YAML manifest and config files. In addition to that, Kubernetes uses YAML’s more advanced features, like how to work with blobs of text or with a more complex “array in a hash in an array” type of structure.
As developers, you will manually create Config files, and YAML or JSON manifests for each Docker container keeping into account syntax and all attributes. With time, developers end up with a huge wall of small YAML files that define all of the resources in their environment. Oftentimes, developers’ artifacts grow exponentially and become extremely difficult to manage.
This is a complexity that development teams should handle along with product development, and with time it becomes a burden. This is why you need to choose the right tools that make you focus more on your development and spend less time managing your infrastructure.
With CloudPlex, developers no longer need to write the manifest files, nor search for valid parameters and supported values. Developers just configure services using a visual interface, in a single view. The platform performs validation and generates all related manifest and config files, which can also be downloaded and used on any K8s cluster.
The screenshot is a visual interface used by the developer to create the same application as above. As you can see, the developer can create the application simply by dragging and dropping containers from a palette to the canvass and configuring the containers visually in the Config Panel:
First published here