mirror of https://github.com/istio/istio.io.git
431 lines
23 KiB
Markdown
431 lines
23 KiB
Markdown
---
|
|
title: Debugging Envoy and Istiod
|
|
description: Describes tools and techniques to diagnose Envoy configuration issues related to traffic management.
|
|
weight: 20
|
|
keywords: [debug,proxy,status,config,pilot,envoy]
|
|
aliases:
|
|
- /help/ops/traffic-management/proxy-cmd
|
|
- /help/ops/misc
|
|
- /help/ops/troubleshooting/proxy-cmd
|
|
owner: istio/wg-user-experience-maintainers
|
|
test: no
|
|
---
|
|
|
|
Istio provides two very valuable commands to help diagnose traffic management configuration problems,
|
|
the [`proxy-status`](/docs/reference/commands/istioctl/#istioctl-proxy-status)
|
|
and [`proxy-config`](/docs/reference/commands/istioctl/#istioctl-proxy-config) commands. The `proxy-status` command
|
|
allows you to get an overview of your mesh and identify the proxy causing the problem. Then `proxy-config` can be used
|
|
to inspect Envoy configuration and diagnose the issue.
|
|
|
|
If you want to try the commands described below, you can either:
|
|
|
|
* Have a Kubernetes cluster with Istio and Bookinfo installed (as described in
|
|
[installation steps](/docs/setup/getting-started/) and
|
|
[Bookinfo installation steps](/docs/examples/bookinfo/#deploying-the-application)).
|
|
|
|
OR
|
|
|
|
* Use similar commands against your own application running in a Kubernetes cluster.
|
|
|
|
## Get an overview of your mesh
|
|
|
|
The `proxy-status` command allows you to get an overview of your mesh. If you suspect one of your sidecars isn't
|
|
receiving configuration or is out of sync then `proxy-status` will tell you this.
|
|
|
|
{{< text bash >}}
|
|
$ istioctl proxy-status
|
|
NAME CDS LDS EDS RDS ISTIOD VERSION
|
|
details-v1-558b8b4b76-qzqsg.default SYNCED SYNCED SYNCED SYNCED istiod-6cf8d4f9cb-wm7x6 1.7.0
|
|
istio-ingressgateway-66c994c45c-cmb7x.istio-system SYNCED SYNCED SYNCED NOT SENT istiod-6cf8d4f9cb-wm7x6 1.7.0
|
|
productpage-v1-6987489c74-nc7tj.default SYNCED SYNCED SYNCED SYNCED istiod-6cf8d4f9cb-wm7x6 1.7.0
|
|
prometheus-7bdc59c94d-hcp59.istio-system SYNCED SYNCED SYNCED SYNCED istiod-6cf8d4f9cb-wm7x6 1.7.0
|
|
ratings-v1-7dc98c7588-5m6xj.default SYNCED SYNCED SYNCED SYNCED istiod-6cf8d4f9cb-wm7x6 1.7.0
|
|
reviews-v1-7f99cc4496-rtsqn.default SYNCED SYNCED SYNCED SYNCED istiod-6cf8d4f9cb-wm7x6 1.7.0
|
|
reviews-v2-7d79d5bd5d-tj6kf.default SYNCED SYNCED SYNCED SYNCED istiod-6cf8d4f9cb-wm7x6 1.7.0
|
|
reviews-v3-7dbcdcbc56-t8wrx.default SYNCED SYNCED SYNCED SYNCED istiod-6cf8d4f9cb-wm7x6 1.7.0
|
|
{{< /text >}}
|
|
|
|
If a proxy is missing from this list it means that it is not currently connected to a Istiod instance so will not be
|
|
receiving any configuration.
|
|
|
|
* `SYNCED` means that Envoy has acknowledged the last configuration {{< gloss >}}Istiod{{< /gloss >}} has sent to it.
|
|
* `NOT SENT` means that Istiod hasn't sent anything to Envoy. This usually is because Istiod has nothing to send.
|
|
* `STALE` means that Istiod has sent an update to Envoy but has not received an acknowledgement. This usually indicates
|
|
a networking issue between Envoy and Istiod or a bug with Istio itself.
|
|
|
|
## Retrieve diffs between Envoy and Istiod
|
|
|
|
The `proxy-status` command can also be used to retrieve a diff between the configuration Envoy has loaded and the
|
|
configuration Istiod would send, by providing a proxy ID. This can help you determine exactly what is out of sync and
|
|
where the issue may lie.
|
|
|
|
{{< text bash json >}}
|
|
$ 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 (RDS last loaded at Tue, 04 Aug 2020 11:52:54 IST)
|
|
{{< /text >}}
|
|
|
|
Here you can see that the listeners and routes match but the clusters are out of sync.
|
|
|
|
## Deep dive into Envoy configuration
|
|
|
|
The `proxy-config` command can be used to see how a given Envoy instance is configured. This can then be used to
|
|
pinpoint any issues you are unable to detect by just looking through your Istio configuration and custom resources.
|
|
To get a basic summary of clusters, listeners or routes for a given pod use the command as follows (changing clusters
|
|
for listeners or routes when required):
|
|
|
|
{{< text bash >}}
|
|
$ istioctl proxy-config cluster -n istio-system istio-ingressgateway-7d6874b48f-qxhn5
|
|
SERVICE FQDN PORT SUBSET DIRECTION TYPE DESTINATION RULE
|
|
BlackHoleCluster - - - STATIC
|
|
agent - - - STATIC
|
|
details.default.svc.cluster.local 9080 - outbound EDS details.default
|
|
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_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
|
|
{{< /text >}}
|
|
|
|
In order to debug Envoy you need to understand Envoy clusters/listeners/routes/endpoints and how they all interact.
|
|
We will use the `proxy-config` command with the `-o json` and filtering flags to follow Envoy as it determines where
|
|
to send a request from the `productpage` pod to the `reviews` pod at `reviews:9080`.
|
|
|
|
1. If you query the listener summary on a pod you will notice Istio generates the following listeners:
|
|
* A listener on `0.0.0.0:15006` that receives all inbound traffic to the pod and a listener on `0.0.0.0:15001` that receives all outbound traffic to the pod, then hands the request over to a virtual listener.
|
|
* A virtual listener per service IP, per each non-HTTP for outbound TCP/HTTPS traffic.
|
|
* A virtual listener on the pod IP for each exposed port for inbound traffic.
|
|
* A virtual listener on `0.0.0.0` per each HTTP port for outbound HTTP traffic.
|
|
|
|
{{< text bash >}}
|
|
$ istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs
|
|
ADDRESS PORT MATCH DESTINATION
|
|
10.96.0.10 53 ALL Cluster: outbound|53||kube-dns.kube-system.svc.cluster.local
|
|
0.0.0.0 80 App: HTTP Route: 80
|
|
0.0.0.0 80 ALL PassthroughCluster
|
|
10.100.93.102 443 ALL Cluster: outbound|443||istiod.istio-system.svc.cluster.local
|
|
10.111.121.13 443 ALL Cluster: outbound|443||istio-ingressgateway.istio-system.svc.cluster.local
|
|
10.96.0.1 443 ALL Cluster: outbound|443||kubernetes.default.svc.cluster.local
|
|
10.100.93.102 853 App: HTTP Route: istiod.istio-system.svc.cluster.local:853
|
|
10.100.93.102 853 ALL Cluster: outbound|853||istiod.istio-system.svc.cluster.local
|
|
0.0.0.0 9080 App: HTTP Route: 9080
|
|
0.0.0.0 9080 ALL PassthroughCluster
|
|
0.0.0.0 9090 App: HTTP Route: 9090
|
|
0.0.0.0 9090 ALL PassthroughCluster
|
|
10.96.0.10 9153 App: HTTP Route: kube-dns.kube-system.svc.cluster.local:9153
|
|
10.96.0.10 9153 ALL Cluster: outbound|9153||kube-dns.kube-system.svc.cluster.local
|
|
0.0.0.0 15001 ALL PassthroughCluster
|
|
0.0.0.0 15006 Addr: 10.244.0.22/32:15021 inbound|15021|mgmt-15021|mgmtCluster
|
|
0.0.0.0 15006 Addr: 10.244.0.22/32:9080 Inline Route: /*
|
|
0.0.0.0 15006 Trans: tls; App: HTTP TLS; Addr: 0.0.0.0/0 Inline Route: /*
|
|
0.0.0.0 15006 App: HTTP; Addr: 0.0.0.0/0 Inline Route: /*
|
|
0.0.0.0 15006 App: Istio HTTP Plain; Addr: 10.244.0.22/32:9080 Inline Route: /*
|
|
0.0.0.0 15006 Addr: 0.0.0.0/0 InboundPassthroughClusterIpv4
|
|
0.0.0.0 15006 Trans: tls; App: TCP TLS; Addr: 0.0.0.0/0 InboundPassthroughClusterIpv4
|
|
0.0.0.0 15010 App: HTTP Route: 15010
|
|
0.0.0.0 15010 ALL PassthroughCluster
|
|
10.100.93.102 15012 ALL Cluster: outbound|15012||istiod.istio-system.svc.cluster.local
|
|
0.0.0.0 15014 App: HTTP Route: 15014
|
|
0.0.0.0 15014 ALL PassthroughCluster
|
|
0.0.0.0 15021 ALL Inline Route: /healthz/ready*
|
|
10.111.121.13 15021 App: HTTP Route: istio-ingressgateway.istio-system.svc.cluster.local:15021
|
|
10.111.121.13 15021 ALL Cluster: outbound|15021||istio-ingressgateway.istio-system.svc.cluster.local
|
|
0.0.0.0 15090 ALL Inline Route: /stats/prometheus*
|
|
10.111.121.13 15443 ALL Cluster: outbound|15443||istio-ingressgateway.istio-system.svc.cluster.local
|
|
{{< /text >}}
|
|
|
|
1. From the above summary you can see that every sidecar has a listener bound to `0.0.0.0:15006` which is where IP tables routes all inbound pod traffic to and a listener bound to `0.0.0.0:15001` which is where IP tables routes all outbound pod traffic to. The `0.0.0.0:15001` listener hands the request over to the virtual listener that best matches the original destination of the request, if it can find a matching one. Otherwise, it sends the request to the `PassthroughCluster` which connects to the destination directly.
|
|
|
|
{{< text bash json >}}
|
|
$ istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs --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"
|
|
}
|
|
}
|
|
],
|
|
"name": "virtualOutbound-catchall-tcp"
|
|
}
|
|
],
|
|
"trafficDirection": "OUTBOUND",
|
|
"hiddenEnvoyDeprecatedUseOriginalDst": true
|
|
}
|
|
]
|
|
{{< /text >}}
|
|
|
|
1. Our request is an outbound HTTP request to port `9080` this means it gets handed off to the `0.0.0.0:9080` virtual
|
|
listener. This listener then looks up the route configuration in its configured RDS. In this case it will be looking
|
|
up route `9080` in RDS configured by Istiod (via ADS).
|
|
|
|
{{< text bash json >}}
|
|
$ istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs -o json --address 0.0.0.0 --port 9080
|
|
...
|
|
"rds": {
|
|
"configSource": {
|
|
"ads": {},
|
|
"resourceApiVersion": "V3"
|
|
},
|
|
"routeConfigName": "9080"
|
|
}
|
|
...
|
|
{{< /text >}}
|
|
|
|
1. The `9080` route configuration only has a virtual host for each service. Our request is heading to the reviews
|
|
service so Envoy will select the virtual host to which our request matches a domain. Once matched on domain Envoy
|
|
looks for the first route that matches the request. In this case we don't have any advanced routing so there is only
|
|
one route that matches on everything. This route tells Envoy to send the request to the
|
|
`outbound|9080||reviews.default.svc.cluster.local` cluster.
|
|
|
|
{{< text bash json >}}
|
|
$ istioctl proxy-config routes productpage-v1-6c886ff494-7vxhs --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.98.88.0",
|
|
"10.98.88.0:9080"
|
|
],
|
|
"routes": [
|
|
{
|
|
"name": "default",
|
|
"match": {
|
|
"prefix": "/"
|
|
},
|
|
"route": {
|
|
"cluster": "outbound|9080||reviews.default.svc.cluster.local",
|
|
"timeout": "0s",
|
|
}
|
|
}
|
|
]
|
|
...
|
|
{{< /text >}}
|
|
|
|
1. This cluster is configured to retrieve the associated endpoints from Istiod (via ADS). So Envoy will then use the
|
|
`serviceName` field as a key to look up the list of Endpoints and proxy the request to one of them.
|
|
|
|
{{< text bash json >}}
|
|
$ istioctl proxy-config cluster productpage-v1-6c886ff494-7vxhs --fqdn reviews.default.svc.cluster.local -o json
|
|
[
|
|
{
|
|
"name": "outbound|9080||reviews.default.svc.cluster.local",
|
|
"type": "EDS",
|
|
"edsClusterConfig": {
|
|
"edsConfig": {
|
|
"ads": {},
|
|
"resourceApiVersion": "V3"
|
|
},
|
|
"serviceName": "outbound|9080||reviews.default.svc.cluster.local"
|
|
},
|
|
"connectTimeout": "10s",
|
|
"circuitBreakers": {
|
|
"thresholds": [
|
|
{
|
|
"maxConnections": 4294967295,
|
|
"maxPendingRequests": 4294967295,
|
|
"maxRequests": 4294967295,
|
|
"maxRetries": 4294967295
|
|
}
|
|
]
|
|
},
|
|
}
|
|
]
|
|
{{< /text >}}
|
|
|
|
1. To see the endpoints currently available for this cluster use the `proxy-config` endpoints command.
|
|
|
|
{{< text bash json >}}
|
|
$ istioctl proxy-config endpoints productpage-v1-6c886ff494-7vxhs --cluster "outbound|9080||reviews.default.svc.cluster.local"
|
|
ENDPOINT STATUS OUTLIER CHECK CLUSTER
|
|
172.17.0.7:9080 HEALTHY OK outbound|9080||reviews.default.svc.cluster.local
|
|
172.17.0.8:9080 HEALTHY OK outbound|9080||reviews.default.svc.cluster.local
|
|
172.17.0.9:9080 HEALTHY OK outbound|9080||reviews.default.svc.cluster.local
|
|
{{< /text >}}
|
|
|
|
## Inspecting bootstrap configuration
|
|
|
|
So far we have looked at configuration retrieved (mostly) from Istiod, however Envoy requires some bootstrap configuration that
|
|
includes information like where Istiod can be found. To view this use the following command:
|
|
|
|
{{< text bash json >}}
|
|
$ istioctl proxy-config bootstrap -n istio-system istio-ingressgateway-7d6874b48f-qxhn5
|
|
{
|
|
"bootstrap": {
|
|
"node": {
|
|
"id": "router~172.30.86.14~istio-ingressgateway-7d6874b48f-qxhn5.istio-system~istio-system.svc.cluster.local",
|
|
"cluster": "istio-ingressgateway",
|
|
"metadata": {
|
|
"CLUSTER_ID": "Kubernetes",
|
|
"EXCHANGE_KEYS": "NAME,NAMESPACE,INSTANCE_IPS,LABELS,OWNER,PLATFORM_METADATA,WORKLOAD_NAME,MESH_ID,SERVICE_ACCOUNT,CLUSTER_ID",
|
|
"INSTANCE_IPS": "10.244.0.7",
|
|
"ISTIO_PROXY_SHA": "istio-proxy:f98b7e538920abc408fbc91c22a3b32bc854d9dc",
|
|
"ISTIO_VERSION": "1.7.0",
|
|
"LABELS": {
|
|
"app": "istio-ingressgateway",
|
|
"chart": "gateways",
|
|
"heritage": "Tiller",
|
|
"istio": "ingressgateway",
|
|
"pod-template-hash": "68bf7d7f94",
|
|
"release": "istio",
|
|
"service.istio.io/canonical-name": "istio-ingressgateway",
|
|
"service.istio.io/canonical-revision": "latest"
|
|
},
|
|
"MESH_ID": "cluster.local",
|
|
"NAME": "istio-ingressgateway-68bf7d7f94-sp226",
|
|
"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",
|
|
"WORKLOAD_NAME": "istio-ingressgateway"
|
|
},
|
|
"userAgentBuildVersion": {
|
|
"version": {
|
|
"majorNumber": 1,
|
|
"minorNumber": 15
|
|
},
|
|
"metadata": {
|
|
"build.type": "RELEASE",
|
|
"revision.sha": "f98b7e538920abc408fbc91c22a3b32bc854d9dc",
|
|
"revision.status": "Clean",
|
|
"ssl.version": "BoringSSL"
|
|
}
|
|
},
|
|
},
|
|
...
|
|
{{< /text >}}
|
|
|
|
## Verifying connectivity to Istiod
|
|
|
|
Verifying connectivity to Istiod is a useful troubleshooting step. Every proxy container in the service mesh should be able to communicate with Istiod. This can be accomplished in a few simple steps:
|
|
|
|
1. Create a `sleep` pod:
|
|
|
|
{{< text bash >}}
|
|
$ kubectl create namespace foo
|
|
$ kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo
|
|
{{< /text >}}
|
|
|
|
1. Test connectivity to Istiod using `curl`. The following example invokes the v1 registration API using default Istiod configuration parameters and mutual TLS enabled:
|
|
|
|
{{< text bash >}}
|
|
$ 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/version
|
|
{{< /text >}}
|
|
|
|
You should receive a response listing the version of Istiod.
|
|
|
|
## What Envoy version is Istio using?
|
|
|
|
To find out the Envoy version used in deployment, you can `exec` into the container and query the `server_info` endpoint:
|
|
|
|
{{< text bash >}}
|
|
$ kubectl exec -it productpage-v1-6b746f74dc-9stvs -c istio-proxy -n default -- pilot-agent request GET server_info --log_as_json | jq {version}
|
|
{
|
|
"version": "2d4ec97f3ac7b3256d060e1bb8aa6c415f5cef63/1.17.0/Clean/RELEASE/BoringSSL"
|
|
}
|
|
{{< /text >}}
|