Integrar Amazon Elastic Container Registry con Jenkins

10

Estoy tratando de integrar el nuevo Elastic Container Registry (ECR) de Amazon con mi servicio de compilación Jenkins. Estoy usando el complemento Cloudbees Docker Build & Publish para crear imágenes de contenedor y publicarlas en un registro.

Para usar ECR en lugar de mi registro privado, ejecuté el comando AWS CLI aws --region us-east-1 ecr get-loginque arroja un docker logincomando para ejecutar, pero simplemente copié la contraseña y creé una credencial de Jenkins del tipo "Nombre de usuario con contraseña" a partir de esa contraseña (el nombre de usuario es siempre "AWS").

¡Y eso funciona bien! El problema es que la contraseña de ECR generada por la AWS CLI solo es válida durante 12 horas. Así que en este momento, tengo que regenerar manualmente la contraseña dos veces al día y actualizar la pantalla de credenciales de Jenkins manualmente, de lo contrario, mis compilaciones comienzan a fallar.

¿Hay alguna manera de generar tokens de inicio de sesión de ECR permanentes o de alguna manera automatizar la generación de tokens?

Guss
fuente

Respuestas:

6

Esto ahora es posible usando amazon-ecr-credential-helper como se describe en https://aws.amazon.com/blogs/compute/authenticating-amazon-ecr-repositories-for-docker-cli-with-credential-helper/ .

El resumen de esto es:

  • Asegúrese de que su instancia de Jenkins tenga las credenciales de AWS adecuadas para extraer / impulsar con su repositorio ECR. Estos pueden ser en forma de variables de entorno, un archivo de credenciales compartido o un perfil de instancia.
  • Coloque el binario docker-credential-ecr-login en uno de los directorios en $ PATH.
  • Escriba el archivo de configuración de Docker en el directorio de inicio del usuario de Jenkins, por ejemplo, /var/lib/jenkins/.docker/config.json. con el contenido{"credsStore": "ecr-login"}
  • Instale el complemento Docker Build and Publish y asegúrese de que el usuario jenkins pueda contactar al demonio Docker.
  • Finalmente, cree un proyecto con un paso de compilación que publique la imagen acoplable
Klugscheißer
fuente
4

Como dijo @Connor McCarthy, mientras esperamos que Amazon presente una mejor solución para claves más permanentes, mientras tanto tendríamos que generar las claves en el servidor Jenkins de alguna manera.

Mi solución es tener un trabajo periódico que actualice las credenciales de Jenkins para ECR cada 12 horas automáticamente, utilizando la API Groovy. Esto se basa en esta respuesta muy detallada , aunque hice algunas cosas de manera diferente y tuve que modificar el script.

Pasos:

  1. Asegúrese de que su maestro Jenkins pueda acceder a la API de AWS requerida. En mi configuración, el maestro Jenkins se ejecuta en EC2 con un rol de IAM, por lo que solo tuve que agregar el permiso ecr:GetAuthorizationTokenal rol de servidor. [ Actualización ] para conseguir cualquier empuja completan con éxito, también había necesidad de conceder estos permisos: ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability, ecr:PutImage. Amazon tiene una política incorporada que ofrece estas capacidades, llamada AmazonEC2ContainerRegistryPowerUser.
  2. Asegúrese de que la AWS CLI esté instalada en el maestro. En mi configuración, con el maestro ejecutándose en un contenedor de Debian Docker, acabo de agregar este paso de compilación de shell al trabajo de generación de claves: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 el complemento Groovy que le permite ejecutar el script Groovy como parte del sistema Jenkins.
  4. En la pantalla de credenciales, busque su clave de AWS ECR, haga clic en "Avanzado" y registre su "ID". Para este ejemplo, voy a suponer que es "12345".
  5. Cree un nuevo trabajo, con un lanzamiento periódico de 12 horas, y agregue un paso de compilación del "script Groovy del sistema" con el siguiente 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)
}

Tenga en cuenta:

  • el uso de la cadena codificada "AWS"como nombre de usuario para las credenciales de ECR: así es como funciona ECR, pero si tiene múltiples credenciales con el nombre de usuario "AWS", entonces necesitará actualizar el script para ubicar las credenciales basadas en campo de descripción o algo así.
  • Debe usar la ID real de su clave ECR real en el script, porque la API para credenciales reemplaza el objeto de credenciales con un nuevo objeto en lugar de simplemente actualizarlo, y el enlace entre el paso de compilación de Docker y la clave es por la ID. Si usa el valor nullpara la ID (como en la respuesta que vinculé antes), se creará una nueva ID y se perderá la configuración de las credenciales en el paso de compilación del acoplador.

Y eso es todo: el script debería poder ejecutarse cada 12 horas y actualizar las credenciales de ECR, y podemos continuar usando los complementos de Docker.

Guss
fuente
3

Estaba investigando exactamente este mismo problema también. No se me ocurrió la respuesta que ninguno de nosotros estaba buscando, pero pude crear una solución alternativa con scripting de shell. Hasta que AWS salga con una mejor solución para las credenciales de ECR, planeo hacer algo en este sentido.

Reemplacé el paso Docker Build and Publish del trabajo de Jenkins con el paso Execute Shell. Utilicé el siguiente script (probablemente podría escribirse mejor) para construir y publicar mi contenedor en ECR. Reemplace las variables entre paréntesis <> según sea necesario:

#!/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}
Connor McCarthy
fuente
Suena muy razonable. la cosa es que me gusta Docker Build and Publish, y prefiero seguir usándolo, ya que simplifica mi vida. Tengo varias compilaciones de contenedores en el sistema y deseo agregar más, e integrar ese script en cada compilación es más complicado de lo que estoy dispuesto a vivir. Tengo una solución alternativa que estoy agregando como respuesta.
Guss
2

Usar https://wiki.jenkins-ci.org/display/JENKINS/Amazon+ECR con el complemento Docker Build and Publish funciona bien.

Danilo
fuente
Lo instalé, pero no pude averiguar qué hacer con él: no tiene configuración ni interfaz de usuario.
Guss
Instala el complemento. En el paso de compilación y publicación de Docker, tiene un menú desplegable llamado "Credenciales de registro". Haga clic en "Agregar" junto a él, seleccione como tipo "Credenciales de AWS" en el cuadro de diálogo. Ingrese la clave de acceso / clave secreta.
Danilo
Ahora veo. Lástima que no sea compatible con los perfiles de instancia.
Guss
Si. Pero por ahora prefiero esta solución.
Danilo