Locust EKS Istio 安裝完整歷程:K8s 1.34 版本選型、ARM64 架構、八個除錯問題、Gateway 安裝、NLB 重用決策、跨 namespace xDS 認證失敗¶
文檔資訊
- 分類: architecture
- 難度: advanced
- 預估閱讀時間: 35 分鐘
- 標籤:
istio,eks,k8s-1.34,locust,jenkins,nlb,multi-cluster,dry-run,ci-cd,mesh-naming,crlf,openssl,ca-cert,debugging,crashloopbackoff,istiod,arm64,aarch64,exec-format-error,ecr,multi-arch,imagepullbackoff,istio-1.26.2,istio-1.29.0,docker.io,ca-not-authorized,gateway,helm,nlb-reuse,xds,authentication-failure,namespace-migration
摘要¶
K8s 1.34 升級後,為 Locust EKS cluster 安裝 Istio 1.29.0 的完整歷程。從版本選型(1.26.2 EOL 風險→1.29.0)、ARM64 架構不匹配(私有 ECR amd64 映像→docker.io 官方 multi-arch 解法)、CA 憑證生成(openssl basicConstraints 必要性)、CRLF 換行符問題,到 Gateway 安裝機制(3_3_installGateway.sh 透過 --set key=null 清除 chart 預設值)、NLB 重用決策(patch selector/ports 避免改 DNS),以及跨 namespace xDS 認證失敗(第八個問題)。Jenkins kubeContext:null 靜默失敗有 build #121 完整 log 佐證。
關鍵學習¶
-
K8s 1.34 需要 Istio 1.25+,最終使用 1.29.0(1.26.2 EOL 至 2026/08,之後無官方安全修補)
-
Locust EKS 節點為 ARM64(aarch64),私有 ECR 僅有 amd64 映像,導致 exec format error。最終解法:使用 docker.io 官方 multi-arch 映像
-
openssl 生成 CA 憑證必須包含 basicConstraints: CA:true 和 keyUsage: keyCertSign,否則 istiod 報 certificate is not authorized to sign other certificates
-
CRLF 換行符(Windows 編輯器)導致 env: bash\r: No such file or directory,每次提交前需 dos2unix
-
Helm chart 的 values.yaml 預設值無法被 -f 完全覆蓋,chart 預設 key 仍存在,需用 --set key=null 明確清除
-
ISTIO_DEPLOY_PATH 不能寫死版本號,必須動態跟隨 ISTIO_VERSION 參數,否則路徑仍指向舊版目錄
-
Gateway pod 部署至非 istio-system namespace 時,istio-proxy 與 istiod 的 xDS 連線會報 authentication failure,readiness probe 持續失敗 760 次/29 分鐘
-
透過 JSON Patch NLB Service 的 selector 和 ports 可重用現有 NLB,避免修改 DNS record
-
Jenkins kubeContext:null 時,|| true 吃掉 exit code,pipeline 繼續執行直到最後才 FAILURE(build #121 血淋淋教訓)
技術細節¶
Istio 版本相容性¶
K8s 1.34 需要 Istio 1.25+,最終成功安裝版本為 1.29.0。
- Istio 1.26.2:EOL 警告,官方支援至 2026 年 8 月,之後停止安全修補
- Istio 1.29.0:最終成功版本,使用
docker.io官方 multi-arch 映像(同時支援 amd64/arm64)
問題一:CRLF 換行符¶
Windows 編輯器儲存腳本含 CRLF 換行符,Linux 執行失敗:
修正:每次從 Windows 編輯後執行 dos2unix。
問題二:Docker 不可用¶
2_genClusterIstioCA.sh 原先依賴 Docker 生成 CA 憑證,改用 openssl 直接生成,消除 Docker 依賴。
問題三:ISTIO_DEPLOY_PATH 雙重問題¶
腳本存在兩個問題:(1) fallback 邏輯指向舊版 istio-1.24.1;(2) 腳本內有硬寫死的版本號。
錯誤輸出:使用 fallback deploy 目錄:/aws/base_helm/istio/istio-1.24.1/deploy,而非 1.26.2 或 1.29.0。需同時修正兩處,確保路徑動態跟隨 ISTIO_VERSION 參數。
問題四(根本原因):ARM64 架構不匹配¶
Locust EKS 節點架構(實際確認):
私有 ECR 中的 Istio 映像為 amd64,無法在 ARM64 節點執行,錯誤訊息:
問題五:私有 ECR 無 1.29.0 映像¶
升級至 1.29.0 後,私有 ECR 根本沒有對應版本的映像(ImagePullBackOff),ECR 路徑:313249118980.dkr.ecr.ap-southeast-1.amazonaws.com/ps-ecr-repo/istio/pilot:1.29.0: not found。
最終解法:docker.io 官方 multi-arch 映像¶
在 3_2_installIstio.sh 加入 ISTIO_HUB 參數,設定為 docker.io 時跳過私有 ECR,直接使用官方映像。
問題六/七:CA 憑證缺少 CA 約束¶
openssl 生成憑證時必須加入:
否則 istiod 報:certificate is not authorized to sign other certificates
Gateway 安裝機制(3_3_installGateway.sh)¶
3_3_installGateway.sh 動態生成最小化 values YAML,並透過 --set key=null 清除 Helm chart 預設值(ALB ingress、TCP ports 等),確保 locust-eks 只部署 HTTP port 80 的 gateway。
dry-run 輸出(已驗證)確認以下方式可正確清除 chart 預設值:
helm upgrade istio-ingress-gateway /aws/helm/IstioGateway \
--install -n istio-system --kube-context locust-eks \
-f /tmp/gateway-values-locust-eks.yaml \
--set gatewayMap.alb-ingress-gateway-dev=null \
--set gatewayMap.ingressgateway-dev.servers.testRule=null \
--set gatewayMap.ingressgateway-dev.servers.testRule2=null \
--set gatewayMap.ingressgateway-dev.servers.redisRuleMaster1=null \
--set gatewayMap.ingressgateway-dev.servers.valkeyRuleMaster2=null \
--set gatewayMap.ingressgateway-dev.servers.postgreSqlRule=null \
--set gatewayMap.ingressgateway-dev.servers.rdsSqlRule=null \
--set albIngressMap.alb-ingress-dev=null
第八個問題:跨 namespace xDS 認證失敗¶
Gateway pod 部署至 loadtest namespace 後,istio-proxy 與 istiod.istio-system.svc:15012 建立 xDS gRPC 連線失敗:
DeltaAggregatedResources gRPC config stream to xds-grpc closed: 16, authentication failure{via_upstream}
upstream terminated with unexpected error rpc error: code = Unauthenticated desc = authentication failure
Readiness probe 持續報 connection refused on port 15021,Pod 狀態為 Unhealthy(760 次失敗/29分鐘)。
根本原因:Istio 的 trust domain 驗證基於 SPIFFE URI,格式為 spiffe://<trust-domain>/ns/<namespace>/sa/<serviceaccount>。istiod 預設只信任 istio-system namespace 的 gateway,loadtest namespace 的 gateway pods 的 SA token 不在信任域內,導致 mTLS 握手失敗。
Jenkins kubeContext:null 靜默失敗(build #121 完整 log)¶
build #121 log 直接呈現完整靜默失敗鏈:
kubeContext: null
error: context "null" does not exist
++ true ← || true 吃掉 exit code
No pods found matching ps-func-web-beta
ECR push 成功(#839, #840 均 SUCCESS),但 pod restart 完全跳過,pipeline 最終才以 FAILURE 結束。
What Changed¶
Jenkins build #121 完整 log 確認靜默失敗鏈:直接呈現 kubeContext: null → error: context "null" does not exist → || true 吃掉 exit code 的完整靜默失敗鏈,確認 ECR push(#839, #840)成功但 pod restart 被跳過的實際順序。這是最直接的佐證,不再是推論。
第八個問題的完整錯誤 log:authentication failure{via_upstream} 和 code = Unauthenticated desc = authentication failure 的完整輸出,以及 readiness probe 在 port 15021 持續失敗(760 次/29分鐘)的事件記錄,補強了跨 namespace xDS 信任域問題的技術細節。
NLB 重用方案的 dry-run 驗證:3_4_migrateGatewayToLoadtest.sh --dry-run 的完整輸出確認了 JSON Patch 方案的可行性,patch 後 locust-mingo-locust-master 的 selector 指向 {app: istio-ingressgateway-dev, istio: ingressgateway},NLB endpoint 完全不需變動。
So What¶
本案例完整揭示了將 Istio 部署到 ARM64 EKS cluster 的四層陷阱,每一層都有不直觀的錯誤訊息:
- 架構層:
exec format error看起來像映像損壞,實際是 amd64/arm64 不匹配 - 映像層:私有 ECR 版本落後,升版後立即 ImagePullBackOff
- 憑證層:
certificate is not authorized to sign在 CA 約束缺失時才出現,容易誤判 - 信任域層(新確認):Gateway 跨 namespace 部署時,
authentication failure不直觀,容易誤判為網路問題,readiness probe 持續 760 次失敗是可量化的症狀
NLB 重用決策的模式(patch selector/ports 而非建新 NLB 改 DNS)是生產環境遷移的標準手法,有 dry-run 輸出驗證可行性,值得作為組織內的標準 SOP。
Jenkins || true 吃掉 exit code 導致靜默失敗的模式,在 CI/CD pipeline 中非常危險,build #121 是實際血淋淋的教訓。
Trade-offs¶
- NLB vs ALB:使用 NLB。延遲更低、成本更低;缺少 WAF、path routing 等 L7 功能,但 loadtest 場景已足夠
- 改 DNS vs patch NLB selector:patch selector。零停機、無 DNS TTL 等待;代價是 Service 的 selector/ports 與原始設計分離,需文件記錄
- Gateway 在 istio-system vs loadtest:istio-system 是預設位置,RBAC/trust domain 問題少;loadtest 可重用現有 NLB,但需額外配置 istiod 信任域,否則 xDS 認證失敗(目前未解)
- openssl vs docker 生成 CA 憑證:使用 openssl。消除 Docker 依賴;但必須確保 CA 約束參數正確(basicConstraints, keyUsage)
- 私有 ECR vs 官方 docker.io multi-arch 映像:使用官方 docker.io。無需維護多架構映像推送;代價是依賴外網拉取(需 NAT Gateway)
- 1.26.2 vs 1.29.0:使用 1.29.0。支援期更長(1.26.2 EOL 2026/08);但私有 ECR 需額外準備(本次改用官方映像繞過)
Try It Fast¶
# 0. 修正 CRLF 換行符(每次從 Windows 編輯後必做)
dos2unix 3_2_installIstio.sh 2_genClusterIstioCA.sh 3_3_installGateway.sh 3_4_migrateGatewayToLoadtest.sh
# 1. 確認節點架構(aarch64 = ARM64 = 需要 multi-arch 映像)
kubectl --context locust-eks get nodes -o wide
# 2. 安裝 Istio 1.29.0(docker.io hub,支援 arm64 multi-arch)
./3_2_installIstio.sh --dry-run dev ap-southeast-1 locust-eks 313249118980 1.29.0 locust-eks "loadtest"
./3_2_installIstio.sh dev ap-southeast-1 locust-eks 313249118980 1.29.0 locust-eks "loadtest"
# 3. 安裝後驗證(istiod + ingressgateway-dev 應 1/1 Running)
kubectl --context locust-eks get pods -n istio-system
# 4. 建立 Gateway(只含 HTTP port 80)
./3_3_installGateway.sh --dry-run locust-eks dev-locust.pocket-store.make-wish.club
./3_3_installGateway.sh locust-eks dev-locust.pocket-store.make-wish.club
# 5. 遷移 Gateway 至 loadtest(重用現有 NLB,不改 DNS)
./3_4_migrateGatewayToLoadtest.sh --dry-run locust-eks
./3_4_migrateGatewayToLoadtest.sh locust-eks
# 6. 即時診斷
kubectl --context locust-eks logs -n istio-system -l app=istiod --tail=20
# exec format error = 架構不匹配(hub 仍指向 amd64 映像)
# ImagePullBackOff = ECR 無對應版本映像
# certificate is not authorized to sign = CA 憑證缺少 CA 約束
# authentication failure = Gateway pod 跨 namespace,xDS 信任域未配置
# 7. 修復 CA 憑證問題
kubectl --context locust-eks delete secret cacerts -n istio-system
# 重新執行安裝腳本(會重新生成正確的 CA 憑證)
# 8. 診斷 xDS 認證失敗(Gateway 在非 istio-system namespace)
kubectl --context locust-eks logs -n loadtest -l app=istio-ingressgateway-dev --tail=20
kubectl --context locust-eks get authorizationpolicy -n istio-system
Recommendation¶
- 已完成:Istio 1.29.0 成功安裝(docker.io 官方 multi-arch 映像),istiod 和 ingressgateway-dev 均
1/1 Running - 已完成:Gateway 資源建立(
3_3_installGateway.sh),只含 HTTP port 80,host 為dev-locust.pocket-store.make-wish.club - 待解決(最優先):xDS 認證失敗:Gateway pod 在 loadtest namespace 持續報
authentication failure(760 次/29 分鐘)。診斷方向:確認 istiod 的AuthorizationPolicy是否限制來源 namespace;確認MeshConfig.trustDomain設定;若問題複雜,可改回 istio-system 部署,直接更新 DNS record 指向新 NLB endpointae8d4d53caccc40c5add507ee42cb60f-07a04c45a623e737.elb.ap-southeast-1.amazonaws.com - 修復 Jenkins kubeContext:null:在 Configure stage 加入
if (!kubeContext) error('kubeContext 不能為空'),防止靜默失敗(build #121 已佐證此 bug) - CA 憑證生成標準化:確保
2_genClusterIstioCA.sh包含-addext 'basicConstraints=critical,CA:true'和-addext 'keyUsage=critical,keyCertSign,cRLSign' - 建立 dos2unix 慣例:腳本提交前確認換行符為 LF,或在 CI/CD pipeline 加入自動 dos2unix
- ECR 映像管理:若之後需改回私有 ECR,每次升級前先確認 ECR 有對應版本的 ARM64 映像