Risoluzione dei problemi di avvio dei carichi di lavoro in Cloud Service Mesh

Questo documento illustra i problemi comuni di Cloud Service Mesh e come risolverli. Per ulteriore assistenza, consulta Assistenza.

Connessione rifiutata quando si raggiunge un endpoint Cloud Service Mesh

Potresti riscontrare intermittentemente errori di connessione rifiutata (ECONNREFUSED) con la comunicazione dai tuoi cluster ai tuoi endpoint, ad esempio Memorystore Redis, Cloud SQL o qualsiasi servizio esterno che il tuo workload dell'applicazione deve raggiungere.

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, sono presenti regole iptables che reindirizzano tutto il traffico in uscita a Envoy. Poiché Istio-Proxy non è ancora pronto, le regole iptables reindirizzeranno il traffico a un proxy sidecar non ancora avviato e, di conseguenza, l'applicazione riceverà l'errore ECONNREFUSED.

I passaggi che seguono descrivono in dettaglio come verificare se si tratta dell'errore che stai riscontrando:

  1. Controlla i log di Stackdriver con il seguente filtro per identificare i pod ha 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 Stackdriver legacy, 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:

    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. Utilizza il seguente filtro per visualizzare gli eventi di avvio del 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 quando il contenitore istio-proxy non è ancora pronto, è normale ricevere errori di connessione rifiutata. Nell'esempio precedente, il pod tentava di connettersi a Redis non appena 2020-03-31T10:41:15.552128897Z ma da 2020-03-31T10:41:58Z istio-proxy stava ancora non superando i probe di idoneità.

    Anche se il contenitore istio-proxy è stato avviato per primo, è possibile che non sia stato pronto abbastanza rapidamente prima che l'app tentasse già di 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 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 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. L'endpoint istio-proxy health è il seguente:

    http://localhost:15020/healthz/ready
    

Condizione di gara durante l'inserimento di file collaterali tra Vault e Cloud Service Mesh

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 questi casi, i pod creati rimangono bloccati nello stato di inizializzazione dopo aver riavviato un deployment o ne aver eseguito 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 race condition. Sia Istio che vault inseriscono il valore il sidecar e Istio devono essere gli ultimi a eseguire questa operazione, il proxy istio non è in esecuzione durante i container init. 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. Per questo motivo, il contenitore init deve essere l'ultimo, in modo che il proxy sia attivo e funzionante immediatamente dopo la configurazione delle regole iptables. Purtroppo l'ordine non è deterministico, quindi se Istio viene inserito pirmo si arresta in modo anomalo.

Per risolvere il problema, consenti l'indirizzo IP di vault in modo che il traffico diretto all'IP di Vault non venga reindirizzato al proxy Envoy, che non è ancora pronto e quindi blocca la comunicazione. A questo scopo, viene creata una nuova annotazione denominato excludeOutboundIPRanges.

Per Cloud Service Mesh gestito, è possibile solo a livello di deployment o pod livello inferiore a 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 una con un IstioOperator in spec.values.global.proxy.excludeIPRanges, per esempio:

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

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