Risoluzione dei problemi del proxy in Anthos Service Mesh

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

Connessione rifiutata quando si raggiunge un endpoint con Istio

Potresti riscontrare a intermittenza errori di connessione rifiutata (ECONNREFUSED) nella comunicazione dai cluster agli endpoint, ad esempio Memorystore Redis, Cloud SQL o qualsiasi servizio esterno che il carico di lavoro delle applicazioni deve raggiungere.

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

I passaggi seguenti spiegano come verificare se si tratta dell'errore che stai riscontrando:

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

    L'esempio seguente mostra un tipico messaggio di errore:

    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 legacy di Stackdriver, utilizza 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 il pod in questione:

    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 di questo pod.

  6. Utilizza 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 che gli errori si verificano quando Envoy non è pronto.

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

    Anche se il container istio-proxy è stato avviato per primo, è possibile che non sia diventato pronto abbastanza rapidamente prima che l'app stesse già tentando di connettersi all'endpoint esterno.

    Se questo è il tuo problema, continua con la seguente procedura di risoluzione dei problemi.

  8. Annota la configurazione a livello di pod. Questa opzione è disponibile solo a livello di 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 di provare a effettuare altre richieste ai servizi esterni. Ad esempio, all'avvio dell'applicazione, avvia un loop che invia richieste all'endpoint di integrità istio-proxy e continua solo una volta ottenuto un valore 200. L'endpoint di integrità istio-proxy è il seguente:

    http://localhost:15020/healthz/ready
    

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

Quando utilizzi vault per la gestione dei secret, a volte vault inserisce il file collaterale prima di istio, causando il blocco dei pod nello stato Init. In questo caso, i pod creati si bloccano nello stato di inizializzazione dopo il riavvio di un deployment o l'esecuzione del deployment di un nuovo deployment. 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 race condition, sia Istio che vault inseriscono il file collaterale e Istio devono essere l'ultimo a farlo. Il proxy istio non è in esecuzione durante i container di inizializzazione. Il contenitore di inizializzazione istio configura le regole iptables per reindirizzare tutto il traffico al proxy. Poiché non è ancora in esecuzione, queste regole non reindirizzano a niente, bloccando tutto il traffico. Questo è il motivo per cui il container init deve essere l'ultimo, in modo che il proxy sia attivo e in esecuzione subito dopo la configurazione delle regole iptables. Sfortunatamente, l'ordine non è deterministico, quindi se Istio viene inserito prima, non funziona.

Per risolvere i problemi di questa condizione, consenti l'indirizzo IP di vault in modo che il traffico verso l'IP Vault non venga reindirizzato al proxy Envoy che non è ancora pronto e, di conseguenza, blocca la comunicazione. A tal fine, deve essere aggiunta una nuova annotazione denominata excludeOutboundIPRanges.

Per Anthos Service Mesh gestito, questa operazione è possibile solo a livello di deployment o pod in spec.template.metadata.annotations, ad esempio:

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

Per Anthos Service Mesh nel cluster, esiste 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.