将Amazon Elastic Container Registry与Jenkins集成


10

我正在尝试将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登录令牌,或者以某种方式自动生成令牌?

Answers:


6

https://aws.amazon.com/blogs/compute/authenticating-amazon-ecr-repositories-for-docker-cli-with-credential-helper/中所述,现在可以使用amazon-ecr-credential-helper来实现。

它的简称是:

  • 确保您的Jenkins实例具有正确的AWS凭证以拉/推您的ECR存储库。这些可以采用环境变量,共享凭据文件或实例配置文件的形式。
  • 将docker-credential-ecr-login二进制文件放入$ PATH中的目录之一。
  • 将Docker配置文件写入Jenkins用户的主目录下,例如/var/lib/jenkins/.docker/config.json。与内容{"credsStore": "ecr-login"}
  • 安装Docker Build and Publish插件,并确保jenkins用户可以联系Docker守护程序。
  • 最后,使用发布Docker镜像的构建步骤创建一个项目

4

正如@Connor McCarthy所说的那样,在等待亚马逊为更多永久密钥提供更好的解决方案的同时,与此同时,我们需要以某种方式在Jenkins服务器上生成密钥。

我的解决方案是使用Groovy API定期执行一项工作,每12小时自动更新一次ECR的Jenkins凭证。这是基于这个非常详细的答案的,尽管我做了一些不同的事情并且不得不修改脚本。

脚步:

  1. 确保您的Jenkins管理员可以访问所需的AWS API。在我的设置中,Jenkins主服务器在具有IAM角色的EC2上运行,因此我只需ecr:GetAuthorizationToken要向服务器角色添加权限。[ update ]要成功完成任何推送,您还需要授予以下权限:ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability, ecr:PutImage。Amazon的内置政策提供了这些功能,称为AmazonEC2ContainerRegistryPowerUser
  2. 确保在主服务器上安装了AWS CLI。在我的设置中,将主服务器运行在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插件。


3

我也在调查这个完全相同的问题。我俩都没有想出答案,但是我能够使用Shell脚本创建解决方法。在AWS为ECR凭证提供更好的解决方案之前,我计划按照这些方针做一些事情。

我将Jenkins作业的Docker Build and Publish步骤替换为Execute Shell步骤。我使用以下脚本(可能写得更好)来构建容器并将其发布到ECR。根据需要替换<>括号中的变量:

#!/bin/bash

#Variables
REG_ADDRESS="<your ECR Registry Address>"
REPO="<your ECR Repository>"
IMAGE_VERSION="v_"${BUILD_NUMBER}
WORKSPACE_PATH="<path to the workspace directory of the Jenkins job>"

#Login to ECR Repository
LOGIN_STRING=`aws ecr get-login --region us-east-1`
${LOGIN_STRING}

#Build the containerexit
cd ${WORKSPACE_PATH}
docker build -t ${REPO}:${IMAGE_VERSION} .

#Tag the build with BUILD_NUMBER version and Latests
docker tag ${REPO}:${IMAGE_VERSION} ${REPO_ADDRESS}/${REPO}:${IMAGE_VERSION}

#Push builds
docker push ${REG_ADDRESS}/${REPO}:${IMAGE_VERSION}

听起来很合理。事实是-我喜欢Docker Build and Publish,而我宁愿继续使用它,因为它简化了我的生活。我在系统中有多个容器版本,并且想要添加更多,并且将该脚本集成到每个版本中比我愿意忍受的麻烦更多。我有一个替代解决方案,正在添加作为答案。
2015年

2

结合使用https://wiki.jenkins-ci.org/display/JENKINS/Amazon+ECR和Docker Build and Publish插件即可正常工作。


我已经安装了它-但无法弄清楚该怎么做:它没有配置,也没有UI。
古斯

安装插件。在Docker Build and Publish步骤中,您会看到一个名为“注册表凭据”的下拉列表。单击它旁边的“添加”,在对话框中选择“ AWS凭据”类型。输入访问密钥/秘密密钥。
达尼洛

现在我明白了。太糟糕了,它不支持实例配置文件。
古斯

是。但是现在我更喜欢这种解决方案。
达尼洛
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.