Kubernetes上的蓝/绿部署

暴风骤雨
• 阅读 2380

引言

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

但是,有许多旧版应用程序不能很好地与滚动更新配合使用,某些应用程序只需要部署一个新版本并立即转换到新版本即可。 为此,我们需要执行蓝/绿部署,将现有版本(蓝色)一起部署应用程序的新副本(绿色), 然后将更新过的应用程序对应的ingress/router切换到新版本(绿色 ,接着等待旧的(蓝色)版本完成发送给它的请求,在绝大多数情况下,应用的流量会立刻切换到新版本。
Kubernetes上的蓝/绿部署
Kubernetes不支持内置的蓝/绿部署,这里使用的方法是创建一个新的deployment,然后更新该应用程序的服务以指向新的deployment。

蓝色部署

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

Kubernetes上的蓝/绿部署
通过将以下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

看起来像这样:

Kubernetes上的蓝/绿部署
测试这个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
Kubernetes上的蓝/绿部署

更新应用

为了切换到“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

现在的情况变成了下面这样
Kubernetes上的蓝/绿部署
立即更新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上提供了一个教程和一些示例清单。

点赞
收藏
评论区
推荐文章
Tommy744 Tommy744
4年前
PaaS失败了吗?让我们看看Cloud Foundry的优势
软件团队常见的行为方式可以总结如下:1.软件部署从Heroku或Firebase开始。2.在应用程序需要快速扩展时,开始使用Docker进行容器化。3.在遇到Docker困境的时候,考虑使用Kubernetes等容器编排工具。(https://cdn.thenewstack.io/media/2020/12/5105a24aimage011.
DevOpSec DevOpSec
4年前
Kubernetes(k8s)中文文档 Kubernetes概述
简介Kubernetes(https://www.kubernetes.org.cn/)是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。Kubernetes一个核心的特点就是能够自主的管理容
Stella981 Stella981
3年前
Minikube之Win10单机部署
Kubernetes(k8s)是自动化容器操作的开源平台,基于这个平台,你可以进行容器部署,资源调度和集群扩容等操作。如果你曾经用过Docker部署容器,那么可以将Docker看成Kubernetes底层使用的组件,Kubernetes是Docker的上层封装,通过它可以很方便的进行Docker集群的管理。今天我们使用minikube在单机上进行Kubern
Stella981 Stella981
3年前
Kubernetes 部署 Nebula 图数据库集群
Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效,Kubernetes提供了应用部署,规划,更新,维护的一种机制。<br/Kubernetes在设计结构上定义了一系列的构建模块,其目的是为了提供一个可以部署、维护和扩展应用程序的机制,组成Kubernetes
Stella981 Stella981
3年前
Kerberos无约束委派的攻击和防御
 0x00前言简介当ActiveDirectory首次与Windows2000Server一起发布时,Microsoft就提供了一种简单的机制来支持用户通过Kerberos对Web服务器进行身份验证并需要授权用户更新后端数据库服务器上的记录的方案。这通常被称为Kerberosdoublehopissue(双跃点问题),
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Stella981 Stella981
3年前
Kubernetes(K8S)
一、简介  Kubernetes是Google公司在2014年6月开源的一个容器集群管理系统,使用Go语言开发,也叫K8S。Kubernetes的目标是让部署容器化的应用简单并且高效,Kubernetes提供了应用部署,规划,更新,维护的一种机制。Kubernetes一个核心的特点就是能够自主的管理容器来保证云平台中的容器按照用户的期望状态运行着
Stella981 Stella981
3年前
K8s(7)
仪表板是基于Web的Kubernetes用户界面。您可以使用仪表板将容器化应用程序部署到Kubernetes集群,对容器化应用程序进行故障排除,以及管理集群资源。您可以使用仪表板来概述群集上运行的应用程序,以及创建或修改单个Kubernetes资源(例如部署,作业,守护进程等)。例如,您可以使用部署向导扩展部署,启动滚动更新,重新启动Pod或部署新应用程序
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
K8S知道,K9S呢?
k9s是用于管理Kubernetes集群的CLI。通过封装kubectl功能,k9s可以让开发者快速查看并解决运行Kubernetes时的日常问题。部分特性跟踪在Kubernetes集群运行的资源的实时活动处理Kubernetes标准资源和自定义资源跟踪与资源相关联的
飞龙AI 飞龙AI
2个月前
DevEcoStudio 中使用模拟器时如何过滤日志
DevEcoStudio中使用模拟器时如何过滤日志鸿蒙核心技术鸿蒙开发者工具DevEcoStudio在HilogSettingsFilter设置Logmessage:A03d00/JSAPP当你看到不断更新的日志时,你会不会崩溃因为Nofilters模式下