Debugging Envoy and Pilot
If you want to try the commands described below, you can either:
- Have a Kubernetes cluster with Istio and Bookinfo installed (as described ininstallation steps and).
OR
- Use similar commands against your own application running in a Kubernetes cluster.
The proxy-status
command allows you to get an overview of your mesh. If you suspect one of your sidecars isn’treceiving configuration or is out of sync then proxy-status
will tell you this.
If a proxy is missing from this list it means that it is not currently connected to a Pilot instance so will not bereceiving any configuration.
SYNCED
means that Envoy has acknowledged the last configuration Pilot has sent to it.NOT SENT
means that Pilot hasn’t sent anything to Envoy. This usually is because Pilot has nothing to send.STALE
means that Pilot has sent an update to Envoy but has not received an acknowledgement. This usually indicatesa networking issue between Envoy and Pilot or a bug with Istio itself.
Retrieve diffs between Envoy and Istio Pilot
The proxy-status
command can also be used to retrieve a diff between the configuration Envoy has loaded and theconfiguration Pilot would send, by providing a proxy ID. This can help you determine exactly what is out of sync andwhere the issue may lie.
$ istioctl proxy-status details-v1-6dcc6fbb9d-wsjz4.default
--- Pilot 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
Here you can see that the listeners and routes match but the clusters are out of sync.
$ istioctl proxy-config cluster -n istio-system istio-ingressgateway-7d6874b48f-qxhn5
SERVICE FQDN PORT SUBSET DIRECTION TYPE
BlackHoleCluster - - - STATIC
details.default.svc.cluster.local 9080 - outbound EDS
heapster.kube-system.svc.cluster.local 80 - outbound EDS
istio-citadel.istio-system.svc.cluster.local 8060 - outbound EDS
istio-citadel.istio-system.svc.cluster.local 15014 - outbound EDS
istio-egressgateway.istio-system.svc.cluster.local 80 - outbound EDS
...
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 whereto send a request from the productpage
pod to the reviews
pod at reviews:9080
.
If you query the listener summary on a pod you will notice Istio generates the following listeners:
- A listener on
0.0.0.0:15001
that receives all traffic into and out of the pod, then hands the request over toa 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.
- A listener on
172.21.252.250 15005 TCP <--+
172.21.252.250 15011 TCP |
172.21.79.56 42422 TCP |
172.21.160.5 443 TCP |
172.21.157.6 443 TCP |
172.21.117.222 443 TCP |
172.21.0.10 53 TCP |
172.21.126.131 443 TCP | Receives outbound non-HTTP traffic for relevant IP:PORT pair from listener `0.0.0.0_15001`
172.21.160.5 31400 TCP |
172.21.81.159 9102 TCP |
172.21.0.1 443 TCP |
172.21.126.131 80 TCP |
172.21.119.8 443 TCP |
172.21.112.64 80 TCP |
172.21.179.54 443 TCP |
172.21.165.197 443 TCP <--+
0.0.0.0 9090 HTTP <-+
0.0.0.0 8060 HTTP |
0.0.0.0 15010 HTTP |
0.0.0.0 15003 HTTP |
0.0.0.0 15004 HTTP |
0.0.0.0 15014 HTTP | Receives outbound HTTP traffic for relevant port from listener `0.0.0.0_15001`
0.0.0.0 15007 HTTP |
0.0.0.0 8080 HTTP |
0.0.0.0 9091 HTTP |
0.0.0.0 9080 HTTP |
0.0.0.0 80 HTTP <-+
0.0.0.0 15001 TCP // Receives all inbound and outbound traffic to the pod from IP tables and hands over to virtual listener
172.30.164.190 9080 HTTP // Receives all inbound traffic on 9080 from listener `0.0.0.0_15001`
- From the above summary you can see that every sidecar has a listener bound to
0.0.0.0:15001
which is whereIP tables routes all inbound and outbound pod traffic to. This listener hasuseOriginalDst
set to true which meansit hands the request over to the listener that best matches the original destination of the request.If it can’t find any matching virtual listeners it sends the request to thePassthroughCluster
which connects to the destination directly.
$ istioctl proxy-config listeners productpage-v1-6c886ff494-7vxhs --port 15001 -o json
[
{
"name": "virtual",
"address": {
"socketAddress": {
"address": "0.0.0.0",
"portValue": 15001
}
},
"filterChains": [
{
"filters": [
{
"name": "envoy.tcp_proxy",
"config": {
"cluster": "PassthroughCluster",
"stat_prefix": "PassthroughCluster"
}
}
]
}
],
"useOriginalDst": true
}
]
- Our request is an outbound HTTP request to port
9080
this means it gets handed off to the0.0.0.0:9080
virtuallistener. This listener then looks up the route configuration in its configured RDS. In this case it will be lookingup route9080
in RDS configured by Pilot (via ADS).
- The
9080
route configuration only has a virtual host for each service. Our request is heading to the reviewsservice so Envoy will select the virtual host to which our request matches a domain. Once matched on domain Envoylooks for the first route that matches the request. In this case we don’t have any advanced routing so there is onlyone route that matches on everything. This route tells Envoy to send the request to theoutbound|9080||reviews.default.svc.cluster.local
cluster.
$ istioctl proxy-config routes productpage-v1-6c886ff494-7vxhs --name 9080 -o json
[
{
"name": "9080",
"virtualHosts": [
{
"name": "reviews.default.svc.cluster.local:9080",
"reviews.default.svc.cluster.local",
"reviews.default.svc.cluster.local:9080",
"reviews:9080",
"reviews.default.svc.cluster",
"reviews.default.svc.cluster:9080",
"reviews.default.svc",
"reviews.default.svc:9080",
"reviews.default",
"reviews.default:9080",
"172.21.152.34",
"172.21.152.34:9080"
],
"routes": [
{
"match": {
"prefix": "/"
},
"route": {
"cluster": "outbound|9080||reviews.default.svc.cluster.local",
"timeout": "0.000s"
},
...
- This cluster is configured to retrieve the associated endpoints from Pilot (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.
$ 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": {}
},
"serviceName": "outbound|9080||reviews.default.svc.cluster.local"
},
"connectTimeout": "1.000s",
"circuitBreakers": {
"thresholds": [
{}
]
}
}
]
- To see the endpoints currently available for this cluster use the
proxy-config
endpoints command.
$ istioctl proxy-config endpoints productpage-v1-6c886ff494-7vxhs --cluster "outbound|9080||reviews.default.svc.cluster.local"
ENDPOINT STATUS OUTLIER CHECK CLUSTER
172.17.0.17:9080 HEALTHY OK outbound|9080||reviews.default.svc.cluster.local
172.17.0.18:9080 HEALTHY OK outbound|9080||reviews.default.svc.cluster.local
172.17.0.5:9080 HEALTHY OK outbound|9080||reviews.default.svc.cluster.local
Inspecting bootstrap configuration
So far we have looked at configuration retrieved (mostly) from Pilot, however Envoy requires some bootstrap configuration thatincludes information like where Pilot can be found. To view this use the following command:
$ 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": {
"POD_NAME": "istio-ingressgateway-7d6874b48f-qxhn5",
"istio": "sidecar"
},
"buildVersion": "0/1.8.0-dev//RELEASE"
},
...
Verifying connectivity to Pilot is a useful troubleshooting step. Every proxy container in the service mesh should be able to communicate with Pilot. This can be accomplished in a few simple steps:
- Get the name of the Istio Ingress pod:
- Exec into the Istio Ingress pod:
$ kubectl exec -it $INGRESS_POD_NAME -n istio-system /bin/bash
- Test connectivity to Pilot using
curl
. The following example invokes the v1 registration API using default Pilot configuration parameters and mutual TLS enabled:
$ curl -k --cert /etc/certs/cert-chain.pem --cacert /etc/certs/root-cert.pem --key /etc/certs/key.pem https://istio-pilot:8080/debug/edsz
If mutual TLS is disabled:
$ curl http://istio-pilot:8080/debug/edsz
You should receive a response listing the “service-key” and “hosts” for each service in the mesh.
What Envoy version is Istio using?
$ kubectl exec -it PODNAME -c istio-proxy -n NAMESPACE pilot-agent request GET server_info
{
}
Install and use Istio with the Istio CNI plugin, allowing operators to deploy services with lower privilege.
Describes the configuration model for Istio's policy enforcement and telemetry mechanisms.
Describes the telemetry and monitoring features provided by Istio.
Describes the various Istio features focused on traffic routing and control.