Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
242 changes: 242 additions & 0 deletions content/zh/blog/2021/external-locality-failover/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
---
title: "为外部服务配置故障转移"
description: 了解如何为网格外部的端点配置本地负载均衡和故障转移。
publishdate: 2021-06-04
attribution: "Ram Vennam (Solo.io)"
keywords: [locality,region,failover,Istio,outlier,external]
---

Istio 强大的 API 可用于解决各种使用服务网格时遇到的问题。
许多用户对其强大的入口和东西向流量能力都比较了解,但是除此之外它也为出口(向外)流量提供了诸多功能。
当您的应用程序需要与外部服务(例如云服务商提供的数据库端点)通信时,
该功能就可以派上用场。根据工作负载运行的位置,通常可以有多个端点供用户选择。
例如,Amazon 的 DynamoDB 就可以提供跨区域的[多个端点](https://docs.aws.amazon.com/general/latest/gr/ddb.html)。
由于延迟原因,常常希望选择使用离您工作负载最近的端点,
但是为了防止未按照预期正常工作的情况发生,您可能需要配置自动故障转移使流量可以指向另一个端点。

与在服务网格内运行的服务类似,您可以对 Istio
进行离群检测配置来实现将流量指向健康端点的故障转移操作,
并且该配置仍然对您的应用程序完全透明。在此示例中,我们将使用
Amazon DynamoDB 端点选择与 Google Kubernetes Engine(GKE)
集群中运行的工作负载处于相同或接近的主要区域。
另外我们还会为其配置一个故障转移区域。

|路由|端点|
|--- |--- |
|主路由|http://dynamodb.us-east-1.amazonaws.com|
|故障路由|http://dynamodb.us-west-1.amazonaws.com|

![故障转移](./external-locality-failover.png)

## 使用 ServiceEntry 定义外部端点 {#define-external-endpoints-using-a-serviceentry}

[本地负载均衡](/zh/docs/tasks/traffic-management/locality-load-balancing/)基于 `region`
或 `zone` 工作,这通常是从 Kubernetes 节点上设置的标签推断出来的。
首先,确定您工作负载所处的位置:

{{< text bash >}}
$ kubectl describe node | grep failure-domain.beta.kubernetes.io/region
failure-domain.beta.kubernetes.io/region=us-east1
failure-domain.beta.kubernetes.io/region=us-east1
{{< /text >}}

在此示例中,GKE 集群节点在 `us-east1` 区域中运行。

接下来,创建一个 `ServiceEntry` 来聚合您要使用的端点。在此示例中,
我们选择了 `mydb.com` 作为 host。这也是您应用程序需要配置的连接地址。
然后将主要端点的 `locality` 设置为与您工作负载相同的区域:

{{< text yaml >}}
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: external-svc-dns
spec:
hosts:
- mydb.com
location: MESH_EXTERNAL
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS
endpoints:
- address: dynamodb.us-east-1.amazonaws.com
locality: us-east1
ports:
http: 80
- address: dynamodb.us-west-1.amazonaws.com
locality: us-west
ports:
http: 80
{{< /text >}}

让我们部署一个 sleep 容器作为发送请求的测试源。

{{< text bash >}}
$ kubectl apply -f @samples/sleep/sleep.yaml@
{{< /text >}}

从这个 sleep 容器中尝试发起对 `http://mydb.com` 的 5 次访问:

{{< text bash >}}
$ for i in {1..5}; do kubectl exec deploy/sleep -c sleep -- curl -sS http://mydb.com; echo; sleep 2; done
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
{{< /text >}}

您将看到 Istio 会分别向两个端点都发送请求。
但是我们只希望请求被发送到与我们节点标记为相同区域的端点中。

为此,我们需要配置一个 `DestinationRule`。

## 使用 `DestinationRule` 设置故障转移条件 {#set-failover-conditions-using-a-destinationrule}

Istio 的 `DestinationRule` 允许您配置负载均衡、连接池和离群检测设置。
我们可以指定用于将端点标识为不健康并将其从负载均衡池中删除的条件。

{{< text yaml >}}
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: mydynamodb
spec:
host: mydb.com
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 1
interval: 15s
baseEjectionTime: 1m
{{< /text >}}

上面的 `DestinationRule` 将端点配置为每 15 秒扫描一次,如果任何端点出现
5xx 错误代码形式的失败请求,即使只出现一次,在接下来的一分钟内它也会被标记为不健康状态。
在此熔断机制未被触发时,流量将被路由到与 Pod 相同的区域。

如果我们再次运行 curl 命令,应该看到流量总是流向 `us-east1` 端点。

{{< text bash >}}
$ for i in {1..5}; do kubectl exec deploy/sleep -c sleep -- curl -sS http://mydb.com; echo; sleep 2; done

healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
healthy: dynamodb.us-east-1.amazonaws.com
{{< /text >}}

## 模拟失败 {#simulate-a-failure}

接下来,让我们看看如果 us-east 端点出现故障会发生什么情况。
为了模拟这种情况,让我们对 ServiceEntry 进行修改并为 `us-east` 端点设置一个无效端口:

{{< text yaml >}}
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: external-svc-dns
spec:
hosts:
- mydb.com
location: MESH_EXTERNAL
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS
endpoints:
- address: dynamodb.us-east-1.amazonaws.com
locality: us-east1
ports:
http: 81 # INVALID - This is purposefully wrong to trigger failover
- address: dynamodb.us-west-1.amazonaws.com
locality: us-west
ports:
http: 80
{{< /text >}}

再次运行 curl 命令,结果展示流量在无法连接到 us-east
端点后自动故障转移到 us-west 区域:

{{< text bash >}}
$ for i in {1..5}; do kubectl exec deploy/sleep -c sleep -- curl -sS http://mydb.com; echo; sleep 2; done
upstream connect error or disconnect/reset before headers. reset reason: connection failure
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
healthy: dynamodb.us-west-1.amazonaws.com
{{< /text >}}

您可以通过运行以下命令检查 us-east 端点的离群检测状态:

{{< text bash >}}
$ istioctl pc endpoints <sleep-pod> | grep mydb
ENDPOINT STATUS OUTLIER CHECK CLUSTER
52.119.226.80:81 HEALTHY FAILED outbound|80||mydb.com
52.94.12.144:80 HEALTHY OK outbound|80||mydb.com
{{< /text >}}

## HTTPS 的故障转移 {#failover-for-https}

为外部 HTTPS 服务配置故障转移同样简单。您的应用程序仍然可以继续使用纯
HTTP 协议,并且您可以让 Istio 代理将 TLS 源指向 HTTPS。

{{< text yaml >}}
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: external-svc-dns
spec:
hosts:
- mydb.com
ports:
- number: 80
name: http-port
protocol: HTTP
targetPort: 443
resolution: DNS
endpoints:
- address: dynamodb.us-east-1.amazonaws.com
locality: us-east1
- address: dynamodb.us-west-1.amazonaws.com
locality: us-west
{{< /text >}}

上面的 ServiceEntry 在 80 端口上定义了 `mydb.com` 服务,
并将流量重定向到 443 端口上的真实 DynamoDB 端点。

{{< text yaml >}}
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: mydynamodb
spec:
host: mydb.com
trafficPolicy:
tls:
mode: SIMPLE
loadBalancer:
simple: ROUND_ROBIN
localityLbSetting:
enabled: true
failover:
- from: us-east1
to: us-west
outlierDetection:
consecutive5xxErrors: 1
interval: 15s
baseEjectionTime: 1m
{{< /text >}}

`DestinationRule` 现在执行 TLS 源并配置离群检测。
该规则还配置了一个[故障转移](/zh/docs/reference/config/networking/destination-rule/#LocalityLoadBalancerSetting)字段,
您可以在其中准确指定哪些区域是故障转移目标。当您定义了多个区域时,这非常有用。

## 总结 {#wrapping-up}

Istio 的 `VirtualService` 和 `DestinationRule` API 提供流量路由、
故障恢复和故障注入功能,因此您可以创建具有弹性的应用程序。
ServiceEntry API 也将其中许多功能扩展到服务网格之外的服务中。