Kubernetes, a popular open-source container management solution, provides convenient methods for developers and system administrators to deploy containerized applications declaratively.

Imperative vs. Declarative Approach

The classic imperative way of managing software involves several steps or tasks, sometimes some of these steps are manual. When working in a team, it is usually required that these steps be documented and, in an ideal case, automated. Preparing good documentation for a classic imperative administrative procedure and automating these steps can be non-trivial tasks, even if each of these steps is simple.

A declarative approach for administrative tasks is intended to solve such challenges. With a declarative approach, an administrator defines a target state for a system (application, server, or cluster). Typically, a domain-specific language (DSL) is used to describe the target state. An administrative tool, such as Kubernetes, takes this definition as an input and takes care of how to achieve the target state from the current observable state. The main benefits of the declarative approach are:

Idempotency : The definition of the target state can be applied multiple times and if the system’s state is unchanged, no changes are made to the system.

Predictability : If there are changes in the system’s state, the administrative tool identifies the actions required to achieve the target state from the current state. The same principle applies when there are changes to the definition itself: the tool identifies the actions required for the system to achieve the new target state from the old one. As a result, at any moment it is possible for a user to identify differences between the target (defined) and the current (observable) system states. For example, Kubernetes has the command line option ‘–dry-run’ to show the required action to achieve the target state from the current state without actually taking these actions.

Traceability : The definition of the target state is a text file or multiple files. Such files can be placed under version control, with all the benefits of version control. Teams can track changes to the configuration, use different review and approval flows for changes, and apply different versions of configuration to the system, including rolling back the changes using the previous version. In Kubernetes, building block definitions, such as pods or replication controllers, are text files in YAML or JSON format with well-defined schema.

Also, since the target system’s state is defined in a text file, which is machine and human readable, it is easier to use it to document the target state and to verify that the system’s state is as expected.

As we discussed in this article, Kubernetes provides simple but efficient building blocks, such as pods and replication controllers. However, using pods and replication controllers to deploy an application is at least in part an imperative form of managing software, because it usually requires manual steps. At the same time, Kubernetes provides another building block, a deployment, which enables completely declarative application deployment.

What is a Kubernetes Deployment?

A Kubernetes deployment can define and manage replica set, which is the next generation of replication controllers. At the same time, a replica set defines and creates the required number of pod replicas.

In addition to what a replica set offers, a deployment gives you declarative control over the update strategy used for the deployment, for example, how many additional and how many unavailable pod replicas are allowed.

The main benefit of a Kubernetes deployment is how it manages updates. For example, a deployment checks if a new revision that is being rolled out is working properly and stops the rollout if it is not. Also, you can define a wait time that a pod needs to be ready without its containers crashing before a pod is considered available, which can help avoid incomplete/failed updates and gives certain containers a bit more time to get ready. Furthermore, a deployment keeps a history of its revisions, which is used for rollbacks, as well as a log of events, which you can use to audit releases and view changes to your deployment.

Container Orchestration with Kubernetes: Intro and Installation Guide

Examples

The following examples show Kubernetes deployments in action and help to understand the basic deployment use cases. In these examples, we will use the existing image echoserver, which is a simple HTTP server that responds with the http headers it receives.

Step 1: Create a new deployment

The simplest way to create a new deployment for a single-container pod is to use ‘kubectl run’:

$ kubectl run echoserver --image=gcr.io/google_containers/echoserver:1.4 --port=8080 --replicas=2 deployment "echoserver" created

Under the hood, the command creates a new deployment, using the specified image (echoserver), a new replica set, which manages two replicas of the pod. In addition, we specify the port number to let the container expose port 8080.

To check that two replicas of the echoserver are running:

$ kubectl get pods NAME READY STATUS RESTARTS AGE echoserver-5z1bh 1/1 Running 0 1m echoserver-nhfb1 1/1 Running 0 1m

Step 2: Expose the deployment

To access our application, we need to expose its port using, for example, the command

` kubectl expose deployment `:

$ kubectl expose deployment echoserver --type=NodePort service "echoserver" exposed

The following command shows the exposed port. You can use this port to access the application:

$ kubectl describe services/echoserver ... NodePort: <unset> 30512/TCP ...

Step 3: Edit the deployment: change a number of replicas

The newly created deployment is a regular Kubernetes resource, which can be edited. To get the deployment in YAML format, use the following command:

$ kubectl get deployment echoserver -o yaml apiVersion: extensions/v1beta1 kind: Deployment ...

You can store this deployment in a file, edit it, and use a changed file to update the deployment:

$ kubectl get deployment echoserver -o yaml > echoserver.yaml # Edit echoserver.yaml in your editor $ kubectl replace -f echoserver.yaml

Kubernetes also provides a more convenient way to edit the existing resources without saving them in a temporary file. Use the following command to open the echoserver deployment in your default text editor and change the number of replicas to 3, for example:

$ kubectl edit deployment echoserver # Edit the deployment, change the number of replicas to 3 deployment "echoserver" edited

To check that two replicas of the echoserver are running:

$ kubectl get pods NAME READY STATUS RESTARTS AGE echoserver-5p5ja 1/1 Running 0 1m echoserver-5z1bh 1/1 Running 0 2m echoserver-nhfb1 1/1 Running 0 2m

Step 4: Working with rollout history

Use ‘kubectl rollout history’ deployment to see revisions of the deployment:

$ kubectl rollout history deployment echoserver deployments "echoserver": REVISION CHANGE-CAUSE 1 <none>

As we can see, there is one revision, which corresponds to our change of replicas. Let’s say we want to use another image for our application. Use the command ‘kubectl edit deployment’ to open the echoserver deployment in your default text editor and change the image from ‘echoserver:1.4’ to ‘echoserver:1.3’:

$ kubectl edit deployment echoserver # Edit the deployment, change the image from # gcr.io/google_containers/echoserver:1.4 to # gcr.io/google_containers/echoserver:1.3 deployment "echoserver" edited

The deployment controller replaced all of the pods with new ones, one by one. Let’s check the revisions:

$ kubectl rollout history deployment echoserver deployments "echoserver": REVISION CHANGE-CAUSE 1 <none> 2 <none>

To check the deployment status, use the following command:

$ kubectl describe deployment echoserver ... Replicas: 3 updated | 3 total | 3 available | 0 unavailable ...

In a real use case, a new image may contain regressions and you may want to roll back the deployment to the old image. If this is the case, then use the command ‘kubectl rollout undo deployment’:

$ kubectl rollout undo deployment echoserver deployment "echoserver" rolled back

Step 5: Delete the deployment

To delete the deployment, replication controller and all of the managed pod’s replicas, use the command ‘kubectl delete deployment’:

$ kubectl delete deployment echoserver deployment "echoserver" deleted

Questions about the arrangement, coordination and management of containers ? Discover 12 Kubernetes key features here

Kubernetes Deployment for Real Applications

In the previous examples, we used a few simple operations with deployments. For real applications, you may want to use other deployment features, such as defining update strategy, maxSurge, maxUnavailable, and minReadySeconds parameters. You may also want to create a new deployment from a file, rather than creating it imperatively using the command ‘kubectl run’. For example, a deployment for the WordPress application may look like this:

apiVersion : extensions/v1beta1 kind : Deployment metadata : name : wordpress-deployment spec : replicas : 3 strategy : type : RollingUpdate template : metadata : labels : app : wordpress track : production spec : containers : - name : "wordpress" image : "wordpress:4.5-apache" ports : - containerPort : 80 env : - name : WORDPRESS_DB_HOST value : "mysql" - name : WORDPRESS_DB_USER value : "wpuser" - name : WORDPRESS_DB_PASSWORD value : "wppassword" - name : WORDPRESS_DB_NAME value : "wpdatabase"

In this example, we define a specification for a replica set in the ‘spec’ session, a template for the pod’s replicas in the ‘template’ section. Note that the pod template also sets the environment variables required by the WordPress container. In addition, the pod’s replicas have two labels ‘app: wordpress’ and ‘track: production’, which are used by the deployment and replica set to manage pod’s replicas.

A Kubernetes deployment enables application deployments to be made declaratively. Under the hood, the deployment manages pods and replica sets, providing additional parameters to manage application updates, while supporting a history of its revisions and enabling the user to roll back the deployment to a specific revision. A deployment ensures that only a specific number of pods are down while they are being updated (by default, 1 unavailable pod is allowed).

At the same time, the deployment makes sure that only a set number of pods are created in excess of the desired number of pods (by default, 1 additional pod is allowed). In other words, a Kubernetes deployment is another high-level Kubernetes building block that extends the functionality of replica sets and replication controllers. It also allows user to effectively replace manual, imperative steps for creating replica sets, scaling them up or down, and updating managed pods.