一、金丝雀发布的高级功能¶
如上只简单介绍了一些ingress开源默认支持的Annotation。
日常工作中基于开源ingress-nginx实线的高级功能:
通过修改 nginx.ingress.kubernetes.io/configuration-snippet配置,并且配置正则实现:
- 当header头中有关键字(foo 或 new)字段的时候,自动将流量转发至new-nginx
- nginx.ingress.kubernetes.io/configuration-snippet (用于插入 location 块代码段);
- nginx.ingress.kubernetes.io/server-snippet (用于插入 server 块中的代码段);
#还原环境
[root@master01 6]# kaf ingress-canary.yaml
[root@master01 6]# k delete ing new-nginx-ingress nginx-ingress
#创建yaml文件
[root@master01 6]# vim ingress-canary-adv.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: new-nginx-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($http_name ~ "^.*foo$|^.*new$") {
proxy_pass http://new-nginx.default:80;
break;
}
spec:
ingressClassName: nginx
rules:
- host: nginx.zhang-qing.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: old-nginx
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: new-nginx
port:
number: 80
#重新应用
[root@master01 6]# kaf ingress-canary-adv.yaml
测试验证:
[root@master01 6]#curl -H "name: new" http://nginx.zhang-qing.com
new
[root@master01 6]#curl -H "name: foo" http://nginx.zhang-qing.com
new
[root@master01 6]#curl -H "Host: nginx.zhang-qing.com" http://nginx.zhang-qing.com
old
环境清理
[root@master01 6]#k delete -f ingress-canary-adv.yaml -f ingress-canary.yaml -f ingress-canary-new.yaml
二、阿里开源ingress-nginx实现¶
2.1 基础理论¶
Nginx Ingress Controller通过Annotation来支持应用服务的灰度发布机制。
nginx.ingress.kubernetes.io/service-match:该注解用来配置新版本服务的路由匹配规则。
nginx.ingress.kubernetes.io/service-match: |
<service-name>: <match-rule>
# 参数说明:
# service-name:服务名称,满足match-rule的请求会被路由到该服务中。
# match-rule:路由匹配规则
#
# 路由匹配规则:
# 1. 支持的匹配类型
# - header:基于请求头,支持正则匹配和完整匹配。
# - cookie:基于cookie,支持正则匹配和完整匹配。
# - query:基于请求参数,支持正则匹配和完整匹配。
#
# 2. 匹配方式
# - 正则匹配格式:/{regular expression}/,//表明采用正则方式匹配。
# - 完整匹配格式:"{exact expression}",""表明采用完整方式匹配。
路由匹配规则配置示例:
# 请求头中满足foo正则匹配^bar$的请求被转发到新版本服务new-nginx中。
new-nginx: header("foo", /^bar$/)
# 请求头中满足foo完整匹配bar的请求被转发到新版本服务new-nginx中。
new-nginx: header("foo", "bar")
# cookie中满足foo正则匹配^sticky-.+$的请求被转发到新版本服务new-nginx中。
new-nginx: cookie("foo", /^sticky-.+$/)
# query param中满足foo完整匹配bar的请求被转发到新版本服务new-nginx中。
new-nginx: query("foo", "bar")
nginx.ingress.kubernetes.io/service-weight :该注解用来配置新旧版本服务的流量权重。
nginx.ingress.kubernetes.io/service-weight: |
<new-svc-name>:<new-svc-weight>, <old-svc-name>:<old-svc-weight>
参数说明:
new-svc-name:新版本服务名称
new-svc-weight:新版本服务权重
old-svc-name:旧版本服务名称
old-svc-weight:旧版本服务权重
配置示例:
nginx.ingress.kubernetes.io/service-weight: |
new-nginx: 20, old-nginx: 60
2.2 案例¶
创建老服务的:Deployment、Service。
apiVersion: apps/v1
kind: Deployment
metadata:
name: old-nginx
spec:
replicas: 2
selector:
matchLabels:
app: old-nginx
template:
metadata:
labels:
app: old-nginx
run: old-nginx
spec:
containers:
- name: old-nginx
image: registry.cn-hangzhou.aliyuncs.com/abroad_images/old-nginx:latest
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: old-nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: old-nginx
sessionAffinity: None
type: ClusterIP
Ingress资源创建:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gray-release
namespace: default
spec:
ingressClassName: nginx
rules:
- host: nginx.zhang-qing.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: old-nginx
port:
number: 80
灰度发布新版本服务
发布一个新版本的Nginx服务并配置路由规则。
apiVersion: apps/v1
kind: Deployment
metadata:
name: new-nginx
spec:
replicas: 1
selector:
matchLabels:
app: new-nginx
template:
metadata:
labels:
app: new-nginx
run: new-nginx
spec:
containers:
- name: new-nginx
image: registry.cn-hangzhou.aliyuncs.com/abroad_images/new-nginx:latest
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: new-nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: new-nginx
sessionAffinity: None
type: ClusterIP
设置满足特定规则的客户端才能访问新版本服务。以下示例仅请求头中满足 foo=bar 的客户端请求才能路由到新版本服务。
- 修改如上步骤创建的Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gray-release
namespace: default
annotations:
nginx.ingress.kubernetes.io/service-match: |
new-nginx: header("foo", /^bar$/) # 正则匹配精确值 "bar"
spec:
ingressClassName: nginx
rules:
- host: nginx.zhang-qing.com
http:
paths:
- name: old-version
path: /
pathType: Prefix
backend:
service:
name: old-nginx
port:
number: 80
- name: new-version
path: /
pathType: Prefix
backend:
service:
name: new-nginx
port:
number: 80
测试验证
执行以下命令,访问当前服务:
$ curl -H "Host: nginx.zhang-qing.com" http://nginx.zhang-qing.com
old
执行以下命令,请求头中满足 foo=bar 的客户端请求访问服务:
$ curl -H "Host: nginx.zhang-qing.com" -H "foo: bar"
http://nginx.zhang-qing.com
new