Proxyprobleme in Anthos Service Mesh beheben

In diesem Dokument werden häufige Probleme mit Anthos Service Mesh und deren Behebung erläutert. Weitere Informationen finden Sie unter Support.

Verbindung abgelehnt, wenn ein Endpunkt mit Istio erreicht wird

Bei der Kommunikation von Ihren Clustern zu Ihren Endpunkten können zeitweise Fehler aufgrund einer abgelehnten Verbindung (ECONNREFUSED) auftreten, z. B. Memorystore Redis, Cloud SQL oder einen externen Dienst, den Ihre Anwendungsarbeitslast erreichen muss.

Dieser Fehler kann auftreten, wenn Ihre Anwendungsarbeitslast schneller initiiert wird als deristio-Proxy-Container (Envoy) und versucht, einen externen Endpunkt zu erreichen. Da in dieser Phase istio-init (initContainer) bereits ausgeführt wurde, sind iptables-Regeln vorhanden, die den gesamten ausgehenden Traffic an Envoy weiterleiten. Da istio-proxy noch nicht bereit ist, leiten die iptables-Regeln den Traffic an einen noch nicht gestarteten Sidecar-Proxy weiter. Daher erhält die Anwendung den Fehler ECONNREFUSED.

In den folgenden Schritten wird beschrieben, wie Sie prüfen können, ob dieser Fehler auftritt:

  1. Prüfen Sie die Google Cloud-Beobachtbarkeitslogs mit dem folgenden Filter, um herauszufinden, bei welchen Pods das Problem aufgetreten ist.

    Das folgende Beispiel zeigt eine typische Fehlermeldung:

    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. Prüfen Sie die Google Cloud-Beobachtbarkeitslogs mit dem folgenden Filter, um zu bestätigen, dass der Istio-Proxy-Container (Envoy) nicht bereit ist.

     resource.labels.pod_name="$POD_FROM_STEP_1$"
     resource.type="k8s_container"
     resource.labels.container_name="istio-proxy"
     textPayload:"Envoy proxy is NOT ready"
    
  3. Suchen Sie nach einem Vorkommen des Problems. Wenn Sie Legacy-Stackdriver verwenden, verwenden Sie resource.type="container".

    resource.type="k8s_container"
    textPayload:"$ERROR_MESSAGE$"
    
  4. Maximieren Sie das letzte Vorkommen, um den Namen des Pods zu erhalten, und notieren Sie sich dann den pod_name unter resource.labels.

  5. Ermitteln Sie, wann das Problem zum ersten Mal für diesen Pod aufgetreten ist:

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

    Beispielausgabe:

    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
    
  6. Notieren Sie sich den Zeitstempel des ersten Fehlers für diesen Pod.

  7. Verwenden Sie den folgenden Filter, um die Pod-Startereignisse aufzurufen.

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

    Beispielausgabe:

    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}
    
  8. Verwenden Sie die Zeitstempel von Fehlern und istio-proxy-Startereignisse, um zu prüfen, ob die Fehler auftreten, wenn Envoy nicht bereit ist.

    Wenn die Fehler auftreten, während der istio-proxy-Container noch nicht bereit ist, erhalten Sie normalerweise Fehlermeldungen, weil die Verbindung abgelehnt wurde. Im vorherigen Beispiel versuchte der Pod, eine Verbindung zu Redis herzustellen, sobald 2020-03-31T10:41:15.552128897Z, aber von 2020-03-31T10:41:58Z istio-proxy immer noch die Bereitschaftsprüfungen fehlschlug.

    Obwohl der istio-proxy-Container zuerst gestartet wurde, ist es möglich, dass er nicht schnell genug bereit war, bevor die Anwendung bereits versuchte, eine Verbindung zum externen Endpunkt herzustellen.

    Wenn dies das Problem ist, fahren Sie mit den folgenden Schritten zur Fehlerbehebung fort.

  9. Versehen Sie die Konfiguration auf Pod-Ebene. Diese Option ist nur auf Pod-Ebene und nicht auf globaler Ebene verfügbar.

    annotations:
    proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
    
  10. Ändern Sie den Anwendungscode so, dass geprüft wird, ob Envoy bereit ist, bevor versucht wird, weitere Anfragen an externe Dienste zu senden. Initiieren Sie beispielsweise beim Start der Anwendung eine Schleife, die Anfragen an den istio-proxy-Gesundheitsendpunkt sendet und erst dann fortgesetzt wird, wenn ein 200-Fehler empfangen wird. Der istio-proxy-Systemdiagnoseendpunkt ist so:

    http://localhost:15020/healthz/ready
    

Race-Bedingung während Sidecar-Injektion zwischen Vault und Istio

Wenn Sie vault für die Secret-Verwaltung verwenden, fügt vault manchmal die Sidecar-Datei vor istio ein. Dadurch bleiben Pods im Status Init hängen. In diesem Fall verbleiben die erstellten Pods nach dem Neustart einer Bereitstellung oder der Bereitstellung einer neuen Bereitstellung im Init-Status. Beispiel:

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

Dieses Problem wird durch eine Race-Bedingung verursacht. Sowohl Istio als auch vault fügen das Sidecar und Istio als Letztes ein. Der istio-Proxy wird in Init-Containern nicht ausgeführt. Der Init-Container istio richtet iptables-Regeln ein, um den gesamten Traffic an den Proxy weiterzuleiten. Da sie noch nicht ausgeführt wird, werden durch diese Regeln keine Weiterleitungen ausgeführt, sodass der gesamte Traffic blockiert wird. Aus diesem Grund muss der Init-Container der letzte sein, sodass der Proxy sofort nach dem Einrichten der iptables-Regeln aktiv ist und ausgeführt wird. Leider ist die Reihenfolge nicht deterministisch. Wenn Istio also zuerst eingeschleust wird, funktioniert es nicht.

Um diesen Fehler zu beheben, müssen Sie die IP-Adresse vault zulassen, damit der an die Vault-IP-Adresse gehende Traffic nicht an den Envoy-Proxy weitergeleitet wird, der noch nicht bereit ist und die Kommunikation daher blockiert. Dazu muss eine neue Annotation mit dem Namen excludeOutboundIPRanges hinzugefügt werden.

Bei einem verwalteten Anthos Service Mesh ist dies nur auf Deployment- oder Pod-Ebene unter spec.template.metadata.annotations möglich. Beispiel:

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

Anthos Service Mesh im Cluster kann mit einem IstioOperator unter spec.values.global.proxy.excludeIPRanges als globales Netzwerk festgelegt werden. Beispiel:

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

Starten Sie Ihre Arbeitslasten neu, nachdem Sie die Annotation hinzugefügt haben.