一、使用 Nginx 实现金丝雀发布¶
假设我们有两个命名空间,一个是正在使用的生产环境Production,另一个是用于灰度测试的Canary。在发布应用时,可以将应用先发布至Canary,然后切一部分流量到Canary,之后慢慢将流量全部切换到上面即可。
下面开始先创建v1版本
1.先创建模拟 Production(生产)环境的 Namespace 和服务
[root@k8s-master01 ~]# kubectl create ns production
[root@k8s-master01 ~]# kubectl create deploy canary-v1 --image=registry.cn-hangzhou.aliyuncs.com/abroad_images/canary:v1 -n production
[root@k8s-master01 ~]# kubectl expose deploy canary-v1 --port 8080 -n production
创建完成服务后,查看服务,观察到服务已成功创建
[root@k8s-master01 ~]# kubectl get svc -n production
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
canary-v1 ClusterIP 10.0.239.16 <none> 8080/TCP 41s
2.创建Ingress
[root@k8s-master01 ~]# kubectl create ingress canary-v1 --rule=canary.com/*=canary-v1:8080 -n production
查看Ingress
[root@k8s-master01 ~]# kubectl get ingress -n production
NAME CLASS HOSTS ADDRESS PORTS AGE
canary-v1 nginx canary.com 80 8s
3.在win主机上修改hosts文件,文件路径为:C:\Windows\System32\drivers\etc\hosts
192.168.1.35 canary.com
4.打开浏览器,输入canary.com后,显示Canary v1

当然你也可以选择一台主机进行测试
[root@k8s-master01 ~]# curl -H "Host:canary.com" 192.168.1.35
<h1>Canary v1</h1>
上面创建完成v1版本后,接着创建v2版本来充当灰度环境
1.创建 v2 版本的命名空间、应用和 Service
[root@k8s-master01 ~]# kubectl create ns canary
[root@k8s-master01 ~]# kubectl create deploy canary-v2 --image=registry.cn-hangzhou.aliyuncs.com/abroad_images/canary:v2 -n canary
[root@k8s-master01 ~]# kubectl expose deploy canary-v2 --port 8080 -n canary
查看服务
[root@k8s-master01 ~]# kubectl get svc -n canary
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
canary-v2 ClusterIP 10.0.76.59 <none> 8080/TCP 5s
2.访问服务,此时会返回 Canary v2
[root@k8s-master01 ~]# curl 10.0.76.59:8080
<h1>Canary v2</h1>
上面生产环境和灰度环境已经准备完毕后,此时需要做的就是把生产环境的流量切入到灰度环境。因此在创建v2 版本的 Ingress 时,添加注释,完成生产环境流量切入到灰度环境流量。下面进行演示说明:
1.创建v2 版本的 Ingress
编写Ingress文件
[root@k8s-master01 ~]# vim canary-v2.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
name: canary-v2
namespace: canary
spec:
ingressClassName: nginx # for k8s >= 1.22+
rules:
- host: canary.com
http:
paths:
- backend:
service:
name: canary-v2
port:
number: 8080
path: /
pathType: ImplementationSpecific
上面参数说明:
nginx.ingress.kubernetes.io/canary: "true":表示启用了金丝雀发布策略。nginx.ingress.kubernetes.io/canary-weight: "10":表示新版本的金丝雀比例为 10%,即将 10% 的流量引导到此版本
创建该ingress
[root@k8s-master01 study-ingress]# kubectl create -f canary-v2.yaml
2.在k8s-master01主机上修改/etc/hosts文件,添加canary.com和192.168.1.35的映射关系
[root@k8s-master01 ~]# vim /etc/hosts
192.168.1.35 k8s-node02 nginx.test.com canary.com
3.安装Ruby工具及编写 Ruby 脚本
安装 Ruby 工具
[root@k8s-master01 ~]# yum install ruby -y
编写 Ruby 脚本
[root@k8s-master01 ~]# vim test-canary.rb
counts = Hash.new(0)
100.times do
output = `curl -s canary.com | grep 'Canary' | awk '{print $2}' | awk -F "<" '{print $1}'`
counts[output.strip.split.last] += 1
end
puts counts
上面参数说明:
创建了一个名为 counts 的哈希表,用于存储统计结果。这个哈希表中的键(Key)是字符串,表示响应中的 'Canary' 字符串,值(Value)是整数,表示该字符串出现的次数。
counts = Hash.new(0)
使用循环,总共进行了 100 次 HTTP 请求。每次请求通过 curl 命令从 canary.com 网站获取内容,然后使用 grep、awk 等命令提取响应中的 'Canary' 字符串,并将其存储在变量 output 中。
100.times do
output = `curl -s canary.com | grep 'Canary' | awk '{print $2}' | awk -F "<" '{print $1}'`
counts[output.strip.split.last] += 1
end
通过 output.strip.split.last,从 output 中获取到最后一个单词,并存储在哈希表 counts 中。如果响应中包含多个 'Canary' 字符串,那么就统计每个不同的字符串出现的次数。最后,将统计结果打印输出,显示不同的 'Canary' 字符串和它们出现的次数。
puts counts
4.使用 Ruby 脚本进行测试,此脚本会输出 v1 和 v2 的访问次数比值。观察到输出 v1 和 v2 的访问次数比值为9:1
[root@k8s-master01 ~]# ruby test-canary.rb
{"v1"=>89, "v2"=>11}
二、环境清理¶
1.清除命名空间production的所有deploy,svc,ingress
[root@k8s-master01 ~]# kubectl delete deploy,svc,ingress -n production --all
2.清除命名空间canary的所有deploy,svc,ingress
[root@k8s-master01 ~]# kubectl delete deploy,svc,ingress -n canary --all
3.清除命名空间study-ingress的所有deploy,svc,ingress
[root@k8s-master01 ~]# kubectl delete deploy,svc,ingress -n study-ingress --all
4.删除所有命名空间study-ingress,production,canary
[root@k8s-master01 ~]# kubectl delete ns study-ingress production canary
5.删除Ingress Controller
[root@k8s-master01 ~]# cd ingress-nginx
[root@k8s-master01 ingress-nginx]# helm delete ingress-nginx -n ingress-nginx