Kubernetes rolling updates
Note: this tutorial is done with Kubernetes v1.17.2, Docker 19.03.5 on MacOS 0.15.2.
Kubernetes
Kubernetes cluster
- A node is a virtual machine or a physical computer that serves as a worker machine in a Kubernetes cluster.
- The Master is responsible for managing the cluster. The master coordinates all activities in your cluster, such as scheduling applications, maintaining applications’ desired state, scaling applications, and rolling out new updates.
Kubernetes core concepts
- A Pod is a Kubernetes abstraction that represents a group of one or more application containers (such as Docker or rkt), and some shared resources for those containers. A Pod models an application-specific “logical host” and can contain different application containers which are relatively tightly coupled.
- A Service is an abstraction which defines a logical set of Pods and a policy by which to access them. A Service routes traffic across a set of Pods. Services are the abstraction that allow pods to die and replicate in Kubernetes without impacting your application.
- A Deployment instructs Kubernetes to deploy containerized applications to a Kubernetes cluster.
- Self-healing mechanism: Kubernetes takes care of replacing the down cluster with a new one.
- Rolling updates: Kubernetes deploys the updated app to a new available pod then swap it with the current version of the app
A very simple server
For demonstration purpose, we write a server which listens at the port 8080 and responses a string “Hello World!” to every request from clients.
// server.js
var http = require('http');
var handleRequest = function(request, response) {
console.log('Received request for URL: ' + request.url);
response.writeHead(200);
response.end('Hello World!');
};
var www = http.createServer(handleRequest);
www.listen(8080);
Then we write a Dockerfile for our containerized application
FROM node:6.14.2
EXPOSE 8080
COPY server.js .
CMD [ "node", "server.js" ]
Requirements
We install minikube
and Docker in order to manage Kubernetes clusters.
A Kubernetes cluster could be started with the following command minikube start
.
To ensure that our cluster is operating normally, we should see the following
output from minikube status
command.
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
Deploy our app
The recommended workflow is uploading a Docker image to a registry, creating a Kubernetes pod, and granting the pod the access to the image. In order to simply the setup of this tutorial, we could apply this solution to let the pod have direct access to the Docker images stored inside a Kubernetes node.
eval $(minikube docker-env)
To deploy our app, we firstly need to build a Docker image
docker build -t myimage:v1 .
We create a Kubernetes Deployment by executing
kubectl create deployment myapp --image=myimage:v1
By default, the containerized application only exposes itself to other apps in the same cluster. We create a Kubernetes Service to expose our web app so external users could interact with it.
kubectl expose deployments/myservice --type="NodePort" --port 8080 --name myservice
The following scripts help us to verify whether our app is functioning normally.
export NODE_PORT=$(kubectl get services/myservice -o \
go-template='{{(index .spec.ports 0).nodePort}}')
export POD_NAME=$(kubectl get pods -o \
go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
# Make a request to the web app
curl $(minikube ip):$NODE_PORT
We should see the response text “Hello World”.
Rolling updates
In order to prepare for our rolling update, we need to scale our app by adding
some replicas
kubectl scale deployments/myapp --replicas=3
.
To simply put, these 3 replicas are 3 exact copies of our app.
For demonstrating the new update of the app, we simply modify server.js to
make the server return a string “Hello World v2!” to every client’s request.
response.end('Hello World v2!');
docker build -t myimage:v2 .
After setting the desired image (myimage:v2)
kubectl set image deployments/myapp myimage=myimage:v2
,
we perform the rolling update with the following command
kubectl rollout status deployments/myapp
The expected output of curl $(minikube ip):$NODE_PORT
should be “Hello World v2!” by now.
Kubernetes also make it very simple to rollback to the previous version of the app
kubectl rollout undo deployments/myapp
Cleaning up
Finally, we clean up our tutorial by deleting resources (e.g., services, deployments) and stopping minikube.
kubectl delete service myservice
kubectl delete deployment myapp
minikube stop
We should also removing the Docker images if we don’t plan to work with them later on.