Envoy 示例

让我们以 Web 前端和 customer 服务为例,看看 Envoy 如何确定将请求从 Web 前端发送到 customer 服务(customers.default.svc.cluster.local)的位置。使用 istioctl proxy-config 命令,我们可以列出 web 前端 pod 的所有监听器。

$ istioctl proxy-config listeners web-frontend-64455cd4c6-p6ft2
ADDRESS      PORT  MATCH   DESTINATION
10.124.0.10  53    ALL     Cluster: outbound|53||kube-dns.kube-system.svc.cluster.local
0.0.0.0      80    ALL     PassthroughCluster
10.124.0.1   443   ALL     Cluster: outbound|443||kubernetes.default.svc.cluster.local
10.124.3.113 443   ALL     Cluster: outbound|443||istiod.istio-system.svc.cluster.local
10.124.7.154 443   ALL     Cluster: outbound|443||metrics-server.kube-system.svc.cluster.local
10.124.7.237 443   ALL     Cluster: outbound|443||istio-egressgateway.istio-system.svc.cluster.local
10.124.8.250 443   ALL     Cluster: outbound|443||istio-ingressgateway.istio-system.svc.cluster.local
10.124.3.113 853   ALL     Cluster: outbound|853||istiod.istio-system.svc.cluster.local
0.0.0.0      8383  ALL     PassthroughCluster
0.0.0.0      15001 ALL     PassthroughCluster
0.0.0.0      15006 ALL     Inline Route: /*
0.0.0.0      15010 ALL     PassthroughCluster
10.124.3.113 15012 ALL     Cluster: outbound|15012||istiod.istio-system.svc.cluster.local
0.0.0.0      15014 ALL     PassthroughCluster
0.0.0.0      15021 ALL     Non-HTTP/Non-TCP
10.124.8.250 15021 ALL     Cluster: outbound|15021||istio-ingressgateway.istio-system.svc.cluster.local
0.0.0.0      15090 ALL     Non-HTTP/Non-TCP
10.124.7.237 15443 ALL     Cluster: outbound|15443||istio-egressgateway.istio-system.svc.cluster.local
10.124.8.250 15443 ALL     Cluster: outbound|15443||istio-ingressgateway.istio-system.svc.cluster.local
10.124.8.250 31400 ALL     Cluster: outbound|31400||istio-ingressgateway.istio-system.svc.cluster.local

从 Web 前端到客户的请求是一个向外的 HTTP 请求,端口为 80。这意味着它被移交给了0.0.0.0:80的虚拟监听器。我们可以使用 Istio CLI 按地址和端口来过滤监听器。你可以添加-o json来获得监听器的 JSON 表示:

$ istioctl proxy-config listeners web-frontend-58d497b6f8-lwqkg --address 0.0.0.0 --port 80 -o json
...
"rds": {
   "configSource": {"ads": {},
      "resourceApiVersion": "V3"
   },
   "routeConfigName": "80"
},
...

Listener 使用 RDS(路由发现服务)来寻找路由配置(在我们的例子中是 80)。路由附属于监听器,包含将虚拟主机映射到集群的规则。这允许我们创建流量路由规则,因为 Envoy 可以查看头文件或路径(请求元数据)并对流量进行路由。

一个路由(route)选择一个集群(cluster)。一个集群是一组接受流量的类似的上游主机 —— 它是一个端点的集合。例如,Web 前端服务的所有实例的集合就是一个集群。我们可以在一个集群内配置弹性功能,如断路器、离群检测和 TLS 配置。

使用 routes 命令,我们可以通过名称过滤所有的路由来获得路由的详细信息。

$ istioctl proxy-config routes  web-frontend-58d497b6f8-lwqkg --name 80 -o json

[
    {
        "name": "80",
        "virtualHosts": [
            {
                "name": "customers.default.svc.cluster.local:80",
                "domains": [
                    "customers.default.svc.cluster.local",
                    "customers.default.svc.cluster.local:80",
                    "customers",
                    "customers:80",
                    "customers.default.svc.cluster",
                    "customers.default.svc.cluster:80",
                    "customers.default.svc",
                    "customers.default.svc:80",
                    "customers.default",
                    "customers.default:80",
                    "10.124.4.23",
                    "10.124.4.23:80"
                ],
                ],
                "routes": [
                    {
                        "match": {"prefix": "/"},
                        "route": {
                            "cluster": "outbound|80|v1|customers.default.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {"name": "envoy.retry_host_predicates.previous_hosts"}
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [503]
                            },
                            "maxGrpcTimeout": "0s"
                        },
...

路由80配置为每个服务都有一个虚拟主机。然而,由于我们的请求被发送到customers.default.svc.cluster.local,Envoy 会选择与其中一个域匹配的虚拟主机(customers.default.svc.cluster.local:80)。

一旦域被匹配,Envoy 就会查看路由,并选择第一个匹配请求的路由。由于我们没有定义任何特殊的路由规则,它匹配第一个(也是唯一的)定义的路由,并指示 Envoy 将请求发送到名为 outbound|80|v1|customers.default.svc.cluster.local 的集群。

注意集群名称中的 v1 是因为我们部署了一个 DestinationRule 来创建 v1 子集。如果一个服务没有子集,这部分就留空:outbound|80||customers.default.svc.cluster.local

现在我们有了集群的名称,我们可以查询更多的细节。为了得到一个清楚显示 FQDN、端口、子集和其他信息的输出,你可以省略 -o json 标志。

$ istioctl proxy-config cluster web-frontend-58d497b6f8-lwqkg --fqdn customers.default.svc.cluster.local
SERVICE FQDN                            PORT     SUBSET     DIRECTION     TYPE     DESTINATION RULE
customers.default.svc.cluster.local     80       -          outbound      EDS      customers.default
customers.default.svc.cluster.local     80       v1         outbound      EDS      customers.default

最后,使用集群的名称,我们可以查询请求最终将到达的实际端点:

$ istioctl proxy-config endpoints  web-frontend-58d497b6f8-lwqkg --cluster "outbound|80|v1|customers.default.svc.cluster.local"
ENDPOINT            STATUS      OUTLIER CHECK     CLUSTER
10.120.0.4:3000     HEALTHY     OK                outbound|80|v1|customers.default.svc.cluster.local

端点地址等于客户应用程序正在运行的 pod IP。如果我们扩展 customer 的部署,额外的端点会出现在输出中,像这样:

$ istioctl proxy-config endpoints web-frontend-58d497b6f8-lwqkg --cluster "outbound|80|v1|customers.default.svc.cluster.local"
ENDPOINT            STATUS      OUTLIER CHECK     CLUSTER
10.120.0.4:3000     HEALTHY     OK                outbound|80|v1|customers.default.svc.cluster.local
10.120.3.2:3000     HEALTHY     OK                outbound|80|v1|customers.default.svc.cluster.local

我们也可以用下图来形象地说明上述流程。

Envoy 详情
Envoy 详情

上一页
下一页