前言
环境:centos7.9
下面使用ingress-nginx模拟k8s是如何进行灰度发布业务的。
灰度发布(也叫金丝雀发布)
前提条件:已安装好ingress-nginx,这里提前安装好了ingress-nginx并在每个node上启动了一个30080端可30443端口;
制作2个版本的镜像
mkdir /root/canary-depoly
[root@matser canary-depoly]# vim Dockerfile #先来制作一个V1版本的nginx镜像
FROM nginx
RUN echo "Welcome to nginx! I am V1." >/usr/share/nginx/html/index.html
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 80
STOPSIGNAL SIGQUIT
CMD ["nginx", "-g", "daemon off;"]
[root@matser canary-depoly]# docker build -t nginx:v1 .
[root@matser canary-depoly]# vim Dockerfile #再来制作一个V2版本的nginx镜像
FROM nginx
RUN echo "Welcome to nginx! I am V2." >/usr/share/nginx/html/index.html
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 80
STOPSIGNAL SIGQUIT
CMD ["nginx", "-g", "daemon off;"]
[root@matser canary-depoly]# docker build -t nginx:v2 .
#到这里两个版本的镜像已经制作外部
创建v1版的服务
#创建v1版本的deployment
[root@matser canary-depoly]# vim deloyment-nginx-v1.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-nginx-v1
namespace: default
spec:
replicas: 4
selector:
matchLabels:
app: nginx-v1
template:
metadata:
labels:
app: nginx-v1
spec:
containers:
- image: nginx:v1
imagePullPolicy: IfNotPresent
name: nginx-v1
ports:
- containerPort: 80
name: http
protocol: TCP
restartPolicy: Always
#创建service
[root@matser canary-depoly]# vim service-nginx.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: svc-nginx-v1
name: svc-nginx-v1
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-v1
[root@matser canary-depoly]#
创建ingress访问v1版的服务
[root@matser canary-depoly]# cat ingress-nginx-v1.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress-v1
spec:
rules:
- host: www.test.com
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: svc-nginx-v1
port:
number: 80
ingressClassName: nginx
[root@matser canary-depoly]#
定义nginx负载均衡器
这里使用了一个nginx负载均衡器:
找一台nginx服务器,配置反向代理,反向代理到node节点上的ingress开的30080端口:
[root@nginx ~]# cat /etc/nginx/nginx.conf
http {
....................................
upstream server_pools {
server 192.168.118.141:30080; #node1节点,30080是ingress-nginx-controller的service端口
server 192.168.118.142:30080; #node2节点,30080是ingress-nginx-controller的service端口
}
server {
listen 8888; #nginx的端口
server_name _;
location / { #加上反向代理
proxy_pass http://server_pools;
proxy_set_header Host $host; #必须加上这个
}
}
}
[root@nginx ~]# vim /etc/hosts #将ingress定义的www.test.com域名解析到nginx服务器上
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 www.test.com
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
模拟外部访问v1版的服务
在nginx服务器上模拟用户客户端访问。现在都是访问v1版本,如下:
[root@nginx ~]# for i in $(seq 1 10);do curl www.test.com:8888;done
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
[root@nginx ~]#
创建V2版本的deployment和service
[root@matser canary-depoly]# vim deloyment-nginx-v2.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-nginx-v2
namespace: default
spec:
replicas: 4
selector:
matchLabels:
app: nginx-v2
template:
metadata:
labels:
app: nginx-v2
spec:
containers:
- image: nginx:v2
imagePullPolicy: IfNotPresent
name: nginx-v2
ports:
- containerPort: 80
name: http
protocol: TCP
restartPolicy: Always
[root@matser canary-depoly]#
#创建访问v2版本应用的service
[root@matser canary-depoly]# vim service-nginx-v2.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: svc-nginx-v2
name: svc-nginx-v2
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-v2
[root@matser canary-depoly]#
#创建灰度发布的 ingress-nginx-v2.yaml
[root@matser canary-depoly]# vim ingress-nginx-v2.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress-v2
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "30"
spec:
rules:
- host: www.test.com
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: svc-nginx-v2
port:
number: 80
ingressClassName: nginx
[root@matser canary-depoly]#
访问应用,查看是否是灰度发布了
#可以看到,基本是会有30%的流量现在是访问v2版本的应用了
[root@nginx ~]# for i in $(seq 1 10);do curl www.test.com:8888;done
Welcome to nginx! I am V2.
Welcome to nginx! I am V2.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V2.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
Welcome to nginx! I am V1.
[root@nginx ~]#
比较两个ingress的不同
[root@matser canary-depoly]# cat ingress-nginx-v1.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress-v1 #ingress的名字
spec:
rules:
- host: www.test.com #域名
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: svc-nginx-v1 #service的名称
port:
number: 80 #service的端口
ingressClassName: nginx
[root@matser canary-depoly]# cat ingress-nginx-v2.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress-v2
annotations:
nginx.ingress.kubernetes.io/canary: "true" #启用金丝雀
nginx.ingress.kubernetes.io/canary-weight: "30" #30%的流量
spec:
rules:
- host: www.test.com #域名相同
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: svc-nginx-v2 #service的名称
port:
number: 80
ingressClassName: nginx
[root@matser canary-depoly]#
#对比我们发现,在创建ingress2的时候,ingress2定义的名称和service的名称等都可以不同,但是定义的域名要与ingress1的相同,同时还要加上注解表示启动金丝雀和配置权重表示分发多少流量。
灰度发布还可以根据请求头来实现,上面仅展示了根据权重来分发流量;