Istio的運維-診斷工具(istio 系列五)

Istio的運維-診斷工具

在參考官方文檔的時候發現環境偶爾會出現問題,因此插入一章與調試有關的內容,便於簡單問題的定位。涵蓋官方文檔的診斷工具章節

目錄

  • Istio的運維-診斷工具
    • 使用istioctl命令行工具
      • istioctl自動補全
      • 查看網格的狀態
      • 獲取代理配置
    • 調試Envoy和istiod
      • 獲取網格概況
      • 檢索Envoy和istiod的差異
      • 深入探究Envoy配置
      • 檢查bootstrap配置
      • 校驗到istiod的連通性
    • 通過istioctl的輸出理解網格
      • 校驗pod是否在網格中
      • 校驗destination rule配置
      • 校驗virtual service配置
      • 校驗流量路由
      • 檢查strict mutual TLS(官方文檔待更新)
      • 卸載
    • 使用istioctl analyse診斷配置
      • 分析現有的集群/本地文件或二者
    • 組件內省
    • 組件日誌
      • 日誌作用域
      • 控制輸出
      • 日誌滾動
      • 組件調試

使用istioctl命令行工具

首先可以通過日誌或Introspection檢查各個組件,如果不足以支持問題定位,可以參考如下操作:

istioctl是一個可以用於調試和診斷istio服務網格的工具。Istio項目為Bash和ZSH運行下的istioctl提供了自動補全功能。

建議安裝對應istio版本的istioctl

istioctl自動補全

  • 將如下內容添加到 ~/.bash_profile 文件中

    [[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]] && . "/usr/local/etc/profile.d/bash_completion.sh"
    
  • 使用bash時,將在tools命令中的istioctl.bash文件拷貝到$HOME目錄下,然後執行如下操作即可

    $ source ~/istioctl.bash
    

查看網格的狀態

可以使用istioctl proxy-statusistioctl ps命令查看網格的狀態。如果輸出結果中缺少某個代理,說明該代理當前沒有連接到Pilot實例,因而無法接收到任何配置。如果狀態為stale,表示當前存在網絡故障,或Pilot需要擴容。

獲取代理配置

可以使用istioctl proxy-configistioctl pc檢索代理配置信息。

例如,使用如下方式可以檢索特定pod中的Envoy實例的集群配置信息。

$ istioctl proxy-config cluster <pod-name> [flags]

使用如下方式可以檢索特定pod中的Envoy實例的bootstrap配置信息。

$ istioctl proxy-config bootstrap <pod-name> [flags]

使用如下方式可以檢索特定pod中的Envoy實例的listener(監聽器)配置信息。

$ istioctl proxy-config listener <pod-name> [flags]

使用如下方式可以檢索特定pod中的Envoy實例的route(路由)配置信息。

$ istioctl proxy-config route <pod-name> [flags]

使用如下方式可以檢索特定pod中的Envoy實例的endpoint (後端)配置信息。

$ istioctl proxy-config endpoints <pod-name> [flags]

更多參見下一節調試Envoy和istiod

調試Envoy和istiod

istio提供了兩個非常有用的命令來診斷流量管理配置問題:proxy-status 和proxy-config。proxy-status可以獲取網格的概述並確定導致問題的代理。proxy-config可以檢查Envoy配置並診斷該問題。

如果要嘗試如下命令,可以:

  • 安裝Bookinfo
  • 使用kubernetes集群中部署類似應用

獲取網格概況

通過proxy-status命令可以查看網格的概況,了解是否有sidecar無法接收配置或無法保持同步。

如果某個代理沒有出現在輸出列表中,則說明該代理沒有連接到istiod實例,因此也無法接收任何配置信息。狀態信息如下:

  • SYNCED:表示Envoy確認了istiod發過來的配置
  • NOT SENT:表示istiod還沒有發送配置到Envoy。通常時因為istiod當前沒有需要發送的配置信息
  • STALE:表示istiod發送了一個更新到Envoy,但沒有接收到確認。通常表示Envoy和istiod之間的網絡出現了問題,或istio本身出現了bug。
$ istioctl ps                                                                               
NAME                                                  CDS      LDS       EDS       RDS        PILOT                     VERSION
details-v1-78d78fbddf-psnmk.default                   SYNCED   SYNCED    SYNCED    SYNCED     istiod-788cf6c878-4pq5g   1.6.0
istio-ingressgateway-569669bb67-dsd5h.istio-system    SYNCED   SYNCED    SYNCED    NOT SENT   istiod-788cf6c878-4pq5g   1.6.0
productpage-v1-85b9bf9cd7-d8hm8.default               SYNCED   SYNCED    SYNCED    SYNCED     istiod-788cf6c878-4pq5g   1.6.0
prometheus-79878ff5fd-tjdxx.istio-system              SYNCED   SYNCED    SYNCED    SYNCED     istiod-788cf6c878-4pq5g   1.6.0
ratings-v1-6c9dbf6b45-xlf2q.default                   SYNCED   SYNCED    SYNCED    SYNCED     istiod-788cf6c878-4pq5g   1.6.0
reviews-v1-564b97f875-q5l9r.default                   SYNCED   SYNCED    SYNCED    SYNCED     istiod-788cf6c878-4pq5g   1.6.0
reviews-v2-568c7c9d8f-vcd94.default                   SYNCED   SYNCED    SYNCED    SYNCED     istiod-788cf6c878-4pq5g   1.6.0
reviews-v3-67b4988599-psllq.default                   SYNCED   SYNCED    SYNCED    SYNCED     istiod-788cf6c878-4pq5g   1.6.0
sleep-78484c89dd-fmxbc.default                        SYNCED   SYNCED    SYNCED    SYNCED     istiod-788cf6c878-4pq5g   1.6.0

檢索Envoy和istiod的差異

proxy-status加上proxy ID可以檢索Envoy加載的配置和istiod發送的配置之間的差異,通過這種方式可以確定哪部分內容沒有被同步,並確定可能存在的問題。

下面的例子可以看到ingressgateway的listeners和routers配置都與istiod發過來的配置匹配,但clusters不匹配。

$ istioctl proxy-status details-v1-6dcc6fbb9d-wsjz4.default
--- Istiod Clusters
+++ Envoy Clusters
@@ -374,36 +374,14 @@
             "edsClusterConfig": {
                "edsConfig": {
                   "ads": {

                   }
                },
                "serviceName": "outbound|443||public-cr0bdc785ce3f14722918080a97e1f26be-alb1.kube-system.svc.cluster.local"
-            },
-            "connectTimeout": "1.000s",
-            "circuitBreakers": {
-               "thresholds": [
-                  {
-
-                  }
-               ]
-            }
-         }
-      },
-      {
-         "cluster": {
-            "name": "outbound|53||kube-dns.kube-system.svc.cluster.local",
-            "type": "EDS",
-            "edsClusterConfig": {
-               "edsConfig": {
-                  "ads": {
-
-                  }
-               },
-               "serviceName": "outbound|53||kube-dns.kube-system.svc.cluster.local"
             },
             "connectTimeout": "1.000s",
             "circuitBreakers": {
                "thresholds": [
                   {

                   }

Listeners Match
Routes Match

深入探究Envoy配置

proxy-config命令可以查看一個Envoy實例的配置,用於定位無法通過查看istio配置和用戶資源發現的問題。例如,使用如下命令可以獲取特定pod的clusters,listeners或routes概要。注:首先通過istioctl ps查看出不匹配的代理,然後使用istioctl pc查看具體的不匹配的信息。

$ istioctl proxy-config cluster -n istio-system istio-ingressgateway-7d6874b48f-qxhn5
SERVICE FQDN                                           PORT    SUBSET  DIRECTION  TYPE
BlackHoleCluster                                       -       -       -          STATIC
agent                                                  -       -       -          STATIC
details.default.svc.cluster.local                      9080    -       outbound   EDS
istio-ingressgateway.istio-system.svc.cluster.local    80      -       outbound   EDS
istio-ingressgateway.istio-system.svc.cluster.local    443     -       outbound   EDS
istio-ingressgateway.istio-system.svc.cluster.local    15021   -       outbound   EDS
istio-ingressgateway.istio-system.svc.cluster.local    15443   -       outbound   EDS
istiod.istio-system.svc.cluster.local                  443     -       outbound   EDS
istiod.istio-system.svc.cluster.local                  853     -       outbound   EDS
istiod.istio-system.svc.cluster.local                  15010   -       outbound   EDS
istiod.istio-system.svc.cluster.local                  15012   -       outbound   EDS
istiod.istio-system.svc.cluster.local                  15014   -       outbound   EDS
kube-dns.kube-system.svc.cluster.local                 53      -       outbound   EDS
kube-dns.kube-system.svc.cluster.local                 9153    -       outbound   EDS
kubernetes.default.svc.cluster.local                   443     -       outbound   EDS
...                                                                               
productpage.default.svc.cluster.local                  9080    -       outbound   EDS
prometheus.istio-system.svc.cluster.local              9090    -       outbound   EDS
prometheus_stats                                       -       -       -          STATIC
ratings.default.svc.cluster.local                      9080    -       outbound   EDS
reviews.default.svc.cluster.local                      9080    -       outbound   EDS
sds-grpc                                               -       -       -          STATIC
xds-grpc                                               -       -       -          STRICT_DNS
zipkin                                                 -       -       -          STRICT_DNS

為了調試Envoy,首先需要理解Envoy的clusters/listeners/routes/endpoints,以及它們之間是如何交互的。下面將使用帶有-o json和篩選標誌的proxy config命令來跟蹤Envoy,因為它決定在哪裡將請求從productpage pod發送到reviews pod的 reviews:9080

  1. 如果請求了一個pod的listener概要,可以看到istio生成了如下listeners:

    • 一個0.0.0.0:15006的listener,用於接收到pod的入站流量;以及一個 0.0.0.0:15001的listener,用於接收所有到pod的出站流量,然後將請求交給一個 virtual listener。
    • 每個kubernetes service IP都對應一個virtual listener,非HTTP的listener用於出站的TCP/HTTPS流量
    • pod IP中的virtual listener暴露了接收入站流量的端口
    • 0.0.0.0的HTTP類型的virtual listener,用於出站的HTTP流量

    Istio使用的端口信息如下:

    Port Protocol Used by Description
    15000 TCP Envoy Envoy admin port (commands/diagnostics)
    15001 TCP Envoy √ Envoy Outbound
    15006 TCP Envoy √ Envoy Inbound
    15020 HTTP Envoy Istio agent Prometheus telemetry
    15021 HTTP Envoy Health checks
    15090 HTTP Envoy Envoy Prometheus telemetry
    15010 GRPC Istiod XDS and CA services (plaintext)
    15012 GRPC Istiod XDS and CA services (TLS)
    8080 HTTP Istiod Debug interface
    443 HTTPS Istiod Webhooks
    15014 HTTP Mixer, Istiod Control plane monitoring
    15443 TLS Ingress and Egress Gateways SNI
    9090 HTTP Prometheus Prometheus
    42422 TCP Mixer Telemetry – Prometheus
    15004 HTTP Mixer, Pilot Policy/Telemetry – mTLS
    9091 HTTP Mixer Policy/Telemetry

    可以看到TYPE字段是沒有HTTPS的,HTTPS作為TCP類型。下面是productpage的listeners,刪減了部分信息。10.84開頭的是各個kubernetes service的CLUSTER-IP,以172.20開頭的是kubernetes的node IP,以nodePort方式暴露服務。

    $ istioctl proxy-config listeners productpage-v1-85b9bf9cd7-d8hm8.default
    ADDRESS          PORT     TYPE    
    0.0.0.0          443      TCP     <--+
    10.84.71.37      443      TCP        |
    10.84.223.189    443      TCP        |
    10.84.100.226    15443    TCP        |
    10.84.121.154    443      TCP        |
    10.84.142.44     443      TCP        | #從0.0.0.0_15001相關IP:PORT上接收出站的non-HTTP流量
    10.84.155.219    443      TCP        |
    172.20.127.212   9100     TCP        |
    10.84.205.103    443      TCP        | 
    10.84.167.116    443      TCP        |
    172.20.127.211   9100     TCP     <--+
    10.84.113.197    9979     HTTP+TCP<--+
    0.0.0.0          9091     HTTP+TCP   |
    10.84.30.227     9092     HTTP+TCP   |
    10.84.108.37     8080     HTTP+TCP   |
    10.84.158.64     8443     HTTP+TCP   |
    10.84.202.185    8080     HTTP+TCP   |
    10.84.21.252     8443     HTTP+TCP   |
    10.84.215.56     8443     HTTP+TCP   |
    0.0.0.0          60000    HTTP+TCP   | # 從0.0.0.0_15001的相關端口上接收出站的HTTP+TCP流量
    10.84.126.74     8778     HTTP+TCP   |
    10.84.126.74     8080     HTTP+TCP   |
    10.84.123.207    8080     HTTP+TCP   |
    10.84.30.227     9091     HTTP+TCP   |
    10.84.229.5      8080     HTTP+TCP<--+
    0.0.0.0          9080     HTTP+TCP     # 從 0.0.0.0_15006 上接收所有到9080的入站流量
    0.0.0.0          15001    TCP          # 從IP tables接收pod的所有出站流量,並移交給虛擬偵聽器
    0.0.0.0          15006    HTTP+TCP     # Envoy 入站
    0.0.0.0          15090    HTTP         # Envoy Prometheus 遙測
    0.0.0.0          15021    HTTP         # 健康檢查
    

    下面是productpage Pod中實際監聽的端口信息,與上述對應。

    $ ss -ntpl                                 
    State          Recv-Q        Send-Q        Local Address:Port          Peer Address:Port
    LISTEN         0             128                 0.0.0.0:15090              0.0.0.0:*
    LISTEN         0             128               127.0.0.1:15000              0.0.0.0:*
    LISTEN         0             128                 0.0.0.0:9080               0.0.0.0:*
    LISTEN         0             128                 0.0.0.0:15001              0.0.0.0:*
    LISTEN         0             128                 0.0.0.0:15006              0.0.0.0:*
    LISTEN         0             128                 0.0.0.0:15021              0.0.0.0:*
    LISTEN         0             128                       *:15020                    *:* 
    
  2. 從上述輸出概要中可以看到每個sidecar都有一個綁定到 0.0.0.0:15006的listener,IP tables會將所有入站的Pod流量導入該listener;以及一個綁定到 0.0.0.0:15001的listener,IP tables會將所有出站流量導入該listener,該listener有一個字段useOriginalDst設置為true,表示會使用最佳匹配原始目的地的方式將請求分發到virtual listener,如果沒有找到任何virtual listener,將會直接發送到連接目的地的PassthroughCluster

    $ istioctl pc listener productpage-v1-85b9bf9cd7-d8hm8.default --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",
                                "accessLog": [
                                    {
                                        "name": "envoy.file_access_log",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog",
                                            "path": "/dev/stdout",
                                            "format": "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% \"%DYNAMIC_METADATA(istio.mixer:status)%\" \"%UPSTREAM_TRANSPORT_FAILURE_REASON%\" %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" \"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" %UPSTREAM_CLUSTER% %UPSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_REMOTE_ADDRESS% %REQUESTED_SERVER_NAME% %ROUTE_NAME%\n"
                                        }
                                    }
                                ]
                            }
                        }
                    ],
                    "name": "virtualOutbound-catchall-tcp"
                }
            ],
            "useOriginalDst": true,
            "trafficDirection": "OUTBOUND"
        }
    ]
    
  3. 應用的請求為一個出站HTTP請求,會到達9080端口,這意味着請求將傳遞給0.0.0.0:9080 virtual listener。該listener會查看其RDS中配置的路由。這種情況下會查找istiod配置的RDS的9080路由

    $ istioctl pc listener productpage-v1-85b9bf9cd7-d8hm8.default  -o json --address 0.0.0.0 --port 9080
    [
        {
            "name": "0.0.0.0_9080",
            "address": {
                "socketAddress": {
                    "address": "0.0.0.0",
                    "portValue": 9080
                }
            },
            "filterChains": [
                {
                    "filterChainMatch": {
                        "applicationProtocols": [
                            "http/1.0",
                            "http/1.1",
                            "h2c"
                        ]
                    },
                    "filters": [
                        {
                            "name": "envoy.http_connection_manager",
                            "typedConfig": {
                                "@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
                                "statPrefix": "outbound_0.0.0.0_9080",
                                "rds": {
                                    "configSource": {
                                        "ads": {}
                                    },
                                    "routeConfigName": "9080"
                                },
    ...
    ]
    
  4. 9080的路由配置中每個服務只有一個virtual host。由於應用的請求會傳遞到reviews服務,因此Envoy會選擇請求與域相匹配的virtual host。一旦匹配到域,Envoy會查看匹配請求的第一個路由。下面場景中,由於沒有配置任何高級路由,因此只有一條可以匹配的路由,該路由告訴Envoy將請求發送到 outbound|9080||reviews.default.svc.cluster.local集群。

    $ istioctl proxy-config routes productpage-v1-85b9bf9cd7-d8hm8.default  --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.84.110.152",
                        "10.84.110.152:9080"
                    ],
                    "routes": [
                        {
                            "name": "default",
                            "match": {
                                "prefix": "/"
                            },
                            "route": {
                                "cluster": "outbound|9080||reviews.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"
                            },
                            "decorator": {
                                "operation": "reviews.default.svc.cluster.local:9080/*"
                            }
                        }
                    ],
                    "includeRequestAttemptCount": true
                }
            ],
            "validateClusters": false
        }
    ]
    
  5. cluster的配置用於從istiod中檢索後端。Envoy會使用serviceName作為key在Endpoints列表中進行查找,並將請求傳遞到這些後端。

    $  istioctl pc cluster productpage-v1-85b9bf9cd7-d8hm8.default  --fqdn reviews.default.svc.cluster.local -o json
    [
        {
           ...
            "name": "outbound|9080||reviews.default.svc.cluster.local",
            "type": "EDS",
            "edsClusterConfig": {
                "edsConfig": {
                    "ads": {}
                },
                "serviceName": "outbound|9080||reviews.default.svc.cluster.local"
            },
            "connectTimeout": "10s",
            "circuitBreakers": {
                "thresholds": [
                    {
                        "maxConnections": 4294967295,
                        "maxPendingRequests": 4294967295,
                        "maxRequests": 4294967295,
                        "maxRetries": 4294967295
                    }
                ]
            },
            "filters": [
                {
                    "name": "istio.metadata_exchange",
                    "typedConfig": {
                        "@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
                        "typeUrl": "type.googleapis.com/envoy.tcp.metadataexchange.config.MetadataExchange",
                        "value": {
                            "protocol": "istio-peer-exchange"
                        }
                    }
                }
            ]
        }
    ]
    
  6. 使用proxy-config endpoint命令查看本集群中當前可用的後端

    $ istioctl pc endpoint productpage-v1-85b9bf9cd7-d8hm8.default --cluster "outbound|9080||reviews.default.svc.cluster.local"
    ENDPOINT            STATUS      OUTLIER CHECK     CLUSTER
    10.80.3.55:9080     HEALTHY     OK                outbound|9080||reviews.default.svc.cluster.local
    10.80.3.56:9080     HEALTHY     OK                outbound|9080||reviews.default.svc.cluster.local
    10.80.3.58:9080     HEALTHY     OK                outbound|9080||reviews.default.svc.cluster.local
    

流量方向為:listener(應用出站port)->route(routeConfigName)->cluster(domain)->endpoint(serviceName)

檢查bootstrap配置

到目前為止已經查看了istiod的大部分配置,然而,Envoy需要一些如哪裡可以發現istiod的bootstrap配置,使用如下方式查看:

$  istioctl proxy-config bootstrap -n istio-system istio-ingressgateway-569669bb67-dsd5h.istio-system
{
    "bootstrap": {
        "node": {
            "id": "router~10.83.0.14~istio-ingressgateway-569669bb67-dsd5h.istio-system~istio-system.svc.cluster.local",
            "cluster": "istio-ingressgateway",
            "metadata": {
                    "CLUSTER_ID": "Kubernetes",
                    "CONFIG_NAMESPACE": "istio-system",
                    "EXCHANGE_KEYS": "NAME,NAMESPACE,INSTANCE_IPS,LABELS,OWNER,PLATFORM_METADATA,WORKLOAD_NAME,MESH_ID,SERVICE_ACCOUNT,CLUSTER_ID",
                    "INSTANCE_IPS": "10.83.0.14,fe80::6871:95ff:fe5b:9e3e",
                    "ISTIO_PROXY_SHA": "istio-proxy:12cfbda324320f99e0e39d7c393109fcd824591f",
                    "ISTIO_VERSION": "1.6.0",
                    "LABELS": {
                                "app": "istio-ingressgateway",
                                "chart": "gateways",
                                "heritage": "Tiller",
                                "istio": "ingressgateway",
                                "pod-template-hash": "569669bb67",
                                "release": "istio",
                                "service.istio.io/canonical-name": "istio-ingressgateway",
                                "service.istio.io/canonical-revision": "latest"
                            },
                    "MESH_ID": "cluster.local",
                    "NAME": "istio-ingressgateway-569669bb67-dsd5h",
                    "NAMESPACE": "istio-system",
                    "OWNER": "kubernetes://apis/apps/v1/namespaces/istio-system/deployments/istio-ingressgateway",
...
                    "ROUTER_MODE": "sni-dnat",
                    "SDS": "true",
                    "SERVICE_ACCOUNT": "istio-ingressgateway-service-account",
                    "TRUSTJWT": "true",
                    "WORKLOAD_NAME": "istio-ingressgateway"
                },
...
}

校驗到istiod的連通性

服務網格中的所有Envoy代理容器都應該連接到istiod,使用如下步驟測試:

  1. 創建一個sleep pod

    $ kubectl create namespace foo
    $ kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo
    
  2. 使用curl測試到istiod的連通性。下面調用v1註冊API,使用默認的istiod配置參數,並啟用雙向TLS認證

    $ kubectl exec $(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name}) -c sleep -n foo -- curl -sS istiod.istio-system:15014/debug/endpointz
    

通過istioctl的輸出理解網格

如下內容是一個實驗特性,僅用於評估

istio 1.3中包含一個istioctl experimental describe命令。該CLI命令提供了解影響pod的配置所需的信息。本節展示如何使用該experimental 子命令查看一個pod是否在網格中,以及檢查該pod的配置。該命令的基本使用方式為:

$ istioctl experimental describe pod <pod-name>[.<namespace>] #或
$ istioctl experimental describe pod <pod-name> -n <namespace> 

校驗pod是否在網格中

如果一個pod不在網格中,istioctl describe會显示一個告警信息,此外,如果pod缺少istio需要的配置時也會給出告警信息。

$ istioctl experimental describe pod  mutatepodimages-7575797d95-qn7p5
Pod: mutatepodimages-7575797d95-qn7p5
   Pod does not expose ports
WARNING: mutatepodimages-7575797d95-qn7p5 is not part of mesh; no Istio sidecar
--------------------
Error: failed to execute command on sidecar: error 'execing into mutatepodimages-7575797d95-qn7p5/default istio-proxy container: container istio-proxy is not valid for pod mutatepodimages-7575797d95-qn7p5

如果一個pod在網格中,則不會產生告警。

$ istioctl x describe pod ratings-v1-6c9dbf6b45-xlf2q
Pod: ratings-v1-6c9dbf6b45-xlf2q
   Pod Ports: 9080 (details), 15090 (istio-proxy)
--------------------
Service: details
   Port: http 9080/HTTP targets pod port 9080
Pilot reports that pod enforces HTTP/mTLS and clients speak HTTP

輸出為:

  • pod的服務容器端口,上述為ratings的9080端口
  • pod中的istio-proxy端口,15090
  • pod服務使用的協議,9080端口的http協議
  • pod設置的mutual TLS

校驗destination rule配置

可以使用istioctl describe檢查應用到一個pod的destination rule。例如執行如下命令部署destination rule

$ kubectl apply -f samples/bookinfo/networking/destination-rule-all-mtls.yaml

查看ratings pod

$ export RATINGS_POD=$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')
$ istioctl x describe pod $RATINGS_POD
Pod: ratings-v1-6c9dbf6b45-xlf2q
   Pod Ports: 9080 (ratings), 15090 (istio-proxy)
--------------------
Service: ratings
   Port: http 9080/HTTP targets pod port 9080
DestinationRule: ratings for "ratings"
   Matching subsets: v1
      (Non-matching subsets v2,v2-mysql,v2-mysql-vm)
   Traffic Policy TLS Mode: ISTIO_MUTUAL
Pilot reports that pod enforces HTTP/mTLS and clients speak mTLS

輸出為:

  • 應用到ratings 服務的ratings destination rule
  • 匹配pod的ratings destination rule,上述為v1
  • destination rule定義的其他subset
  • pod接收HTTP或mutual TLS,但客戶端使用mutual TLS

校驗virtual service配置

部署如下virtual service

$ kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml

查看v1版本的reviews服務:

$ export REVIEWS_V1_POD=$(kubectl get pod -l app=reviews,version=v1 -o jsonpath='{.items[0].metadata.name}')
istioctl x describe pod $REVIEWS_V1_POD
$ istioctl x describe pod $REVIEWS_V1_POD
Pod: reviews-v1-564b97f875-q5l9r
   Pod Ports: 9080 (reviews), 15090 (istio-proxy)
--------------------
Service: reviews
   Port: http 9080/HTTP targets pod port 9080
DestinationRule: reviews for "reviews"
   Matching subsets: v1
      (Non-matching subsets v2,v3)
   Traffic Policy TLS Mode: ISTIO_MUTUAL
VirtualService: reviews
   1 HTTP route(s)

輸出結果與前面的ratings pod類型,但多了到pod的virtual service路由。

istioctl describe命令不僅僅显示了影響pod的virtual service。如果一個virtual service配置的host為一個pod,但流量不可達,會輸出告警信息,這種請求可能發生在當一個virtual service如果沒有可達的pod subset時。例如:

$ export REVIEWS_V2_POD=$(kubectl get pod -l app=reviews,version=v2 -o jsonpath='{.items[0].metadata.name}')
istioctl x describe pod $REVIEWS_V2_POD
[root@bastion istio-1.6.0]# istioctl x describe pod $REVIEWS_V2_POD
Pod: reviews-v2-568c7c9d8f-vcd94
...
VirtualService: reviews
   WARNING: No destinations match pod subsets (checked 1 HTTP routes)
      Route to non-matching subset v1 for (everything)

告警信息給出導致問題的原因,檢查的路由數目,以及其他路由信息。例如,由於virtual service將所有的流量到導入了v1 subset,因此v2 pod無法接收到任何流量。

如果刪除如下destination rule:

$ kubectl delete -f samples/bookinfo/networking/destination-rule-all-mtls.yaml

可以看到如下信息:

$ istioctl x describe pod $REVIEWS_V1_POD
Pod: reviews-v1-564b97f875-q5l9r
   Pod Ports: 9080 (reviews), 15090 (istio-proxy)
--------------------
Service: reviews
   Port: http 9080/HTTP targets pod port 9080
VirtualService: reviews
   WARNING: No destinations match pod subsets (checked 1 HTTP routes)
      Warning: Route to subset v1 but NO DESTINATION RULE defining subsets!

輸出展示了已刪除destination rule,但沒有刪除依賴它的virtual service。該virtual service將流量路由到v1 subset,但沒有定義v1 subset的destination rule。因此流量無法分發到v1版本的pod。

恢復環境:

$ kubectl apply -f samples/bookinfo/networking/destination-rule-all-mtls.yaml

校驗流量路由

istioctl describe也可以展示流量權重。如理如下命令會將90%的流量導入reviews服務的v1 subset,將10%的流量導入reviews服務的v2 subset。

$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-90-10.yaml

查看reviews v1` pod:

$ istioctl x describe pod $REVIEWS_V1_POD
...
VirtualService: reviews
   Weight 90%

輸出显示90%的reviews服務的流量導入到了v1 subset中。

部署其他類型的路由,如部署指定HTTP首部的路由:

$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-jason-v2-v3.yaml

再次查看pod:

$ istioctl x describe pod $REVIEWS_V1_POD
...
VirtualService: reviews
   WARNING: No destinations match pod subsets (checked 2 HTTP routes)
      Route to non-matching subset v2 for (when headers are end-user=jason)
      Route to non-matching subset v3 for (everything)

由於查看了位於v1 subset的pod,而virtual service將包含 end-user=jason 的流量分發給v2 subset,其他流量分發給v3 subset,v1 subset沒有任何流量導入,此時會輸出告警信息。

檢查strict mutual TLS(官方文檔待更新)

根據mutual TLS遷移指南,可以給ratings服務啟用strict mutual TLS。

$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: ratings-strict
spec:
  selector:
    matchLabels:
      app: ratings
  mtls:
    mode: STRICT
EOF

執行如下命令查看ratings pod,輸出显示ratings pod已經使用mutual TLS防護。

$ istioctl x describe pod $RATINGS_POD
Pilot reports that pod enforces mTLS and clients speak mTLS

有時,將mutual TLS切換位STRICT模式時會對部署的組件造成影響,通常是因為destination rule不匹配新配置造成的。例如,如果配置Bookinfo客戶端不使用mutualTLS,而使用明文的HTTP destination rules:

$ kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml

如果在瀏覽器傻瓜打開Bookinfo,會显示Ratings service is currently unavailable,使用如下命令查看原因:

$ istioctl x describe pod $RATINGS_POD
...
WARNING Pilot predicts TLS Conflict on ratings-v1-f745cf57b-qrxl2 port 9080 (pod enforces mTLS, clients speak HTTP)
  Check DestinationRule ratings/default and AuthenticationPolicy ratings-strict/default

輸出中有一個描述destination rule和authentication policy衝突的告警信息。

使用如下方式恢復:

$ kubectl apply -f samples/bookinfo/networking/destination-rule-all-mtls.yaml

卸載

$ kubectl delete -f samples/bookinfo/platform/kube/bookinfo.yaml
$ kubectl delete -f samples/bookinfo/networking/bookinfo-gateway.yaml
$ kubectl delete -f samples/bookinfo/networking/destination-rule-all-mtls.yaml
$ kubectl delete -f samples/bookinfo/networking/virtual-service-all-v1.yaml

使用istioctl analyse診斷配置

istioctl analyze是一個可以探測istio配置中潛在錯誤的診斷工具,它可以診斷現有的集群或一組本地配置文件,會同時診斷這兩者。

可以使用如下方式診斷當前的kubernetes:

$ istioctl analyze --all-namespaces

例如,如果某些命名空間沒有啟用istiod注入,會打印如下告警信息:

Warn [IST0102] (Namespace openshift) The namespace is not enabled for Istio injection. Run 'kubectl label namespace openshift istio-injection=enabled' to enable it, or 'kubectl label namespace openshift istio-injection=disabled' to explicitly mark it as not needing injection

分析現有的集群/本地文件或二者

上述的例子用於分析一個存在的集群,但該工具也可以支持分析本地kubernetes yaml的配置文件集,或同時分析本地文件和集群。當分析一個本地文件集時,這些文件集應該是完全自包含的。通常用於分析需要部署到集群的一個完整的配置文件集。

分析特定的本地kubernetes yaml文件集:

$ istioctl analyze --use-kube=false a.yaml b.yaml

分析當前目錄中的所有yaml文件:

$ istioctl analyze --use-kube=false *.yaml

模擬將當前目錄中的files部署到當前集群中:

$ istioctl analyze *.yaml

使用istioctl analyze --help命令查看完整的選項。更多analyse的使用參見Q&A.

組件內省

Istio組件是用一個靈活的內省框架構建的,它使檢查和操作運行組件的內部狀態變得簡單。組件會開放一個端口,用於通過web瀏覽器的交互式視圖獲取組件的狀態,或使用外部工具通過REST訪問。

Mixer, PilotGalley 都實現了ControlZ 功能(1.6版本可以查看istiod)。當啟用這些組件時將記錄一條消息,指示要連接的IP地址和端口,以便與ControlZ交互。

2018-07-26T23:28:48.889370Z     info    ControlZ available at 100.76.122.230:9876

可以使用如下命令進行端口轉發,類似kubectl的port-forward,用於遠程訪問。

$ istioctl dashboard controlz <podname> -n <namespaces>

組件日誌

日誌作用域

組件的日誌按照作用域進行分類。取決於組件提供的功能,不同的組件有不同的作用域。所有的組件都有一個default的作用域,用於未分類的日誌消息。

各個組件的日誌作用域參見:reference documentation。

每個作用域對應一個唯一的日誌級別:

  1. none
  2. error
  3. warning
  4. info
  5. debug

其中none表示沒有劃分作用域的輸出,debug會最大化輸出。默認的作用域為info,用於在一般情況下為istio提供何時的日誌輸出。

可以使用 --log_output_level 控制輸出級別:

控制輸出

日誌信息通常會發送到組件的標準輸出流中。 --log_target選項可以將輸出重定向到任意(數量的)位置,可以通過逗號分割的列表給出文件系統的路徑。stdoutstderr分別表示標準輸出和標準錯誤輸出流。

日誌滾動

istio組件能夠自動管理日誌滾動,將大的日誌切分為小的日誌文件。--log_rotate選項允許指定用於滾動的基本文件名。派生的名稱將用於單個日誌文件。

--log_rotate_max_age選項指定文件發生滾動前的最大時間(天為單位),--log_rotate_max_size選項用於指定文件滾動發生前的最大文件大小(MB為單位), --log_rotate_max_backups選項控制保存的滾動文件的最大數量,超過該值的老文件會被自動刪除。

組件調試

--log_caller--log_stacktrace_level選項可以控制日誌信息是否包含程序員級別的信息。在跟蹤組件bug時很有用,但日常用不到。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

網頁設計最專業,超強功能平台可客製化

您可能也會喜歡…