Kubernetes有一个资源对象,称为Deployments。 当你将应用程序更新到新版本时,Deployments具备进行容器滚动更新的功能。 滚动更新是一种更新应用程序的好方法,由于应用程序在更新过程当中使用的资源与未更新时使用的资源数量大体相同,从而对性能和可用性的影响最小。nginx
可是,有许多旧版应用程序不能很好地与滚动更新配合使用,某些应用程序只须要部署一个新版本并当即转换到新版本便可。 为此,咱们须要执行蓝/绿部署,将现有版本(蓝色)一块儿部署应用程序的新副本(绿色), 而后将更新过的应用程序对应的ingress/router切换到新版本(绿色 ,接着等待旧的(蓝色)版本完成发送给它的请求,在绝大多数状况下,应用的流量会马上切换到新版本。
Kubernetes不支持内置的蓝/绿部署,这里使用的方法是建立一个新的deployment,而后更新该应用程序的服务以指向新的deployment。git
Kubernetes deployment指定一组应用程序实例,它建立了一个副本集(replicaset),该副本集负责保持指定数量的实例正常运行。github
经过将如下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
测试这个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
为了切换到“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
如今的状况变成了下面这样
当即更新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上提供了一个教程和一些示例清单。