2

introduction

Kubernetes has a resource object called Deployments. When you update the application to a new version, Deployments has the function of rolling the container. Rolling updates are a good way to update applications, because the resources used by the application during the update process are roughly the same as the number of resources used when the application is not updated, which has the least impact on performance and availability.

However, there are many older applications that do not work well with rolling updates. Some applications only need to deploy a new version and immediately switch to the new version. To do this, we need to perform a blue/green deployment, deploy the existing version (blue) together with a new copy of the application (green), and then switch the ingress/router corresponding to the updated application to the new version (green, then Wait for the old (blue) version to complete the request sent to it. In most cases, the application traffic will immediately switch to the new version.
image.png
Kubernetes does not support built-in blue/green deployment. The method used here is to create a new deployment, and then update the application's service to point to the new deployment.

Blue deployment

Kubernetes deployment specifies a group of application instances, which creates a replica set (replicaset), which is responsible for keeping the specified number of instances running normally.

image.png
Create a "blue" deployment by saving the following yaml to the file blue.yaml.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-1.10
spec:
  replicas: 3
  template:
    metadata:
      labels:
        name: nginx
        version: "1.10"
    spec:
      containers: 
        - name: nginx
          image: nginx:1.10
          ports:
            - name: http
              containerPort: 80

Use kubectl command line to create deployment

$ kubectl apply -f blue.yaml

After the deployment is complete, we can provide a way to access the deployment instance by creating a service. Service and deployment are separated, which means that there is no need to explicitly point service to deployment. What you have to do is to specify a label selector (label selector), which is used to list the pods that make up the service. When using deployment, the tag selector is usually set to match the pod of the deployment.
In this example, there are two labels, name=nginx and version=1.10. We set them as the label selector of the following service and save it to service.yaml.

apiVersion: v1
kind: Service
metadata: 
  name: nginx
  labels: 
    name: nginx
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector: 
    name: nginx
    version: "1.10"
  type: LoadBalancer

When creating the service, create a load balancer that can be accessed outside the cluster.

$ kubectl apply -f service.yaml

It looks like this:

image.png
Test whether the service is accessible and get its version number.

$ EXTERNAL_IP=$(kubectl get svc nginx -o jsonpath="{.status.loadBalancer.ingress[*].ip}")
$ curl -s http://$EXTERNAL_IP/version | grep nginx

Green deployment

Now create a new deployment called green deployment (green deployment), use green.yaml to create

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-1.11
spec:
  replicas: 3
  template:
    metadata:
      labels:
        name: nginx
        version: "1.11"
    spec:
      containers: 
        - name: nginx
          image: nginx:1.11
          ports:
            - name: http
              containerPort: 80

Execute creation

$ kubectl apply -f green.yaml

Now there are two deployments but the service still points to blue deployment
image.png

Update app

In order to switch to the "green" deployment, we will update the service selector. Edit service.yaml and change the selector version to "1.11" to match the pod in the "green" deployment.

apiVersion: v1
kind: Service
metadata: 
  name: nginx
  labels: 
    name: nginx
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector: 
    name: nginx
    version: "1.11"
  type: LoadBalancer

Update the current nginx service

$ kubectl apply -f service.yaml

The situation now becomes the following
image.png
Update the service selector immediately and you will see that the new version of nginx is receiving external traffic

$ EXTERNAL_IP=$(kubectl get svc nginx -o jsonpath="{.status.loadBalancer.ingress[*].ip}")
$ curl -s http://$EXTERNAL_IP/version | grep nginx

automation

Use scripts to implement automated blue/green deployment. The following script uses the name of the service, the version to be deployed, and the path of the yaml file of green deployment, and uses kubectl to perform a complete blue/green deployment, and uses jq to parse it from the API. Output the original JSON file. Before updating the service definition, it waits for the green deployment to be ready by checking the status.conditions on the deployment object.
A script is provided below

#!/bin/bash
# bg-deploy.sh <servicename> <version> <green-deployment.yaml>
# Deployment name should be <service>-<version>
DEPLOYMENTNAME=$1-$2
SERVICE=$1
VERSION=$2
DEPLOYMENTFILE=$3
kubectl apply -f $DEPLOYMENTFILE
# Wait until the Deployment is ready by checking the MinimumReplicasAvailable condition.
READY=$(kubectl get deploy $DEPLOYMENTNAME -o json | jq '.status.conditions[] | select(.reason == "MinimumReplicasAvailable") | .status' | tr -d '"')
while [[ "$READY" != "True" ]]; do
    READY=$(kubectl get deploy $DEPLOYMENTNAME -o json | jq '.status.conditions[] | select(.reason == "MinimumReplicasAvailable") | .status' | tr -d '"')
    sleep 5
done
# Update the service selector with the new version
kubectl patch svc $SERVICE -p "{\"spec\":{\"selector\": {\"name\": \"${SERVICE}\", \"version\": \"${VERSION}\"}}}"
echo "Done."

If you want to learn more, I have provided a tutorial and some sample lists github


EngineerLeo
598 声望38 粉丝

专注于云原生、AI等相关技术