Интеграция Amazon Elastic Container Registry с Jenkins

10

Я пытаюсь интегрировать новый Elastic Container Registry (ECR) Amazon с моей службой сборки Jenkins. Я использую плагин Cloudbees Docker Build & Publish для создания изображений контейнеров и их публикации в реестре.

Чтобы использовать ECR вместо моего личного реестра, я выполнил команду CLI AWS, aws --region us-east-1 ecr get-loginкоторая издает docker loginкоманду для запуска, - но я просто скопировал пароль и создал учетные данные Jenkins типа «Имя пользователя с паролем» из этого пароля (имя пользователя всегда "AWS").

И это прекрасно работает! Проблема заключается в том, что пароль ECR, генерируемый интерфейсом командной строки AWS, действителен только в течение 12 часов. Поэтому сейчас мне приходится вручную перегенерировать пароль два раза в день и вручную обновить экран учетных данных Jenkins, в противном случае мои сборки начинают давать сбой.

Есть ли способ генерировать постоянные токены входа в ECR или как-то автоматизировать генерацию токенов?

Guss
источник

Ответы:

6

Теперь это возможно с помощью 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.
  • Запишите файл конфигурации Docker в домашний каталог пользователя Jenkins, например, /var/lib/jenkins/.docker/config.json. с содержанием{"credsStore": "ecr-login"}
  • Установите плагин Docker Build and Publish и убедитесь, что пользователь jenkins может связаться с демоном Docker.
  • Наконец, создайте проект с шагом сборки, который публикует образ докера
Klugscheißer
источник
4

Как сказал @Connor McCarthy, ожидая, пока Amazon придумает лучшее решение для более постоянных ключей, в то же время нам нужно как-то самим сгенерировать ключи на сервере Jenkins.

Мое решение состоит в том, чтобы иметь периодическую работу, которая обновляет учетные данные Jenkins для ECR каждые 12 часов автоматически, используя Groovy API. Это основано на этом очень подробном ответе , хотя я сделал несколько вещей по-другому, и мне пришлось изменить сценарий.

шаги:

  1. Убедитесь, что ваш мастер Jenkins может получить доступ к необходимому API AWS. В моей настройке мастер Jenkins работает на EC2 с ролью IAM, поэтому мне просто нужно было добавить разрешение ecr:GetAuthorizationTokenдля роли сервера. [ Обновление ] Чтобы получить какие - либо толчки успешно завершены, вы также должны предоставить эти разрешения: ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability, ecr:PutImage. Amazon имеет встроенную политику, которая предлагает эти возможности, называется AmazonEC2ContainerRegistryPowerUser.
  2. Убедитесь, что на главном компьютере установлен интерфейс командной строки AWS. В моей настройке, когда мастер работает в доке-контейнере Debian, я только что добавил этот шаг сборки оболочки в задание генерации ключа: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 в сценарии, поскольку API для учетных данных заменяет объект учетных данных новым объектом, а не просто обновляет его, а привязка между этапом сборки Docker и ключом осуществляется с помощью идентификатора. Если вы используете значение nullдля идентификатора (как в ответе, который я связывал ранее), то будет создан новый идентификатор, и настройка учетных данных на этапе сборки докера будет потеряна.

И все - скрипт должен запускаться каждые 12 часов и обновлять учетные данные ECR, и мы можем продолжать использовать плагины Docker.

Guss
источник
3

Я тоже изучал эту проблему. Я не придумал ответ, который искали ни один из нас, но я смог создать обходной путь с использованием сценариев оболочки. Пока AWS не предложит лучшее решение для учетных данных ECR, я планирую что-то делать в этом направлении.

Я заменил шаг «Сборка и публикация Docker» задания Jenkins на шаг «Выполнить оболочку». Я использовал следующий скрипт (возможно, мог бы быть написан лучше), чтобы построить и опубликовать свой контейнер в 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, и я скорее продолжаю использовать его, так как это упрощает мою жизнь. У меня есть несколько сборок контейнеров в системе, и я хочу добавить больше, и интеграция этого скрипта в каждую сборку доставляет больше хлопот, чем я хочу жить. У меня есть альтернативное решение, которое я добавляю в качестве ответа.
Guss
2

Использование https://wiki.jenkins-ci.org/display/JENKINS/Amazon+ECR с плагином Docker Build and Publish прекрасно работает.

Данило
источник
Я установил его - но не мог понять, что с ним делать: у него нет конфигурации и нет пользовательского интерфейса.
Guss
Установите плагин. На шаге «Сборка и публикация Docker» у вас есть раскрывающийся список «Учетные данные реестра». Нажмите «Добавить» рядом с ним, выберите тип диалога «AWS Credentials» в диалоговом окне. Введите ключ доступа / секретный ключ.
Данило
Теперь я вижу. Жаль, что он не поддерживает профили экземпляров.
Guss
Да. Но сейчас я предпочитаю это решение.
Данило