调试 Envoy 和 Istiod

    如果您想尝试以下的命令,需要:

    • 有一个安装了 Istio 和 Bookinfo 应用的 Kubernetes 集群(正如在 安装步骤和 所描述的那样)。

    或者

    • 使用类似的命令在 Kubernetes 集群中运行您自己的应用。

    proxy-status 命令容许您获取网格的概况。如果您怀疑某一个 sidecar 没有接收到配置或配置不同步时,proxy-status 将告诉您原因。

    如果列表中缺少代理,这意味着它目前没有连接到 Istiod 实例,因此不会接收任何配置。

    • SYNCED 意思是 Envoy 知晓了 Istiod 已经将最新的配置发送给了它。
    • NOT SENT 意思是 Istiod 没有发送任何信息给 Envoy。这通常是因为 Istiod 没什么可发送的。
    • STALE 意思是 Istiod 已经发送了一个更新到 Envoy,但还没有收到应答。这通常意味着 Envoy 和 Istiod 之间存在网络问题,或者 Istio 自身的 bug。

    检查 Envoy 和 Istiod 的差异

    通过提供代理 ID,proxy-status 命令还可以用来检查 Envoy 已加载的配置和 Istiod 发送给它的配置有什么异同,这可以帮您准确定位哪些配置是不同步的,以及问题出在哪里。

    1. $ istioctl proxy-status details-v1-6dcc6fbb9d-wsjz4.default
    2. --- Istiod Clusters
    3. +++ Envoy Clusters
    4. @@ -374,36 +374,14 @@
    5. "edsClusterConfig": {
    6. "edsConfig": {
    7. "ads": {
    8. }
    9. },
    10. "serviceName": "outbound|443||public-cr0bdc785ce3f14722918080a97e1f26be-alb1.kube-system.svc.cluster.local"
    11. - },
    12. - "connectTimeout": "1.000s",
    13. - "circuitBreakers": {
    14. - "thresholds": [
    15. - {
    16. -
    17. - }
    18. - ]
    19. - }
    20. - }
    21. - },
    22. - {
    23. - "cluster": {
    24. - "name": "outbound|53||kube-dns.kube-system.svc.cluster.local",
    25. - "type": "EDS",
    26. - "edsClusterConfig": {
    27. - "edsConfig": {
    28. - "ads": {
    29. -
    30. - }
    31. - },
    32. - "serviceName": "outbound|53||kube-dns.kube-system.svc.cluster.local"
    33. },
    34. "connectTimeout": "1.000s",
    35. "circuitBreakers": {
    36. "thresholds": [
    37. {
    38. }
    39. Listeners Match
    40. Routes Match (RDS last loaded at Tue, 04 Aug 2020 11:52:54 IST)

    proxy-config 命令可以用来查看给定的 Envoy 是如何配置的。这样就可以通过 Istio 配置和自定义资源来查明任何您无法检测到的问题。下面的命令为给定 Pod 提供了集群、监听器或路由的基本概要(当需要时可以为监听器或路由改变集群):

    1. $ istioctl proxy-config cluster -n istio-system istio-ingressgateway-7d6874b48f-qxhn5
    2. SERVICE FQDN PORT SUBSET DIRECTION TYPE DESTINATION RULE
    3. BlackHoleCluster - - - STATIC
    4. agent - - - STATIC
    5. details.default.svc.cluster.local 9080 - outbound EDS details.default
    6. istio-ingressgateway.istio-system.svc.cluster.local 80 - outbound EDS
    7. istio-ingressgateway.istio-system.svc.cluster.local 443 - outbound EDS
    8. istio-ingressgateway.istio-system.svc.cluster.local 15021 - outbound EDS
    9. istio-ingressgateway.istio-system.svc.cluster.local 15443 - outbound EDS
    10. istiod.istio-system.svc.cluster.local 443 - outbound EDS
    11. istiod.istio-system.svc.cluster.local 853 - outbound EDS
    12. istiod.istio-system.svc.cluster.local 15010 - outbound EDS
    13. istiod.istio-system.svc.cluster.local 15012 - outbound EDS
    14. istiod.istio-system.svc.cluster.local 15014 - outbound EDS
    15. kube-dns.kube-system.svc.cluster.local 53 - outbound EDS
    16. kube-dns.kube-system.svc.cluster.local 9153 - outbound EDS
    17. kubernetes.default.svc.cluster.local 443 - outbound EDS
    18. ...
    19. productpage.default.svc.cluster.local 9080 - outbound EDS
    20. prometheus_stats - - - STATIC
    21. ratings.default.svc.cluster.local 9080 - outbound EDS
    22. reviews.default.svc.cluster.local 9080 - outbound EDS
    23. sds-grpc - - - STATIC
    24. xds-grpc - - - STRICT_DNS
    25. zipkin - - - STRICT_DNS

    为了调试 Envoy 您需要理解 Envoy 集群、监听器、路由、endpoints 以及它们是如何交互的。我们将使用带有 -o json 参数的 proxy-config 命令,根据标志过滤出并跟随特定的 Envoy,它将请求从 productpage pod 发送到 reviews pod 9080 端口。

    1. $ istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs
    2. ADDRESS PORT MATCH DESTINATION
    3. 10.96.0.10 53 ALL Cluster: outbound|53||kube-dns.kube-system.svc.cluster.local
    4. 0.0.0.0 80 App: HTTP Route: 80
    5. 0.0.0.0 80 ALL PassthroughCluster
    6. 10.100.93.102 443 ALL Cluster: outbound|443||istiod.istio-system.svc.cluster.local
    7. 10.111.121.13 443 ALL Cluster: outbound|443||istio-ingressgateway.istio-system.svc.cluster.local
    8. 10.96.0.1 443 ALL Cluster: outbound|443||kubernetes.default.svc.cluster.local
    9. 10.100.93.102 853 App: HTTP Route: istiod.istio-system.svc.cluster.local:853
    10. 10.100.93.102 853 ALL Cluster: outbound|853||istiod.istio-system.svc.cluster.local
    11. 0.0.0.0 9080 App: HTTP Route: 9080
    12. 0.0.0.0 9080 ALL PassthroughCluster
    13. 0.0.0.0 9090 App: HTTP Route: 9090
    14. 0.0.0.0 9090 ALL PassthroughCluster
    15. 10.96.0.10 9153 App: HTTP Route: kube-dns.kube-system.svc.cluster.local:9153
    16. 10.96.0.10 9153 ALL Cluster: outbound|9153||kube-dns.kube-system.svc.cluster.local
    17. 0.0.0.0 15001 ALL PassthroughCluster
    18. 0.0.0.0 15006 Addr: 10.244.0.22/32:15021 inbound|15021|mgmt-15021|mgmtCluster
    19. 0.0.0.0 15006 Addr: 10.244.0.22/32:9080 Inline Route: /*
    20. 0.0.0.0 15006 Trans: tls; App: HTTP TLS; Addr: 0.0.0.0/0 Inline Route: /*
    21. 0.0.0.0 15006 App: HTTP; Addr: 0.0.0.0/0 Inline Route: /*
    22. 0.0.0.0 15006 App: Istio HTTP Plain; Addr: 10.244.0.22/32:9080 Inline Route: /*
    23. 0.0.0.0 15006 Addr: 0.0.0.0/0 InboundPassthroughClusterIpv4
    24. 0.0.0.0 15006 Trans: tls; App: TCP TLS; Addr: 0.0.0.0/0 InboundPassthroughClusterIpv4
    25. 0.0.0.0 15010 App: HTTP Route: 15010
    26. 0.0.0.0 15010 ALL PassthroughCluster
    27. 10.100.93.102 15012 ALL Cluster: outbound|15012||istiod.istio-system.svc.cluster.local
    28. 0.0.0.0 15014 App: HTTP Route: 15014
    29. 0.0.0.0 15014 ALL PassthroughCluster
    30. 0.0.0.0 15021 ALL Inline Route: /healthz/ready*
    31. 10.111.121.13 15021 App: HTTP Route: istio-ingressgateway.istio-system.svc.cluster.local:15021
    32. 10.111.121.13 15021 ALL Cluster: outbound|15021||istio-ingressgateway.istio-system.svc.cluster.local
    33. 0.0.0.0 15090 ALL Inline Route: /stats/prometheus*
    34. 10.111.121.13 15443 ALL Cluster: outbound|15443||istio-ingressgateway.istio-system.svc.cluster.local
    1. 从上面的信息可以看到,每一个 sidecar 有一个绑定到 0.0.0.0:15001 的监听器,来确定 IP 表将所有进出 Pod 的流量路由到哪里。监听器设置 useOriginalDst 为 true 意味着它将请求传递给最适合原始请求目的地的监听器。如果找不到匹配的虚拟监听器,它会将请求发送到直接连接到目的地的 PassthroughCluster

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

      1. $ istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs -o json --address 0.0.0.0 --port 9080
      2. ...
      3. "rds": {
      4. "config_source": {
      5. "ads": {}
      6. },
      7. "route_config_name": "9080"
      8. }
      9. ...
    3. 对每个服务,9080 路由配置只有一个虚拟主机。我们的请求会走到 reviews 服务,因此 Envoy 将选择一个虚拟主机把请求匹配到一个域。一旦匹配到,Envoy 会寻找请求匹配到的第一个路由。本例中我们没有设置任何高级路由规则,因此路由会匹配任何请求。这一路由告诉 Envoy 发送请求到 outbound|9080||reviews.default.svc.cluster.local 集群。

      1. $ istioctl proxy-config routes productpage-v1-6c886ff494-7vxhs --name 9080 -o json
      2. [
      3. {
      4. "name": "9080",
      5. "virtualHosts": [
      6. {
      7. "name": "reviews.default.svc.cluster.local:9080",
      8. "domains": [
      9. "reviews.default.svc.cluster.local",
      10. "reviews.default.svc.cluster.local:9080",
      11. "reviews",
      12. "reviews:9080",
      13. "reviews.default.svc.cluster",
      14. "reviews.default.svc.cluster:9080",
      15. "reviews.default.svc",
      16. "reviews.default.svc:9080",
      17. "reviews.default",
      18. "reviews.default:9080",
      19. "10.98.88.0",
      20. "10.98.88.0:9080"
      21. ],
      22. "routes": [
      23. {
      24. "name": "default",
      25. "match": {
      26. "prefix": "/"
      27. },
      28. "route": {
      29. "cluster": "outbound|9080||reviews.default.svc.cluster.local",
      30. }
      31. ]
      32. ...
      1. $ istioctl proxy-config cluster productpage-v1-6c886ff494-7vxhs --fqdn reviews.default.svc.cluster.local -o json
      2. [
      3. {
      4. "name": "outbound|9080||reviews.default.svc.cluster.local",
      5. "type": "EDS",
      6. "edsClusterConfig": {
      7. "edsConfig": {
      8. "ads": {},
      9. "resourceApiVersion": "V3"
      10. },
      11. "serviceName": "outbound|9080||reviews.default.svc.cluster.local"
      12. },
      13. "connectTimeout": "10s",
      14. "circuitBreakers": {
      15. "thresholds": [
      16. {
      17. "maxConnections": 4294967295,
      18. "maxPendingRequests": 4294967295,
      19. "maxRequests": 4294967295,
      20. "maxRetries": 4294967295
      21. }
      22. ]
      23. },
      24. }
      25. ]
    4. 要查看此集群当前可用的 endpoint,请使用 proxy-config endpoints 命令。

    检查 bootstrap 配置

    到目前为止,我们已经查看了从 Istiod 检索到的配置(大部分),然而 Envoy 需要一些 bootstrap 配置,其中包括诸如在何处可以找到 Istiod 之类的信息。使用下面的命令查看:

    1. $ istioctl proxy-config bootstrap -n istio-system istio-ingressgateway-7d6874b48f-qxhn5
    2. {
    3. "bootstrap": {
    4. "node": {
    5. "id": "router~172.30.86.14~istio-ingressgateway-7d6874b48f-qxhn5.istio-system~istio-system.svc.cluster.local",
    6. "cluster": "istio-ingressgateway",
    7. "metadata": {
    8. "CLUSTER_ID": "Kubernetes",
    9. "EXCHANGE_KEYS": "NAME,NAMESPACE,INSTANCE_IPS,LABELS,OWNER,PLATFORM_METADATA,WORKLOAD_NAME,MESH_ID,SERVICE_ACCOUNT,CLUSTER_ID",
    10. "INSTANCE_IPS": "10.244.0.7",
    11. "ISTIO_PROXY_SHA": "istio-proxy:f98b7e538920abc408fbc91c22a3b32bc854d9dc",
    12. "ISTIO_VERSION": "1.7.0",
    13. "LABELS": {
    14. "app": "istio-ingressgateway",
    15. "chart": "gateways",
    16. "heritage": "Tiller",
    17. "istio": "ingressgateway",
    18. "pod-template-hash": "68bf7d7f94",
    19. "release": "istio",
    20. "service.istio.io/canonical-name": "istio-ingressgateway",
    21. "service.istio.io/canonical-revision": "latest"
    22. },
    23. "MESH_ID": "cluster.local",
    24. "NAME": "istio-ingressgateway-68bf7d7f94-sp226",
    25. "NAMESPACE": "istio-system",
    26. "OWNER": "kubernetes://apis/apps/v1/namespaces/istio-system/deployments/istio-ingressgateway",
    27. "ROUTER_MODE": "sni-dnat",
    28. "SDS": "true",
    29. "SERVICE_ACCOUNT": "istio-ingressgateway-service-account",
    30. "WORKLOAD_NAME": "istio-ingressgateway"
    31. },
    32. "userAgentBuildVersion": {
    33. "version": {
    34. "majorNumber": 1,
    35. "minorNumber": 15
    36. },
    37. "metadata": {
    38. "build.type": "RELEASE",
    39. "revision.sha": "f98b7e538920abc408fbc91c22a3b32bc854d9dc",
    40. "revision.status": "Clean",
    41. "ssl.version": "BoringSSL"
    42. }
    43. },
    44. },
    45. ...

    验证与 Istiod 的连通性是一个有用的故障排除步骤。服务网格内的每个代理容器都应该能和 Istiod 通信。这可以通过几个简单的步骤来实现:

    1. 创建一个 sleep pod:

      1. $ kubectl create namespace foo
      2. $ kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo

    Istio 使用的 Envoy 版本是什么?

    要在部署中找出 Envoy 的版本,您可以通过 exec 进入容器并查询 终端: