引言
Kubernetes 有一个资源对象,称为 Deployments。当你将应用程序更新到新版本时,Deployments 具备进行容器滚动更新的性能。滚动更新是一种更新应用程序的好办法,因为应用程序在更新过程中应用的资源与未更新时应用的资源数量大致相同,从而对性能和可用性的影响最小。
然而,有许多旧版应用程序不能很好地与滚动更新配合应用,某些应用程序只须要部署一个新版本并立刻转换到新版本即可。为此,咱们须要执行蓝 / 绿部署,将现有版本(蓝色)一起部署应用程序的新正本(绿色),而后将更新过的应用程序对应的 ingress/router 切换到新版本(绿色,接着期待旧的(蓝色)版本实现发送给它的申请,在绝大多数状况下,利用的流量会立即切换到新版本。
Kubernetes 不反对内置的蓝 / 绿部署,这里应用的办法是创立一个新的 deployment,而后更新该应用程序的服务以指向新的 deployment。
蓝色部署
Kubernetes deployment 指定一组应用程序实例,它创立了一个正本集(replicaset),该正本集负责放弃指定数量的实例失常运行。
通过将以下 yaml 保留到文件 blue.yaml 中来创立“blue”deployment。
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 命令行创立 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: 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。
$ 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/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 上提供了一个教程和一些示例清单。