The basic concept

Grayscale publishing (also known as canary publishing) is a smooth transition between black and white publishing. A/B testing can be carried out on it, that is, some users continue to use product feature A and some users start to use product feature B. If users have no objection to B, the scope can be gradually expanded to migrate all users to B. Grayscale publishing can ensure the stability of the whole system, and problems can be found and adjusted at the beginning of the grayscale to ensure its impact.

A blue-green deployment is to run the old version, deploy the new version, test it, verify that it’s OK, cut traffic to the new version, and upgrade the old version to the new version at the same time.

Gray scale is the coexistence of different versions, blue and green is the switch between the old and new versions, the starting point of the two modes is different.

Environment to prepare

1. Download and install Minikube

Minikube is a tool that can quickly deploy Kubernetes and run containers on a single machine. Due to limited conditions, I use it to learn kubernetes knowledge.

Mac OSX

The curl - Lo minikube && at https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/releases/v1.13.0/minikube-darwin-amd64 chmod +x minikube && sudo mv minikube /usr/local/bin/Copy the code

Linux

The curl - Lo minikube && at https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/releases/v1.13.0/minikube-linux-amd64 chmod +x minikube && sudo mv minikube /usr/local/bin/Copy the code

2. Start

Docker-engine must be installed in advance for the local environment

minikube start --driver=none
Copy the code

After successful startup, view the launched Pods

kubectl get pods -A

NAMESPACE              NAME                                        READY   STATUS    RESTARTS   AGE
kube-system            coredns-6c76c8bb89-nz22j                    1/1     Running   2          24h
kube-system            etcd-minikube                               1/1     Running   2          24h
kube-system            kube-apiserver-minikube                     1/1     Running   2          24h
kube-system            kube-controller-manager-minikube            1/1     Running   2          24h
kube-system            kube-proxy-2qwq9                            1/1     Running   2          24h
kube-system            kube-scheduler-minikube                     1/1     Running   2          24h
kube-system            storage-provisioner                         1/1     Running   3          24h
kubernetes-dashboard   dashboard-metrics-scraper-c95fcf479-7qnhf   1/1     Running   0          24h
kubernetes-dashboard   kubernetes-dashboard-5c448bc4bf-6gccm       1/1     Running   0          24h
Copy the code

3. Prepare an image

Prepare the Dockerfile file

Dockerfile

FROM python:alpine 
RUN pip install flask -i https://pypi.douban.com/simple
COPY app.py /app.py
EXPOSE 5000
ENTRYPOINT ["python", "/app.py"]
Copy the code

app.py

from flask import Flask from flask import request from flask import jsonify import socket app = Flask(__name__) @app.route('/') def index(): return jsonify({'Version': 'v1', 'Hostname': socket.gethostname(), 'Address': socket.gethostbyname(socket.gethostname()), 'Message': 'Hello, World', }) if __name__ == '__main__': App. The run (' 0.0.0.0, 5000)Copy the code

Build the first image:

docker build . -t flask-app:v1
Copy the code

Build the second image:

Let’s change v1 to v2 in app.py

docker build . -t flask-app:v2
Copy the code

So we have two mirror images.

Blue green deployment

Prepare the Deployment and service files as follows:

deployment-v1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: flask-app
      version: v1
  template:
    metadata:
      labels:
        app: flask-app
        version: v1
    spec:
      containers:
      - image: flask-app:v1
        name: flask-app
        ports:
        - containerPort: 5000
Copy the code

deployment-v2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-app-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: flask-app
      version: v2
  template:
    metadata:
      labels:
        app: flask-app
        version: v2
    spec:
      containers:
      - image: flask-app:v2
        name: flask-app
        ports:
        - containerPort: 5000
Copy the code

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: flask-app
spec:
  ports:
  - name: "http"
    port: 5000
    protocol: TCP
    targetPort: 5000
  selector:
    app: flask-app
    version: v1
  type: NodePort
Copy the code

Execute kubectl apply -f deployment-v1.yaml

Run kubectl apply -f service.yaml

Run the minikube IP command to view the node IP address. Kubectl get SVC command to view the nodeport port

Run: curl $http://${node_ip}:${node_port}

Output:

{" Address ", "172.17.0.4", "Hostname" : "cd76c45c - kpzn5 flask - app - 69", "Message" : "Hello, World", "Version" : "v1"}Copy the code

Execute kubectl apply -f deployment-v2.yaml

Change all v1 in service.yaml to v2

Run kubectl apply -f service.yaml

To continue: curl $http://${node_ip}:${node_port}

Output:

{" Address ", "172.17.0.8", "Hostname" : "flask - app - f77677 v2-6748 - vb4rx", "Message" : "Hello, World", "Version" : "v2"}Copy the code

Gray released

Clean up the previous Deployment and Service before grayscale publishing

kubectl delete -f deployment-v1.yaml
kubectl delete -f deployment-v2.yaml
kubectl delete -f service.yaml
Copy the code

Prepare a few files deployment-canary-v1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-app-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: flask-app
  template:
    metadata:
      labels:
        app: flask-app
    spec:
      containers:
      - image: flask-app:v1
        name: flask-app
        ports:
        - containerPort: 5000
Copy the code

deployment-canary-v2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-app-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: flask-app
  template:
    metadata:
      labels:
        app: flask-app
    spec:
      containers:
      - image: flask-app:v2
        name: flask-app
        ports:
        - containerPort: 5000
Copy the code

service-canary.yaml

apiVersion: v1
kind: Service
metadata:
  name: flask-app
spec:
  ports:
  - name: "http"
    port: 5000
    protocol: TCP
    targetPort: 5000
  selector:
    app: flask-app
  type: NodePort
Copy the code

Perform:

kubectl apply -f deployment-canary-v1.yaml
kubectl apply -f deployment-canary-v2.yaml
kubectl apply -f service-canary.yaml
Copy the code

Run kubectl get SVC to view nodeport

Perform:

while true; do curl http://${node_ip}:${node_port}; done
Copy the code

Output:

{" Address ", "172.17.0.7", "Hostname" : "cd76c45c - knn4c flask - app - 69", "Message" : "Hello, World ", "Version" : "v1"} {" Address ":" 172.17.0.4 ", "Hostname" : "flask - app - v2-7 c957654cc - 2 MTBB", "Message" : "Hello, World ", "Version" : "v2"} {" Address ":" 172.17.0.4 ", "Hostname" : "flask - app - v2-7 c957654cc - 2 MTBB", "Message" : "Hello, World ", "Version" : "v2"} {" Address ":" 172.17.0.4 ", "Hostname" : "flask - app - v2-7 c957654cc - 2 MTBB", "Message" : "Hello, World ", "Version" : "v2"} {" Address ":" 172.17.0.7 ", "Hostname" : "cd76c45c - knn4c flask - app - 69", "Message" : "Hello, World ", "Version" : "v1"} {" Address ":" 172.17.0.7 ", "Hostname" : "cd76c45c - knn4c flask - app - 69", "Message" : "Hello, World ", "Version" : "v1"} {" Address ":" 172.17.0.4 ", "Hostname" : "flask - app - v2-7 c957654cc - 2 MTBB", "Message" : "Hello, World","Version":"v2"}Copy the code

Using the service roundrobin load balancing function, you can see that v1 and V2 services coexist.