Risoluzione dei problemi relativi al proxy in Cloud Service Mesh

Questo documento spiega i problemi comuni di Cloud Service Mesh e come risolverli. Se hai bisogno di ulteriore assistenza, consulta Ricevere assistenza.

Connessione rifiutata quando si raggiunge un endpoint con Istio

Potresti riscontrare a intermittenza errori di connessione rifiutata (ECONNREFUSED) con la comunicazione dai cluster agli endpoint, ad esempio Memorystore Redis, Cloud SQL o qualsiasi servizio esterno necessario per il carico di lavoro dell'applicazione senza ostacoli.

Questo può verificarsi quando il carico di lavoro dell'applicazione viene avviato più velocemente rispetto container istio-proxy (Envoy) e tenta di raggiungere un endpoint esterno. Poiché in questa fase istio-init (initContainer) è già stato eseguito, ci sono Sono state applicate regole iptables che reindirizzano tutto il traffico in uscita verso Envoy. Dal giorno istio-proxy non è ancora pronto, le regole iptables reindirizzano il traffico a un proxy sidecar non ancora avviato e, pertanto, l'applicazione riceve ECONNREFUSED errore.

I passaggi seguenti spiegano come verificare se questo è l'errore che stai in cui si riscontrano:

  1. Controlla i log di Stackdriver con il seguente filtro per identificare i pod che hanno riscontrato il problema.

    L'esempio seguente mostra un messaggio di errore tipico:

    Error: failed to create connection to feature-store redis, err=dial tcp   192.168.9.16:19209: connect: connection refused
    [ioredis] Unhandled error event: Error: connect ECONNREFUSED
    
  2. Cerca un'occorrenza del problema. Se utilizzi la versione precedente di Stackdriver, quindi usa resource.type="container".

    resource.type="k8s_container"
    textPayload:"$ERROR_MESSAGE$"
    
  3. Espandi l'ultima occorrenza per ottenere il nome del pod, quindi prendi nota di pod_name in resource.labels.

  4. Ottieni la prima occorrenza del problema per quel pod:

    resource.type="k8s_container"
    resource.labels.pod_name="$POD_NAME$"
    

    Output di esempio:

    E 2020-03-31T10:41:15.552128897Z
    post-feature-service post-feature-service-v1-67d56cdd-g7fvb failed to create
    connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect:
    connection refused post-feature-service post-feature-service-v1-67d56cdd-g7fvb
    
  5. Prendi nota del timestamp del primo errore per questo pod.

  6. Usa il filtro seguente per visualizzare gli eventi di avvio dei pod.

    resource.type="k8s_container"
    resource.labels.pod_name="$POD_NAME$"
    

    Output di esempio:

    I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Container image "docker.io/istio/proxyv2:1.3.3" already present on machine  spec.containers{istio-proxy}
    I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Created container  spec.containers{istio-proxy}
    I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Started container  spec.containers{istio-proxy}
    I 2020-03-31T10:41:15Z spec.containers{APP-CONTAINER-NAME} Created container  spec.containers{APP-CONTAINER-NAME}
    W 2020-03-31T10:41:17Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503  spec.containers{istio-proxy}
    W 2020-03-31T10:41:26Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503  spec.containers{istio-proxy}
    W 2020-03-31T10:41:28Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503  spec.containers{istio-proxy}
    W 2020-03-31T10:41:31Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503  spec.containers{istio-proxy}
    W 2020-03-31T10:41:58Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503  spec.containers{istio-proxy}
    
  7. Utilizza i timestamp degli errori e degli eventi di avvio istio-proxy per confermare si verificano quando Envoy non è pronto.

    Se gli errori si verificano mentre il container istio-proxy non è ancora pronto, è normale ottenere errori di connessione rifiutata. Nell'esempio precedente, il pod stava tentando di connettersi a Redis non appena era 2020-03-31T10:41:15.552128897Z, ma a 2020-03-31T10:41:58Z istio-proxy continuava a non superare i controlli di idoneità.

    Anche se il container istio-proxy è stato avviato per primo, è possibile che non è pronto abbastanza velocemente prima che l'app stesse già provando a connettersi all'endpoint esterno.

    Se si tratta del problema che stai riscontrando, continua con i seguenti passaggi per la risoluzione dei problemi.

  8. Annota la configurazione a livello di pod. Questa opzione è disponibile solo nel pod e non a livello globale.

    annotations:
    proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
    
  9. Modifica il codice dell'applicazione in modo che verifichi se Envoy è pronto prima tenta di effettuare altre richieste a servizi esterni. Ad esempio, all'avvio dell'applicazione, avvia un ciclo che invia richieste all'endpoint di salute istio-proxy e continua solo dopo aver ottenuto un codice 200. Il proxy istio l'endpoint di integrità è il seguente:

    http://localhost:15020/healthz/ready
    

Condizione di gara durante l'iniezione di sidecar tra vault e istio

Quando utilizzi vault per la gestione dei secret, a volte vault inietta il sidecar prima di istio, causando il blocco dei pod nello stato Init. In questi casi, i pod creati rimangono bloccati nello stato Init dopo il riavvio di un deployment eseguendo il deployment di uno nuovo. Ad esempio:

E 2020-03-31T10:41:15.552128897Z
post-feature-service post-feature-service-v1-67d56cdd-g7fvb failed to create
connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect:
connection refused post-feature-service post-feature-service-v1-67d56cdd-g7fvb

Questo problema è causato da una condizione di gara, sia Istio che vault iniettano il sidecar e Istio deve essere l'ultimo a farlo, il proxy istio non è in esecuzione durante i contenitori di inizializzazione. Il contenitore init istio configura le regole iptables per reindirizzare tutto il traffico al proxy. Poiché non è ancora in esecuzione, queste regole non reindirizzano a nulla e bloccano tutto il traffico. Questo è il motivo per cui il container init deve essere l'ultimo, quindi il proxy è attivo e in esecuzione subito dopo l'applicazione delle regole iptables configurazione. Purtroppo l'ordine non è deterministico, quindi se viene inserito Istio prima si rompe.

Per risolvere questa condizione, consenti l'indirizzo IP di vault in modo che il traffico l'indirizzo all'IP Vault non viene reindirizzato al proxy Envoy che non è pronto bloccare la comunicazione. Per farlo, è necessario aggiungere una nuova annotazione excludeOutboundIPRanges.

Per Cloud Service Mesh gestito, è possibile solo a livello di deployment o pod sotto spec.template.metadata.annotations, ad esempio:

apiVersion: apps/v1
kind: Deployment
...
...
...
spec:
  template:
    metadata:
      annotations:
        traffic.sidecar.istio.io/excludeOutboundIPRanges:

Per Cloud Service Mesh nel cluster, è disponibile un'opzione per impostarlo come globale con un IstioOperator in spec.values.global.proxy.excludeIPRanges, ad esempio:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  values:
    global:
      proxy:
        excludeIPRanges: ""

Dopo aver aggiunto l'annotazione, riavvia i carichi di lavoro.