服务网格ASM为应用服务提供了跨地域流量分布和跨地域故障转移能力。跨地域流量分布功能可以将流量按照设定的权重路由至多个集群,实现多地域负载均衡。跨地域故障转移功能可以在某地域服务发生故障时,将该地域流量转移至其他地域,实现跨地域容灾。本文以Bookinfo应用为例,介绍如何使用跨地域故障转移和流量分布能力实现跨地域容灾和流量负载均衡。

前提条件

已创建ASM实例。具体操作,请参见创建ASM实例

网络规划

在进行操作前,您需要对vSwitch、VPC和集群的网段、名称等信息进行规划,本文规划如下:

  • vSwich和VPC的网络规划
    • vSwitch网络规划
      注意 为了避免使用CEN打通VPC网络后产生路由冲突,两个vSwitch不能使用相同的网段。
      vSwitch名称 VPC IPv4网段
      vpc-hangzhou-switch-1 vpc-hangzhou 192.168.0.0/24
      vpc-shanghai-switch-1 vpc-shanghai 192.168.2.0/24
    • VPC网络规划
      VPC名称 Region IPv4网段
      vpc-hangzhou cn-hangzhou 192.168.0.0/16
      vpc-shanghai cn-shanghai 192.168.0.0/16
  • 集群的网络规划
    集群名称 Region VPC Pod CIDR Service CIDR
    ack-hangzhou cn-hangzhou vpc-hangzhou 10.45.0.0/16 172.16.0.0/16
    ack-shanghai cn-shanghai vpc-shanghai 10.47.0.0/16 172.18.0.0/16

步骤一:创建不同地域的集群

  1. 按照以上规划创建2个杭州和上海地域vSwitch,然后使用vSwitch创建VPC。具体操作,请参见创建交换机创建专有网络
  2. 使用上文创建的VPC和网络规划创建杭州和上海地域的集群。具体操作,请参见创建Kubernetes托管版集群

步骤二:使用CEN实现跨地域VPC网络互通

  1. 创建CEN实例。
    1. 登录云企业网控制台
    2. 云企业网实例页面,单击创建云企业网实例
    3. 创建云企业网实例面板设置参数,然后单击确定
      参数 描述
      名称 输入实例名称。

      名称长度为2~128个字符,以英文字母或中文开头,可包含数字、下划线(_)和短划线(-)。

      描述 输入实例描述信息。
      实例类型 实例类型,本文选择专有网络(VPC)。
      地域 选择所选实例的地域,本文选择华东1(杭州)。
      网络实例 选择要加载的实例,选择上文创建的杭州地域的VPC。
  2. 加载网络实例。
    1. 企业网实例页面,找到上文创建的云企业网实例,单击实例ID。
    2. 网络实例管理页签,单击加载网络实例
    3. 加载网络实例面板同账号页签下设置参数,然后单击确定
      参数 描述
      实例类型 实例类型,本文选择专有网络(VPC)
      地域 选择所选实例的地域,本文选择华东2(上海)。
      网络实例 选择要加载的实例,选择上文创建的上海地域的VPC。
  3. 购买带宽包,具体操作,请参见购买带宽包
  4. 设置跨地域互通带宽。
    1. 企业网实例页面,找到上文创建的云企业网实例,单击实例ID。
    2. 单击跨地域互通带宽管理页签,然后单击设置跨地域带宽
    3. 设置跨地域带宽面板设置带宽包为上文购买的带宽包,互通地域为华东2(上海)到华东1(杭州),然后单击确定
  5. 添加安全组规则。
    在两个集群的安全组内添加对方集群的Pod网络CIDR,允许对方集群的Pod网段地址访问本机。
    1. 登录容器服务管理控制台
    2. 集群列表页面单击ack-shanghai集群右侧操作列下的详情
    3. 集群信息页面单击基本信息页签。
      查看ack-shanghai集群的Pod网络CIDR,然后返回集群列表页面。
    4. 集群列表页面单击ack-hangzhou集群右侧操作列下的详情
    5. 集群信息页面单击集群资源页签,然后单击安全组右侧的安全组ID。
    6. 安全组详情页签入方向下单击手动添加
    7. 设置协议类型全部为ack-shanghai集群的Pod网络CIDR,其他为默认值,然后单击操作列下的保存
    8. 重复执行以上步骤,查看ack-hangzhou集群的Pod网络CIDR,然后在ack-shanghai集群的安全组中,添加ack-hangzhou集群的Pod网络CIDR。

步骤三:将Pod路由信息发布至CEN

  1. 登录容器服务管理控制台
  2. 集群列表页面单击ack-hangzhou集群右侧操作列下的详情
  3. 在集群信息页面单击集群资源页签,然后单击虚拟专有网络VPC右侧VPC ID。
  4. 在VPC的详情页面路由器基本信息区域查看路由器ID。
  5. 在专有网络控制台左侧导航栏单击路由表
  6. 路由表页面找到上文获取的路由器ID的路由实例名称,然后单击路由实例名称。
  7. 路由条目列表页签下单击自定义
  8. 单击Pod CIDR网段的子网段右侧的发布,本文为10.45.0.0/16的子网段。
  9. 发布路由的对话框单击确定
  10. 重复执行以上步骤,将ack-shanghai集群的Pod路由信息发布至CEN。
  11. 验证ack-hangzhou和ack-shanghai集群Pod路由信息是否都发布至CEN。
    在杭州地域路由表详情页面路由条目列表页签下单击动态。可以看到ack-shanghai集群PodCIDR的路由信息和vpc-shanghai-switch-1的IPv4网段的路由信息。在上海地域路由表详情页面也可以看到ack-hangzhou集群PodCIDR的路由信息和vpc-hangzhou-switch-1的IPv4网段的路由信息。说明ack-hangzhou和ack-shanghai集群Pod路由信息都发布至CEN。

步骤四:添加集群到ASM实例。

添加杭州地域和上海地域的集群到同一个ASM实例中。

  1. 登录ASM控制台
  2. 在左侧导航栏,选择服务网格 > 网格管理
  3. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理
  4. 在网格详情页面左侧导航栏选择数据平面(服务发现) > Kubernetes集群,然后在右侧页面单击添加
  5. 添加集群面板,选中杭州地域的集群,然后单击确定
  6. 重要提示对话框中单击确定
  7. 重复执行以上步骤,将上海地域的集群添加到该ASM实例中。

步骤五:在ASM中配置入口网关

  1. 查看ack-shanghai集群的ID。
    1. 登录容器服务管理控制台
    2. 集群列表页面单击ack-shanghai集群右侧操作列下的详情
    3. 在集群信息页面单击基本信息页签。
      基本信息区域查看集群ID。
  2. 登录ASM控制台
  3. 在左侧导航栏,选择服务网格 > 网格管理
  4. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理
  5. 在网格详情页面左侧导航栏单击ASM网关
  6. ASM网关页面,单击部署默认入口网关
  7. 部署入口网关面板设置部署集群为ack-hangzhou集群,负载均衡类型公网访问,选择负载均衡类型,其他采用默认设置。然后单击确定
  8. ASM网关页面单击ingressgateway右侧操作列下的YAML
  9. 编辑面板补充ack-shanghai集群的ID,然后单击确定
    spec:
      clusterIds:
        - ack-hangzhou cluster-id
        - ack-shanghai cluster-id 

步骤六:部署演示应用BookInfo

  1. 使用kubectl连接到ack-hangzhou集群。具体操作,请参见通过kubectl工具连接集群
  2. 使用以下内容,创建ack-hangzhou-k8s.yaml
    # Details service
    apiVersion: v1
    kind: Service
    metadata:
      name: details
      labels:
        app: details
        service: details
    spec:
      ports:
      - port: 9080
        name: http
      selector:
        app: details
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: bookinfo-details
      labels:
        account: details
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: details-v1
      labels:
        app: details
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: details
          version: v1
      template:
        metadata:
          labels:
            app: details
            version: v1
        spec:
          serviceAccountName: bookinfo-details
          containers:
          - name: details
            image: docker.io/istio/examples-bookinfo-details-v1:1.16.2
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 9080
            securityContext:
              runAsUser: 1000
    ---
    # Ratings service
    apiVersion: v1
    kind: Service
    metadata:
      name: ratings
      labels:
        app: ratings
        service: ratings
    spec:
      ports:
      - port: 9080
        name: http
      selector:
        app: ratings
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: bookinfo-ratings
      labels:
        account: ratings
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ratings-v1
      labels:
        app: ratings
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: ratings
          version: v1
      template:
        metadata:
          labels:
            app: ratings
            version: v1
        spec:
          serviceAccountName: bookinfo-ratings
          containers:
          - name: ratings
            image: docker.io/istio/examples-bookinfo-ratings-v1:1.16.2
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 9080
            securityContext:
              runAsUser: 1000
    ---
    # Reviews service
    apiVersion: v1
    kind: Service
    metadata:
      name: reviews
      labels:
        app: reviews
        service: reviews
    spec:
      ports:
      - port: 9080
        name: http
      selector:
        app: reviews
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: bookinfo-reviews
      labels:
        account: reviews
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: reviews-v1
      labels:
        app: reviews
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: reviews
          version: v1
      template:
        metadata:
          labels:
            app: reviews
            version: v1
        spec:
          serviceAccountName: bookinfo-reviews
          containers:
          - name: reviews
            image: docker.io/istio/examples-bookinfo-reviews-v1:1.16.2
            imagePullPolicy: IfNotPresent
            env:
            - name: LOG_DIR
              value: "/tmp/logs"
            ports:
            - containerPort: 9080
            volumeMounts:
            - name: tmp
              mountPath: /tmp
            - name: wlp-output
              mountPath: /opt/ibm/wlp/output
            securityContext:
              runAsUser: 1000
          volumes:
          - name: wlp-output
            emptyDir: {}
          - name: tmp
            emptyDir: {}
    ---
    # Productpage services
    apiVersion: v1
    kind: Service
    metadata:
      name: productpage
      labels:
        app: productpage
        service: productpage
    spec:
      ports:
      - port: 9080
        name: http
      selector:
        app: productpage
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: bookinfo-productpage
      labels:
        account: productpage
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: productpage-v1
      labels:
        app: productpage
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: productpage
          version: v1
      template:
        metadata:
          labels:
            app: productpage
            version: v1
        spec:
          serviceAccountName: bookinfo-productpage
          containers:
          - name: productpage
            image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 9080
            volumeMounts:
            - name: tmp
              mountPath: /tmp
            securityContext:
              runAsUser: 1000
          volumes:
          - name: tmp
            emptyDir: {}
    ---
    	  
  3. 执行以下命令,在ack-hangzhou集群部署BookInfo应用。
    kubectl apply -f ack-hangzhou-k8s.yaml
  4. 使用kubectl连接到ack-shanghai集群。具体操作,请参见通过kubectl工具连接集群
    说明 使用kubectl连接到ack-shanghai集群时,您需要将ack-hangzhou集群的kubeconfig切换成ack-shanghai集群的kubeconfig。
  5. 使用以下内容,创建ack-shanghai.yaml
    # Details service
    apiVersion: v1
    kind: Service
    metadata:
      name: details
      labels:
        app: details
        service: details
    spec:
      ports:
      - port: 9080
        name: http
      selector:
        app: details
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: bookinfo-details
      labels:
        account: details
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: details-v1
      labels:
        app: details
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: details
          version: v1
      template:
        metadata:
          labels:
            app: details
            version: v1
        spec:
          serviceAccountName: bookinfo-details
          containers:
          - name: details
            image: docker.io/istio/examples-bookinfo-details-v1:1.16.2
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 9080
            securityContext:
              runAsUser: 1000
    ---
    # Ratings service
    apiVersion: v1
    kind: Service
    metadata:
      name: ratings
      labels:
        app: ratings
        service: ratings
    spec:
      ports:
      - port: 9080
        name: http
      selector:
        app: ratings
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: bookinfo-ratings
      labels:
        account: ratings
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ratings-v1
      labels:
        app: ratings
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: ratings
          version: v1
      template:
        metadata:
          labels:
            app: ratings
            version: v1
        spec:
          serviceAccountName: bookinfo-ratings
          containers:
          - name: ratings
            image: docker.io/istio/examples-bookinfo-ratings-v1:1.16.2
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 9080
            securityContext:
              runAsUser: 1000
    ---
    # Reviews service
    apiVersion: v1
    kind: Service
    metadata:
      name: reviews
      labels:
        app: reviews
        service: reviews
    spec:
      ports:
      - port: 9080
        name: http
      selector:
        app: reviews
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: bookinfo-reviews
      labels:
        account: reviews
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: reviews-v2
      labels:
        app: reviews
        version: v2
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: reviews
          version: v2
      template:
        metadata:
          labels:
            app: reviews
            version: v2
        spec:
          serviceAccountName: bookinfo-reviews
          containers:
          - name: reviews
            image: docker.io/istio/examples-bookinfo-reviews-v2:1.16.2
            imagePullPolicy: IfNotPresent
            env:
            - name: LOG_DIR
              value: "/tmp/logs"
            ports:
            - containerPort: 9080
            volumeMounts:
            - name: tmp
              mountPath: /tmp
            - name: wlp-output
              mountPath: /opt/ibm/wlp/output
            securityContext:
              runAsUser: 1000
          volumes:
          - name: wlp-output
            emptyDir: {}
          - name: tmp
            emptyDir: {}
    ---
    # Productpage services
    apiVersion: v1
    kind: Service
    metadata:
      name: productpage
      labels:
        app: productpage
        service: productpage
    spec:
      ports:
      - port: 9080
        name: http
      selector:
        app: productpage
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: bookinfo-productpage
      labels:
        account: productpage
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: productpage-v1
      labels:
        app: productpage
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: productpage
          version: v1
      template:
        metadata:
          labels:
            app: productpage
            version: v1
        spec:
          serviceAccountName: bookinfo-productpage
          containers:
          - name: productpage
            image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 9080
            volumeMounts:
            - name: tmp
              mountPath: /tmp
            securityContext:
              runAsUser: 1000
          volumes:
          - name: tmp
            emptyDir: {}
    ---
    	  
  6. 执行以下命令,在ack-shanghai集群部署BookInfo应用。
    kubectl apply -f ack-shanghai.yaml
  7. 使用kubectl连接到ASM。具体操作,请参见通过kubectl连接ASM实例
    说明 使用kubectl连接到ASM时,您需要将ack-shanghai集群的kubeconfig切换成ASM的kubeconfig。
  8. 使用以下内容,创建asm.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: bookinfo-gateway
    spec:
      selector:
        istio: ingressgateway # use istio default controller
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - "*"
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: bookinfo
    spec:
      hosts:
      - "*"
      gateways:
      - bookinfo-gateway
      http:
      - match:
        - uri:
            exact: /productpage
        - uri:
            prefix: /static
        - uri:
            exact: /login
        - uri:
            exact: /logout
        - uri:
            prefix: /api/v1/products
        route:
        - destination:
            host: productpage
            port:
              number: 9080
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: productpage
    spec:
      host: productpage
      subsets:
      - name: v1
        labels:
          version: v1
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: reviews
    spec:
      host: reviews
      subsets:
      - name: v1
        labels:
          version: v1
      - name: v2
        labels:
          version: v2
      - name: v3
        labels:
          version: v3
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: ratings
    spec:
      host: ratings
      subsets:
      - name: v1
        labels:
          version: v1
      - name: v2
        labels:
          version: v2
      - name: v2-mysql
        labels:
          version: v2-mysql
      - name: v2-mysql-vm
        labels:
          version: v2-mysql-vm
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: details
    spec:
      host: details
      subsets:
      - name: v1
        labels:
          version: v1
      - name: v2
        labels:
          version: v2
    ---
    	  
  9. 执行以下命令,在ASM创建路由规则。
    kubectl apply -f asm.yaml
  10. 验证Bookinfo应用是否部署成功。
    1. 登录容器服务管理控制台
    2. 在控制台左侧导航栏中,单击集群
    3. 集群列表页面单击ack-hangzhou集群右侧操作列下的详情
    4. 在集群管理页左侧导航栏中,选择网络 > 服务
    5. 服务页面顶部设置命名空间为Istio-system,查看istio-ingressgateway右侧外部端点下端口为80的IP地址。
    6. 在浏览器地址栏中输入入口网关IP地址/productpage
      多次刷新页面,可以看到以下图片轮流出现。review1review1

步骤七:使用跨地域流量分布和跨地域故障转移

设置跨地域流量分布

  1. 登录ASM控制台
  2. 在左侧导航栏,选择服务网格 > 网格管理
  3. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理
  4. 在网格信息页面基本信息区域单击跨地域负载均衡右侧的启用跨地域流量分布
    说明 如果您已经启用跨地域故障转移,您需要禁用跨地域故障转移后,才能启用跨地域流量分布。
  5. 跨地域流量分布对话框设置策略为cn-hangzhou,然后单击新建策略
  6. 单击展开图标,然后单击添加图标,设置目标为cn-hangzhou,权重为90%。
  7. 单击添加图标,设置目标为cn-shanghai,权重为10%,单击确认
  8. 执行以下命令,循环请求10次BookInfo应用,验证跨地域流量分布是否成功。
    for ((i=1;i<=10;i++));do curl http://<ack-hangzhou集群中80端口的入口网关地址>/productpage 2>&1|grep full.stars;done

    预期输出:

    <!-- full stars: -->
    <!-- full stars: -->

    可以看到访问10次,输出2行full stars,说明10次请求中9次路由到了ack-hangzhou集群的v1版本reviews服务,1次路由到了ack-shanghai集群的v2版本reviews服务,流量按照权重路由到多个集群成功。

设置跨地域故障转移

  1. 停用ack-hangzhou集群的review。
    1. 登录容器服务管理控制台
    2. 在控制台左侧导航栏中,单击集群
    3. 在集群管理页左侧导航栏中,选择工作负载 > 无状态
    4. 无状态页面设置命名空间为default,单击reviews-v1右侧操作列下的伸缩
    5. 伸缩页面设置所需容器组数量为0,然后单击确定
  2. 配置DestinationRule。
    配置DestinationRule,当1s内无法请求到reviews服务,该reviews服务将被移除1min。
    1. 登录ASM控制台
    2. 在左侧导航栏,选择服务网格 > 网格管理
    3. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理
    4. 在网格详情页面左侧导航栏选择流量管理 > 目标规则
    5. 目标规则页面单击reviews右侧操作列下的YAML
    6. 编辑面板增加以下内容,然后单击确定
      spec:
        ......
        trafficPolicy:
          connectionPool:
            http:
              maxRequestsPerConnection: 1
          outlierDetection:
            baseEjectionTime: 1m
            consecutive5xxErrors: 1
            interval: 1s
      • maxRequestsPerConnection:最大连接数量。
      • baseEjectionTime:最小的移除时间长度。
      • consecutive5xxErrors:连续错误数量。
      • interval:移除检测的时间间隔。
  3. 启用跨地域故障转移。
    1. 在网格信息页面基本信息区域单击跨地域负载均衡右侧的启用跨地域故障转移
      说明 如果您已经启用跨地域流量分布,您需要禁用跨地域流量分布后,才能启用跨地域故障转移。
    2. 跨地域故障转移对话框中设置当策略源是cn-shanghai,源故障转移至cn-hangzhou,当策略源是cn-hangzhou,源故障转移至cn-shanghai,然后单击确认
  4. 执行以下命令,循环请求10次BookInfo应用,并对路由到v2版本reviews服务的结果数量进行统计。
    for ((i=1;i<=10;i++));do curl http://<ack-hangzhou集群中80端口的入口网关地址>/productpage 2>&1|grep full.stars;done|wc -l

    预期输出:

    20

    可以看到访问10次,返回20(每次路由到v2版本reviews服务会返回两行包含full stars的结果),说明10次请求全部路由到了ack-shanghai集群的v2版本reviews服务,跨地域故障转移成功。