Kaniko ECR connection Issue & debug 心得
記錄讓 GitLab runner 上的 Kaniko 以 IRSA role 推送 image 到 ECR 失敗的除錯過程,最後發現是 IRSA trusted policy 設定問題。
-
目的:讓 internal-internal 身上具備 IRSA role 的 gitlab runner pod,可以透過 role 的權限推送 image 至 ECR(instead of IAM user access key)
-
官方教學 GitHub - GoogleContainerTools/kaniko: Build Container Images In Kubernetes
- 給予需要推送 image 權限的 kaniko pod 所在的 instance 相關權限,可以使用 AWS managed policy:
EC2InstanceProfileForImageBuilderECRContainerBuilds - 需設定以下環境變數:
AWS_SDK_LOAD_CONFIG=true:繼承 runner manager pod 相關的 AWS 環境變數AWS_EC2_METADATA_DISABLED=true:當 kaniko 所在的 EC2 具有 instance profile 時需設定,讓 kaniko 可以去吃到正確的 credentials
- 如果不使用 instance role 的話,可以將 EKS secret mount 到 kaniko pod 上
- 給予需要推送 image 權限的 kaniko pod 所在的 instance 相關權限,可以使用 AWS managed policy:
-
Kaniko 向 ECR 推 image 的工具:Amazone-ecr-credential-helper
因為在 debug 的過程中,還是沒有權限可以推送 image 到 ECR,因此稍微去了解了一下 kaniko 是透過什麼機制來對 ECR 連線
-
在 Configuration section 有提到應該要給予
/root/.docker/config.json以下內容,:{ "credHelpers": { "public.ecr.aws": "ecr-login", "<aws_account_id>.dkr.ecr.<region>.amazonaws.com": "ecr-login" } }其他 issue 討論會需要加這段設定也是基於這個 credential helper repo 來的:
-
在 AWS credentials section 也有提及
AWS_SDK_LOAD_CONFIG開啟後有以下三個效果- 透過環境變數 (
role_arnandsource_profile) 進行 assume role - 可使用
credential_process所拿到的權限 - 可以拿到 IRSA 的權限
- 透過環境變數 (
-
不過在 debug 過程中,不管設定檔怎麼加都沒辦法讓 kaniko 正確推送 image,因此推測是更基本的權限問題沒有設定好。且 gitlab runner manager pod 和 job pod 裡面所包含的環境變數一致,因此下一步決定在 runner manager pod 測試
aws sts get-caller-identity。但 runner manager pod 並沒有 awscli,安裝起來也很麻煩,因此決定仿照 runner pod 所使用的 service account,開一個 awscli pod 來做測試
-
Runner pod 環境變數有以下的內容,符合 amazon-ecr-credential-helper 裡面所提到需要的內容,也確實有拿到正確的 IRSA role
AWS_DEFAULT_REGION=ap-northeast-1 AWS_REGION=ap-northeast-1 AWS_ROLE_ARN=arn:aws:iam::123456789012:role/gitlab-runner20250424045204511300000028 AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token AWS_STS_REGIONAL_ENDPOINTS=regional -
AWS_WEB_IDENTITY_TOKEN_FILE這個路徑存的內容像是 Assume role 之後會有的 token,因此我把 token 內容拿到 local 存成AWS_STS_TOKEN測試aws sts get-caller-identity的結果。但因為 role 本身只允許AssumeRoleWithWebIdentity,且我的 local 端沒辦法執行這件事(只能做一般的 assume role),因此這條路是失敗的 -
接下來我執行一個 kaniko push image job,並讓他
sleep 3600好讓我進去 debug,並且下了以下指令,檢查 kaniko 是否有已經可以連線的 ECR repo:/kaniko/docker-credential-ecr-login list # 正常應該返回物件,但我收到空值 -
最後因為 job pod 也沒有
awscli可以使用,因此開了一個 pod 仿照 gitlab-runner service account 的設定:apiVersion: v1 kind: Pod metadata: name: awscli-test namespace: gitlab-runner spec: serviceAccountName: gitlab-runner-x86 containers: - name: awscli image: amazon/aws-cli command: ["/bin/bash"] args: ["-c", "sleep 3600"] env: - name: AWS_REGION value: ap-east-1 restartPolicy: Neverkubectl apply -f awscli-test.yaml kubectl exec -it awscli-test -n gitlab-runner -- bash # in pod aws sts get-caller-identity -
結果發現是 IRSA trusted policy 沒有改允許 SA 的 namespace 和 SA 的名字 😇
心得:在使用廣泛流通的工具時,通常 debug 到後來如果開始鬼打牆,就要有警覺「既然這東西廣泛流通,且專案上並沒有什麼特別的 limitation」時,就不太可能需要追到太深的地方去 debug。更常出現的問題會是最基本的權限設定問題,或是一些基本的限制沒寫清楚(舉例:使用 vxlan 時忘記讓 security group allow UDP,因為忘記 UDP 和 TCP 是分開的兩個協定;或者像這次一樣 trusted policy 沒寫好)