Ingress蓝绿发布
Ingress常用注解说明
Nginx Ingress支持通过配置注解(Annotations)
来实现不同场景下的发布和测试,可以满足灰度发布
、蓝绿发布
、A/B测试
等业务场景。具体实现过程如下:
为服务创建两个Ingress
:
- 一个为
常规Ingress
, - 另一个为带
nginx.ingress.kubernetes.io/canary: "true"
注解的Ingress,称为Canary Ingress(金丝雀发布)
; - 为
Canary Ingress(金丝雀发布)
配置流量切分策略Annotation
,两个Ingress相互配合
,即可实现多种场景的发布和测试。
Nginx Ingress的Annotation
支持以下几种规则:
Annotation | 作用 |
---|---|
nginx.ingress.kubernetes.io/canary-by-header | 适用于灰度发布 ,基于Header 的流量切分,如果请求头中包含指定的header名称,并且值为“always”,就将该请求转发给Canary Ingress定义的对应后端服务。如果值为“never”则不转发,可用于回滚到旧版本。如果为其他值则忽略该annotation,并通过优先级将请求流量分配到其他规则。 |
nginx.ingress.kubernetes.io/canary-by-header-value | 必须与canary-by-header一起使用,可自定义请求头的取值,包含但不限于“always”或“never”。当请求头的值命中指定的自定义值时,请求将会转发给Canary Ingress定义的对应后端服务,如果是其他值则忽略该annotation,并通过优先级将请求流量分配到其他规则。 |
nginx.ingress.kubernetes.io/canary-by-header-pattern | 与canary-by-header-value 类似,唯一区别是该annotation 用正则表达式匹配请求头的值 ,而不是某一个固定值。如果该annotation 与canary-by-header-value 同时存在,该annotation 将被忽略。 |
nginx.ingress.kubernetes.io/canary-by-cookie | 基于Cookie 的流量切分,适用于灰度发布。与canary-by-header类似,该annotation用于cookie,仅支持“always”和“never”,无法自定义取值。 |
nginx.ingress.kubernetes.io/canary-weight | 基于服务权重 的流量切分,适用于蓝绿部署。表示Canary Ingress所分配流量的百分比,取值范围[0-100]。例如,设置为100,表示所有流量都将转发给Canary Ingress对应的后端服务。 |
以上注解规则会按优先级进行评估,优先级
为:
canary-by-header(请求头)
-> canary-by-cookie
-> canary-weight(服务权重)
。
yaml资源清单
蓝色版本和绿色版本的区别
- deployment的name不同
- Labels不同
- 镜像版本tag不同
- svc的name不同
绿色版本yml资源清单
apiVersion: apps/v1 # 指定 Deployment 的 API 版本
kind: Deployment # 声明资源类型为 Deployment
metadata: # 元数据部分
name: demo # Deployment 的名称
labels: # 标签部分
app: demo # 标签键值对,用于标识和选择资源
spec: # Deployment 的规格定义
replicas: 1 # 副本数量,指定运行的 Pod 数量
selector: # 用于选择匹配的 Pod
matchLabels: # 匹配的标签
app: demo # 匹配 app=demo 的 Pod
template: # Pod 模板定义
metadata: # Pod 的元数据
labels: # Pod 的标签
app: demo # 标签键值对,用于选择和标识 Pod
spec: # Pod 的规格定义
containers: # 容器列表
- name: demo # 容器名称
imagePullPolicy: Always # 镜像拉取策略,始终拉取最新镜像
image: registry.cn-shanghai.aliyuncs.com/kubesre01/demo:v1 # 容器镜像地址
ports: # 容器端口配置
- containerPort: 8080 # 容器监听的端口号
---
apiVersion: v1 # 指定 Service 的 API 版本
kind: Service # 声明资源类型为 Service
metadata: # 元数据部分
name: demo-svc # Service 的名称
spec: # Service 的规格定义
type: ClusterIP # Service 类型,默认为 ClusterIP
selector: # 用于选择关联的 Pod
app: demo # 选择标签 app=demo 的 Pod
ports: # Service 的端口配置
- port: 8080 # Service 暴露的端口号
targetPort: 8080 # 映射到 Pod 的目标端口号
蓝色版本yaml资源清单
apiVersion: apps/v1 # 指定 API 版本为 apps/v1,用于定义 Deployment
kind: Deployment # 声明资源类型为 Deployment
metadata: # 元数据部分
name: demo-new # Deployment 的名称
labels: # 标签部分
app: demo-new # 标签键值对,用于标识该 Deployment
spec: # 规范部分
replicas: 1 # 副本数量,指定运行的 Pod 数量
selector: # 选择器部分
matchLabels: # 匹配的标签
app: demo-new # 选择具有 app=demo-new 标签的 Pod
template: # Pod 模板
metadata: # Pod 的元数据
labels: # 标签部分
app: demo-new # Pod 的标签,用于与选择器匹配
spec: # Pod 的规范部分
containers: # 容器列表
- name: demo-new # 容器名称
imagePullPolicy: Always # 镜像拉取策略,始终拉取最新镜像
image: registry.cn-shanghai.aliyuncs.com/kubesre01/demo:v2 # 容器使用的镜像
ports: # 容器端口配置
- containerPort: 8080 # 容器监听的端口号
---
apiVersion: v1 # 指定 API 版本为 v1,用于定义 Service
kind: Service # 声明资源类型为 Service
metadata: # 元数据部分
name: demo-new-svc # Service 的名称
spec: # 规范部分
type: ClusterIP # Service 类型为 ClusterIP,默认类型
selector: # 选择器部分
app: demo-new # 选择具有 app=demo-new 标签的 Pod
ports: # 端口配置
- port: 8080 # Service 暴露的端口号
targetPort: 8080 # 映射到 Pod 的目标端口号
主Ingress
默认将流量路由到主服务
。
apiVersion: networking.k8s.io/v1 # 定义 Ingress 的 API 版本
kind: Ingress # 声明资源类型为 Ingress
metadata: # 元数据部分
name: demo # Ingress 的名称为 demo
spec: # 规范部分
rules: # 定义 Ingress 的规则
- host: demo.intel.dev # 指定主机名为 demo.intel.dev
http: # 定义 HTTP 路由规则
paths: # 定义路径规则
- path: /info # 指定路径为 /info
pathType: Prefix # 路径匹配类型为 Prefix(前缀匹配)
backend: # 定义后端服务
service: # 指定服务信息
name: demo-svc # 服务名称为 demo-svc
port: # 服务端口信息
number: 8080 # 服务端口号为 8080
ingressClassName: nginx # 指定 Ingress 的类名为 nginx
金丝雀Ingress
基于客户端请求头的流量切分
- 在注解中开启金丝雀发布功能
- 为ingress添加
请求头
- 设置
请求头为指定值
时负载到绿色版本的svc
apiVersion: networking.k8s.io/v1 # 使用 Kubernetes 的 Ingress API 版本 v1
kind: Ingress # 定义资源类型为 Ingress
metadata:
name: demo-new-canary # 定义 Ingress 的名称为 demo-new-canary
annotations: # 定义 Ingress 的注解,用于配置额外的功能
# 启用金丝雀发布功能
nginx.ingress.kubernetes.io/canary: "true"
# 指定请求头名称为 "X-Beta-User"
nginx.ingress.kubernetes.io/canary-by-header: "X-Beta-User"
# 当请求头 "X-Beta-User" 的值为 "green" 时,将流量路由到金丝雀版本
# 这里的 "X-Beta-User" 是一个示例值,可以根据实际需求进行修改
# 例如,可以使用 "X-Beta-User" 来标识特定的用户或请求来源
nginx.ingress.kubernetes.io/canary-by-header-value: "green"
spec:
rules: # 定义 Ingress 的路由规则
- host: demo.intel.dev # 指定主机名为 demo.intel.dev,匹配该域名的请求
http: # 定义 HTTP 路由规则
paths: # 定义路径规则
- path: /info # 匹配路径为 /info 的请求
pathType: Prefix # 路径匹配类型为 Prefix,表示以 /info 为前缀的路径都会匹配
backend: # 定义后端服务
service: # 指定后端服务的配置
name: demo-new-svc # 后端服务的名称为 demo-new-svc
port: # 定义后端服务的端口
number: 8080 # 后端服务的端口号为 8080
ingressClassName: nginx # 指定使用 nginx 作为 Ingress 控制器
结果验证
# 使用 curl 命令向目标 URL 发送 HTTP 请求
## -H 参数用于设置请求头
### "X-Beta-User: green" 是一个自定义请求头,用于标识内测用户
curl -H "X-Beta-User: green" http://demo.intel.dev/info
# 没有请求头则访问到老的版本
curl http://demo.intel.dev/info
基于客户端来源IP的流量切分
apiVersion: networking.k8s.io/v1 # 定义 Ingress 资源的 API 版本
kind: Ingress # 声明资源类型为 Ingress
metadata:
name: demo-new-canary # 定义 Ingress 的名称
annotations: # 为 Ingress 添加注解
# # 启用金丝雀发布功能
nginx.ingress.kubernetes.io/canary: "true"
# 根据请求头 X-Forwarded-For 进行金丝雀流量分配
nginx.ingress.kubernetes.io/canary-by-header: "X-Forwarded-For"
# 当请求头的值为指定 IP 时,将流量分发到 金丝雀版本
# 假定这个IP是测试部门的IP
nginx.ingress.kubernetes.io/canary-by-header-value: "123.253.189.223"
spec:
rules: # 定义 Ingress 的路由规则
- host: demo.intel.dev # 指定主机名
http:
paths: # 定义路径规则
- path: /info # 指定路径为 /info
pathType: Prefix # 路径匹配类型为前缀匹配
backend: # 定义后端服务
service:
name: demo-new-svc # 后端服务的名称
port:
number: 8080 # 后端服务的端口号
ingressClassName: nginx # 指定使用的 IngressClass 为 nginx
结果验证
#### "X-Forwarded-For:123.253.189.223" 模拟客户端 IP 地址
curl -H "X-Forwarded-For:123.253.189.223" http://demo.intel.dev/info
基于服务权重的流量切分
apiVersion: networking.k8s.io/v1 # 指定 Ingress 的 API 版本
kind: Ingress # 定义资源类型为 Ingress
metadata:
name: demo-new-canary # 定义 Ingress 的名称
annotations: # 定义 Ingress 的注解
# 启用金丝雀发布功能
nginx.ingress.kubernetes.io/canary: "true"
# 根据请求头 X-Forwarded-For 进行金丝雀流量分配
nginx.ingress.kubernetes.io/canary-by-header: "X-Forwarded-For"
# 将 20% 的流量分配给金丝雀版本
nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
rules: # 定义 Ingress 的规则
- host: demo.intel.dev # 定义主机名
http:
paths: # 定义 HTTP 路径规则
- path: /info # 定义路径为 /info
pathType: Prefix # 路径匹配类型为前缀匹配
backend: # 定义后端服务
service:
name: demo-new-svc # 后端服务的名称
port:
number: 8080 # 后端服务的端口号
ingressClassName: nginx # 指定使用的 IngressClass 为 nginx
结果验证
# 使用 for 循环发送 100 次 HTTP 请求到指定的 URL
for i in {1..100}; do
# curl 命令用于发送 HTTP 请求
# http://demo.intel.dev/info 是目标 URL,表示访问 demo.intel.dev 的 /info 路径
curl http://demo.intel.dev/info;
done;
# 查看结果是否符合20%服务权重的设置。
# 提前设置好新版本的回显标记
基于IP来源区域来切分IP—方案未验证
- 修改
Nginx Ingress Controller
的ConfigMap
,添加geo模块
以匹配特定 IP 地址段
。
示例ConfigMap
配置:
apiVersion: v1 # API版本,v1表示核心组的资源
kind: ConfigMap # 资源类型,这里是ConfigMap
metadata: # 元数据部分
name: nginx-ingress-controller # ConfigMap的名称
namespace: ingress-nginx # ConfigMap所在的命名空间
data: # 数据部分
geoip: | # geoip配置数据,使用多行字符串格式
geo $region { # 定义一个geo变量,用于根据IP地址分配区域
default unknown; # 默认值为unknown
123.253.189.0/24 region-a; # 指定IP地址范围对应的区域为region-a
}
- 使用
nginx.ingress.kubernetes.io/configuration-snippet
注解,根据$region
变量进行流量分发
。
apiVersion: networking.k8s.io/v1 # 定义 Kubernetes Ingress 的 API 版本
kind: Ingress # 资源类型为 Ingress
metadata: # 元数据部分
name: demo-new-canary # Ingress 的名称为 demo-new-canary
annotations: # 注解部分
# 启用金丝雀发布功能
nginx.ingress.kubernetes.io/canary: "true"
# 如果请求的 region 是 "region-a",设置服务名称为 "demo-new-svc"
# $region 是一个 NGINX 变量,通常由外部输入(如请求头、客户端 IP 地址等)或上游配置(如 Nginx 的 geo 模块)定义。
# $service_name 是一个自定义变量,可以被后续的 NGINX 配置引用,用于动态选择后端服务。
nginx.ingress.kubernetes.io/configuration-snippet: | # 自定义 NGINX 配置片段
if ($region = "region-a") {
set $service_name "demo-new-svc"; #
}
spec: # 规范部分
rules: # 定义 Ingress 的规则
- host: demo.intel.dev # 规则适用于主机名 demo.intel.dev
http: # HTTP 路由规则
paths: # 定义路径规则
- path: /info # 匹配路径为 /info
pathType: Prefix # 路径类型为前缀匹配
backend: # 后端服务配置
service: # 指定服务
name: demo-new-svc # 服务名称为 demo-new-svc
port: # 服务端口配置
number: 8080 # 服务端口号为 8080
ingressClassName: nginx # 使用的 Ingress 类为 nginx
基于User-Agent的浏览切分
- 未完待续