In the previous blog of this 10-part series, we discussed Logging & Monitoring. This section introduces various strategies used to manage the lifecycle of Kubernetes applications, ensuring high availability and continuously improving performance.
Here are the eight other blogs in the series:
- Certified Kubernetes Administrator Exam Series (Part-1): Core Concepts
- Certified Kubernetes Administrator Exam Series (Part-2): Scheduling
- Certified Kubernetes Administrator Exam Series (Part-5): Cluster Maintenance
- Certified Kubernetes Administrator Exam Series (Part-6): Security
- Certified Kubernetes Administrator Exam Series (Part-7): Storage
- Certified Kubernetes Administrator Exam Series (Part-8): Networking
- Certified Kubernetes Administrator Exam Series (Part-9): Troubleshooting
- Certified Kubernetes Administrator Exam Series (Part-10): Practice Topics
When deploying a Kubernetes application into production, there are several strategies to stage and update cluster resources without affecting availability. This allows application users to have uninterrupted access even when developers are making changes and pushing updates to the application.
Rolling Updates & Rollback
Rollouts and Versioning
When a deployment is created, it triggers a rollout. Every new rollout, in turn, creates a deployment version, let’s call the first Revision1 (for our reference). When an application is upgraded by updating containers, a new rollout is triggered, creating a newer deployment revision, Revision2.
This makes it easy to keep track of changes in the deployment and roll them back whenever necessary. Below is a manifest file that creates a new deployment, myapp-deployment:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
- name: rss-reader
image: nickchase/rss-php-nginx:v1
ports:
- containerPort: 88To display running deployments, use the command:
kubectl get deploymentTo check the status of a rollout, use the kubectl rollout status command:
kubectl rollout status deployment/myapp-deploymentTo update the image of the application to nginx:1.17 use this command:
kubectl set image deploy myapp-deployment front-end=nginx:1.17To view the current image version of the app, run the describe pods command:
kubectl describe podsIn the Image field of the output, verify that you are running the latest image nginx:1.17
To roll back the deployment to your last working version, use the rollout undo command:
kubectl rollout undo deployment myapp-deploymentFor rollout history, use this command:
kubectl rollout history deployment/myapp-deploymentDeployment Strategy
There are two kinds of deployment strategies in Kubernetes: recreate and rolling update.
A. Recreate strategy
In the Recreate strategy, all old POD instances are brought down before newer instances are brought up. This introduces a problem of application unavailability during an update.
The recreate strategy can be desirable for a number of reasons:
- When updated applications require prerequisite data and configuration settings
- The POD is mounted with a ReadWriteOnce volume that cannot be shared with other replicas
- The application doesn’t support multiple versions
B. Rolling Updates
Rolling Updates is a strategy that ensures high availability by incrementally replacing POD instances. Under this strategy, POD instances are taken down and replaced one by one, making the update process seamless. Kubernetes assumes rolling updates to be the default rollout strategy and performs such updates when the strategy is not specified.
.spec.strategy specifies the strategy used to replace old Pods with new ones. .spec.strategy.type can be “Recreate” or “RollingUpdate”.
Docker Commands and Arguments
When we run a docker container built on the Ubuntu OS image:
docker run ubuntuThis initiates the container run and then exits immediately. To check the number of running containers, use the command:
docker psThe above command will not list stopped containers. For checking all, including stopped containers:
docker ps -aThis shows it's in Exited state:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4a947ab4d03 ubuntu "/bin/bash" 58 seconds ago Exited (0) 53 seconds ago pedantic_chaumThis is because containers are made to run specific tasks/processes and not Operating Systems. Once the task is complete, the container exits. A container, therefore, only lives for as long as the task running inside it is alive.
Commands and arguments define the processes that run in a container once it starts. This can be seen in the configuration files for popular Docker images. The CMD argument for the nginx image is [“nginx”]. For the mysql official image, this argument is [“mysqld”].
The Ubuntu container that ran earlier is a plain OS image. It uses [“bash”] as its default CMD argument. bash is not a process, but it listens for commands from the CLI terminal. If there are no commands from the terminal, the container exits.
One way to override a container’s default commands is to append the docker run command when initiating the container:
docker run ubuntu sleep 5In the case above, the container will start, run the sleep program, wait for 5 seconds, and then exit. It is also possible to use the OS as the base image and specify a command in a new Dockerfile. This way, the container will always run this command when it starts. For instance, it is possible to create a Dockerfile named ubuntu-sleeper with the following specs:
FROM ubuntu
CMD sleep 5The CMD arguments can be specified in both shell and exec forms as:
CMD command param1 for instance CMD sleep 5.
CMD [“command”, “param”] for instance CMD [“sleep”, “5”].
The new image can be built using the docker build command:
docker build -t ubuntu-sleeper .The container is then run using the command:
docker run ubuntu-sleeperBy default, a container will always start, run the sleep program, wait for 5 seconds, and then exit. To change the number of seconds it sleeps, this can be appended to the docker run command:
docker run ubuntu-sleeper sleep 10In this case, the command that runs at startup is sleep 10 so the container starts, runs the sleep program, waits for 10 seconds, and then exits.
If one wants to specify the number of seconds in the command line while the sleep program executes automatically, it is best to use the ENTRYPOINT instruction. This instruction specifies the program that executes when the container is running, but the number of seconds can be specified on the CLI. The Dockerfile for this container would be:
FROM ubuntu
ENTRYPOINT ["sleep"] Running the command docker run ubuntu-sleeper 10 means that the instruction executed at container runtime is sleep 10. Running this container without a command-line argument returns a ‘missing operand’ error. To configure the application with a default argument value (number of seconds), it is best to combine ENTRYPOINT and CMD instructions, as shown below:
FROM Ubuntu
ENTRYPOINT ["sleep"]
CMD ["5"]In this case, if no command-line arguments are specified, the sleep 5 program is executed when the container is running. If an argument is specified on the command line, the CMD instruction is ignored, for instance:
docker run ubuntu-sleeper 10 will run the container with the sleep 10 program. When it is necessary to modify the ENTRYPOINT append the docker run command with the newer --entrypoint specified as a flag:
docker run --entrypoint echo ubuntu-sleeper 10Kubernetes Commands and Arguments
The previous section explored the configuration of commands and arguments in Dockerfiles using ENTRYPOINT and CMD instructions. In Kubernetes, these instructions can be specified in the definition files for the PODs running these docker containers. Let’s consider the YAML definition file for the ubuntu-sleeper POD:
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-sleeper-pod
spec:
containers:
- name: ubuntu-sleeper
image: ubuntu-sleeper
args: ["10"]The args field in the POD definition file is the Kubernetes equivalent of the CMD instruction in a Dockerfile. To represent an ENTRYPOINT in a POD definition file, the command field is used:
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-sleeper-pod
spec:
containers:
- name: ubuntu-sleeper
image: ubuntu
command: ["sleep"]
args: ["10"]Configuring Environment Variables
Environment variables in Kubernetes are configured using the env property. This property is an array, and a number of items can be specified under the property. Each item has a name and a value property, as shown in the simple POD definition file below:
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: kodekloud/simple-webapp
ports:
- containerPort: 8080
env:
- name: APP_COLOR
value: pinkTo list the Pod’s container environment variables, use this command:
kubectl exec simple-webapp-color -- envThis is known as the plain key-value of setting environment variables. The variables can also be set using configMaps and secrets, which are explored in the coming sections.
Configuring ConfigMaps
In a cluster that uses numerous Pod instances, it gets difficult to manage the environment data stored across multiple YAML definition files. Environment variable information can be taken out of individual Pod definition files and managed centrally using objects known as configMaps.
These objects store environment data in the form of key-value pairs and pass them to applications when injected into the Pod definition files.
ConfigMaps can be created in two ways: imperatively and declaratively.
With the imperative method, the configMap is created by stating the key-value pairs directly in the command line, i.e:
kubectl create configmap \
<config-name> –from-literal=<key>=<value>
–from-literal=<key2>=<value2> For instance, we could create the configMap app-config by running the command:
kubectl create configmap \
<config-name> --from-literal=APP_COLOR=blue \
--from-literal=APP_MOD=prodIf there are many environment variables, the command may get too complex, and the variables can be managed by writing them onto a file imperatively:
kubectl create configmap \
<config-name> --from-file= file-pathData is read from this file and stored as environment data in the config-name file. In the declarative method, a YAML file is used to store the configuration data. For instance, the configMap specifications for the sample app simple-webapp-color would be:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_COLOR: blue
APP_MOD: prodThe configMap data is then injected into the Pod by specifying it in a YAML definition file as follows:
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: kodekloud/simple-webapp
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-configTo list the Pod’s container environment variables, which are managed by configMaps, use the command:
kubectl exec simple-webapp-color -- envTo list the configMaps, use the command:
kubectl get configmapsTo get the data of the app-config configMap, use the command:
kubectl describe configmaps app-configSecrets
ConfigMaps are great for storing environment data to be used by resources within the Kubernetes cluster. They are, however, not suitable for sensitive data that require high security. Secrets store information in an encoded format, making them suitable for highly sensitive data.
Just like configMaps, secrets can be created imperatively or declaratively. Let’s assume we are trying to create a secret as follows:
DB_Host: MySQL
DB_User: root
DB_Password: paswrd
Using the imperative method, a secret is created directly on the command line without the need for a definition file, i.e:
kubectl create secret generic \
<secret-name> --from-literal=<key>=<value> \
--from-literal=<key2>=<value2>To encode the values, the following command is used on a Linux host:
echo -n '<value>' | base64Since we are trying to encode: mysql, root and paswrd, our secret values will be bXlzcWw=, cm9vdA== and cGFzd3Jk respectively.
So the imperative command will be:
kubectl create secret generic \
app-secret --from-literal=DB_Host=bXlzcWw= \
--from-literal=DB_User=cm9vdA== \
--from-literal=DB_Passowrd=cGFzd3JkThis command also gets complicated when there are numerous environment variables to specify. The secrets can also be written onto files, as follows:
kubectl create secret \
<secret-name> --from-file= file-pathUsing the declarative method, the secret is first created in a YAML definition file:
apiVersion: v1
kind: Secret
metadata:
name: app-secret
data:
DB_Host: bXlzcWw=
DB_User: cm9vdA==
DB-Password: cGFzd3JkThe secret is then created by running the command:
kubectl create -f secret-data.yamlTo view secrets, use the command:
kubectl get secretsThe newly created secret can be inspected using the command:
kubectl describe secretsTo get the secrets as presented in YAML format, run this command:
kubectl get secret app-secret -o yamlThe secrets can be decoded back to plain text format by running the following command on a Linux host:
echo -n '<value>' | base64 --decodeTo inject a secret into a POD, it is specified as secretRef under envFrom in the POD definition file:
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: kodekloud/simple-webapp
ports:
- containerPort: 8080
envFrom:
- secretRef:
name: app-secretTo list the Pod’s container environment variables, use this command:
kubectl exec simple-webapp-color -- envMulti-Container PODs
Microservices architecture allows for the creation of light, agile, and reusable code. This makes it easy to scale the application up and down and easily manage deployments by updating only those services requiring an upgrade. In some cases, services may need to work together without having to be merged.
While they operate with the same number of replicas, they are developed and deployed independently. Deploying these services in Multi-Container Pods will result in them sharing resources and a lifecycle, making it easier to communicate since they can refer to each other as localHost.
To create a multi-container Pod, the new container’s information is added to the containers section under spec in the Pod definition file, as shown:
apiVersion: v1
kind: pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: kodekloud/simple-webapp
ports:
- containerPort: 8080
- name: log-agent
image: log-agentThis concludes the Application Lifecycle Management section of the CKA certification exam.
You can now proceed to the next part of this series: Certified Kubernetes Administrator Exam Series (Part-5): Cluster Maintenance.
Here is the previous part of the series: Certified Kubernetes Administrator Exam Series (Part-3): Logging & Monitoring.
Research Questions
Here is a quick quiz to help you assess your knowledge. Leave your answers in the comments below and tag us back.
Quick Tip – Questions below may include a mix of DOMC and MCQ types.
1. Which command can be used to inspect the deployment and identify the number of Pods deployed by it?
[A] kubectl inspect pod
[B] kubectl inspect deploy
[C] kubectl describe deployment
[D] kubectl describe pod
2. There are two kinds of deployment strategies in Kubernetes: The Recreate and Rolling Update Strategies.
[A] True
[B] False
3. Upgrade the application by setting the image on the deployment to kodekloud/web app-color:v3
Deployment Name: frontend
Deployment Image: kodekloud/webapp-color:v3
ContainerName: frontend
Solution:
kubectl set image deploy/frontend frontend=kodekloud/web app-color:v34. Create a pod with the Ubuntu image to run a container to sleep for 5000 seconds.
Pod Name: ubuntu-sleeper-2
Command: sleep 5000
Solution:
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-sleeper-2
spec:
containers:
- name: ubuntu
image: ubuntu
command:
- "sleep"
- "5000"5. Create a pod with the given specifications. By default, it displays a blue background. Set the given command-line arguments to change it to green.
Pod Name: webapp-green
Image: kodekloud/webapp-color
Command line arguments: --color=green
Solution:
apiVersion: v1
kind: Pod
metadata:
name: webapp-green
labels:
name: webapp-green
spec:
containers:
- name: simple-webapp
image: kodekloud/webapp-color
args: ["--color", "green"]6. The Recreate strategy is the default rollout strategy.
[A] True
[B] False
7. Add the environment variable on the POD to display a pink background.
Pod Name: webapp-color
Image Name: kodekloud/webapp-color
Env: APP_COLOR=pink
Solution:
apiVersion: v1
kind: Pod
metadata:
name: webapp-color
spec:
containers:
- env:
- name: APP_COLOR
value: pink
image: kodekloud/webapp-color
name: webapp-color8. Create a new ConfigMap for the webapp-color POD. Use the spec given below.
ConfigName Name: webapp-config-map
Data: APP_COLOR=darkblue
Solution:
$ kubectl create configmap web app-config-map --from-literal=APP_COLOR=darkblue9. Create a multi-container pod with 2 containers. Use the spec given below.
If the pod goes into the crashloopbackoff then add sleep 1000 in the lemon container.
PODName: yellow
Container 1 Name: lemon
Container 1 Image: busybox
Container 2 Name: gold
Container 2 Image: redis
Solution:
apiVersion: v1
kind: Pod
metadata:
name: yellow
spec:
containers:
- name: lemon
image: busybox
command:
- sleep
- "1000"
- name: gold
image: redisConclusion
This part of the course offers an in-depth introduction to how application deployments behave in the production environment. By exploring the different rollout strategies, this section outlines information with guidance on choosing the right deployment strategy for different kinds of applications. KodeKloud’s curriculum also includes practicals on how to perform rollbacks when the updates result in undesired changes in the application.
This section is crucial for prospective Kubernetes administrators since it is a guide on how to manage applications from inception to retirement. With the knowledge explored in this section, the candidate can easily create running applications based on CMD and ENTRYPOINT instructions, and manage application environments using Environment Variables, ConfigMaps, and Secrets.
Exam Preparation Course
Our CKA Exam Preparation course explains all the Kubernetes concepts included in the certification’s curriculum. After each topic, you get interactive quizzes to help you internalize the concepts learned. At the end of the course, we have mock exams that will help familiarize you with the exam format, time management, and question types.
Explore our CKA exam preparation course curriculum.
Discussion