Deployment with Kubernetes

How to deploy your application using Kubernetes?

Kamil Lelonek
Kamil Lelonek  - Software Engineer

--

This tutorial will introduce you to the technical details of deploying your application to a Kubernetes cluster. You will learn what YAML definitions are and how to prepare them to have your project up and running in your desired environment.

I made an assumption you are already familiar with all of Kubernetes basic concepts and have a cluster available. Otherwise, you may want to read my previous article which will teach you initial elements and simple setup to begin with:

Let’s get started!

Introduction

Objects in the Kubernetes API are abstractions that represent a state of your system: deployed containerized applications and workloads, their associated network and disk resources, and other information about what your cluster does.

From my recent blogpost, you should know that Kubernetes also contains a number of higher-level abstractions called Controllers built upon the basic objects, and provide additional functionality along with convenience features:

Objects are “records of intent” — once you create them, the Kubernetes will constantly work to ensure that these objects exist. By creating an object, you’re effectively telling the Kubernetes what you want your cluster’s workload to look like; this is your cluster’s desired state.

Installation

To work with Kubernetes objects — either to create, modify, or delete them — you’ll need to use the Kubernetes API. When you use the kubectl command-line interface, for example, the CLI makes the necessary Kubernetes API calls for you.

Using kubectl, you can inspect cluster resources — create, delete, and update components — look at your new cluster, and bring up example apps.

You will find the detailed installation here:

YAML

When you create an object in Kubernetes, you must provide the object spec that describes its desired state, as well as some basic information about the object (such as a name).

When you use the Kubernetes API to create an object (either directly or via kubectl), the API request must include that information as JSON in a request body. Most often, you provide the information in a .yaml file and kubectl converts the information to JSON when making the API request.

Required Fields

In the .yaml file for the Kubernetes object you want to create, you’ll need to set values for the following fields:

  • apiVersion - which version of the Kubernetes API you’re using to create this object;
  • kind - what kind of object you want to create;
  • metadata - data that helps uniquely identify the object, including a name string and an optional namespace.

You’ll also need to provide the object spec field. The precise format of the object spec is different for every Kubernetes object, and contains nested fields specific to that object. The Kubernetes API Reference can help you find the spec format for all of the objects you can create using Kubernetes.

Deployment

A deployment controller lets you manage a set of identical pods, scale, roll out, and roll back versions of your applications. Everyone who runs applications on Kubernetes cluster uses a deployment. Without it, you’d need to create, update, and delete a bunch of pods manually.

For deployment, you declare a single object in a YAML file:

Firstly, have a look at theapiVersion value. apps/v1 is the most common API group in Kubernetes, with many core objects. It includes functionality related to running applications on Kubernetes like Deployments.

After that, let’s see the spec contents that describe your desired state for the object and governs its configuration. As you already know, it’s the characteristics you want the object to have.

When you create the Deployment, you might set its spec to define how many replicas of the application you want to run. The Kubernetes system updates the status to match your spec. Actually, .spec.replicas is an optional field that defaults to 1.

The selector field defines how the Deployment finds which Pods to manage. In our case, you simply select a label that is defined in the Pod template (app: api). .spec.selector.matchLabels must match .spec.template.metadata.labels and specify a label selector for the Pods targeted by this deployment.

The .spec.template has exactly the same schema as a Pod, except it is nested and does not have an apiVersion or kind. Deployment uses a Pod template to create the Pods for which it is responsible. The template field contains the following sub-fields:

  • The Pods are labeled as app: apiusing the labels field.
  • The Pod template’s specification (.template.spec field) indicates that the Pods run some container based on the given image.
  • Container is named example-container using the name field.
  • Port 4444 will be exposed so that the container can accept traffic.

And that’s basically the entire definition of Deployment in its minimal scope.

envsubst

Last but not least, I’d like to explain the “magic” with environmental variables inside a YAML file. You may wonder how exactly it is supposed to work. Let me answer you briefly and explain what the envsubst command actually is.

The envsubst program substitutes the values of environment variables. In the normal operation mode, standard input is copied to standard output, with references to environment variables of the form $VARIABLE or ${VARIABLE} being replaced with the corresponding values.

Let’s see this in action:

~/Desktop » echo $USER
squixy
~/Desktop » echo 'You username is: $USER'
You username is: $USER
~/Desktop » echo 'You username is: $USER' | envsubst
You username is: squixy

This is how it works in the simplest form, reading input from the command line and replacing specific forms with your environmental variables. It’s pretty useful but we actually want to use it with .yaml files. We can do that as well:

~/Desktop » cat k8s.yml
---
apiVersion: apps/v1
kind: Deployment
spec:
replicas: ${NO_REPLICAS}
~/Desktop » echo $NO_REPLICAS~/Desktop » export NO_REPLICAS=3
~/Desktop » echo $NO_REPLICAS
3
~/Desktop » envsubst < k8s.yml
---
apiVersion: apps/v1
kind: Deployment
spec:
replicas: 3

As you can see, there’s a variable definition inside the YAML file. We substitute it with what we have defined in our environment by redirecting the file contents to the envsubst command.

Applying the configuration

To finally apply the Kubernetes configuration, you should pipe YAML file definition into variables substitution and pass the result as a file:

~/Desktop » cat k8s.yml | envsubst | kubectl apply -f -
deployment.apps/example-deployment configured
ingress.extensions/example-ingress unchanged
service/example-api unchanged

As your last concern, you may wonder how to automate this process. What I usually do is to invoke the above script in a CI server where all the necessary environment variables are exported. This way I’m able to delegate the entire workflow and provide continuous delivery of the applications I build.

Subscribe to get the latest content immediately
https://tinyletter.com/KamilLelonek

Summary

Hopefully, this article introduced you to Kubernetes configuration definition, deployment, and automation of the entire process quite well.

With the knowledge you have now, you are able to describe your Kubernetes structure and apply it to a cluster. You can have a YAML file which explains your architecture or infrastructure to anyone else.

You should be also already familiar with the basic concepts and practical strategies so you can finally start deploying your applications. Do not hesitate to try that in your team and don’t be afraid of experimenting with any changes.

--

--