#!/usr/bin/env bash # T65 - Routing chain diagnosis: NC (route -> cluster not in CDS) vs UH (cluster in CDS, # 0 healthy endpoints in EDS) produce distinct Envoy response flags. # # IMPORTANT ENVIRONMENT NOTE (see result.txt for full diagnosis): # This cluster's kubeadm/CoreDNS clusterDomain is "homelab.local", but Istio's # proxy.clusterDomain / service registry hostname convention (used by DestinationRule # host / VirtualService destination.host / CDS cluster naming) is still the default # "cluster.local" (NOT reconfigured to match). Therefore: # - VirtualService `hosts:` (route/domain match against the request's Host header) # MUST use the real DNS domain: *.svc.homelab.local # - DestinationRule `host:` and VirtualService route `destination.host` MUST use # the Istio-registered service hostname: *.svc.cluster.local # Mixing these up (e.g. using svc.homelab.local for DestinationRule host) causes ALL # subset clusters -- including the "healthy" baseline -- to never compile into CDS, # producing NC for everything. This convention was cross-validated against the # pre-existing working namespace `mesh-test` in this same cluster (its DestinationRules # use *.svc.cluster.local host for in-mesh services). set -euo pipefail NS="istio-vt-t65" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cleanup() { echo "[cleanup] deleting namespace ${NS}" kubectl delete namespace "${NS}" --wait=false --ignore-not-found >/dev/null 2>&1 || true } trap cleanup EXIT echo "[setup] creating namespace ${NS}" kubectl create namespace "${NS}" kubectl label namespace "${NS}" istio-injection=enabled echo "[setup] applying manifest.yaml" kubectl apply -f "${SCRIPT_DIR}/manifest.yaml" echo "[wait] client pod Ready" kubectl -n "${NS}" wait --for=condition=Ready pod/client --timeout=90s echo "[wait] chain-echo-v1 deployment available" kubectl -n "${NS}" wait --for=condition=available deploy/chain-echo-v1 --timeout=60s echo "[wait] letting xDS config propagate to sidecar" sleep 5 echo "[test] baseline (expect 200)" kubectl -n "${NS}" exec client -c curl -- curl -s -o /dev/null -w 'baseline_v1=%{http_code}\n' \ http://chain-echo."${NS}".svc.homelab.local/ echo "[test] nc_case (expect 503, response flag NC cluster_not_found)" kubectl -n "${NS}" exec client -c curl -- curl -s -o /dev/null -w 'nc_case=%{http_code}\n' \ -H 'x-target: nc' http://chain-echo."${NS}".svc.homelab.local/ echo "[observe] recent istio-proxy access log (client sidecar)" kubectl -n "${NS}" logs client -c istio-proxy --since=20s | tail -5 echo "[observe] CDS cluster count containing v2-undefined-in-dr (expect 0 -- never compiled)" istioctl proxy-config cluster "client.${NS}" -o json | \ jq '[.[] | select(.name | contains("v2-undefined-in-dr"))] | length' echo "[test] uh_case (expect 503, response flag UH no_healthy_upstream)" kubectl -n "${NS}" exec client -c curl -- curl -s -o /dev/null -w 'uh_case=%{http_code}\n' \ -H 'x-target: uh' http://chain-echo."${NS}".svc.homelab.local/ echo "[observe] endpoints for v3-mismatched-selector cluster (expect empty table -- cluster exists, 0 endpoints)" istioctl proxy-config endpoint "client.${NS}" \ --cluster "outbound|80|v3-mismatched-selector|chain-echo.${NS}.svc.cluster.local" echo "[observe] recent istio-proxy access log (client sidecar)" kubectl -n "${NS}" logs client -c istio-proxy --since=20s | tail -5 echo "[done] T65 checks complete"