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

Istio的運維-診斷工具

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

使用istioctl命令行工具

首先能夠經過日誌Introspection檢查各個組件,若是不足以支持問題定位,能夠參考以下操做:mysql

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

建議安裝對應istio版本的istioctl程序員

istioctl自動補全

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

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

    $ source ~/istioctl.bash

查看網格的狀態

可使用istioctl proxy-statusistioctl ps命令查看網格的狀態。若是輸出結果中缺乏某個代理,說明該代理當前沒有鏈接到Pilot實例,於是沒法接收到任何配置。若是狀態爲stale,表示當前存在網絡故障,或Pilot須要擴容。sql

獲取代理配置

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

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

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

使用以下方式能夠檢索特定pod中的Envoy實例的bootstrap配置信息。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-statusproxy-configproxy-status能夠獲取網格的概述並肯定致使問題的代理。proxy-config能夠檢查Envoy配置並診斷該問題。

若是要嘗試以下命令,能夠:

獲取網格概況

經過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時頗有用,但平常用不到。

相關文章
相關標籤/搜索