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上提供了一个教程和一些示例清单。

相关文章
相关标签/搜索