通过Ingress Controller来实现应用的流量复制

跨集群流量复制是通过将生产环境的流量镜像到另一个测试环境中,帮助进行系统仿真测试和问题定位。这种方式可以在不影响生产环境的情况下,对应用服务进行全面的测试和故障排查。本文将介绍如何通过Nginx Ingress Controller实现在不同ACK集群间的流量复制。

前提条件

应用场景

流量复制(Traffic Mirror)功能应用于以下两个场景:

  • 真实流量模拟测试:

    在系统进行重大重构或者发布新功能时,往往需要对系统进行压测以事先评估新系统的承载能力。传统情况下,在线下环境模拟线上各种测试数据来对新系统进行测试,但是这种方式往往并不能有效地模拟出线上真实的访问量,尤其是模拟正常流量中混杂着各色的异常流量。针对这种情况,可以通过将线上的应用流量复制到指定的线下环境来对新系统进行仿真测试。

  • 问题排查:

    线上系统遇到性能瓶颈,但是又不能快速地定位出问题时,这时可以采用流量复制的方式来将应用的真实流量引导到线下环境来进行问题定位。

本示例场景中ACK集群一个名为K8s Product Cluster(生产环境),另一个名为K8s Stage Cluster(测试环境)。

image

前置说明

将K8s Product Cluster(生产环境)中的应用100%的访问流量镜像,到K8s Stage Cluster(测试环境)中对应的应用服务,即将所有访问域名example.com的请求复制并转发到example1.com

image

步骤一:测试环境中部署基础应用

  1. 在K8s Stage Cluster(测试环境)中使用以下示例应用的YAML内容,创建名为my-nginx.yaml文件。

    说明

    K8s Stage Cluster(测试环境)作为复制流量的接收方,只部署接收流量的应用服务,不用做任何配置修改。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
            imagePullPolicy: Always
            name: nginx
            ports:
            - containerPort: 80
              protocol: TCP
          restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        app: nginx
      type: NodePort
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: nginx-ingress
    spec:
      rules:
      - host: example1.com
        http:
          paths:
          - path: /
            backend:
              service: 
                name: nginx-service
                port:
                  number: 80
            pathType: ImplementationSpecific
  2. 执行以下命令,部署示例应用my-nginx。

    kubectl apply -f my-nginx.yaml
  3. 执行以下命令,查看该应用的Ingress配置。

    kubectl get ing nginx-ingress

    预期输出:

    NAME            HOSTS         ADDRESS      PORTS       AGE                                                         
    nginx-ingress   example1.com  47.**.**.53   80          8m
  4. 域名解析后,执行以下命令,测试访问应用域名。

    curl http://example1.com

步骤二:生产环境中配置流量复制

说明

在K8s Product Cluster(生产环境)部署应用服务后,需要在Ingress中添加流量镜像的注释。

  1. 在K8s Product Cluster(生产环境)中使用以下示例应用的YAML内容,创建名为my-nginx.yaml文件。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
            imagePullPolicy: Always
            name: nginx
            ports:
            - containerPort: 80
              protocol: TCP
          restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        app: nginx
      type: NodePort
  2. 执行以下命令,部署示例应用my-nginx。

    kubectl apply -f my-nginx.yaml
  3. 使用以下示例Ingress的YAML内容,创建名为my-ingress.yaml文件。

    • 配置nginx.ingress.kubernetes.io/mirror-target,指向在K8s Stage Cluster(测试环境集群)步骤3中获取的ADDRESS。仅适用于HTTP或HTTPS协议,更多详情请参见ingress-nginx_mirror

    • 配置nginx.ingress.kubernetes.io/mirror-host指向在K8s Stage Cluster(测试环境集群)步骤3中获取的HOSTS

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: nginx-ingress
      annotations:
        nginx.ingress.kubernetes.io/mirror-target: "http://47.**.**.53$request_uri"  #指定镜像请求的目标后端地址。
        nginx.ingress.kubernetes.io/mirror-request-body: "off"            # 关闭将请求体(request body)发送到镜像目标后端,如果需要请求体去掉此注释即可。
        nginx.ingress.kubernetes.io/mirror-host: "example1.com"           # 设置流量镜像请求的Host头。
    spec:
      rules:
      - host: example.com
        http: 
          paths:
          - path: /
            backend:
              service: 
                name: nginx-service
                port:
                  number: 80
            pathType: ImplementationSpecific
  4. 执行以下命令,部署示例镜像Ingress。

    kubectl apply -f my-ingress.yaml
  5. 执行以下命令,查看该应用的Ingress配置。

    kubectl get ing nginx-ingress

    预期输出:

    NAME            HOSTS          ADDRESS        PORTS     AGE                                                       
    nginx-ingress   example.com   39.**.**.54   80        1m
  6. 执行以下命令,测试访问应用域名。

    curl http://example.com

结果验证

访问K8s Product Cluster(生产环境)中的应用域名example.com。通过执行以下命令,可以看到每次请求该域名时,都会生成一个相同的请求并转发到K8s Stage Cluster(测试环境)中对应的服务。

kubectl -n kube-system logs --tail=0 -f nginx-ingress-controller-674c96ffbc-9mc8n

流量复制结果验证