Erstes istioctl-Werkzeug bei Vorfall
istioctl proxy-status zeigt Sync-Stand jedes
Sidecars. SYNCED = ACK erhalten, NOT SENT =
nichts zu senden (meist normal), STALE = gesendet, kein
ACK → Netz istiod/Proxy oder Bug, ERROR = NACK
→ Config prüfen.
istioctl proxy-status istioctl proxy-config routes <pod>.<ns> -o json istioctl proxy-config clusters <pod>.<ns> istioctl proxy-config listeners <pod>.<ns> istioctl proxy-config endpoints <pod>.<ns> istioctl proxy-config secrets <pod>.<ns> # Statisches Lint: VirtualService/DR-Konflikte etc. istioctl analyze -n prod # Bug-Report: Konfig + Logs, # Secret-Inhalte nur mit --full-secrets istioctl bug-report
Live-Log eines Sidecars
istioctl proxy-config log <pod> --level debug
setzt das Log-Level live ohne Pod-Restart. Komponenten-spezifisch
z.B. --level rbac:debug,jwt:debug. Nach
Diagnose zurück auf warning.
Häufige Fehlerbilder
404 NR: keine Route, Host- oder Path-Match greift
nicht, Reihenfolge der http[] prüfen.
503 UF: Connect zum Upstream scheitert, App-Port
≠ targetPort oder TLS-Mismatch (DR
DISABLE gegen STRICT).
503 UC: Upstream schließt bestehende
Verbindung, oft Idle-Timeout der App kürzer als Envoy-Pool.
503 UH: kein gesunder Endpoint (Readiness, Outlier
Detection).
OUTPUT_CERTS-Scraping: read: connection reset by peer
App-originated mTLS (Prometheus/Alloy-Federate via
ISTIO_META_OUTPUT_CERTS +
/etc/istio-certs/{cert-chain,key,root-cert}.pem)
bricht mit RST, obwohl Ziel-PeerAuthentication
PERMISSIVE ist und Allow-all greift.
Ursache fast immer: Client-Sidecar wrapt den
App-mTLS in einen zweiten ISTIO_MUTUAL-Tunnel.
Eine DR mit host: "*.local" +
exportTo: ["*"] (typisch STRICT-Migration-Helper in
istio-system) matcht via EndpointSlice-Lookup auch
direkte Pod-IP-Calls. Ergebnis: TLS-in-TLS. Ziel-15006
terminiert nur outer; inner TLS-Bytes landen als Klartext auf
dem App-Port, Backend erwartet HTTP, schließt.
PERMISSIVE ist
Inbound-Entscheidung nach der Transport-Terminierung und
heilt nichts, was outbound passiert.
Fix: excludeOutboundPorts am
Scraper-Pod (port-scoped) oder eigene DR mit
tls.mode: DISABLE auf den Ziel-Service (spezifischer
als *.local, gewinnt).
# wraps der Client-Sidecar?
# alpn=istio* + sni=outbound_ = Beweis:
istioctl pc cluster <pod>.<ns> --fqdn <ziel> -o json \
| jq '.[]|(.transportSocket,
.transportSocketMatches[]?.transportSocket)
|select(.).typedConfig
|{sni,alpn:.commonTlsContext.alpnProtocols}'
# welche *.local-DR greift?
kubectl get dr -A -o json | jq -r '.items[]|
select(.spec.host|test("\\*\\.local"))|
.metadata.namespace+"/"+.metadata.name'