概述

如何在腾讯云 Kubernetes 集群实现蓝绿发布和灰度发布?通常要向集群额外部署其它开源工具来实现,比如 Nginx Ingress,Traefik 等,或者让业务上 Service Mesh(服务网格),利用服务网格的能力来实现。这些方案多多少少都是需要一点点门槛的,如果蓝绿发布或灰度发布的需求不复杂,同时不希望让集群引入更多的组件或复杂的用法,可以考虑使用本文的简单方案,利用 Kubernetes 原生的特性以及腾讯云 TKE/EKS 集群自带的 LB 插件实现简单的蓝绿发布和灰度发布。

: 本文适用产品范围: TKE 集群、EKS 集群 (弹性集群)

原理介绍

我们通常使用 Deployment、StatefulSet 等 Kubernetes 自带的工作负载来部署业务,每个工作负载都管理一组 Pod,以 Deployment 为例:

通常还会为每个工作负载创建对应的 Service,Service 通过 selector 来匹配后端 Pod,其它服务或者外部通过访问 Service 即可访问到后端 Pod 提供的服务。要对外暴露可以直接将 Service 类型设置为 LoadBalancer,LB 插件会自动为其创建 CLB (腾讯云负载均衡器) 作为流量入口。

如何实现蓝绿发布?以 Deployment 为例,集群中部署两个不同版本的 Deployment,它们的 Pod 拥有共同的 label,但有一个 label 的值不同,用于区分不同的版本,Service 使用 selector 选中了其中一个版本的 Deployment 的 Pod,通过修改 Service 的 selector 中决定 服务版本的 label 的值来改变 Service 后端对应的 Deployment,实现让服务从一个版本直接切换到另一个版本,即蓝绿发布:

如何实现灰度发布?虽然我们通常会为每个工作负载都创建一个 Service,但 Kubernetes 并没有限制 Service 一定要与工作负载一一对应,因为 Service 是通过 selector 来匹配后端 Pod 的,只要不同工作负载的 Pod 都能被相同 selector 选中,就可以实现一个 Service 对应多个版本的工作负载的效果,调整不同版本工作负载的副本数就相当于调整不同版本服务的权重,实现灰度发布:

使用 YAML 创建资源

本文的示例将使用 yaml 的方式部署工作负载和创建 Service,有两种操作方式。

方式一:在 TKE 或 EKS 控制台右上角点击 YAML 创建资源,然后将本文示例的 yaml 粘贴进去:

方式二:将示例的 yaml 保存成文件,然后使用 kubectl 指定 yaml 文件来创建,如: kubectl apply -f xx.yaml

部署多版本工作负载

要实现蓝绿发布或灰度发布,首先我们需要在集群中部署多个版本的工作负载,这里以简单的 nginx 为例,部署第一个版本:

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-v1
spec:
replicas: 3
selector:
matchLabels:
app: nginx
version: v1
template:
metadata:
labels:
app: nginx
version: v1
spec:
containers:
- name: nginx
image: "openresty/openresty:centos"
ports:
- name: http
protocol: TCP
containerPort: 80
volumeMounts:
- mountPath: /usr/local/openresty/nginx/conf/nginx.conf
name: config
subPath: nginx.conf
volumes:
- name: config
configMap:
name: nginx-v1
---
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: nginx
version: v1
name: nginx-v1
data:
nginx.conf: |-
worker_processes 1;
events {
accept_mutex on;
multi_accept on;
use epoll;
worker_connections 1024;
}
http {
ignore_invalid_headers off;
server {
listen 80;
location / {
access_by_lua '
local header_str = ngx.say("nginx-v1")
';
}
}
}

再部署第二个版本:

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-v2
spec:
replicas: 3
selector:
matchLabels:
app: nginx
version: v2
template:
metadata:
labels:
app: nginx
version: v2
spec:
containers:
- name: nginx
image: "openresty/openresty:centos"
ports:
- name: http
protocol: TCP
containerPort: 80
volumeMounts:
- mountPath: /usr/local/openresty/nginx/conf/nginx.conf
name: config
subPath: nginx.conf
volumes:
- name: config
configMap:
name: nginx-v2
---
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: nginx
version: v2
name: nginx-v2
data:
nginx.conf: |-
worker_processes 1;
events {
accept_mutex on;
multi_accept on;
use epoll;
worker_connections 1024;
}
http {
ignore_invalid_headers off;
server {
listen 80;
location / {
access_by_lua '
local header_str = ngx.say("nginx-v2")
';
}
}
}

可以在控制台看到部署的情况:

实现蓝绿发布

为我们部署的 Deployment 创建 LoadBalancer 类型的 Service 对外暴露服务,指定使用 v1 版本的服务:

apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: LoadBalancer
ports:
- port: 80
protocol: TCP
name: http
selector:
app: nginx
version: v1

测试访问:

$ for i in {1..10}; do curl EXTERNAL-IP; done; # 替换 EXTERNAL-IP 为 Service 的 CLB IP 地址
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1

全是 v1 版本的响应,现在我们切到 v2 版本,修改 Service 的 selector,让它选中 v2 版本的服务,如果在控制台改,先找到对应 Service,点击 编辑YAML:

修改 selector 部分:

  selector:
app: nginx
version: v2

或者也可以直接用 kubectl 修改:

kubectl patch service nginx -p '{"spec":{"selector":{"version":"v2"}}}'

再次测试访问:

$ for i in {1..10}; do curl EXTERNAL-IP; done; # 替换 EXTERNAL-IP 为 Service 的 CLB IP 地址
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2

全是 v2 版本的响应,成功实现了蓝绿发布。

实现灰度发布

相比蓝绿发布,我们为不给 Service 指定使用 v1 版本的服务,从 selector 中删除 version 标签,让 Service 同时选中两个版本的 Deployment 的 Pod:

apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: LoadBalancer
ports:
- port: 80
protocol: TCP
name: http
selector:
app: nginx

测试访问:

$ for i in {1..10}; do curl EXTERNAL-IP; done; # 替换 EXTERNAL-IP 为 Service 的 CLB IP 地址
nginx-v1
nginx-v1
nginx-v2
nginx-v2
nginx-v2
nginx-v1
nginx-v1
nginx-v1
nginx-v2
nginx-v2

可以看到,一半是 v1 版本的响应,另一半是 v2 版本的响应。现在我们来调节 v1 和 v2 版本的 Deployment 的副本,将 v1 版本调至 1 个副本,v2 版本调至 4 个副本。

可以通过控制台操作:

也可以通过 kubectl 操作:

kubectl scale deployment/nginx-v1 --replicas=1
kubectl scale deployment/nginx-v2 --replicas=4

然后再次进行访问测试:

$ for i in {1..10}; do curl EXTERNAL-IP; done; # 替换 EXTERNAL-IP 为 Service 的 CLB IP 地址nginx-v2nginx-v1nginx-v2nginx-v2nginx-v2nginx-v2nginx-v1nginx-v2nginx-v2nginx-v2$ for i in {1..10}; do curl EXTERNAL-IP; done; # 替换 EXTERNAL-IP 为 Service 的 CLB IP 地址
nginx-v2
nginx-v1
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v1
nginx-v2
nginx-v2
nginx-v2

可以看到,10 次访问中只有 2 次返回了 v1 版本,v1 与 v2 的响应比例与其副本数比例一致,为 1:4,通过控制不同版本服务的副本数就实现了灰度发布。

总结

本文我们介绍了如何在有限的条件下在 Kubernetes 集群中实现简单的蓝绿发布与灰度发布,对于一些简单的发布需求场景可以考虑使用这种方案。

【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!

手把手教你在 TKE 集群中实现简单的蓝绿发布和灰度发布的更多相关文章

  1. 手把手教你搭建FastDFS集群(中)

    手把手教你搭建FastDFS集群(中) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u0 ...

  2. 手把手教你搭建FastDFS集群(下)

    手把手教你搭建FastDFS集群(下) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u0 ...

  3. 手把手教你搭建FastDFS集群(上)

    手把手教你搭建FastDFS集群(上) 本文链接:https://blog.csdn.net/u012453843/article/details/68957209        FastDFS是一个 ...

  4. 手把手教你Linux服务器集群部署.net网站 - Linux系统安装和设置

    在开源软件已成趋势化的今天,微软这‘老古董’也开始向开源方向发力,这对我们.NET开发者是极大的喜讯.而在开源软件中, Linux就是其中一个优秀的代表,几乎各行业和计算机有关的都有它的身影,其中一点 ...

  5. 手把手教你Linux服务器集群部署.net网站 - 让MVC网站运行起来

    一.Linux下面安装需要软件 我们这里需要安装的软件有: 1) Mono 3.2.8 : C#跨平台编译器,能使.Net运行与Linux下,目前.net 4.0可以完美运行在该平台下 2) ngin ...

  6. 手把手教你使用容器服务 TKE 集群审计排查问题

    概述 有时候,集群资源莫名被删除或修改,有可能是人为误操作,也有可能是某个应用的 bug 或恶意程序调用 apiserver 接口导致,需要找出 "真凶".这时候,我们需要为集群开 ...

  7. redis之(十五)redis的集群中的哨兵角色

    一:redis集群的哨兵的目的是什么?. (1)监控主redis和从redis数据库是否正常运行 (2)主redis出现故障,自动将其中一台从redis升级为主redis.将原先的主redis转变成从 ...

  8. 在开启DRS的集群中修复VMware虚拟主机启动问题

    通过iSCSI方式连接到ESXi主机上的外挂存储意外失联了一段时间,导致部分虚拟主机在集群中呈现出孤立的状态,单独登陆到每台ESXi上可以看到这些虚拟主机都变成了unknow状态.因为有过上一次(VM ...

  9. Redis设置认证密码 Redis使用认证密码登录 在Redis集群中使用认证密码

    Redis默认配置是不需要密码认证的,也就是说只要连接的Redis服务器的host和port正确,就可以连接使用.这在安全性上会有一定的问题,所以需要启用Redis的认证密码,增加Redis服务器的安 ...

随机推荐

  1. JavaScript的数据类型判断学习理解和数据处理

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. Shell编程—正则表达式

    1什么是正则表达式 1.1定义 正则表达式是你所定义的模式模板,Linux工具可以用它来过滤文本.Linux 工具(比如sed编辑器或gawk程序)能够在处理数据时使用正则表达式对数据进行模式匹配. ...

  3. 数据操纵DML

    数据操纵DML 1. 在dept表中插入两行数据 (1)50,'IT','SHENYANG';(2)60,'HR','DALIAN'; 2. 设置保存点beforeup 3. 更新dept表,将60号 ...

  4. 【转】Echarts自适应

    var myChart1 = echarts.init(document.getElementById('chart1')); var option = myChart1.getOption(); w ...

  5. jdk8的下载、安装、配置

    jdk官方网址:https://www.oracle.com/java/technologies/javase-downloads.html 小编微信和公众号(很高兴能与各位交流学习) 以下是具体步骤 ...

  6. python安装wordcloud库报错

    pip install wordcloud 安装成了这样 红彤彤的一片 解决方法 https://www.lfd.uci.edu/~gohlke/pythonlibs/#wordcloud 下载对应版 ...

  7. 无法创建新虚拟机: 无法打开配置文件“F:\BigData\vm12\centos01\centos01.vmx”: 拒绝访问。

    退出,右键vmware选择以管理员身份运行即可.

  8. python小白入门基础(三:整型)

    # Number(int float str complex) #int 整型(正整数 0 负整数)intvar_1 = 100print(intvar_1)invar_2 = 0 print(inv ...

  9. 1090 Highest Price in Supply Chain (25 分)(模拟建树,找树的深度)牛客网过,pat没过

    A supply chain is a network of retailers(零售商), distributors(经销商), and suppliers(供应商)-- everyone invo ...

  10. 小程序开发-Canvas画布组件

    Canvas画布 基本使用方法: 在wxml中添加canvas组件 <canvas canvas-id='canvasDemo' class='demo'></canvas> ...