Integrar o Amazon Elastic Container Registry ao Jenkins


10

Estou tentando integrar o novo Elastic Container Registry (ECR) da Amazon ao meu serviço de compilação Jenkins. Estou usando o plug-in Cloudbees Docker Build & Publish para criar imagens de contêiner e publicá-las em um registro.

Para usar o ECR em vez do meu registro privado, executei o comando AWS CLI aws --region us-east-1 ecr get-loginque envia um docker logincomando para execução - mas apenas copiei a senha e criei credenciais Jenkins do tipo "Nome de usuário com senha" a partir dessa senha (o nome de usuário é sempre "AWS").

E isso funciona bem! O problema é que a senha do ECR gerada pela AWS CLI é válida apenas por 12 horas. Portanto, agora, preciso gerar novamente a senha manualmente duas vezes por dia e atualizar a tela de credenciais do Jenkins manualmente, caso contrário minhas compilações começarão a falhar.

Existe uma maneira de gerar tokens de login ECR permanentes ou de alguma forma automatizar a geração de tokens?

Respostas:


6

Agora isso é possível usando o amazon-ecr-credential-helper, conforme descrito em https://aws.amazon.com/blogs/compute/authenticating-amazon-ecr-repositories-for-docker-cli-with-credential-helper/ .

O resumo é:

  • Verifique se sua instância do Jenkins possui as credenciais da AWS adequadas para puxar / enviar com seu repositório de ECR. Elas podem estar na forma de variáveis ​​de ambiente, um arquivo de credencial compartilhado ou um perfil de instância.
  • Coloque o binário docker-credential-ecr-login em um dos diretórios em $ PATH.
  • Escreva o arquivo de configuração do Docker no diretório inicial do usuário Jenkins, por exemplo, /var/lib/jenkins/.docker/config.json. com o conteúdo{"credsStore": "ecr-login"}
  • Instale o plug-in Build and Publish do Docker e verifique se o usuário jenkins pode entrar em contato com o daemon do Docker.
  • Por fim, crie um projeto com uma etapa de construção que publique a imagem do docker

4

Como @Connor McCarthy disse, enquanto esperava a Amazon encontrar uma solução melhor para chaves mais permanentes, nesse meio tempo precisaríamos gerar as chaves no servidor Jenkins de alguma forma.

Minha solução é ter um trabalho periódico que atualize as credenciais Jenkins para ECR a cada 12 horas automaticamente, usando a API do Groovy. Isso se baseia nesta resposta muito detalhada , embora eu tenha feito algumas coisas de maneira diferente e precisei modificar o script.

Passos:

  1. Verifique se o seu mestre Jenkins pode acessar a API da AWS necessária. Na minha configuração, o mestre Jenkins está sendo executado no EC2 com uma função do IAM, então tive que adicionar a permissão ecr:GetAuthorizationTokenà função de servidor. [ Atualização ] para obter qualquer empurra concluída com êxito, você também precisaria conceder essas permissões: ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability, ecr:PutImage. A Amazon possui uma política interna que oferece esses recursos, chamados AmazonEC2ContainerRegistryPowerUser.
  2. Verifique se a AWS CLI está instalada no mestre. Na minha configuração, com o mestre sendo executado em um contêiner do docker debian, acabei de adicionar esta etapa de construção do shell ao trabalho de geração de chaves: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. Instale o plug-in Groovy, que permite executar o script Groovy como parte do sistema Jenkins.
  4. Na tela de credenciais, procure sua chave ECR da AWS, clique em "Avançado" e registre seu "ID". Neste exemplo, vou assumir que é "12345".
  5. Crie um novo trabalho, com um lançamento periódico de 12 horas, e adicione uma etapa de criação "script do Groovy do sistema" com o seguinte script:

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)
}

Observe:

  • o uso da string codificada "AWS"como o nome de usuário das credenciais de ECR - é assim que a ECR funciona, mas se você tiver várias credenciais com o nome de usuário "AWS", será necessário atualizar o script para localizar as credenciais com base no campo de descrição ou algo assim.
  • Você deve usar o ID real da sua chave ECR real no script, porque a API para credenciais substitui o objeto de credenciais por um novo objeto em vez de apenas atualizá-lo, e a ligação entre a etapa de construção do Docker e a chave é pelo ID. Se você usar o valor nulldo ID (como na resposta que eu vinculei antes), um novo ID será criado e a configuração das credenciais na etapa de construção do docker será perdida.

E é isso: o script deve ser executado a cada 12 horas e atualizar as credenciais de ECR, e podemos continuar usando os plug-ins do Docker.


3

Eu também estava investigando esse mesmo problema. Não encontrei a resposta que estávamos procurando, mas consegui criar uma solução alternativa com scripts de shell. Até que a AWS saia com uma solução melhor para as credenciais de ECR, pretendo fazer algo nesse sentido.

Substituí a etapa Docker Build and Publish da tarefa Jenkins pela etapa Execute Shell. Usei o seguinte script (provavelmente poderia ser melhor escrito) para criar e publicar meu contêiner no ECR. Substitua as variáveis ​​entre colchetes, conforme necessário:

#!/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}

Parece muito razoável. o problema é que eu gosto do Docker Build and Publish e continuo a usá-lo, pois simplifica minha vida. Eu tenho várias compilações de contêiner no sistema e quero adicionar mais, e integrar esse script a cada compilação é mais complicado do que estou disposto a conviver. Eu tenho uma solução alternativa que estou adicionando como resposta.
Guss

2

O uso de https://wiki.jenkins-ci.org/display/JENKINS/Amazon+ECR com o plug-in Docker Build and Publish funciona perfeitamente.


Eu o instalei - mas não consegui descobrir o que fazer com ele: ele não tem configuração nem interface do usuário.
Guss

Instale o plugin. Na etapa Docker Build and Publish, você tem uma lista suspensa chamada "Credenciais do Registro". Clique em "Adicionar" ao lado, selecione como tipo "Credenciais da AWS" na caixa de diálogo. Digite a chave de acesso / chave secreta.
Danilo

Agora eu vejo. Pena que não suporta perfis de instância.
Guss

Sim. Mas por enquanto eu prefiro esta solução.
Danilo
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.