將 Amazon Elastic Container Registry 與 Jenkins 集成
我正在嘗試將 Amazon 的新 Elastic Container Registry (ECR) 與我的 Jenkins 建構服務集成。我正在使用 Cloudbees Docker Build & Publish 外掛來建構容器映像並將它們發佈到系統資料庫。
為了使用 ECR 而不是我的私有系統資料庫,我執行了 AWS CLI 命令
aws --region us-east-1 ecr get-login
,該命令會發出一個docker login
要執行的命令 - 但我只是複制了密碼並從該密碼創建了一個類型為“帶密碼的使用者名”的 Jenkins 憑證(使用者名是總是“AWS”)。這很好用!問題是 AWS CLI 生成的 ECR 密碼僅在 12 小時內有效。所以現在,我必須每天兩次手動重新生成密碼並手動更新 Jenkins 憑據螢幕,否則我的建構開始失敗。
有沒有辦法生成永久 ECR 登錄令牌,或者以某種方式自動生成令牌?
正如@Connor McCarthy 所說,在等待亞馬遜為更多永久密鑰提供更好的解決方案的同時,我們需要以某種方式自己在 Jenkins 伺服器上生成密鑰。
我的解決方案是定期使用 Groovy API 每 12 小時自動更新 ECR 的 Jenkins 憑據。這是基於這個非常詳細的答案,儘管我做了一些不同的事情,我不得不修改腳本。
腳步:
- 確保您的 Jenkins master 可以訪問所需的 AWS API。在我的設置中,Jenkins 主伺服器使用 IAM 角色在 EC2 上執行,因此我只需將權限添加
ecr:GetAuthorizationToken
到伺服器角色即可。[更新]要成功完成任何推送,您還需要授予以下權限:ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability, ecr:PutImage
. Amazon 有一個提供這些功能的內置策略,稱為AmazonEC2ContainerRegistryPowerUser
.- 確保 AWS CLI 安裝在主伺服器上。在我的設置中,master 在 debian docker 容器中執行,我剛剛將此 shell 建構步驟添加到密鑰生成作業中:
dpkg -l python-pip >/dev/null 2>&1 || sudo apt-get install python-pip -y; pip list 2>/dev/null | grep -q awscli || pip install awscli
- 安裝Groovy 外掛,它允許您將 Groovy 腳本作為 Jenkins 系統的一部分執行。
- 在憑證螢幕中,查找您的 AWS ECR 密鑰,點擊“高級”並記錄其“ID”。對於這個例子,我假設它是“12345”。
- 創建一個新作業,定期啟動 12 小時,並使用以下腳本添加“系統 Groovy 腳本”建構步驟:
import jenkins.model.* import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl def changePassword = { username, new_password -> def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials( com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class, Jenkins.instance) def c = creds.findResult { it.username == username ? it : null } if ( c ) { println "found credential ${c.id} for username ${c.username}" def credentials_store = Jenkins.instance.getExtensionList( 'com.cloudbees.plugins.credentials.SystemCredentialsProvider' )[0].getStore() def result = credentials_store.updateCredentials( com.cloudbees.plugins.credentials.domains.Domain.global(), c, new UsernamePasswordCredentialsImpl(c.scope, "12345", c.description, c.username, new_password)) if (result) { println "password changed for ${username}" } else { println "failed to change password for ${username}" } } else { println "could not find credential for ${username}" } } println "calling AWS for docker login" def prs = "/usr/local/bin/aws --region us-east-1 ecr get-login".execute() prs.waitFor() def logintext = prs.text if (prs.exitValue()) { println "Got error from aws cli" throw new Exception() } else { def password = logintext.split(" ")[5] println "Updating password" changePassword('AWS', password) }
請注意:
- 使用硬編碼字元串
"AWS"
作為 ECR 憑證的使用者名 - 這就是 ECR 的工作方式,但如果您有多個使用者名為“AWS”的憑證,那麼您需要更新腳本以根據描述欄位什麼的。- 您必須在腳本中使用真實 ECR 密鑰的真實 ID,因為憑證的 API 將憑證對象替換為新對象,而不是僅僅更新它,並且 Docker 建構步驟和密鑰之間的綁定是通過 ID 進行的。如果您使用
null
ID 的值(如我之前連結的答案),則會創建一個新 ID,並且 docker build 步驟中的憑據設置將失去。就是這樣 - 腳本應該能夠每 12 小時執行一次並刷新 ECR 憑據,我們可以繼續使用 Docker 外掛。
現在可以使用amazon-ecr-credential-helper,如https://aws.amazon.com/blogs/compute/authenticating-amazon-ecr-repositories-for-docker-cli-with-credential-helper/中所述。
它的短處是:
- 確保您的 Jenkins 實例具有正確的 AWS 憑證以使用您的 ECR 儲存庫拉/推。這些可以是環境變數、共享憑證文件或實例配置文件的形式。
- 將 docker-credential-ecr-login 二進製文件放在 $PATH 中的目錄之一。
- 在Jenkins使用者的home目錄下寫入Docker配置文件,例如/var/lib/jenkins/.docker/config.json。與內容
{"credsStore": "ecr-login"}
- 安裝 Docker Build and Publish 外掛並確保 jenkins 使用者可以聯繫 Docker 守護程序。
- 最後,創建一個包含發布 docker 鏡像的建構步驟的項目