Ingress-Nginx 是一个K8S ingress控制器,支持配置 Ingress Annotations 来实现不同场景下的灰度发布和测试。 Nginx Annotations 支持以下 4 种 Canary 规则:
nginx.ingress.kubernetes.io/canary-by-header
:基于 Request Header 的流量切分,适用于灰度发布以及 A/B 测试。当 Request Header 设置为always
时,请求将会被一直发送到 Canary 版本;当 Request Header 设置为never
时,请求不会被发送到 Canary 入口;对于任何其他 Header 值,将忽略 Header,并通过优先级将请求与其他金丝雀规则进行优先级的比较。nginx.ingress.kubernetes.io/canary-by-header-value
:要匹配的 Request Header 的值,用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务。当 Request Header 设置为此值时,它将被路由到 Canary 入口。该规则允许用户自定义 Request Header 的值,必须与上一个 annotation (即:canary-by-header)一起使用。nginx.ingress.kubernetes.io/canary-weight
:基于服务权重的流量切分,适用于蓝绿部署,权重范围 0 - 100 按百分比将请求路由到 Canary Ingress 中指定的服务。权重为 0 意味着该金丝雀规则不会向 Canary 入口的服务发送任何请求。权重为 100 意味着所有请求都将被发送到 Canary 入口。nginx.ingress.kubernetes.io/canary-by-cookie
:基于 Cookie 的流量切分,适用于灰度发布与 A/B 测试。用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务的cookie。当 cookie 值设置为always
时,它将被路由到 Canary 入口;当 cookie 值设置为never
时,请求不会被发送到 Canary 入口;对于任何其他值,将忽略 cookie 并将请求与其他金丝雀规则进行优先级的比较。
注意:金丝雀规则按优先顺序进行如下排序:
canary-by-header - > canary-by-cookie - > canary-weight
minikube 配置
开启nginx-ingress
由于我使用的是minikube来搭建集群环境,首先要在minikube中开启nginx-ingress控制器,可以运行下面的命令
minikube addons enable ingress
添加docker 私有仓库访问凭证
首先我们的K8S需要从docker hub中拉取自己域下的镜像,我们必须生成一个凭证。
- 登录docker
docker login -u 用户名
- 为k8s集群创建Secret
kubectl delete secret registry-key // 如果有的话先删除
kubectl -n default create secret docker-registry registry-key \
--docker-server=hub.docker.com \
--docker-username=docker账号 \
--docker-password=docker账号密码 \
--docker-email=邮箱
注意 -n default 为指定命名空间,一般搭建k8s集群时,建议新建一个命名空间来隔离资源。
然后就可以在K8S控制台中,看到我们刚刚创建的secret,详情参考从私有仓库拉取镜像
然后在我们的Deplyment中配置imagePullSecrets为registry-key
正常版本
- Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: product-app
spec:
selector:
matchLabels:
app: product-app
replicas: 1
template:
metadata:
labels:
app: product-app
spec:
imagePullSecrets:
- name: registry-key
containers:
- name: product-app
image: djlxs/gray-app:v2
ports:
- containerPort: 80
- Service
apiVersion: v1
kind: Service
metadata:
name: product-app
spec:
selector:
app: product-app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
- Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: product-app
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: app-ingress.info
http:
paths:
- backend:
service:
name: product-app
port:
number: 80
path: /
pathType: Prefix
灰度版本
- Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: gray-app
spec:
selector:
matchLabels:
app: gray-app
replicas: 1
template:
metadata:
labels:
app: gray-app
spec:
imagePullSecrets:
- name: registry-key
containers:
- name: gray-app
image: djlxs/gray-app:v1
ports:
- containerPort: 80
- Service
apiVersion: v1
kind: Service
metadata:
name: gray-app
spec:
selector:
app: gray-app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
- Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gray-app
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "canary"
nginx.ingress.kubernetes.io/canary-by-header-value: "canary"
spec:
rules:
- host: app-ingress.info
http:
paths:
- backend:
service:
name: gray-app
port:
number: 80
path: /
pathType: Prefix
测试
curl http://app-ingress.info
curl http://app-ingress.info -H "canary:always"
这里设置灰度cookie的值为always,nginx-ingress的方案只支持发布一个灰度版本