调试 Envoy 和 Pilot

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

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

    或者

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

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

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

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

    检查 Envoy 和 Istio Pilot 的差异

    通过提供代理 ID,proxy-status 命令还可以用来检查 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

    从这儿可以看到,监听器和路由是匹配的,但集群不同步。

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

    1. $ istioctl proxy-config cluster -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 15014 - outbound EDS
    8. istio-egressgateway.istio-system.svc.cluster.local 80 - outbound EDS
    9. ...

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

    1. 如果您在一个 Pod 上查询监听器概要信息,您将注意到 Istio 生成了下面的监听器:
      • 0.0.0.0:15001 监听器接收所有进出 Pod 的流量,然后转发请求给一个虚拟监听器。
      • 每个服务 IP 一个虚拟监听器,针对每一个非 HTTP 的外部 TCP/HTTPS 流量。
      • Pod IP 上的虚拟监听器,针对内部流量暴露的端口。
      • 0.0.0.0 监听器,针对外部 HTTP 流量的每个 HTTP 端口。
    1. ADDRESS PORT TYPE
    2. 172.21.252.250 15011 TCP |
    3. 172.21.79.56 42422 TCP |
    4. 172.21.160.5 443 TCP |
    5. 172.21.157.6 443 TCP |
    6. 172.21.117.222 443 TCP |
    7. 172.21.0.10 53 TCP |
    8. 172.21.126.131 443 TCP | Receives outbound non-HTTP traffic for relevant IP:PORT pair from listener `0.0.0.0_15001`
    9. 172.21.160.5 31400 TCP |
    10. 172.21.81.159 9102 TCP |
    11. 172.21.0.1 443 TCP |
    12. 172.21.126.131 80 TCP |
    13. 172.21.119.8 443 TCP |
    14. 172.21.112.64 80 TCP |
    15. 172.21.179.54 443 TCP |
    16. 172.21.165.197 443 TCP <--+
    17. 0.0.0.0 9090 HTTP <-+
    18. 0.0.0.0 8060 HTTP |
    19. 0.0.0.0 15010 HTTP |
    20. 0.0.0.0 15003 HTTP |
    21. 0.0.0.0 15004 HTTP |
    22. 0.0.0.0 15014 HTTP | Receives outbound HTTP traffic for relevant port from listener `0.0.0.0_15001`
    23. 0.0.0.0 15007 HTTP |
    24. 0.0.0.0 8080 HTTP |
    25. 0.0.0.0 9091 HTTP |
    26. 0.0.0.0 9080 HTTP |
    27. 0.0.0.0 80 HTTP <-+
    28. 0.0.0.0 15001 TCP // Receives all inbound and outbound traffic to the pod from IP tables and hands over to virtual listener
    29. 172.30.164.190 9080 HTTP // Receives all inbound traffic on 9080 from listener `0.0.0.0_15001`
    1. 从上面的信息可以看到,每一个 sidecar 有一个绑定到 0.0.0.0:15001 的监听器,来确定 IP 表将所有进出 Pod 的流量路由到哪里。监听器设置 useOriginalDst 为 true 意味着它将请求传递给最适合原始请求目的地的监听器。如果找不到匹配的虚拟监听器,它会将请求发送到直接连接到目的地的 PassthroughCluster

      1. $ istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs --port 15001 -o json
      2. [
      3. {
      4. "name": "virtual",
      5. "address": {
      6. "socketAddress": {
      7. "address": "0.0.0.0",
      8. "portValue": 15001
      9. }
      10. },
      11. "filterChains": [
      12. {
      13. "filters": [
      14. {
      15. "name": "envoy.tcp_proxy",
      16. "config": {
      17. "cluster": "PassthroughCluster",
      18. "stat_prefix": "PassthroughCluster"
      19. }
      20. }
      21. ]
      22. }
      23. ],
      24. "useOriginalDst": true
      25. }
      26. ]
    2. 对每个服务,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:9080",
      10. "reviews:9080",
      11. "reviews.default.svc.cluster",
      12. "reviews.default.svc.cluster:9080",
      13. "reviews.default.svc",
      14. "reviews.default.svc:9080",
      15. "reviews.default",
      16. "reviews.default:9080",
      17. "172.21.152.34",
      18. "172.21.152.34:9080"
      19. ],
      20. "routes": [
      21. {
      22. "match": {
      23. "prefix": "/"
      24. },
      25. "route": {
      26. "cluster": "outbound|9080||reviews.default.svc.cluster.local",
      27. "timeout": "0.000s"
      28. },
      29. ...
    3. 此集群配置为从 Pilot(通过 ADS)检索关联的 endpoints。所以 Envoy 会使用 serviceName 字段作为主键,来检查 endpoint 列表并把请求代理到其中之一。

      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. },
      10. "serviceName": "outbound|9080||reviews.default.svc.cluster.local"
      11. },
      12. "connectTimeout": "1.000s",
      13. "circuitBreakers": {
      14. "thresholds": [
      15. {}
      16. ]
      17. }
      18. }
      19. ]
    4. 要查看此集群当前可用的 endpoint,请使用 proxy-config endpoints 命令。

      1. $ istioctl proxy-config endpoints productpage-v1-6c886ff494-7vxhs --cluster "outbound|9080||reviews.default.svc.cluster.local"
      2. ENDPOINT STATUS OUTLIER CHECK CLUSTER
      3. 172.17.0.17:9080 HEALTHY OK outbound|9080||reviews.default.svc.cluster.local
      4. 172.17.0.18:9080 HEALTHY OK outbound|9080||reviews.default.svc.cluster.local
      5. 172.17.0.5:9080 HEALTHY OK outbound|9080||reviews.default.svc.cluster.local

    检查 bootstrap 配置

    到目前为止,我们已经查看了从 Pilot 检索到的配置(大部分),然而 Envoy 需要一些 bootstrap 配置,其中包括诸如在何处可以找到 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. ...

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

    1. 获取 Istio Ingress pod 的名称:

    2. 通过 exec 进入 Istio Ingress pod:

      1. $ kubectl exec -it $INGRESS_POD_NAME -n istio-system /bin/bash
    3. 使用 curl 测试与 Pilot 的连通性。下面的示例使用了默认的 Pilot 配置参数和开启双向 TLS 来调用 v1 注册 API:

      1. $ curl -k --cert /etc/certs/cert-chain.pem --cacert /etc/certs/root-cert.pem --key /etc/certs/key.pem https://istio-pilot:8080/debug/edsz

      如果双向 TLS 是关闭的:

      1. $ curl http://istio-pilot:8080/debug/edsz

    Istio 使用的 Envoy 版本是什么?

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

    1. $ kubectl exec -it PODNAME -c istio-proxy -n NAMESPACE pilot-agent request GET server_info
    2. {
    3. "version": "48bc83d8f0582fc060ef76d5aa3d75400e739d9e/1.12.0-dev/Clean/RELEASE/BoringSSL"

    Istio 的另一个 Sidecar 代理。

    Mixer 配置模型

    描述 Istio 策略执行和遥测机制的配置模型。

    描述 Istio 提供的遥测和监控特性。

    安装 Istio CNI 插件

    安装并使用 Istio CNI 插件,可以让运维人员用更低的权限来部署服务。

    描述 Istio 多样的流量路由和控制特性。