专栏
天翼云开发者社区

XDS协议浅析

2023-07-13 10:44:17 291阅读

一、背景

xDS(Extension and Discovery Service)是一个用于配置和动态发现服务的协议,用于管理和控制复杂的分布式系统。它是Kubernetes中Envoy代理的核心组件,用于实现服务的负载均衡、流量路由和故障恢复等功能。

  • 动态服务发现:在微服务架构中,服务的数量和实例经常发生变化。xDS协议提供了一种机制,可以动态地发现和注册服务实例,而无需手动配置或静态的硬编码地址。它使得服务发现能够适应服务拓扑的变化,从而实现弹性和可伸缩性。
  • 负载均衡和流量管理:xDS协议支持负载均衡和流量管理策略的动态配置。它允许服务网格控制平面根据实时的负载情况、服务间的依赖关系和其他策略来分配和管理流量。这使得在服务之间实现流量控制、故障转移、AB测试等变得更加灵活和可配置。
  • 配置管理和路由规则:xDS协议提供了一种机制,可以动态地配置和更新服务网格中的路由规则、策略和其他相关配置。通过使用xDS协议,服务网格中的路由规则可以根据需要进行更改,而无需重新部署或重启服务。这使得实施灰度发布、金丝雀发布和其他高级部署策略变得更加容易。
  • 多语言和多平台支持:xDS协议是一种通用的协议,可以在多种编程语言和平台上实现。这意味着您可以在不同的微服务框架和环境中使用xDS协议,实现统一的服务发现和配置管理体验。它提供了一种标准化的接口,使得不同的服务网格组件可以进行交互和协作。
  • 可扩展性:xDS协议设计为可扩展的,可以支持大规模的服务和高并发的流量。它使用了增量更新和缓存等技术,以减少配置传输和处理的开销,并提供了分布式的配置管理和服务发现能力。

xDS协议提供了动态的、灵活的服务发现和配置管理机制,适用于复杂的微服务环境。它能够提高服务网格的可伸缩性、可靠性和可配置性,使得在大规模微服务架构中管理和控制流量变得更加容易和高效。它在Kubernetes和Envoy等现代微服务架构中被广泛使用,用于实现服务网格、API网关和边缘路由等关键功能。

二、XDS结构

2.1 LDS

2.2 RDS

2.3 CDS

2.4 EDS

 

三、运行原理

3.1 框架

3.2 流程

我们以请求从 productpage Pod 发送到 reviews Pod 9080 端口为例,来研究Envoy代理是怎么处理流量的,会借助istioctl proxy-config的命令来具体分析。

3.2.1 Listerner处理

如果在一个 Pod 上查询监听器概要信息,将注意到 Istio 生成了下面的监听器:

    • 0.0.0.0:15001 监听器接收所有进出 Pod 的流量,然后转发请求给一个虚拟监听器。
    • 每个服务 IP 一个虚拟监听器,针对每一个非 HTTP 的外部 TCP/HTTPS 流量。
    • Pod IP 上的虚拟监听器,针对内部流量暴露的端口。
    • 0.0.0.0 监听器,针对外部 HTTP 流量的每个 HTTP 端口。
istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs
ADDRESS       PORT  MATCH                                            DESTINATION
10.96.0.10    53    ALL                                              Cluster: outbound|53||kube-dns.kube-system.svc.cluster.local
0.0.0.0       80    App: HTTP                                        Route: 80
0.0.0.0       80    ALL                                              PassthroughCluster
10.100.93.102 443   ALL                                              Cluster: outbound|443||istiod.istio-system.svc.cluster.local
10.111.121.13 443   ALL                                              Cluster: outbound|443||istio-ingressgateway.istio-system.svc.cluster.local
10.96.0.1     443   ALL                                              Cluster: outbound|443||kubernetes.default.svc.cluster.local
10.100.93.102 853   App: HTTP                                        Route: istiod.istio-system.svc.cluster.local:853
10.100.93.102 853   ALL                                              Cluster: outbound|853||istiod.istio-system.svc.cluster.local
0.0.0.0       9080  App: HTTP                                        Route: 9080
0.0.0.0       9080  ALL                                              PassthroughCluster
0.0.0.0       9090  App: HTTP                                        Route: 9090
0.0.0.0       9090  ALL                                              PassthroughCluster
10.96.0.10    9153  App: HTTP                                        Route: kube-dns.kube-system.svc.cluster.local:9153
10.96.0.10    9153  ALL                                              Cluster: outbound|9153||kube-dns.kube-system.svc.cluster.local
0.0.0.0       15001 ALL                                              PassthroughCluster
0.0.0.0       15006 Addr: 10.244.0.22/32:15021                       inbound|15021|mgmt-15021|mgmtCluster
0.0.0.0       15006 Addr: 10.244.0.22/32:9080                        Inline Route: /*
0.0.0.0       15006 Trans: tls; App: HTTP TLS; Addr: 0.0.0.0/0       Inline Route: /*
0.0.0.0       15006 App: HTTP; Addr: 0.0.0.0/0                       Inline Route: /*
0.0.0.0       15006 App: Istio HTTP Plain; Addr: 10.244.0.22/32:9080 Inline Route: /*
0.0.0.0       15006 Addr: 0.0.0.0/0                                  InboundPassthroughClusterIpv4
0.0.0.0       15006 Trans: tls; App: TCP TLS; Addr: 0.0.0.0/0        InboundPassthroughClusterIpv4
0.0.0.0       15010 App: HTTP                                        Route: 15010
0.0.0.0       15010 ALL                                              PassthroughCluster
10.100.93.102 15012 ALL                                              Cluster: outbound|15012||istiod.istio-system.svc.cluster.local
0.0.0.0       15014 App: HTTP                                        Route: 15014
0.0.0.0       15014 ALL                                              PassthroughCluster
0.0.0.0       15021 ALL                                              Inline Route: /healthz/ready*
10.111.121.13 15021 App: HTTP                                        Route: istio-ingressgateway.istio-system.svc.cluster.local:15021
10.111.121.13 15021 ALL                                              Cluster: outbound|15021||istio-ingressgateway.istio-system.svc.cluster.local
0.0.0.0       15090 ALL                                              Inline Route: /stats/prometheus*
10.111.121.13 15443 ALL                                              Cluster: outbound|15443||istio-ingressgateway.istio-system.svc.cluster.local

从上面的信息可以看到,每一个 Sidecar 有一个绑定到 0.0.0.0:15001 的监听器,来确定 IP 表将所有进出 Pod 的流量路由到哪里。监听器设置 useOriginalDst 为 true 意味着它将请求传递给最适合原始请求目的地的监听器。 如果找不到匹配的虚拟监听器,它会将请求发送到直接连接到目的地的 PassthroughCluster

istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs --port 15001 -o json
[
    {
        "name": "virtualOutbound",
        "address": {
            "socketAddress": {
                "address": "0.0.0.0",
                "portValue": 15001
            }
        },
        "filterChains": [
            {
                "filters": [
                    {
                        "name": "istio.stats",
                        "typedConfig": {
                            "@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
                            "typeUrl": "type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm",
                            "value": {
                                "config": {
                                    "configuration": "{\n  \"debug\": \"false\",\n  \"stat_prefix\": \"istio\"\n}\n",
                                    "root_id": "stats_outbound",
                                    "vm_config": {
                                        "code": {
                                            "local": {
                                                "inline_string": "envoy.wasm.stats"
                                            }
                                        },
                                        "runtime": "envoy.wasm.runtime.null",
                                        "vm_id": "tcp_stats_outbound"
                                    }
                                }
                            }
                        }
                    },
                    {
                        "name": "envoy.tcp_proxy",
                        "typedConfig": {
                            "@type": "type.googleapis.com/envoy.config.filter.network.tcp_proxy.v2.TcpProxy",
                            "statPrefix": "PassthroughCluster",
                            "cluster": "PassthroughCluster"
                        }
                    }
                ],
                "name": "virtualOutbound-catchall-tcp"
            }
        ],
        "trafficDirection": "OUTBOUND",
        "hiddenEnvoyDeprecatedUseOriginalDst": true
    }
]

我们的请求是到端口 9080 的出站 HTTP 请求,它将被传递给 0.0.0.0:9080 的虚拟监听器。这一监听器将检索在它配置的 RDS 里的路由配置。 在这个例子中它将寻找 Istiod(通过 ADS)配置在 RDS 中的路由 9080

istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs -o json --address 0.0.0.0 --port 9080
...
"rds": {
    "config_source": {
        "ads": {}
    },
    "route_config_name": "9080"
}
...

3.2.3 Routes 处理

对每个服务,9080 路由配置只有一个虚拟主机。我们的请求会走到 reviews 服务,因此 Envoy 将选择一个虚拟主机把请求匹配到一个域。一旦匹配到, Envoy 会寻找请求匹配到的第一个路由。本例中我们没有设置任何高级路由规则, 因此路由会匹配任何请求。这一路由告诉 Envoy 发送请求到 outbound|9080||reviews.default.svc.cluster.local 集群。

istioctl proxy-config routes productpage-v1-6c886ff494-7vxhs --name 9080 -o json
[
    {
        "name": "9080",
        "virtualHosts": [
            {
                "name": "reviews.default.svc.cluster.local:9080",
                "domains": [
                    "reviews.default.svc.cluster.local",
                    "reviews.default.svc.cluster.local:9080",
                    "reviews",
                    "reviews:9080",
                    "reviews.default.svc.cluster",
                    "reviews.default.svc.cluster:9080",
                    "reviews.default.svc",
                    "reviews.default.svc:9080",
                    "reviews.default",
                    "reviews.default:9080",
                    "10.98.88.0",
                    "10.98.88.0:9080"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|9080||reviews.default.svc.cluster.local",
                            "timeout": "0s",
                        }
                    }
                ]
...

3.2.4 Cluster处理

此集群配置为从 Istiod(通过 ADS)检索关联的 endpoints。 所以 Envoy 会使用 serviceName 字段作为主键,来检查 endpoint 列表并把请求代理到其中之一。

istioctl proxy-config cluster productpage-v1-6c886ff494-7vxhs --fqdn reviews.default.svc.cluster.local -o json
[
    {
        "name": "outbound|9080||reviews.default.svc.cluster.local",
        "type": "EDS",
        "edsClusterConfig": {
            "edsConfig": {
                "ads": {},
                "resourceApiVersion": "V3"
            },
            "serviceName": "outbound|9080||reviews.default.svc.cluster.local"
        },
        "connectTimeout": "10s",
        "circuitBreakers": {
            "thresholds": [
                {
                    "maxConnections": 4294967295,
                    "maxPendingRequests": 4294967295,
                    "maxRequests": 4294967295,
                    "maxRetries": 4294967295
                }
            ]
        },
    }
]

3.2.5 Endpoints处理

要查看此集群当前可用的 endpoint,请使用 proxy-config endpoints 命令。

istioctl proxy-config endpoints productpage-v1-6c886ff494-7vxhs --cluster "outbound|9080||reviews.default.svc.cluster.local"
ENDPOINT            STATUS      OUTLIER CHECK     CLUSTER
172.17.0.7:9080     HEALTHY     OK                outbound|9080||reviews.default.svc.cluster.local
172.17.0.8:9080     HEALTHY     OK                outbound|9080||reviews.default.svc.cluster.local
172.17.0.9:9080     HEALTHY     OK                outbound|9080||reviews.default.svc.cluster.local

 

  • 1
  • 1
  • 0
0 评论
0/1000
评论(0) 发表评论
网个大鱼

网个大鱼

12 篇文章 1 粉丝
关注

XDS协议浅析

2023-07-13 10:44:17 291阅读

一、背景

xDS(Extension and Discovery Service)是一个用于配置和动态发现服务的协议,用于管理和控制复杂的分布式系统。它是Kubernetes中Envoy代理的核心组件,用于实现服务的负载均衡、流量路由和故障恢复等功能。

  • 动态服务发现:在微服务架构中,服务的数量和实例经常发生变化。xDS协议提供了一种机制,可以动态地发现和注册服务实例,而无需手动配置或静态的硬编码地址。它使得服务发现能够适应服务拓扑的变化,从而实现弹性和可伸缩性。
  • 负载均衡和流量管理:xDS协议支持负载均衡和流量管理策略的动态配置。它允许服务网格控制平面根据实时的负载情况、服务间的依赖关系和其他策略来分配和管理流量。这使得在服务之间实现流量控制、故障转移、AB测试等变得更加灵活和可配置。
  • 配置管理和路由规则:xDS协议提供了一种机制,可以动态地配置和更新服务网格中的路由规则、策略和其他相关配置。通过使用xDS协议,服务网格中的路由规则可以根据需要进行更改,而无需重新部署或重启服务。这使得实施灰度发布、金丝雀发布和其他高级部署策略变得更加容易。
  • 多语言和多平台支持:xDS协议是一种通用的协议,可以在多种编程语言和平台上实现。这意味着您可以在不同的微服务框架和环境中使用xDS协议,实现统一的服务发现和配置管理体验。它提供了一种标准化的接口,使得不同的服务网格组件可以进行交互和协作。
  • 可扩展性:xDS协议设计为可扩展的,可以支持大规模的服务和高并发的流量。它使用了增量更新和缓存等技术,以减少配置传输和处理的开销,并提供了分布式的配置管理和服务发现能力。

xDS协议提供了动态的、灵活的服务发现和配置管理机制,适用于复杂的微服务环境。它能够提高服务网格的可伸缩性、可靠性和可配置性,使得在大规模微服务架构中管理和控制流量变得更加容易和高效。它在Kubernetes和Envoy等现代微服务架构中被广泛使用,用于实现服务网格、API网关和边缘路由等关键功能。

二、XDS结构

2.1 LDS

2.2 RDS

2.3 CDS

2.4 EDS

 

三、运行原理

3.1 框架

3.2 流程

我们以请求从 productpage Pod 发送到 reviews Pod 9080 端口为例,来研究Envoy代理是怎么处理流量的,会借助istioctl proxy-config的命令来具体分析。

3.2.1 Listerner处理

如果在一个 Pod 上查询监听器概要信息,将注意到 Istio 生成了下面的监听器:

    • 0.0.0.0:15001 监听器接收所有进出 Pod 的流量,然后转发请求给一个虚拟监听器。
    • 每个服务 IP 一个虚拟监听器,针对每一个非 HTTP 的外部 TCP/HTTPS 流量。
    • Pod IP 上的虚拟监听器,针对内部流量暴露的端口。
    • 0.0.0.0 监听器,针对外部 HTTP 流量的每个 HTTP 端口。
istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs
ADDRESS       PORT  MATCH                                            DESTINATION
10.96.0.10    53    ALL                                              Cluster: outbound|53||kube-dns.kube-system.svc.cluster.local
0.0.0.0       80    App: HTTP                                        Route: 80
0.0.0.0       80    ALL                                              PassthroughCluster
10.100.93.102 443   ALL                                              Cluster: outbound|443||istiod.istio-system.svc.cluster.local
10.111.121.13 443   ALL                                              Cluster: outbound|443||istio-ingressgateway.istio-system.svc.cluster.local
10.96.0.1     443   ALL                                              Cluster: outbound|443||kubernetes.default.svc.cluster.local
10.100.93.102 853   App: HTTP                                        Route: istiod.istio-system.svc.cluster.local:853
10.100.93.102 853   ALL                                              Cluster: outbound|853||istiod.istio-system.svc.cluster.local
0.0.0.0       9080  App: HTTP                                        Route: 9080
0.0.0.0       9080  ALL                                              PassthroughCluster
0.0.0.0       9090  App: HTTP                                        Route: 9090
0.0.0.0       9090  ALL                                              PassthroughCluster
10.96.0.10    9153  App: HTTP                                        Route: kube-dns.kube-system.svc.cluster.local:9153
10.96.0.10    9153  ALL                                              Cluster: outbound|9153||kube-dns.kube-system.svc.cluster.local
0.0.0.0       15001 ALL                                              PassthroughCluster
0.0.0.0       15006 Addr: 10.244.0.22/32:15021                       inbound|15021|mgmt-15021|mgmtCluster
0.0.0.0       15006 Addr: 10.244.0.22/32:9080                        Inline Route: /*
0.0.0.0       15006 Trans: tls; App: HTTP TLS; Addr: 0.0.0.0/0       Inline Route: /*
0.0.0.0       15006 App: HTTP; Addr: 0.0.0.0/0                       Inline Route: /*
0.0.0.0       15006 App: Istio HTTP Plain; Addr: 10.244.0.22/32:9080 Inline Route: /*
0.0.0.0       15006 Addr: 0.0.0.0/0                                  InboundPassthroughClusterIpv4
0.0.0.0       15006 Trans: tls; App: TCP TLS; Addr: 0.0.0.0/0        InboundPassthroughClusterIpv4
0.0.0.0       15010 App: HTTP                                        Route: 15010
0.0.0.0       15010 ALL                                              PassthroughCluster
10.100.93.102 15012 ALL                                              Cluster: outbound|15012||istiod.istio-system.svc.cluster.local
0.0.0.0       15014 App: HTTP                                        Route: 15014
0.0.0.0       15014 ALL                                              PassthroughCluster
0.0.0.0       15021 ALL                                              Inline Route: /healthz/ready*
10.111.121.13 15021 App: HTTP                                        Route: istio-ingressgateway.istio-system.svc.cluster.local:15021
10.111.121.13 15021 ALL                                              Cluster: outbound|15021||istio-ingressgateway.istio-system.svc.cluster.local
0.0.0.0       15090 ALL                                              Inline Route: /stats/prometheus*
10.111.121.13 15443 ALL                                              Cluster: outbound|15443||istio-ingressgateway.istio-system.svc.cluster.local

从上面的信息可以看到,每一个 Sidecar 有一个绑定到 0.0.0.0:15001 的监听器,来确定 IP 表将所有进出 Pod 的流量路由到哪里。监听器设置 useOriginalDst 为 true 意味着它将请求传递给最适合原始请求目的地的监听器。 如果找不到匹配的虚拟监听器,它会将请求发送到直接连接到目的地的 PassthroughCluster

istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs --port 15001 -o json
[
    {
        "name": "virtualOutbound",
        "address": {
            "socketAddress": {
                "address": "0.0.0.0",
                "portValue": 15001
            }
        },
        "filterChains": [
            {
                "filters": [
                    {
                        "name": "istio.stats",
                        "typedConfig": {
                            "@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
                            "typeUrl": "type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm",
                            "value": {
                                "config": {
                                    "configuration": "{\n  \"debug\": \"false\",\n  \"stat_prefix\": \"istio\"\n}\n",
                                    "root_id": "stats_outbound",
                                    "vm_config": {
                                        "code": {
                                            "local": {
                                                "inline_string": "envoy.wasm.stats"
                                            }
                                        },
                                        "runtime": "envoy.wasm.runtime.null",
                                        "vm_id": "tcp_stats_outbound"
                                    }
                                }
                            }
                        }
                    },
                    {
                        "name": "envoy.tcp_proxy",
                        "typedConfig": {
                            "@type": "type.googleapis.com/envoy.config.filter.network.tcp_proxy.v2.TcpProxy",
                            "statPrefix": "PassthroughCluster",
                            "cluster": "PassthroughCluster"
                        }
                    }
                ],
                "name": "virtualOutbound-catchall-tcp"
            }
        ],
        "trafficDirection": "OUTBOUND",
        "hiddenEnvoyDeprecatedUseOriginalDst": true
    }
]

我们的请求是到端口 9080 的出站 HTTP 请求,它将被传递给 0.0.0.0:9080 的虚拟监听器。这一监听器将检索在它配置的 RDS 里的路由配置。 在这个例子中它将寻找 Istiod(通过 ADS)配置在 RDS 中的路由 9080

istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs -o json --address 0.0.0.0 --port 9080
...
"rds": {
    "config_source": {
        "ads": {}
    },
    "route_config_name": "9080"
}
...

3.2.3 Routes 处理

对每个服务,9080 路由配置只有一个虚拟主机。我们的请求会走到 reviews 服务,因此 Envoy 将选择一个虚拟主机把请求匹配到一个域。一旦匹配到, Envoy 会寻找请求匹配到的第一个路由。本例中我们没有设置任何高级路由规则, 因此路由会匹配任何请求。这一路由告诉 Envoy 发送请求到 outbound|9080||reviews.default.svc.cluster.local 集群。

istioctl proxy-config routes productpage-v1-6c886ff494-7vxhs --name 9080 -o json
[
    {
        "name": "9080",
        "virtualHosts": [
            {
                "name": "reviews.default.svc.cluster.local:9080",
                "domains": [
                    "reviews.default.svc.cluster.local",
                    "reviews.default.svc.cluster.local:9080",
                    "reviews",
                    "reviews:9080",
                    "reviews.default.svc.cluster",
                    "reviews.default.svc.cluster:9080",
                    "reviews.default.svc",
                    "reviews.default.svc:9080",
                    "reviews.default",
                    "reviews.default:9080",
                    "10.98.88.0",
                    "10.98.88.0:9080"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|9080||reviews.default.svc.cluster.local",
                            "timeout": "0s",
                        }
                    }
                ]
...

3.2.4 Cluster处理

此集群配置为从 Istiod(通过 ADS)检索关联的 endpoints。 所以 Envoy 会使用 serviceName 字段作为主键,来检查 endpoint 列表并把请求代理到其中之一。

istioctl proxy-config cluster productpage-v1-6c886ff494-7vxhs --fqdn reviews.default.svc.cluster.local -o json
[
    {
        "name": "outbound|9080||reviews.default.svc.cluster.local",
        "type": "EDS",
        "edsClusterConfig": {
            "edsConfig": {
                "ads": {},
                "resourceApiVersion": "V3"
            },
            "serviceName": "outbound|9080||reviews.default.svc.cluster.local"
        },
        "connectTimeout": "10s",
        "circuitBreakers": {
            "thresholds": [
                {
                    "maxConnections": 4294967295,
                    "maxPendingRequests": 4294967295,
                    "maxRequests": 4294967295,
                    "maxRetries": 4294967295
                }
            ]
        },
    }
]

3.2.5 Endpoints处理

要查看此集群当前可用的 endpoint,请使用 proxy-config endpoints 命令。

istioctl proxy-config endpoints productpage-v1-6c886ff494-7vxhs --cluster "outbound|9080||reviews.default.svc.cluster.local"
ENDPOINT            STATUS      OUTLIER CHECK     CLUSTER
172.17.0.7:9080     HEALTHY     OK                outbound|9080||reviews.default.svc.cluster.local
172.17.0.8:9080     HEALTHY     OK                outbound|9080||reviews.default.svc.cluster.local
172.17.0.9:9080     HEALTHY     OK                outbound|9080||reviews.default.svc.cluster.local

 

文章来自专栏

微服务架构-服务网格

12 篇文章 1 订阅
0 评论
0/1000
评论(0) 发表评论
  • 1
    点赞
  • 1
    收藏
  • 0
    评论