zoukankan      html  css  js  c++  java
  • Traefik的中间件,灰度发布,流量复制

    Kubernetes 1.18.3 部署 Traefik2.2

    Traefik的中间件,灰度发布,流量复制基于上篇文章环境。

    1.部署whoami 应用和SVC

    apiVersion: v1
    kind: Service
    metadata:
      name: whoami
    spec:
      ports:
        - protocol: TCP
          name: web
          port: 80
      selector:
        app: whoami
    ---
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: whoami
      labels:
        app: whoami
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: whoami
      template:
        metadata:
          labels:
            app: whoami
        spec:
          containers:
            - name: whoami
              image: containous/whoami
              ports:
                - name: web
                  containerPort: 80

    2.部署 IngressRoute 对象

    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
      name: simpleingressroute
    spec:
      entryPoints:
        - web
      routes:
      - match: Host(`who.heian.com`) && PathPrefix(`/notls`)
        kind: Rule
        services:
        - name: whoami
          port: 80

    3.配置 HTTPS 路由

    [root@k8s-master1 who]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=who.heian.com" 
    Generating a 2048 bit RSA private key
    ..........................................................................+++
    ..........+++
    writing new private key to 'tls.key'
    -----
    [root@k8s-master1 who]#  kubectl create secret tls who-tls --cert=tls.crt --key=tls.key
    secret/who-tls created
    

    创建一个 HTTPS 访问应用的 IngressRoute 对象

    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
      name: ingressroutetls
    spec:
      entryPoints:
        - websecure
      routes:
      - match: Host(`who.heian.com`) && PathPrefix(`/tls`)
        kind: Rule
        services:
        - name: whoami
          port: 80
      tls:
        secretName: who-tls

    4 . 中间件

    中间件是 Traefik2.0 中一个非常有特色的功能,我们可以根据自己的各种需求去选择不同的中间件来满足服务,Traefik 官方已经内置了许多不同功能的中间件,其中一些可以修改请求,头信息,一些负责重定向,一些添加身份验证等等,而且中间件还可以通过链式组合的方式来适用各种情况。

    traefik middleware overview

    同样比如上面我们定义的 whoami 这个应用,我们可以通过 https://who.heian.com/tls 来访问到应用,但是如果我们用 http 来访问的话呢就不行了,就会404了,因为我们根本就没有简单80端口这个入口点,

    所以要想通过 http 来访问应用的话自然我们需要监听下 web 这个入口点:

    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
      name: ingressroutetls-http
    spec:
      entryPoints:
        - web
      routes:
      - match: Host(`who.heian.com`) && PathPrefix(`/tls`)
        kind: Rule
        services:
        - name: whoami
          port: 80

    注意这里我们创建的 IngressRoute 的 entryPoints 是 web,然后创建这个对象,这个时候我们就可以通过 http 访问到这个应用了。

    但是我们如果只希望用户通过 https 来访问应用的话呢?按照以前的知识,我们是不是可以让 http 强制跳转到 https 服务去,对的,在 Traefik 中也是可以配置强制跳转的,只是这个功能现在是通过中间件来提供的了。

    如下所示,我们使用 redirectScheme 中间件来创建提供强制跳转服务:

    apiVersion: traefik.containo.us/v1alpha1
    kind: Middleware
    metadata:
      name: redirect-https
    spec:
      redirectScheme:
        scheme: https

    然后将这个中间件附加到 http 的服务上面去,因为 https 的不需要跳转:

    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
      name: ingressroutetls-http
    spec:
      entryPoints:
        - web
      routes:
      - match: Host(`who.heian.com`) && PathPrefix(`/tls`)
        kind: Rule
        services:
        - name: whoami
          port: 80
        middlewares: 
        - name: redirect-https

    这个时候我们再去访问 http 服务可以发现就会自动跳转到 https 去了。关于更多中间件的用法可以查看文档 Traefik Docs

    5. 灰度发布

    Traefik2.0 的一个更强大的功能就是灰度发布,灰度发布我们有时候也会称为金丝雀发布(Canary),主要就是让一部分测试的服务也参与到线上去,经过测试观察看是否符号上线要求。

    canary deployment

    比如现在我们有两个名为 appv1 和 appv2 的服务,我们希望通过 Traefik 来控制我们的流量,将 3⁄4 的流量路由到 appv1,¼ 的流量路由到 appv2 去,这个时候就可以利用 Traefik2.0 中提供的带权重的轮询(WRR)来实现该功能

    首先在 Kubernetes 集群中部署上面的两个服务。

    为了对比结果我们这里提供的两个服务一个是 heian99/myapp:v2,一个是heian99/myapp:v1,方便测试。

    appv1 服务的资源清单如下所示:(appv1.yaml)heian99/myapp:v1

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: appv1
    spec:
      selector:
        matchLabels:
          app: appv1
      template:
        metadata:
          labels:
            use: test
            app: appv1
        spec:
          containers:
          - name: myappv1
            image: heian99/myapp:v1
            ports:
            - containerPort: 80
              name: portv1
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: appv1
    spec:
      selector:
        app: appv1
      ports:
      - name: http
        port: 80
        targetPort: portv1
    

    appv2 服务的资源清单如下所示:(appv2.yaml)heian99/myapp:v2

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: appv2
    spec:
      selector:
        matchLabels:
          app: appv2
      template:
        metadata:
          labels:
            use: test
            app: appv2
        spec:
          containers:
          - name: myappv2
            image: heian99/myapp:v2
            ports:
            - containerPort: 80
              name: portv2
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: appv2
    spec:
      selector:
        app: appv2
      ports:
      - name: http
        port: 80
        targetPort: portv2

    直接创建上面两个服务:

    
    [root@k8s-master1 test]# kubectl apply -f .
    deployment.apps/appv1 created
    service/appv1 created
    deployment.apps/appv2 created
    service/appv2 created
    
    [root@k8s-master1 test]# kubectl get pods -l use=test
    NAME                     READY   STATUS    RESTARTS   AGE
    appv1-597bbc966f-chwpj   1/1     Running   0          69s
    appv2-5f5489b4c5-7gsnd   1/1     Running   0          69s
    
    

    在 Traefik2.1 中新增了一个 TraefikService 的 CRD 资源,我们可以直接利用这个对象来配置 WRR,之前的版本需要通过 File Provider,比较麻烦,新建一个描述 WRR 的资源清单:(wrr.yaml)

    apiVersion: traefik.containo.us/v1alpha1
    kind: TraefikService
    metadata:
      name: app-wrr
    spec:
      weighted:
        services:
          - name: appv1
            weight: 3  # 定义权重
            port: 80
            kind: Service  # 可选,默认就是 Service
          - name: appv2
            weight: 1
            port: 80

    然后为我们的灰度发布的服务创建一个 IngressRoute 资源对象:(ingressroute.yaml)

    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
      name: wrringressroute
      namespace: default
    spec:
      entryPoints:
        - web
      routes:
      - match: Host(`app.heian.com`)
        kind: Rule
        services:
        - name: app-wrr
          kind: TraefikService

    不过需要注意的是现在我们配置的 Service 不再是直接的 Kubernetes 对象了,而是上面我们定义的 TraefikService 对象,直接创建上面的两个资源对象,这个时候我们对域名 app.heian.com 做上解析,去浏览器中连续访问 4 次,我们可以观察到 appv1 这应用会收到 3 次请求,而 appv2 这个应用只收到 1 次请求,符合上面我们的 3:1 的权重配置。

    6. 流量复制

    除了灰度发布之外,Traefik 2.0 还引入了流量镜像服务,是一种可以将流入流量复制并同时将其发送给其他服务的方法,镜像服务可以获得给定百分比的请求同时也会忽略这部分请求的响应。

    traefik mirror

    同样的在 2.0 中只能通过 FileProvider 进行配置,在 2.1 版本中我们已经可以通过 TraefikService 资源对象来进行配置了,现在我们部署两个 whoami 的服务,资源清单文件如下所示:

    apiVersion: v1
    kind: Service
    metadata:
      name: v1
    spec:
      ports:
        - protocol: TCP
          name: web
          port: 80
      selector:
        app: v1
    ---
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: v1
      labels:
        app: v1
    spec:
      selector:
        matchLabels:
          app: v1
      template:
        metadata:
          labels:
            app: v1
        spec:
          containers:
            - name: v1
              image: heian99/myapp:v1
              ports:
                - name: web
                  containerPort: 80
    
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: v2
    spec:
      ports:
        - protocol: TCP
          name: web
          port: 80
      selector:
        app: v2
    ---
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: v2
      labels:
        app: v2
    spec:
      selector:
        matchLabels:
          app: v2
      template:
        metadata:
          labels:
            app: v2
        spec:
          containers:
            - name: v2
              image: heian99/myapp:v2
              ports:
                - name: web
                  containerPort: 80

    现在我们创建一个 IngressRoute 对象,将服务 v1 的流量复制 50% 到服务 v2,如下资源对象所示:(mirror-ingress-route.yaml)

    apiVersion: traefik.containo.us/v1alpha1
    kind: TraefikService
    metadata:
      name: app-mirror
    spec:
      mirroring:
        name: v1 # 发送 100% 的请求到 K8S 的 Service "v1"
        port: 80
        mirrors:
        - name: v2 # 然后复制 50% 的请求到 v2
          percent: 50
          port: 80
    ---
    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
      name: mirror-ingress-route
      namespace: default
    spec:
      entryPoints:
      - web
      routes:   
      - match: Host(`mirror.heian.com`)
        kind: Rule
        services:
        - name: app-mirror
          kind: TraefikService # 使用声明的 TraefikService 服务,而不是 K8S 的 Service

    这个时候我们在浏览器中去连续访问4次 mirror.heian.com 可以发现有一半的请求也出现在了 v2 这个服务中:

    人生得意须尽欢,莫使金樽空对月。 天生我材必有用,千金散尽还复来。
  • 相关阅读:
    [置顶] 寻找数组中的值
    详解 Java 的八大基本类型,写得非常好!
    从入门到放弃的 Java 架构师面试题!
    通往大牛之路,百度Java面试题前200页!
    HTML与CSS简单页面效果实例
    JS面向对象
    JS瀑布流效果
    CSS常用操作-图片
    CSS常用操作-导航栏
    CSS常用操作-对齐
  • 原文地址:https://www.cnblogs.com/heian99/p/14608413.html
Copyright © 2011-2022 走看看