如何在腾讯云 Kubernetes 集群实现蓝绿发布和灰度发布?一般要向集群额外部署其它开源工具来实现,好比 Nginx Ingress,Traefik 等,或者让业务上 Service Mesh(服务网格),利用服务网格的能力来实现。这些方案多多少少都是须要一点点门槛的,若是蓝绿发布或灰度发布的需求不复杂,同时不但愿让集群引入更多的组件或复杂的用法,能够考虑使用本文的简单方案,利用 Kubernetes 原生的特性以及腾讯云 TKE/EKS 集群自带的 LB 插件实现简单的蓝绿发布和灰度发布。nginx
注: 本文适用产品范围: TKE 集群、EKS 集群 (弹性集群)后端
咱们一般使用 Deployment、StatefulSet 等 Kubernetes 自带的工做负载来部署业务,每一个工做负载都管理一组 Pod,以 Deployment 为例:centos
一般还会为每一个工做负载建立对应的 Service,Service 经过 selector 来匹配后端 Pod,其它服务或者外部经过访问 Service 便可访问到后端 Pod 提供的服务。要对外暴露能够直接将 Service 类型设置为 LoadBalancer,LB 插件会自动为其建立 CLB (腾讯云负载均衡器) 做为流量入口。api
如何实现蓝绿发布?以 Deployment 为例,集群中部署两个不一样版本的 Deployment,它们的 Pod 拥有共同的 label,但有一个 label 的值不一样,用于区分不一样的版本,Service 使用 selector 选中了其中一个版本的 Deployment 的 Pod,经过修改 Service 的 selector 中决定 服务版本的 label 的值来改变 Service 后端对应的 Deployment,实现让服务从一个版本直接切换到另外一个版本,即蓝绿发布:app
如何实现灰度发布?虽然咱们一般会为每一个工做负载都建立一个 Service,但 Kubernetes 并无限制 Service 必定要与工做负载一一对应,由于 Service 是经过 selector 来匹配后端 Pod 的,只要不一样工做负载的 Pod 都能被相同 selector 选中,就能够实现一个 Service 对应多个版本的工做负载的效果,调整不一样版本工做负载的副本数就至关于调整不一样版本服务的权重,实现灰度发布:负载均衡
本文的示例将使用 yaml 的方式部署工做负载和建立 Service,有两种操做方式。curl
方式一:在 TKE 或 EKS 控制台右上角点击 YAML 建立资源
,而后将本文示例的 yaml 粘贴进去:工具
方式二:将示例的 yaml 保存成文件,而后使用 kubectl 指定 yaml 文件来建立,如: kubectl apply -f xx.yaml
。测试
要实现蓝绿发布或灰度发布,首先咱们须要在集群中部署多个版本的工做负载,这里以简单的 nginx 为例,部署第一个版本:lua
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 集群中实现简单的蓝绿发布与灰度发布,对于一些简单的发布需求场景能够考虑使用这种方案。
【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!