kubernetes中ingress根据head头做灰度

avatar 2022年4月2日18:10:45 评论 758 次浏览

灰度的方式有很多中,这里介绍在kubernetes中ingress根据head头做灰度,灰度的目的是为了在上线之前指定一部分用户可以访问,针对整个业务流程访问都没有问题之后在发布到线上,如果在灰度环境中出现bug也不会影响到所有用户使用,这种发布方式是很多互联网企业比较在意的方式。

一、介绍

在说到ingress之前我们先了解一下ingress,ingress也就是我们使用的nginx,有些东西还是不一样的,可以参考一下:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary

名称 类型 解释
nginx.ingress.kubernetes.io/canary "true","false" 开启灰度发布功能,如果没有开启此属性,则如下属性不生效。
nginx.ingress.kubernetes.io/canary-by-header string 基于 Request Header 的流量切分,适用于灰度发布以及 A/B 测试。当 Request Header 设置为 always时,请求将会被一直发送到 Canary 版本;当 Request Header 设置为 never时,请求不会被发送到 Canary 入口;对于任何其他 Header 值,将忽略 Header,并通过优先级将请求与其他金丝雀规则进行优先级的比较。
nginx.ingress.kubernetes.io/canary-by-header-value string 要匹配的 Request Header 的值,用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务。当 Request Header 设置为此值时,它将被路由到 Canary 入口。该规则允许用户自定义 Request Header 的值,必须与上一个 annotation (即canary-by-header)一起使用。
nginx.ingress.kubernetes.io/canary-by-header-pattern string 正则表达式匹配的 Request Header 的值,用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务。当 Request Header 设置为此值时,它将被路由到 Canary 入口。该规则允许用户自定义 Request Header 的值,必须与上一个 annotation (即canary-by-header)一起使用,如果已经使用canary-by-header-value,那么此属性将被忽略。
nginx.ingress.kubernetes.io/canary-by-cookie string 基于 Cookie 的流量切分,适用于灰度发布与 A/B 测试。用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务的cookie。当 cookie 值设置为 always时,它将被路由到 Canary 入口;当 cookie 值设置为 never时,请求不会被发送到 Canary 入口;对于任何其他值,将忽略 cookie 并将请求与其他金丝雀规则进行优先级的比较。
nginx.ingress.kubernetes.io/canary-weight string 基于服务权重的流量切分,适用于蓝绿部署,权重范围 0 - 100 按百分比将请求路由到 Canary Ingress 中指定的服务。权重为 0 意味着该金丝雀规则不会向 Canary 入口的服务发送任何请求。权重为 100 意味着所有请求都将被发送到 Canary 入口。

二、环境

灰度的场景是通过用户的head头判断用户的请求转发到不同的服务上,这里使用域名demo.wulaoer.org,然后创建了两个服务分别是nginx-v1和nginx-v2,我这里实现的是符合要求的请求到nginx-v2上,不符合的请求到nginx-v1,下面是我的服务。

[wolf@wulaoer.org🔥🔥🔥🔥 test]# kubectl get service -n ops-team
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
nginx-v1       ClusterIP   172.16.80.63     <none>        80/TCP           99m
nginx-v2       ClusterIP   172.16.214.16    <none>        80/TCP           99m

服务已经创建好了,下面给服务做域名解析,我这使用同一个域名解析到两个不同的服务上,解析后测试一下是否能给访问正常。

[wolf@wulaoer.org🔥🔥🔥🔥 test]# kubectl edit ingress -n ops-team ops-nginx-v1
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: ops-nginx-v1
  namespace: ops-tem
  annotations:
    kubesphere.io/creator: admin
spec:
  rules:
    - host: demo.wulaoer.org
      http:
        paths:
          - path: /
            pathType: ImplementationSpecific
            backend:
              service:
                name: nginx-v1
                port:
                  number: 80
[wolf@wulaoer.org🔥🔥🔥🔥 test]# kubectl edit ingress -n ops-team ops-nginx-v2     
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: ops-nginx-v2
  namespace: ops-tem
  annotations:
    kubesphere.io/creator: admin
    nginx.ingress.kubernetes.io/service-match: 'nginx-v2: header("far", "bor")'
spec:
  rules:
    - host: demo.wulaoer.org
      http:
        paths:
          - path: /
            pathType: ImplementationSpecific
            backend:
              service:
                name: nginx-v2
                port:
                  number: 80
[wolf@wulaoer.org🔥🔥🔥🔥 test]# kubectl apply -f ops-team ops-nginx-v1.yaml
[wolf@wulaoer.org🔥🔥🔥🔥 test]# kubectl apply -f ops-team ops-nginx-v2.yaml

正常情况下我们请求域名的时候应该返回两个服务的返回值,但是这里没有,默认访问nginx- v1的值,如果想两者都有在阿里云的ack里需要加[nginx.ingress.kubernetes.io/service-weight: 'nginx-v1: 100, nginx-v2: 100']就会在两个服务之间来回切换。

[wolf@wulaoer.org🔥🔥🔥🔥 ~]# for ((i=0;i<100;i ++));do curl   http://demo.wulaoer.org;done
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v2

三、配置灰度服务

灰度服务要求符合要求的header才可以请求到灰度服务,不符合的header不允许请求灰度服务,这里给灰度的header增加far:bor标签,这样header头为far:bor的服务都请求到nginx-v2服务上了。

[wolf@wulaoer.org🔥🔥🔥🔥 test]# kubectl edit ingress -n ops-team ops-nginx-v2
..........................................
metadata:
  annotations:
    ............................
		nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: far
    nginx.ingress.kubernetes.io/canary-by-header-value: bor
  creationTimestamp: "2022-01-17T03:22:49Z"
............................................

已修改,看下面的测试结果

[wolf@wulaoer.org🔥🔥🔥🔥 ~]# curl -H "far:bor"  http://demo.wulaoer.org
nginx-v2
[wolf@wulaoer.org🔥🔥🔥🔥 ~]# curl   http://demo.wulaoer.org
nginx-v1

实验结束,这里说一个问题,因为我这是在测试环境做的,测试环境是自建的kubernetes服务,生产环境使用的阿里云的ack,两者有明显的区别,首先第一个,阿里云的直接使用两个ingress都不会创建成功,阿里云环境的灰度只需要创建一个ingress,但是在灰度时不能使用权重。

[wolf@wulaoer.org🔥🔥🔥🔥 test]# kubectl edit ingress -n ops-team ops-nginx-v2
..........................................
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: ops-nginx-v2
  namespace: ops-tem
  annotations:
    kubesphere.io/creator: admin
    nginx.ingress.kubernetes.io/service-match: 'nginx-v2: header("far", "bor")'
spec:
  tls:
    - hosts:
        - demo.reach.store
      secretName: reach-ssl
  rules:
    - host: demo.wulaoer.org
      http:
        paths:
          - path: /
            pathType: ImplementationSpecific
            backend:
              service:
                name: nginx-v1
                port:
                  number: 80
          - path: /
            pathType: ImplementationSpecific
            backend:
              service:
                name: nginx-v2
                port:
                  number: 80

不管是阿里云还是自建的,在灰度和正式环境时,第一个创建的ingress都会被认为是正式的,默认请求的服务,除非特别配置才会请求到第二个服务上,所以这个在创建时需要注意。

avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: