5.3.8 地域负载均衡

一个地域定义了workload instance在你的网格中的地理位置。这三个元素定义了一个地域:

  • 地区: 代表较大的地理区域,例如us-east. 一个地区通常包含许多可用 zones。在Kubernetes中,标签topology.kubernetes.io/region确定节点的区域。

  • 区域: 区域内的一组计算资源。通过在区域内的多个区域中运行服务,可以在区域内的区域之间进行故障转移,同时保持最终用户的数据地域性。在Kubernetes中,标签topology.kubernetes.io/zone确定节点的区域。

  • 分区: 允许管理员进一步细分区域,以实现更细粒度的控制,例如“相同机架”。Kubernetes中不存在分区的概念。结果,Istio引入了自定义节点标签topology.istio.io/subzone来定义分区。

如果您使用托管的Kubernetes服务,则云提供商应为您配置区域和区域标签。如果您正在运行自己的Kubernetes集群,则需要将这些标签添加到您的节点上。

地域是分层的,按匹配顺序排列:

  1. 地区

  2. 区域

  3. 分区

这意味着,在foo地区的bar区域中运行Pod是不被认为是在baz地区的bar区域中运行的Pod。

Istio使用地域信息来控制负载平衡行为。按照本系列的任务一,为您的网格配置地域负载均衡。

前置条件

在开始区域负载均衡任务之前,必须首先在多个集群上安装Istio。群集必须跨越三个地区,其中包含四个可用区域。所需集群的数量可能会因您的云提供商所提供的功能而异。

为简单起见,我们假设只有一个primary cluster在网格中。由于更改仅需要应用于一个集群,因此这简化了配置控制平面的过程。

我们将部署 helloWorld 应用程序的多个实例,如下所示:

setup

环境变量

本指南假定将通过 Kubernetes 配置文件 中的上下文切换访问集群。以下环境变量将用于各种上下文:

变量 描述
CTX_PRIMARY 用于主群集的上下文。
CTX_R1_Z1 用于与 region1.zone1 中的 Pod 交互的上下文。
CTX_R1_Z2 用于与 region1.zone2 中的 Pod 交互的上下文。
CTX_R2_Z3 用于与 region2.zone3 中的 Pod 交互的上下文。
CTX_R3_Z4 用于与 region3.zone4 中的 Pod 交互的上下文。

创建 sample 命名空间

首先,启用自动注入 Sidecar 并为 sample 命名空间生成 yaml

cat <<EOF > sample.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: sample
  labels:
    istio-injection: enabled
EOF

为每个集群添加 sample 命名空间:

for CTX in "$CTX_PRIMARY" "$CTX_R1_Z1" "$CTX_R1_Z2" "$CTX_R2_Z3" "$CTX_R3_Z4"; \
do \
  kubectl --context="$CTX" apply -f sample.yaml; \
done

部署helloWorld

使用地域作为版本号,为每个地域生成 helloWorld 的 yaml:

for LOC in "region1.zone1" "region1.zone2" "region2.zone3" "region3.zone4"; \
do \
  ./@samples/helloworld/gen-helloworld.sh@ \
    --version "$LOC" > "helloworld-${LOC}.yaml"; \
done

应用HelloWorldYAML到每个地域的合适集群:

kubectl apply --context="${CTX_R1_Z1}" -n sample \
  -f helloworld-region1.zone1.yaml
kubectl apply --context="${CTX_R1_Z2}" -n sample \
  -f helloworld-region1.zone2.yaml
kubectl apply --context="${CTX_R2_Z3}" -n sample \
  -f helloworld-region2.zone3.yaml
kubectl apply --context="${CTX_R3_Z4}" -n sample \
  -f helloworld-region3.zone4.yaml

部署 sleep

部署 Sleep 应用到 region1 zone1

kubectl apply --context="${CTX_R1_Z1}" \
  -f @samples/sleep/sleep.yaml@ -n sample

等待 helloWorld Pods

等到 HelloWorld 在每个区域的 Pod 都为 Running

kubectl get pod --context="${CTX_R1_Z1}" -n sample -l app="helloworld" \
  -l version="region1.zone1"
NAME                                       READY   STATUS    RESTARTS   AGE
helloworld-region1.zone1-86f77cd7b-cpxhv   2/2     Running   0          30s
kubectl get pod --context="${CTX_R1_Z2}" -n sample -l app="helloworld" \
  -l version="region1.zone2"
NAME                                       READY   STATUS    RESTARTS   AGE
helloworld-region1.zone2-86f77cd7b-cpxhv   2/2     Running   0          30s
kubectl get pod --context="${CTX_R2_Z3}" -n sample -l app="helloworld" \
  -l version="region2.zone3"
NAME                                       READY   STATUS    RESTARTS   AGE
helloworld-region2.zone3-86f77cd7b-cpxhv   2/2     Running   0          30s
kubectl get pod --context="${CTX_R3_Z4}" -n sample -l app="helloworld" \
  -l version="region3.zone4"
NAME                                       READY   STATUS    RESTARTS   AGE
helloworld-region3.zone4-86f77cd7b-cpxhv   2/2     Running   0          30s

恭喜您! 您已成功完成系统配置,现在可以开始进行地域负载均衡任务了

下一步

现在,您可以配置以下负载均衡选项之一:

  • 地域故障转移
  • 地域权重分布

应当仅配置负载均衡选项之一,因为它们是互斥的。尝试同时配置两者可能会导致意外行为。

地域故障转移

在此任务中,您将使用 sleep pod 在 region1.zone1 作为请求源发送到 helloWorld 服务。然后,您将触发故障,这些故障将按照以下顺序导致不同地域之间的故障转移:

地域故障转移顺序

在内部,Envoy优先级用于控制故障转移。这些优先级将按照以下方式分配来自sleepPod(在 region1 zone1)的流量:

优先级 地域 细节
0 region1.zone1 地区、区域、分区全部匹配。
1 None 由于此任务不使用分区,因此没有其他分区的匹配项。
2 region1.zone2 同一个地区内的不用区域。
3 region2.zone3 没有匹配项,但是为 region1->region2 定义了故障转移。
4 region3.zone4 没有匹配项并且没有为 region1->region3 定义故障转移。

配置地域故障转移

应用一个 DestinationRule 配置如下:

  • 异常检测: 用于 helloWorld 服务。这是故障转移正常运行所必须的。特别是,它可以配置Sidecar代理以知道服务的Endpoint何时不正常,最终触发故障转移到下一个地域。
  • 故障转移: 地区之间的策略,这确保了超出地区边界的故障转移将具有可预测的行为。

  • 连接池: 强制每个HTTP请求使用一个新连接的策略。该任务利用Envoy逐出 功能强制将故障转移到下一个位置。一旦逐出,Envoy 将拒绝所有新的请求。由于每个请求都使用一个新连接,这将导致在耗尽后立即进行故障转移。此配置仅用于演示目的。

kubectl --context="${CTX_PRIMARY}" apply -n sample -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: helloworld
spec:
  host: helloworld.sample.svc.cluster.local
  trafficPolicy:
    connectionPool:
      http:
        maxRequestsPerConnection: 1
    loadBalancer:
      simple: ROUND_ROBIN
      localityLbSetting:
        enabled: true
        failover:
          - from: region1
            to: region2
    outlierDetection:
      consecutive5xxErrors: 1
      interval: 1s
      baseEjectionTime: 1m
EOF

验证流量保持在region1.zone1

sleepPod调用helloWorld服务

kubectl exec --context="${CTX_R1_Z1}" -n sample -c sleep \
  "$(kubectl get pod --context="${CTX_R1_Z1}" -n sample -l \
  app=sleep -o jsonpath='{.items[0].metadata.name}')" \
  -- curl -sSL helloworld.sample:5000/hello
Hello version: region1.zone1, instance: helloworld-region1.zone1-86f77cd7b-cpxhv

验证响应中的versionregion1.zone

重复几次,验证响应总是相同的。

故障转移到 region1.zone2

接下来, 触发故障转移到region1.zone2。为此,您在region1.zone1helloWorld逐出 Envoy Sidecar 代理

kubectl --context="${CTX_R1_Z1}" exec \
  "$(kubectl get pod --context="${CTX_R1_Z1}" -n sample -l app=helloworld \
  -l version=region1.zone1 -o jsonpath='{.items[0].metadata.name}')" \
  -n sample -c istio-proxy -- curl -sSL -X POST 127.0.0.1:15000/drain_listeners

sleep Pod 调用 helloWorld 服务:

kubectl exec --context="${CTX_R1_Z1}" -n sample -c sleep \
  "$(kubectl get pod --context="${CTX_R1_Z1}" -n sample -l \
  app=sleep -o jsonpath='{.items[0].metadata.name}')" \
  -- curl -sSL helloworld.sample:5000/hello
Hello version: region1.zone2, instance: helloworld-region1.zone2-86f77cd7b-cpxhv

第一个调用将失败,这将触发故障转移。多次重复该命令,并验证响应中的 version 始终为 region1.zone2

故障转移到 region2.zone3

现在触发故障转移到 region2.zone3。正如您之前所做的,配置 helloWorldregion1.zone2 中调用失败。

kubectl --context="${CTX_R1_Z2}" exec \
  "$(kubectl get pod --context="${CTX_R1_Z2}" -n sample -l app=helloworld \
  -l version=region1.zone2 -o jsonpath='{.items[0].metadata.name}')" \
  -n sample -c istio-proxy -- curl -sSL -X POST 127.0.0.1:15000/drain_listeners

sleepPod 调用helloWorld服务:

kubectl exec --context="${CTX_R1_Z1}" -n sample -c sleep \
  "$(kubectl get pod --context="${CTX_R1_Z1}" -n sample -l \
  app=sleep -o jsonpath='{.items[0].metadata.name}')" \
  -- curl -sSL helloworld.sample:5000/hello
Hello version: region2.zone3, instance: helloworld-region2.zone3-86f77cd7b-cpxhv

第一个调用将失败,这将触发故障转移。多次重复该命令,并验证响应中的version始终为region2.zone3

故障转移到 region3.zone4

现在触发故障转移到 region3.zone4。正如您之前所做的, 配置 helloWorldregion2.zone3 中调用失败。

kubectl --context="${CTX_R2_Z3}" exec \
  "$(kubectl get pod --context="${CTX_R2_Z3}" -n sample -l app=helloworld \
  -l version=region2.zone3 -o jsonpath='{.items[0].metadata.name}')" \
  -n sample -c istio-proxy -- curl -sSL -X POST 127.0.0.1:15000/drain_listeners

sleepPod调用helloWorld服务:

kubectl exec --context="${CTX_R1_Z1}" -n sample -c sleep \
  "$(kubectl get pod --context="${CTX_R1_Z1}" -n sample -l \
  app=sleep -o jsonpath='{.items[0].metadata.name}')" \
  -- curl -sSL helloworld.sample:5000/hello
Hello version: region3.zone4, instance: helloworld-region3.zone4-86f77cd7b-cpxhv

第一次调用将失败,这将触发故障转移。多次重复该命令,并验证响应中的 version 始终为 region3.zone4

恭喜! 您成功配置了地域故障转移!

地域权重分布

在这个任务中,您将使用 region1 zone1 中的 sleep Pod 作为 helloWorld 服务的请求源。您将使用以下分布在不同的地域配置Istio:

地区 区域 流量(%)
region1 zone1 70
region1 zone2 20
region2 zone3 0
region3 zone4 10

配置权重分布

应用 DestinationRule 配置如下:

  • 故障检测 用于 helloWorld 服务。这是 Distribution 正常运行所必需的。特别是,它配置 Sidecar 代理以知道服务的 Endpoint 何时不健康。

  • 权重分布 如上表中所述的 helloWorld 服务。

kubectl --context="${CTX_PRIMARY}" apply -n sample -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: helloworld
spec:
  host: helloworld.sample.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      localityLbSetting:
        enabled: true
        distribute:
        - from: region1/zone1/*
          to:
            "region1/zone1/*": 70
            "region1/zone2/*": 20
            "region3/zone4/*": 10
    outlierDetection:
      consecutive5xxErrors: 100
      interval: 1s
      baseEjectionTime: 1m
EOF

验证分布

sleep Pod 调用 helloWorld 服务:

kubectl exec --context="${CTX_R1_Z1}" -n sample -c sleep \
  "$(kubectl get pod --context="${CTX_R1_Z1}" -n sample -l \
  app=sleep -o jsonpath='{.items[0].metadata.name}')" \
  -- curl -sSL helloworld.sample:5000/hello

重复多次,并验证每个 Pod 的回复数与本指南顶部表格中的预期百分比匹配。

恭喜! 你成功配置了地域权重分布!

清理

1删除生成的文件

rm -f sample.yaml helloworld-region*.zone*.yaml

2删除 sample 命名空间

for CTX in "$CTX_PRIMARY" "$CTX_R1_Z1" "$CTX_R1_Z2" "$CTX_R2_Z3" "$CTX_R3_Z4";
do
  kubectl --context="$CTX" delete ns sample --ignore-not-found=true;
done

恭喜! 您成功地完成了地域负载均衡任务!

Copyright © huangzhongde.cn 2021 all right reserved,powered by Gitbook该文件修订时间: 2022-01-28 00:02:24

results matching ""

    No results matching ""