Kubernetes上的藍/綠部署

引言

Kubernetes有一個資源對象,稱爲Deployments。 當你將應用程序更新到新版本時,Deployments具備進行容器滾動更新的功能。 滾動更新是一種更新應用程序的好方法,由於應用程序在更新過程當中使用的資源與未更新時使用的資源數量大體相同,從而對性能和可用性的影響最小。nginx

可是,有許多舊版應用程序不能很好地與滾動更新配合使用,某些應用程序只須要部署一個新版本並當即轉換到新版本便可。 爲此,咱們須要執行藍/綠部署,將現有版本(藍色)一塊兒部署應用程序的新副本(綠色), 而後將更新過的應用程序對應的ingress/router切換到新版本(綠色 ,接着等待舊的(藍色)版本完成發送給它的請求,在絕大多數狀況下,應用的流量會馬上切換到新版本。
image.png
Kubernetes不支持內置的藍/綠部署,這裏使用的方法是建立一個新的deployment,而後更新該應用程序的服務以指向新的deployment。git

藍色部署

Kubernetes deployment指定一組應用程序實例,它建立了一個副本集(replicaset),該副本集負責保持指定數量的實例正常運行。github

image.png
經過將如下yaml保存到文件blue.yaml中來建立「 blue」deployment。json

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

使用kubectl命令行建立deploymentapi

$ kubectl apply -f blue.yaml

部署完成後,咱們能夠提供一種經過建立service來訪問deployment實例的方法。 service與deployment是分離的,這意味着無需明確將service指向deployment。 你要作的是指定一個標籤選擇器(label selector),該標籤選擇器用於列出組成service的pod。 使用deployment時,一般會設置標籤選擇器使其與deployment的pod匹配。
在本例中有兩個標籤,name= nginx和version= 1.10。 咱們將它們設置爲如下service的標籤選擇器,將其保存到service.yaml。bash

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

建立service的同時建立一個能夠在羣集外部訪問的load balancer。app

$ kubectl apply -f service.yaml

看起來像這樣:curl

image.png
測試這個service是否可訪問並獲取它的版本號。性能

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

綠色部署

如今建立一個新的deployment叫作green deployment(綠色部署),使用green.yaml來建立學習

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

執行建立

$ kubectl apply -f green.yaml

如今有兩個deployment可是service仍然指向blue deployment
image.png

更新應用

爲了切換到「green」deployment,咱們將更新service的selector。 編輯service.yaml並將selector版本更改成「 1.11」,使其與「green」deployment中的pod匹配。

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

更新當前的nginx service

$ kubectl apply -f service.yaml

如今的狀況變成了下面這樣
image.png
當即更新service的selector你將會看到新版本的nginx正在接收外部流量

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

自動化

使用腳本實現自動化的藍/綠部署,如下腳本使用service的名稱,要部署的版本以及green deployment的yaml文件的路徑,並使用kubectl進行完整的藍/綠部署,使用jq從API對其進行解析並輸出原始JSON文件,在更新service definition以前,它經過檢查deployment對象上的status.conditions等待green deployment準備就緒。
下面提供一個腳本

#!/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."

想深刻學習的話,我在github上提供了一個教程和一些示例清單。

相關文章
相關標籤/搜索