EKS Pod 無法連外網導致 MSK IAM Auth JAR 缺失:診斷流程、emptyDir 驗證與腳本自動化修復(融合演化版 v3)¶
文檔資訊
- 分類: debugging
- 難度: intermediate
- 預估閱讀時間: 7 分鐘
- 標籤:
kafka,msk,iam-auth,eks,kubernetes,jenkins,network-policy,java-classpath,emptyDir,kubectl-patch,automation
摘要¶
Jenkins Pipeline 呼叫 kafka-client pod 執行 kafka-topics.sh 時,因 aws-msk-iam-auth JAR 不在 classpath 而拋出 ConfigException。根本原因是 EKS pod 被網路政策封鎖無法從 Maven Central 下載 JAR,且 JAR 存放於 emptyDir volume。本文記錄完整的問題生命週期:問題發現 → 根本原因分析 → emptyDir 清空實際驗證 → kubectl cp 應急 → 自動化修復腳本(CLASSPATH patch + JAR 複製)執行。
關鍵學習¶
-
EKS pod 在限制性網路環境下,runtime curl 下載依賴會靜默失敗(只印 WARN 繼續 sleep),導致工具呼叫時 classpath 不完整
-
Invalid value ... Class could not be found這類 Kafka ConfigException 通常代表 JAR 不在 classpath,而非設定值錯誤 -
emptyDir volume 的 JAR 在 pod 重啟後消失——已透過 kubectl rollout restart 實際驗證(Build #236 再次失敗即為佐證)
-
kubectl cp 是有效的應急手段,但只能維持到下次 pod 重啟
-
修復腳本結合 CLASSPATH patch + kubectl cp 可作為更完整的應急方案,但 CLASSPATH 環境變數顯示為空需要後續驗證
-
正確的永久修法是將 JAR 打入 Docker image,或透過 init container 從內部 artifact repository 取得
技術細節¶
錯誤訊息分析¶
Invalid value software.amazon.msk.auth.iam.IAMClientCallbackHandler
for configuration sasl.client.callback.handler.class:
Class software.amazon.msk.auth.iam.IAMClientCallbackHandler could not be found.
org.apache.kafka.common.config.ConfigException
Kafka Admin Client 初始化時找不到 aws-msk-iam-auth-*-all.jar 中的類別,不是設定錯誤,是 JAR 缺失問題。
Deployment 架構問題¶
kafka-client deployment 的啟動腳本嘗試從 Maven Central 下載 JAR:
curl -fsSL --retry 5 -o /opt/msk/lib/aws-msk-iam-auth.jar \
https://repo1.maven.org/maven2/software/amazon/msk/aws-msk-iam-auth/2.3.2/aws-msk-iam-auth-2.3.2-all.jar
EKS pod 無法連外網(curl: (7) Failed to connect to repo1.maven.org port 443),下載失敗後只印 WARN 並執行 sleep infinity,Pod 狀態顯示 Running 但 JAR 未就位。
emptyDir 問題(已實際驗證)¶
JAR 存放路徑 /opt/msk/lib(掛載為 emptyDir volume)。kubectl rollout restart 後直接確認:
ls: cannot access '/opt/bitnami/kafka/libs/aws-msk-iam-auth.jar': No such file or directory
command terminated with exit code 2
這是造成問題反覆出現的根本原因:每次 pod 重啟(包含正常的 rolling update、node 重新調度)都會清空 emptyDir,JAR 不復存在。
修復腳本執行結果(v3 新增)¶
本次執行了一個自動化修復腳本,策略為:kubectl patch 設定 CLASSPATH 環境變數 + kubectl cp 複製 JAR。
腳本執行成功,JAR 已確認存在:
但有一個值得注意的異常:
CLASSPATH 環境變數顯示為空,可能代表 patch 的變數名稱或注入方式有誤,或是 bitnami/kafka 不透過 CLASSPATH 環境變數載入額外 JAR(而是掃描 /opt/bitnami/kafka/libs/ 目錄)。由於 JAR 已在 libs 目錄中,實際功能應已恢復,但 CLASSPATH 這個問題值得後續確認。
What Changed¶
本次對話(v3)在 v2 確認 emptyDir 清空問題的基礎上,進一步執行了自動化修復腳本。
問題再次發生(Build #236):證明了之前的 kubectl cp 修復確實因 pod 重新調度或重啟而失效,問題在完全相同的 ConfigException 下再度出現。這將舊文檔中對問題「必然復現」的預測,轉化為可觀察的事實。
執行自動化修復腳本:腳本執行了 6 個步驟——patch deployment(CLASSPATH)、restart pod、等待就緒、下載 JAR、上傳 JAR、驗證存在。各步驟均成功,JAR(14M)已確認在 /opt/bitnami/kafka/libs/ 中。
CLASSPATH 環境變數為空的異常:腳本最後確認 CLASSPATH 顯示為空,這可能代表 CLASSPATH patch 方案的實際效用有待驗證。Bitnami Kafka image 的 JAR 載入機制(目錄掃描 vs 環境變數)需要進一步確認。
So What¶
這個場景是一個典型的 Anti-Pattern 完整生命週期示範:在限制性網路環境的 Kubernetes pod 中依賴 runtime 從公網下載依賴。
現在有完整的證據鏈:「問題 → 根本原因分析 → 應急修復 → 應急修復失效驗證 → 自動化修復腳本執行」。CLASSPATH 顯示為空這個異常也提醒工程師:即使腳本「成功」,也需要確認各修復步驟的實際效果,不能只看 exit code。
在私有 EKS cluster 環境中,任何依賴外網下載的機制都是不可靠的,且失敗是靜默的,容易讓人誤以為 pod 正常運作。
Trade-offs¶
- emptyDir + runtime 下載:輕量易部署,但依賴外網,私有 EKS cluster 環境必然失效,且失敗靜默
- JAR 打入 Docker image:最可靠且不依賴外網,但需重新 build image,版本更新需重新打包
- init container + 私有 artifact repository(Nexus/S3):靈活且不依賴外網,但需要額外基礎設施維護成本
- kubectl cp 手動修復:應急快速(已驗證有效),但不持久——pod 重啟後問題必定復現
- 自動化腳本(CLASSPATH patch + kubectl cp):比手動更快,但 CLASSPATH 部分效用存疑;本質上仍是 kubectl cp,不持久
Try It Fast¶
# 診斷:確認 JAR 是否存在
kubectl exec -n ps --context gamania-ps-dev deploy/kafka-client -- \
ls -lah /opt/bitnami/kafka/libs/ | grep aws-msk
# 查看啟動日誌,確認下載是否成功
kubectl logs -n ps deployment/kafka-client --context gamania-ps-dev
# 應急修復:從有外網的機器下載並複製(須在 bastion 執行)
curl -fsSL -o /tmp/aws-msk-iam-auth.jar \
https://repo1.maven.org/maven2/software/amazon/msk/aws-msk-iam-auth/2.3.2/aws-msk-iam-auth-2.3.2-all.jar
POD=$(kubectl get pod -n ps -l app=kafka-client \
-o jsonpath='{.items[0].metadata.name}' --context gamania-ps-dev)
kubectl cp /tmp/aws-msk-iam-auth.jar \
ps/${POD}:/opt/bitnami/kafka/libs/ --context gamania-ps-dev
# 驗證修復
kubectl exec -n ps --context gamania-ps-dev deploy/kafka-client -- \
kafka-topics.sh --list \
--bootstrap-server $BOOTSTRAP_SERVER \
--command-config /opt/msk/conf/iam.properties
# 驗證 CLASSPATH(注意:Bitnami 可能透過目錄掃描而非 CLASSPATH 載入 JAR)
kubectl exec -n ps --context gamania-ps-dev deploy/kafka-client -- env | grep CLASSPATH
# 警告:rollout restart 後 JAR 消失(已驗證,問題必然復現)
# kubectl rollout restart deployment/kafka-client -n ps --context gamania-ps-dev
# => JAR 消失,問題復現
Recommendation¶
- 立即:再次執行 kubectl cp 將 JAR 複製進 pod(當前 pod 已透過腳本修復,但下次重啟後問題將再次出現)
- 確認腳本效果:執行
kubectl exec測試 kafka-topics.sh 是否真的能成功連線,確認當前修復有效 - 短期(最優先):將
aws-msk-iam-auth-2.3.2-all.jar打入 kafka-client Docker image,完全消除 runtime 下載依賴,這是最簡單可靠的修法 - 調查 CLASSPATH 為空:確認 Bitnami Kafka image 的 JAR 載入機制——如果是透過目錄掃描
/opt/bitnami/kafka/libs/,則 CLASSPATH patch 無意義;如果需要 CLASSPATH,則需調查 patch 為何無效 - 中期:評估將 JAR 上傳至內部 S3 bucket 或私有 Maven repository,讓 pod 能從內網取得(適合需要靈活更新版本的場景)
- 長期:檢視整個 EKS private cluster 的外網存取策略,建立 artifact mirror 機制,避免其他工具也有類似的依賴外網下載問題