#!/usr/bin/env bash # T55: DR tcpKeepalive time/interval/probes -> per-socket override, not netns sysctl change. # # IMPORTANT ENVIRONMENTAL NOTE (discovered during verification): # This cluster's kubeadm/coredns clusterDomain is "homelab.local", but Istio's internal # service registry / route-table domain is (unconfigured) "cluster.local". Consequence: # 1. A DestinationRule with host=*.svc.homelab.local matches NO service in the mesh # (istioctl analyze -> IST0174) and is therefore a silent no-op. # 2. Even with the DR host fixed to *.svc.cluster.local, HTTP requests whose Host header # is the homelab.local FQDN don't match any RDS virtual-host domain on the shared # 0.0.0.0_80 listener, so they fall through to PassthroughCluster (200 OK, but ALL # per-service Istio policy silently bypassed). # This script therefore applies the manifest as specified, but for the actual functional # check patches the DR host to the cluster's real registry name and reaches the service via # the bare short name ("echo"), which IS a registered virtual-host alias, so the request # actually lands on the DR-governed Envoy cluster. set -euo pipefail NS=istio-vt-t55 DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cleanup() { echo "[cleanup] deleting namespace ${NS}" kubectl delete namespace "${NS}" --wait=false --ignore-not-found } trap cleanup EXIT echo "[setup] creating namespace ${NS}" kubectl create namespace "${NS}" kubectl label namespace "${NS}" istio-injection=enabled echo "[apply] manifest.yaml (as specified, host=*.svc.homelab.local)" kubectl apply -f "${DIR}/manifest.yaml" echo "[wait] client pod Ready" kubectl -n "${NS}" wait --for=condition=Ready pod/client --timeout=90s echo "[wait] echo deployment rollout" kubectl -n "${NS}" rollout status deploy/echo --timeout=120s echo "[baseline] sysctl net.ipv4.tcp_keepalive_time BEFORE traffic" kubectl -n "${NS}" exec client -c istio-proxy -- sysctl net.ipv4.tcp_keepalive_time echo "[fix] istioctl analyze (expect IST0174 host-mismatch warning against the spec manifest)" istioctl analyze -n "${NS}" || true echo "[fix] patching DR host to match Istio's actual service registry (svc.cluster.local)" kubectl -n "${NS}" patch destinationrule echo-keepalive-socket --type merge \ -p "{\"spec\":{\"host\":\"echo.${NS}.svc.cluster.local\"}}" sleep 3 istioctl analyze -n "${NS}" || true echo "[traffic] two requests via bare short name 'echo' (registered virtual-host alias, DNS-resolvable)" kubectl -n "${NS}" exec client -c curl -- sh -c \ 'curl -s -o /dev/null -w "curl1 http_code=%{http_code}\n" http://echo/ & sleep 2; curl -s -o /dev/null -w "curl2 http_code=%{http_code}\n" http://echo/' echo "[observe] cluster stats (confirm request landed on the DR-governed named cluster, not PassthroughCluster)" kubectl -n "${NS}" exec client -c istio-proxy -- pilot-agent request GET clusters 2>/dev/null \ | grep -E "^outbound\|80\|\|echo\.${NS}|^PassthroughCluster" | grep -E "cx_active|cx_total" echo "[observe] ss -to (expect timer:(keepalive,<~45s>,0) on the client->echo-pod:8080 socket)" kubectl -n "${NS}" exec client -c istio-proxy -- ss -tno echo "[re-check] sysctl net.ipv4.tcp_keepalive_time AFTER traffic (expect unchanged, 7200)" kubectl -n "${NS}" exec client -c istio-proxy -- sysctl net.ipv4.tcp_keepalive_time echo "[done] see result.txt in this directory for the annotated capture from the original run."