基于ASM实现多集群的一站式流量治理

通过ACK One的服务网格功能,您可以实现多集群的一站式应用分发和流量治理。本文介绍如何通过ACK One Fleet实例完成关联集群之间的应用分发和流量治理。

前提条件

背景信息

本文示例展示如何通过ACK One Fleet实例,在多个关联集群上部署Rollouts应用并下发流量治理规则,实现多个版本之间的流量切换。关于多集群管理应用分发的更多信息,请参见应用分发

本文示例操作示意如下图所示:

image
  • 图中①表示用户可以部署相应的Kubernetes原生应用到关联集群,例如Deployment、Service、ConfigMap等。

  • 图中②表示用户可以通过ACK One Fleet实例下发流量治理相关的规则到关联集群,不需要使用服务网格ASMKubeConfig,目前支持的有:

    • Destinationrules

    • Envoyfilters

    • Gateways

    • Serviceentries

    • Sidecars

    • Virtualservices

    • Workloadentries

    • Workloadgroups

  • 图中③表示用户通过访问网关地址访问应用,应用最终根据所部署的流量规则呈现相应的结果。

操作步骤

步骤一:创建应用

  1. 执行以下命令,在default命名空间开启自动注入。

    kubectl label namespace default istio-injection=enabled
  2. 使用以下内容,创建podinfo-meta.yaml文件,包含应用相关的Kubernetes原生资源。

    展开查看podinfo-meta.yaml文件

    apiVersion: v1
    kind: Service
    metadata:
      name: podinfo
      labels:
        app: podinfo
        service: podinfo
    spec:
      selector:
        app: podinfo
      ports:
        - protocol: TCP
          port: 80
          targetPort: 8080
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: podinfo-green
      labels:
        app: podinfo
        version: green
    spec:
      replicas: 4
      minReadySeconds: 5
      revisionHistoryLimit: 5
      progressDeadlineSeconds: 60
      strategy:
        rollingUpdate:
          maxUnavailable: 1
        type: RollingUpdate
      selector:
        matchLabels:
          app: podinfo
          version: green
      template:
        metadata:
          labels:
            app: podinfo
            version: green
        spec:
          containers:
            - name: podinfod
              image: registry.cn-hangzhou.aliyuncs.com/acs/rollouts-demo:green
              imagePullPolicy: IfNotPresent
              ports:
                - name: http
                  containerPort: 8080
                  protocol: TCP
              readinessProbe:
                tcpSocket:
                  port: 8080
                initialDelaySeconds: 5
                timeoutSeconds: 5
    
    
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: podinfo-blue
      labels:
        app: podinfo
        version: blue
    spec:
      replicas: 4
      minReadySeconds: 5
      revisionHistoryLimit: 5
      progressDeadlineSeconds: 60
      strategy:
        rollingUpdate:
          maxUnavailable: 1
        type: RollingUpdate
      selector:
        matchLabels:
          app: podinfo
          version: blue
      template:
        metadata:
          labels:
            app: podinfo
            version: blue
        spec:
          containers:
            - name: podinfod
              image: registry.cn-hangzhou.aliyuncs.com/acs/rollouts-demo:blue
              imagePullPolicy: IfNotPresent
              ports:
                - name: http
                  containerPort: 8080
                  protocol: TCP
              readinessProbe:
                tcpSocket:
                  port: 8080
                initialDelaySeconds: 5
                timeoutSeconds: 5
  3. 执行以下命令,在Fleet实例上添加资源。

    kubectl apply -f podinfo-meta.yaml
  4. 执行以下命令,获取Fleet实例已添加的关联集群信息。

    关于AMC命令行更多信息,请参见AMC命令行帮助

    kubectl amc get managedclusters

    预期输出:

    Name                                Alias       HubAccepted
    c5f4110f2ad88499583fc76cc568a****   ack-hy-01   true
    c7f78dd3b09a146b8b750b4c1c51d****   ack-hy-02   true
  5. 使用以下内容,创建podinfo-app.yaml文件,定义开源KubeVela Application podinfo,实现多集群分发。

    使用上一步获取的关联集群ID替换如下<clusterid1><clusterid2>

    apiVersion: core.oam.dev/v1beta1
    kind: Application
    metadata:
      name: podinfo
      namespace: default
      annotations:
        app.oam.dev/publishVersion: version1
    spec:
      components:
        - name: podinfo
          type: ref-objects
          properties:
            objects:
              - apiVersion: apps/v1
                kind: Deployment
                name: podinfo-blue
              - apiVersion: apps/v1
                kind: Deployment
                name: podinfo-green
              - apiVersion: v1
                kind: Service
                name: podinfo
      policies:
        - type: topology
          name: podinfo-clusters
          properties:
            clusters: ["<clusterid1>","<clusterid2>"]  # 定义下发的目标集群,如需更新目标集群,可在此字段新增或修改。           
  6. 执行如下命令,在Fleet实例上部署应用podinfo

    kubectl apply -f podinfo-app.yaml

步骤二:设置网管规则及虚拟服务

  1. 登录ASM控制台,创建服务网格ASM入口网关。具体操作,请参见创建入口网关

  2. 使用以下内容,创建podinfo-gateway.yaml文件。

    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: podinfo-gateway
    spec:
      selector:
        istio: ingressgateway
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - "*"
  3. 执行以下命令,在Fleet实例上部署Istio网关。

    kubectl apply -f podinfo-gateway.yaml
  4. 使用以下内容,创建virtual-service-all-blue.yaml文件。

    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: podinfo
    spec:
      hosts:
      - "*"
      gateways:
      - podinfo-gateway
      http:
      - match:
        - uri:
            prefix: /
        route:
        - destination:
            host: podinfo
            subset: blue
            port:
              number: 80
  5. 执行以下命令,在Fleet实例上部署虚拟服务。

    kubectl apply -f virtual-service-all-blue.yaml
  6. 使用以下内容,创建destination-rule-all.yaml文件。

    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: podinfo
    spec:
      host: podinfo
      trafficPolicy:
        outlierDetection:
          baseEjectionTime: 30s
          consecutiveErrors: 7
          interval: 30s
      subsets:
      - name: blue
        labels:
          version: blue
      - name: green
        labels:
          version: green
  7. 执行以下命令,在Fleet实例上部署目标规则。

    kubectl apply -f destination-rule-all.yaml

步骤三:结果验证

  1. 执行以下命令,获取ASM网关地址。

    AMC命令行更多信息,请参见AMC命令行帮助

    kubectl amc get svc -n istio-system -m <关联集群>

    预期输出:

    Run on ManagedCluster c5f4110f2ad88499583fc76cc568a**** (ack-hy-01)
    NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                      AGE
    istio-ingressgateway     LoadBalancer   10.12.1**.***   47.113.***.***   80:30315/TCP,443:32***/TCP   47h
    Run on ManagedCluster c7f78dd3b09a146b8b750b4c1c51d**** (ack-hy-02)
    NAME                     TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
    istio-ingressgateway     LoadBalancer   10.75.9**.***   47.113.***.***   80:32101/TCP,443:30***/TCP   47h                     
  2. 在浏览器中访问http://<网关IP>/。

    使用上一步获取的EXTERNAL-IP替换<网关IP>,访问页面如下所示,此时仅展示blue版本。blue

  3. 创建虚拟服务,分配不同的流量比例。

    1. 使用以下内容,创建virtual-service-green-blue-80-20.yaml文件。

      以下示例中green版本权重为80,blue版本权重为20。

      apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      metadata:
        name: podinfo
      spec:
        hosts:
        - "*"
        gateways:
        - podinfo-gateway
        http:
        - match:
          - uri:
              prefix: /
          route:
          - destination:
              host: podinfo
              subset: green
              port:
                number: 80
            weight: 80
          - destination:
              host: podinfo
              subset: blue
              port:
                number: 80
            weight: 20
    2. 执行以下命令,在Fleet实例上部署虚拟服务。

      kubectl apply -f virtual-service-green-blue-80-20.yaml
  4. 继续在浏览器中访问http://<网关IP>/。

    可看到应用greenblue的版本会按照80%和20%流量比例呈现。blue-green