引言

Kubernetes有一个资源对象,称为Deployments。 当你将应用程序更新到新版本时,Deployments具备进行容器滚动更新的性能。 滚动更新是一种更新应用程序的好办法,因为应用程序在更新过程中应用的资源与未更新时应用的资源数量大致相同,从而对性能和可用性的影响最小。

然而,有许多旧版应用程序不能很好地与滚动更新配合应用,某些应用程序只须要部署一个新版本并立刻转换到新版本即可。 为此,咱们须要执行蓝/绿部署,将现有版本(蓝色)一起部署应用程序的新正本(绿色), 而后将更新过的应用程序对应的ingress/router切换到新版本(绿色 ,接着期待旧的(蓝色)版本实现发送给它的申请,在绝大多数状况下,利用的流量会立即切换到新版本。

Kubernetes不反对内置的蓝/绿部署,这里应用的办法是创立一个新的deployment,而后更新该应用程序的服务以指向新的deployment。

蓝色部署

Kubernetes deployment指定一组应用程序实例,它创立了一个正本集(replicaset),该正本集负责放弃指定数量的实例失常运行。


通过将以下yaml保留到文件blue.yaml中来创立“ blue”deployment。

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

应用kubectl命令行创立deployment

$ 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。

apiVersion: v1kind: Servicemetadata:   name: nginx  labels:     name: nginxspec:  ports:    - name: http      port: 80      targetPort: 80  selector:     name: nginx    version: "1.10"  type: LoadBalancer

创立service的同时创立一个能够在群集内部拜访的load balancer。

$ kubectl apply -f service.yaml

看起来像这样:


测试这个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/v1beta1kind: Deploymentmetadata:  name: nginx-1.11spec:  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

更新利用

为了切换到“green”deployment,咱们将更新service的selector。 编辑service.yaml并将selector版本更改为“ 1.11”,使其与“green”deployment中的pod匹配。

apiVersion: v1kind: Servicemetadata:   name: nginx  labels:     name: nginxspec:  ports:    - name: http      port: 80      targetPort: 80  selector:     name: nginx    version: "1.11"  type: LoadBalancer

更新以后的nginx service

$ kubectl apply -f service.yaml

当初的状况变成了上面这样

立刻更新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-$2SERVICE=$1VERSION=$2DEPLOYMENTFILE=$3kubectl 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 5done# Update the service selector with the new versionkubectl patch svc $SERVICE -p "{\"spec\":{\"selector\": {\"name\": \"${SERVICE}\", \"version\": \"${VERSION}\"}}}"echo "Done."

想深刻学习的话,我在github上提供了一个教程和一些示例清单。