Amazon-Web-Services

將 Amazon Elastic Container Registry 與 Jenkins 集成

  • October 27, 2016

我正在嘗試將 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 憑據。這是基於這個非常詳細的答案,儘管我做了一些不同的事情,我不得不修改腳本。

腳步:

  1. 確保您的 Jenkins master 可以訪問所需的 AWS API。在我的設置中,Jenkins 主伺服器使用 IAM 角色在 EC2 上執行,因此我只需將權限添加ecr:GetAuthorizationToken到伺服器角色即可。[更新]要成功完成任何推送,您還需要授予以下權限:ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability, ecr:PutImage. Amazon 有一個提供這些功能的內置策略,稱為AmazonEC2ContainerRegistryPowerUser.
  2. 確保 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
  3. 安裝Groovy 外掛,它允許您將 Groovy 腳本作為 Jenkins 系統的一部分執行。
  4. 在憑證螢幕中,查找您的 AWS ECR 密鑰,點擊“高級”並記錄其“ID”。對於這個例子,我假設它是“12345”。
  5. 創建一個新作業,定期啟動 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 進行的。如果您使用nullID 的值(如我之前連結的答案),則會創建一個新 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 鏡像的建構步驟的項目

引用自:https://serverfault.com/questions/744902