Istio的运维-诊断工具

在参考官方文档的时候发现环境偶尔会出现问题,因此插入一章与调试有关的内容,便于简单问题的定位。涵盖官方文档的诊断工具章节

使用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-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时很有用,但日常用不到。

Istio的运维-诊断工具(istio 系列五)的更多相关文章

  1. Linux运维企业架构实战系列

    Linux运维企业架构项目实战系列 项目实战1-LNMP的搭建.nginx的ssl加密.权限控制的实现 项目实战2-LVS.nginx实现负载均衡系列 2.1 项目实战2.1-实现基于LVS负载均衡集 ...

  2. Ansible运维自动化工具19个常用模块使用实例【转】

    一.模块列表 1.setup 2.ping 3.file 4.copy 5.command 6.shell 7.script 8.cron 9.yum 10.service 11.group 12.u ...

  3. 阿里云运维部署工具AppDeploy详细教程

    AppDeploy是一个通过SSH实现的命令行工具,可完成应用部署和远程运维管理.当前工具实现为两个版本:普通版(伪代码描述语言)和Python版.Python版使用Python语法规则,可实现您的各 ...

  4. 盘点Linux运维常用工具(一)-web篇之httpd

    #前言:想把自己学的各种服务进行分类归档起来,于是就写了盘点Linux运维常用工具,Linux方面使用到的web应用服务有httpd(apache).nginx.tomcat.lighttpd,先了解 ...

  5. 运维自动化工具ansible

    企业级自动化运维工具应用实战ansible 公司计划在年底做一次大型市场促销活动,全面冲刺下交易额,为明年的上市做准备.公司要求各业务组对年底大促做准备,运维部要求所有业务容量进行三倍的扩容,并搭建出 ...

  6. 使用Chef管理windows集群 | 运维自动化工具

    但凡服务器上了一定规模(百台以上),普通的ssh登录管理的模式就越来越举步维艰.试想Linux发布了一个高危漏洞的补丁,你要把手下成百上千台机器都更新该补丁,如果没有一种自动化方式,那么至少要耗上大半 ...

  7. Ansible运维自动化工具

    1>Ansible 1>ansible简介 ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet.cfengine.chef.func.fabri ...

  8. GS运维常用工具及文档

    规范部分   GS产品线性能问题处理流程:http://gsk.inspur.com/File/t-4244 XXX项目性能问题信息收集单-模板:http://gsk.inspur.com/File/ ...

  9. 运维自动化工具---Puppet

    案例环境:-----------------------------------------------------------------主机  操作系统   IP地址  主要软件--------- ...

随机推荐

  1. spark机器学习从0到1决策树(六)

      一.概念 决策树及其集合是分类和回归的机器学习任务的流行方法. 决策树被广泛使用,因为它们易于解释,处理分类特征,扩展到多类分类设置,不需要特征缩放,并且能够捕获非线性和特征交互. 诸如随机森林和 ...

  2. Spring+Struts2+Hibernate框架搭建

    SSH框架版本:Struts-2.3.30  +  Spring-4.2.2  +  Hibernate5.2.2 下图是所需要的Jar包: 下面是项目的结构图: 1.web.xml <?xml ...

  3. Django之from.Form内置字段

    from django import forms Field required=True, 是否允许为空 widget=None, HTML插件 label=None, 用于生成Label标签或显示内 ...

  4. 理解javascript中的连续赋值

    之前在扒源码时经常看到类似的连续赋值操作:  var a = b = 1;  在某度搜了众多前辈的博客,总算对这骚操作有点眉目. Case analysis 首先,javascript中连续赋值最典型 ...

  5. 哈理工新生赛 马拉车+贪心 最大密度子图 AC自动机+DP

    J.Symmys Time Limit: 1000 MS Memory Limit: 262144 K Total Submit: 50 (13 users) Total Accepted: 2 (2 ...

  6. Code Your First API With Node.js and Express: Set Up the Server

    How to Set Up an Express API Server in Node.js In the previous tutorial, we learned what the REST ar ...

  7. 一次 nginx 返回 302 问题解决

    1.问题描述: 应用服务器通过post方式向nginx服务器发送http请求,返回 302 2.问题解决过程 2.1.查询nginx日志,开始以为302错误会在nginx的错误日志error.log, ...

  8. PHP 数据库操作函数笔记

    /建立 或者 关闭mysql服务器 @符号用于屏蔽错误信息 $link=@mysqli_connect('127.0.0.1','root','123456','php1',3306); if(mys ...

  9. byte值的问题

    byte值的问题 byte b1 = 127; byte b2 = (byte)128; //-128 byte b3 = (byte)129; //-127 byte b4 = (byte)130; ...

  10. 用tarjan求LCA板子(比倍增快)

    懒!!直接转载!!!! https://solstice23.top/archives/62