首页 > 系统相关 >Kubernetes 使用 Ingress-nginx 实现灰度发布功能

Kubernetes 使用 Ingress-nginx 实现灰度发布功能

时间:2023-05-09 20:58:03浏览次数:35  
标签:ingress kubernetes Kubernetes Ingress Canary nginx 灰度 canary io

推荐阅读
Helm3(K8S 资源对象管理工具)视频教程:https://edu.csdn.net/course/detail/32506
Helm3(K8S 资源对象管理工具)博客专栏:https://blog.csdn.net/xzk9381/category_10895812.html
本文原文链接:https://blog.csdn.net/xzk9381/article/details/109570832,转载请注明出处。如有发现文章中的任何问题,欢迎评论区留言。

一、Canary 规则说明
Ingress-Nginx 是一个K8S ingress工具,支持配置 Ingress Annotations 来实现不同场景下的灰度发布和测试( Ingress-Nginx 是在0.21.0 版本 中,引入的Canary 功能)。 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

我们可以把以上的四个 annotation 规则可以总体划分为以下两类:

基于权重的 Canary 规则:


基于用户请求的 Canary 规则:


二、部署测试用例
1. 部署正式版本服务
首先创建一个 deployment 代表正式版本的服务,编写 yaml 内容如下:

---
apiVersion: v1
kind: Namespace
metadata:
name: ns-myapp
labels:
name: ns-myapp

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: production
namespace: ns-myapp
spec:
replicas: 1
selector:
matchLabels:
app: production
template:
metadata:
labels:
app: production
spec:
containers:
- name: production
image: mirrorgooglecontainers/echoserver:1.10
ports:
- containerPort: 8080
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
---
apiVersion: v1
kind: Service
metadata:
name: production
namespace: ns-myapp
labels:
app: production
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: production
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
为这个服务创建 Ingress 路由规则,yaml 文件内容如下:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: production
namespace: ns-myapp
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: ingress.test.com
http:
paths:
- backend:
serviceName: production
servicePort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
应用以上 yaml 文件,创建完成后在 k8s 中查看到如下信息:

[k8s-master ~]# kubectl get ingress -n ns-myapp
NAME CLASS HOSTS ADDRESS PORTS AGE
production <none> ingress.test.com 10.16.13.201 80 4m25s

[k8s-master ~]# kubectl get pod -n ns-myapp
NAME READY STATUS RESTARTS AGE
production-5698c4565c-jmjn5 1/1 Running 0 7m11s
1
2
3
4
5
6
7
此时在命令行中访问 ingress.test.com 可以看到如下内容:

# curl ingress.test.com

Hostname: production-5698c4565c-jmjn5

Pod Information:
node name: dumlog013201
pod name: production-5698c4565c-jmjn5
pod namespace: ns-myapp
pod IP: 10.42.0.74

Server values:
server_version=nginx: 1.13.3 - lua: 10008

Request Information:
client_address=10.16.13.201
method=GET
real path=/
query=
request_version=1.1
request_scheme=http
request_uri=http://ingress.test.com:8080/

Request Headers:
accept=*/*
host=ingress.test.com
user-agent=curl/7.64.1
x-forwarded-for=10.2.130.18
x-forwarded-host=ingress.test.com
x-forwarded-port=80
x-forwarded-proto=http
x-real-ip=10.2.130.18
x-request-id=3019362be59228ee2284f5737fa39eb1
x-scheme=http

Request Body:
-no body in request-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
本文原文链接:https://blog.csdn.net/xzk9381/article/details/109570832,转载请注明出处。如有发现文章中的任何问题,欢迎评论区留言。

2. 部署 Canary 版本服务
接下来创建一个 Canary 版本的服务,用于作为灰度测试。

参考将上述 Production 版本的 production.yaml 文件,再创建一个 Canary 版本的应用,包括一个 Canary 版本的 deployment 和 service (为方便快速演示,仅需将 production.yaml 的 deployment 和 service 中的关键字 production 直接替换为 canary,实际场景中可能涉及业务代码变更)。

三、基于权重的 Canary 规则测试
基于权重的流量切分的典型应用场景就是蓝绿部署,可通过将权重设置为 0 或 100 来实现。例如,可将 Green 版本设置为主要部分,并将 Blue 版本的入口配置为 Canary。最初,将权重设置为 0,因此不会将流量代理到 Blue 版本。一旦新版本测试和验证都成功后,即可将 Blue 版本的权重设置为 100,即所有流量从 Green 版本转向 Blue。

使用以下 canary.ingress 的 yaml 文件再创建一个基于权重的 Canary 版本的应用路由 (Ingress)。

注意:要开启灰度发布机制,首先需设置 nginx.ingress.kubernetes.io/canary: "true" 启用 Canary,以下 Ingress 示例的 Canary 版本使用了基于权重进行流量切分的 annotation 规则,将分配 30% 的流量请求发送至 Canary 版本。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: canary
namespace: ns-myapp
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "30"
spec:
rules:
- host: ingress.test.com
http:
paths:
- backend:
serviceName: canary
servicePort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
接下来在命令行中使用如下命令访问域名 ingress.test.com 100次,计算每个版本分配流量的占比:

c=0;p=0;for i in $(seq 100); do result=$(curl -s ingress.test.com | grep Hostname | awk -F: '{print $2}'); [[ ${result} =~ ^[[:space:]]canary ]] && let c++ || let p++; done;echo "production:${p}; canary:${c};"
1
可以得到如下结果:

production:73; canary:28;
1
四、基于用户请求的 Canary 规则测试
1. 基于 Resquest Header
基于 Request Header 进行流量切分的典型应用场景即灰度发布或 A/B 测试场景。

给 Canary 版本的 Ingress 新增一条 annotation :nginx.ingress.kubernetes.io/canary-by-header: canary(这里的 annotation 的 value 可以是任意值),使当前的 Ingress 实现基于 Request Header 进行流量切分。

将 Canary 版本 Ingress 的 yaml 文件修改为如下内容:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: canary
namespace: ns-myapp
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "30"
nginx.ingress.kubernetes.io/canary-by-header: "canary"
spec:
rules:
- host: ingress.test.com
http:
paths:
- backend:
serviceName: canary
servicePort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
说明:金丝雀规则按优先顺序 canary-by-header - > canary-by-cookie - > canary-weight 进行如下排序,因此上面的 ingress 将忽略原有 canary-weight 的规则。

由于上面的 ingress 规则中没有对 canary-by-header: "canary" 提供具体的值,也就是 nginx.ingress.kubernetes.io/canary-by-header-value 规则,所以在访问的时候,只可以为 canary 赋值 never 或 always,当 header 信息为 canary:never 时,请求将不会发送到 canary 版本;当 header 信息为 canary:always 时,请求将会一直发送到 canary 版本。示例如下:

[k8s-master ~ ]# curl -s -H "canary:never" ingress.test.com | grep Hostname
Hostname: production-5698c4565c-jmjn5

[k8s-master ~ ]# curl -s -H "canary:always" ingress.test.com | grep Hostname
Hostname: canary-79c899d85-992nw
1
2
3
4
5
也可以在上一个 annotation (即 canary-by-header)的基础上添加一条 nginx.ingress.kubernetes.io/canary-by-header-value: user-value 。用于通知 Ingress 将匹配到的请求路由到 Canary Ingress 中指定的服务。

将 Canary 版本 Ingress 的 yaml 文件修改为如下内容:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: canary
namespace: ns-myapp
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "30"
nginx.ingress.kubernetes.io/canary-by-header: "canary"
nginx.ingress.kubernetes.io/canary-by-header-value: "true"
spec:
rules:
- host: ingress.test.com
http:
paths:
- backend:
serviceName: canary
servicePort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
上面的 ingress 规则设置了 header 信息为 canary:true,也就是只有满足这个 header 值时才会路由到 canary 版本。示例如下:

[k8s-master ~ ]# curl -s ingress.test.com | grep Hostname
Hostname: production-5698c4565c-jmjn5

[k8s-master ~ ]# curl -s -H "canary:test" ingress.test.com | grep Hostname
Hostname: production-5698c4565c-jmjn5

[k8s-master ~ ]# curl -s -H "canary:true" ingress.test.com | grep Hostname
Hostname: canary-79c899d85-992nw
1
2
3
4
5
6
7
8
五、基于 Cookie 的 Canary 规则测试
与基于 Request Header 的 annotation 用法规则类似。例如在 A/B 测试场景 下,需要让地域为北京的用户访问 Canary 版本。那么当 cookie 的 annotation 设置为 nginx.ingress.kubernetes.io/canary-by-cookie: "users_from_Beijing",此时后台可对登录的用户请求进行检查,如果该用户访问源来自北京则设置 cookieusers_from_Beijing 的值为 always,这样就可以确保北京的用户仅访问 Canary 版本。

将 Canary 版本 Ingress 的 yaml 文件修改为如下内容:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: canary
namespace: ns-myapp
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "user_from_beijing"
spec:
rules:
- host: ingress.test.com
http:
paths:
- backend:
serviceName: canary
servicePort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
访问示例如下:

[k8s-master ~ ]# curl -s -b "user_from_beijing=always" ingress.test.com | grep Hostname
Hostname: canary-79c899d85-992nw

[k8s-master ~ ]# curl -s -b "user_from_beijing=no" ingress.test.com | grep Hostname
Hostname: production-5698c4565c-jmjn5
1
2
3
4
5
本文原文链接:https://blog.csdn.net/xzk9381/article/details/109570832,转载请注明出处。如有发现文章中的任何问题,欢迎评论区留言。
————————————————
版权声明:本文为CSDN博主「店伙计」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xzk9381/article/details/109570832

标签:ingress,kubernetes,Kubernetes,Ingress,Canary,nginx,灰度,canary,io
From: https://www.cnblogs.com/gaoyanbing/p/17386234.html

相关文章

  • kubernetes集群故障处理思路
    kubernetes集群故障处理思路1.0 概述本文主要介绍了pod的创建流程,一般问题处理思路以及一些辅助的检查项,以编快速定位及解决问题1.1 kubernetes故障处理思路概览图k8s集群出现故障,一般可以从两大种情况看,个别pod异常和大量pod异常,针对两种情况,可以参考以下处理思路1.2 po......
  • Minikube:搭建部署单机 Kubernetes
    第一步:安装docker安装过程见连接 Centos安装docker-扰扰-博客园(cnblogs.com)第二步:安装VirtualBox2.1、直接使用yum源方式安装VirtualBox,配置正确的repo文件即可:[virtualbox]name=OracleLinux/RHEL/CentOS-$releasever/$basearch-VirtualBoxbaseurl=http......
  • 搭建 Kubernetes 集群
    简介Kubernetes是一个开源系统,用于容器化应用的自动部署、扩缩和管理。它将构成应用的容器按逻辑单位进行分组以便于管理和发现。搭建环境:CentOSv7.6.1810docker-ce-versionv23.0.5kubernetes-versionv1.23.6本次使用2台服务器进行搭建,运行下面命令写入/etc/hosts文件(......
  • 关于Kubernetes-v1.23.6-master节点的初始化操作
    当我们在master节点、安装部署完docker与Kubernetes/k8s相关的软件后,并启动(docker,kubelet)后,接下来就是需要对master节点进行初始化操作了如下,这里笔者使用的版本的为Kubernetes-v1.23.6,初始化是使用kubeadminit命令,详细的参数如下所示:[root@k8s-masterqq-5201351]#kubea......
  • 办公网段与Kubernetes Pod及Svc网络互通方案
    一、背景   在Kubernetes的网络模型中,基于官方支持的CNI插件Flannel、Calico等,可以轻松实现Pod之间的网络互通,当我们将SpringCloud的微服务部署到Kubernetes中后,无需任何改动微服务的Pod即可通过Eureka注册后进行访问。除此之外还可以通过Ingresscontroller基于80......
  • 关于Kubernetes-v1.23.6-初始化时报错[kubelet-check] It seems like the kubelet isn
    笔者今天在对k8s,v1.23.6版本的的master节点使用如下命令进行初始化时[root@k8s-masterqq-5201351]#kubeadminit\>--apiserver-advertise-address192.18.106.87\>--image-repositoryregistry.aliyuncs.com/google_containers\>--kubernetes-versionv1.23.6\>--......
  • 关于Kubernetes-v1.23.6-初始化时报错[WARNING FileExisting-tc]: tc not found in sy
    今天笔者在部署Kubernetes-v1.23.6版本时,在对master节点使用如下命令进行初始化时,报错:[WARNINGFileExisting-tc]:tcnotfoundinsystempath当然其实也从字符意义上来看,只能算是WARNING提醒,不会影响主要的功能和结果,但既然有这个提醒,就可能就在某些地方是有轻微影响的,为了......
  • kubernetes|EFK日志系统
    前言对于任何基础设施或后端服务系统,日志都是极其重要的,借助日志可以分析程序的运行状态、用户的操作行为等。最早常说的日志监控系统是ELK,即ElasticSearch(负责数据检索)、Logstash(负责数据收集)、Kibana(负责数据展示)三个软件的组合,随着技术的发展,又出现了很多新的名词,比如EFK,......
  • kubernetes域名解析服务CoreDNS
    k8sdns组件历史简介kubernetes的DNS组件历史有三个,分别是skydns、kube-dns和coredns;在k8s1.3版本之前使用的是skydns,之后的版本到1.17及之间的版本都是使用的kube-dns,1.18开始至今主要使用coredns;这些dns组件在k8s当中,主要作用就是解析k8s中servicename所对应的IP地......
  • 使用 External Secrets Operator 管理 Kubernetes 的 Secret
    Kubernetes的Secret机制允许我们将敏感信息存储中央存储库etcd中,这是一种比在Pod定义或容器镜像中存储信息更安全的方式。然而,Kubernetes目前还没有能力管理Secret的生命周期,所以有时候我们需要使用外部系统来管理这些敏感信息。随着我们需要管理的Secret数量的增长,我......