配置问题诊断

Istio 提供了两个非常有价值的命令,用于协助对流量管理方面的配置问题进行诊断:proxy-statusproxy-config

proxy-status 命令可以获取网格的概要信息,可以用来确定代理服务器导致的问题;而 proxy-config 命令则可以用来观察 Envoy 的配置并对问题进行诊断。

要试用下面的命令,首先要满足下列两个条件中的一个:

  • 一个部署了 Istio 和 Bookinfo 的 Kubernetes 集群(例如使用安装步骤中所写的 istio.yaml 完成 Istio 的安装,并完成 Bookinfo 应用部署)。或者

  • Kubernetes 环境下的 Istio 网格上运行自己的应用。

获取网格的概要情况

proxy-status 命令能够用来获取网格的概要情况。如果怀疑某个 Sidecar 无法获取配置,或者同步失败,就可以用这个命令来进行验证。

  1. $ istioctl proxy-status
  2. PROXY CDS LDS EDS RDS PILOT
  3. details-v1-6dcc6fbb9d-wsjz4.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-75bdf98789-tfdvh
  4. istio-egressgateway-c49694485-l9d5l.istio-system SYNCED SYNCED SYNCED (100%) NOT SENT istio-pilot-75bdf98789-tfdvh
  5. istio-ingress-6458b8c98f-7ks48.istio-system SYNCED SYNCED SYNCED (100%) NOT SENT istio-pilot-75bdf98789-n2kqh
  6. istio-ingressgateway-7d6874b48f-qxhn5.istio-system SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-75bdf98789-n2kqh
  7. productpage-v1-6c886ff494-hm7zk.default SYNCED SYNCED SYNCED (100%) STALE istio-pilot-75bdf98789-n2kqh
  8. ratings-v1-5d9ff497bb-gslng.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-75bdf98789-n2kqh
  9. reviews-v1-55d4c455db-zjj2m.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-75bdf98789-n2kqh
  10. reviews-v2-686bbb668-99j76.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-75bdf98789-tfdvh
  11. reviews-v3-7b9b5fdfd6-4r52s.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-75bdf98789-n2kqh

如果一个代理没有出现在这个列表上,就说明该代理目前没有连接到 Pilot 实例上,不会接到任何配置。

  • SYNCED:Envoy 已经接收到了 Pilot 发送的最新配置。
  • SYNCED (100%):Envoy 成功的同步了集群内的所有端点。
  • NOT SENT:Pilot 尚未向 Envoy 发送任何数据,这通常是因为 Pilot 没有需要发送的内容。
  • STALE:Pilot 已经向 Envoy 发出了更新,但是还没有收到响应。这很可能意味着 Envoy 和 Pilot 之间的网络存在故障,或者是 Istio 自身的 Bug。

获取 Envoy 和 Istio Pilot 之间的配置差异

proxy-status 命令还可以通过一个 Proxy ID 作为输入,来获取 Envoy 已经载入的配置和 Pilot 将要发送的配置之间的差异,这有助于识别同步失败的问题,并且对原因分析也有帮助。

  1. $ istioctl proxy-status details-v1-6dcc6fbb9d-wsjz4.default
  2. --- Pilot 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

这些内容中不难发现,监听器和路由都是匹配的,但是集群定义未能同步。

深入了解 Envoy 配置

proxy-config 命令能够用来查看某个 Envoy 实例的配置。通过对 Istio 配置和自定义资源的查看不能确诊问题时,这个命令会大有帮助。要获取网格中一个 Pod 的集群、监听器和路由的概要信息,只要使用如下命令(可以根据需要把 clusters 替换为 listeners 或者 routes):

  1. $ istioctl proxy-config clusters -n istio-system istio-ingressgateway-7d6874b48f-qxhn5
  2. SERVICE FQDN PORT SUBSET DIRECTION TYPE
  3. BlackHoleCluster - - - STATIC
  4. details.default.svc.cluster.local 9080 - outbound EDS
  5. heapster.kube-system.svc.cluster.local 80 - outbound EDS
  6. istio-citadel.istio-system.svc.cluster.local 8060 - outbound EDS
  7. istio-citadel.istio-system.svc.cluster.local 10514 - outbound EDS
  8. istio-egressgateway.istio-system.svc.cluster.local 80 - outbound EDS
  9. ...

要对 Envoy 进行除错,首先要了解一下 Envoy 的集群、监听器、路由、端点的概念,以及这些对象之间的交互过程。我们会使用 proxy-config 命令的 -o json 参数,并对结果进行过滤,来追踪 Envoy 对请求(从 productpage Pod 发向 reviews Pod 上的 reviews:9080)的决策过程:

  • 如果查询一个 Pod 的监听器概要信息,会看到 Istio 生成了如下的监听器:

    • 0.0.0.0:15001 的监听器会接收所有出入 Pod 的流量,然后将请求转交给一个虚拟监听器。
    • 服务 IP 的虚拟监听器,用于 TCP/HTTPS 的非 HTTP 出站流量。
    • Pod IP 的虚拟监听器,用于暴露入站流量的端口。
    • 0.0.0.0 的虚拟监听器用于出站的 HTTP 流量。
  1. $ istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs
  2. ADDRESS PORT TYPE
  3. 172.21.252.250 15005 TCP <--+
  4. 172.21.252.250 15011 TCP |
  5. 172.21.79.56 42422 TCP |
  6. 172.21.160.5 443 TCP |
  7. 172.21.157.6 443 TCP |
  8. 172.21.117.222 443 TCP |
  9. 172.21.0.10 53 TCP |
  10. 172.21.126.131 443 TCP | Receives outbound non-HTTP traffic for relevant IP:PORT pair from listener `0.0.0.0_15001`
  11. 172.21.160.5 31400 TCP |
  12. 172.21.81.159 9102 TCP |
  13. 172.21.0.1 443 TCP |
  14. 172.21.126.131 80 TCP |
  15. 172.21.119.8 443 TCP |
  16. 172.21.112.64 80 TCP |
  17. 172.21.179.54 443 TCP |
  18. 172.21.165.197 443 TCP <--+
  19. 0.0.0.0 9090 HTTP <-+
  20. 0.0.0.0 8060 HTTP |
  21. 0.0.0.0 15010 HTTP |
  22. 0.0.0.0 15003 HTTP |
  23. 0.0.0.0 15004 HTTP |
  24. 0.0.0.0 10514 HTTP | Receives outbound HTTP traffic for relevant port from listener `0.0.0.0_15001`
  25. 0.0.0.0 15007 HTTP |
  26. 0.0.0.0 8080 HTTP |
  27. 0.0.0.0 9091 HTTP |
  28. 0.0.0.0 9080 HTTP |
  29. 0.0.0.0 80 HTTP <-+
  30. 0.0.0.0 15001 TCP // Receives all inbound and outbound traffic to the pod from IP tables and hands over to virtual listener
  31. 172.30.164.190 9080 HTTP // Receives all inbound traffic on 9080 from listener `0.0.0.0_15001`
  • 由上边的概要信息可以看出,每个 Sidecar 都有一个绑定到 0.0.0.0:15001 的监听器,IP tables 会路由 Pod 中所有的入站和出站流量到这一地址。这个监听器的 useOriginalDst 设置为 True,表明他会根据原始目的地来选择监听器,并将流量转发给最合适的监听器。如果找不到匹配的虚拟监听器,就会把请求发送给 BlackHoleCluster,它会返回一个 404。
  1. $ istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs --port 15001 -o json
  2. {
  3. "name": "virtual",
  4. "address": {
  5. "socketAddress": {
  6. "address": "0.0.0.0",
  7. "portValue": 15001
  8. }
  9. },
  10. "filterChains": [
  11. {
  12. "filters": [
  13. {
  14. "name": "envoy.tcp_proxy",
  15. "config": {
  16. "cluster": "BlackHoleCluster",
  17. "stat_prefix": "BlackHoleCluster"
  18. }
  19. }
  20. ]
  21. }
  22. ],
  23. "useOriginalDst": true
  24. }
  • 我们的请求是一个出站的 HTTP 请求,目标是 9080,因此这个请求应该提交给 0.0.0.0:9080 虚拟监听器。这个监听器会在它的 RDS 中查找路由配置,这个例子中,就是在 Pilot(通过 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. ...
  • 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. "172.21.152.34",
  20. "172.21.152.34:9080"
  21. ],
  22. "routes": [
  23. {
  24. "match": {
  25. "prefix": "/"
  26. },
  27. "route": {
  28. "cluster": "outbound|9080||reviews.default.svc.cluster.local",
  29. "timeout": "0.000s"
  30. },
  31. ...
  • 这个集群被配置从 Pilot(通过 ADS)获取端点列表。所以 Envoy 会使用 serviceName 字段作为关键字在端点列表中进行查找,然后将请求转发给查出来的端点中的一个。
  1. $ istioctl proxy-config clusters 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. },
  10. "serviceName": "outbound|9080||reviews.default.svc.cluster.local"
  11. },
  12. "connectTimeout": "1.000s",
  13. "circuitBreakers": {
  14. "thresholds": [
  15. {}
  16. ]
  17. }
  18. }
  19. ]
  • 可以使用 proxy-config endpoints 命令来查看当前集群的可用端点。
  1. $ istioctl proxy-config endpoints productpage-v1-6c886ff494-7vxhs --cluster outbound|9080||reviews.default.svc.cluster.local
  2. ENDPOINT STATUS CLUSTER
  3. 172.17.0.17:9080 HEALTHY outbound|9080||reviews.default.svc.cluster.local
  4. 172.17.0.18:9080 HEALTHY outbound|9080||reviews.default.svc.cluster.local
  5. 172.17.0.5:9080 HEALTHY outbound|9080||reviews.default.svc.cluster.local

观察启动配置

我们已经了解了不少关于(绝大多数)来自于 Pilot 的配置方面的内容,Envoy 自身还有一些启动配置,例如在哪里查找 Pilot。用下面的命令可以查看这些信息:

  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. "POD_NAME": "istio-ingressgateway-7d6874b48f-qxhn5",
  9. "istio": "sidecar"
  10. },
  11. "buildVersion": "0/1.8.0-dev//RELEASE"
  12. },
  13. ...

相关内容

调试 Envoy 和 Pilot

描述如何调试 Pilot 和 Envoy。

安装 Istio CNI

Istio CNI 插件的安装和使用,该插件让运维人员可以用较低的权限来完成网格服务的部署工作。

策略与遥测

描述策略实施和遥测机制。

调试授权

展示授权功能的调试过程。