Intégrer Amazon Elastic Container Registry à Jenkins

10

J'essaie d'intégrer le nouveau registre Elastic Container Registry (ECR) d'Amazon à mon service de génération Jenkins. J'utilise le plugin Cloudbees Docker Build & Publish pour créer des images de conteneurs et les publier dans un registre.

Pour utiliser ECR à la place de mon registre privé, j'ai exécuté la commande AWS CLI aws --region us-east-1 ecr get-loginqui crache une docker logincommande à exécuter - mais je viens de copier le mot de passe et de créer des informations d'identification Jenkins de type "Nom d'utilisateur avec mot de passe" à partir de ce mot de passe (le nom d'utilisateur est toujours "AWS").

Et ça marche bien! Le problème est que le mot de passe ECR généré par l'AWS CLI n'est valide que pendant 12 heures. Donc, pour le moment, je dois régénérer manuellement le mot de passe deux fois par jour et mettre à jour l'écran des informations d'identification Jenkins manuellement, sinon mes versions commencent à échouer.

Existe-t-il un moyen de générer des jetons de connexion ECR permanents ou d'automatiser en quelque sorte la génération de jetons?

Guss
la source

Réponses:

6

Cela est désormais possible en utilisant amazon-ecr-credential-helper comme décrit dans https://aws.amazon.com/blogs/compute/authenticating-amazon-ecr-repositories-for-docker-cli-with-credential-helper/ .

Le bref c'est:

  • Assurez-vous que votre instance Jenkins possède les informations d'identification AWS appropriées pour tirer / pousser avec votre référentiel ECR. Celles-ci peuvent prendre la forme de variables d'environnement, d'un fichier d'informations d'identification partagé ou d'un profil d'instance.
  • Placez le binaire docker-credential-ecr-login dans l'un des répertoires de $ PATH.
  • Écrivez le fichier de configuration Docker sous le répertoire personnel de l'utilisateur Jenkins, par exemple, /var/lib/jenkins/.docker/config.json. avec le contenu{"credsStore": "ecr-login"}
  • Installez le plug-in Docker Build and Publish et assurez-vous que l'utilisateur jenkins peut contacter le démon Docker.
  • Enfin, créez un projet avec une étape de construction qui publie l'image docker
Klugscheißer
la source
4

Comme l'a dit @Connor McCarthy, en attendant qu'Amazon trouve une meilleure solution pour des clés plus permanentes, en attendant, nous aurions besoin de générer nous-mêmes les clés sur le serveur Jenkins.

Ma solution est d'avoir un travail périodique qui met à jour automatiquement les informations d'identification Jenkins pour ECR toutes les 12 heures, à l'aide de l'API Groovy. Ceci est basé sur cette réponse très détaillée , même si j'ai fait quelques choses différemment et j'ai dû modifier le script.

Pas:

  1. Assurez-vous que votre maître Jenkins peut accéder à l'API AWS requise. Dans ma configuration, le maître Jenkins s'exécute sur EC2 avec un rôle IAM, j'ai donc juste dû ajouter l'autorisation ecr:GetAuthorizationTokenau rôle serveur. [ Mise à jour ] Pour obtenir des poussées compléter, vous aurez besoin aussi avec succès à accorder ces autorisations: ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability, ecr:PutImage. Amazon a une politique intégrée qui offre ces capacités, appelées AmazonEC2ContainerRegistryPowerUser.
  2. Assurez-vous que l'AWS CLI est installée sur le maître. Dans ma configuration, avec le maître exécuté dans un conteneur docker debian, je viens d'ajouter cette étape de construction du shell au travail de génération de clés: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. Installez le plugin Groovy qui vous permet d'exécuter le script Groovy dans le cadre du système Jenkins.
  4. Dans l'écran des informations d'identification, recherchez votre clé AWS ECR, cliquez sur "Avancé" et enregistrez son "ID". Pour cet exemple, je vais supposer qu'il s'agit de "12345".
  5. Créez un nouveau travail, avec un lancement périodique de 12 heures, et ajoutez une étape de build "script Groovy système" avec le script suivant:

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

Notez s'il vous plaît:

  • l'utilisation de la chaîne codée en dur "AWS"comme nom d'utilisateur pour les informations d'identification ECR - c'est ainsi que fonctionne ECR, mais si vous avez plusieurs informations d'identification avec le nom d'utilisateur "AWS", vous devrez mettre à jour le script pour localiser les informations d'identification en fonction de la champ de description ou quelque chose.
  • Vous devez utiliser l'ID réel de votre clé ECR réelle dans le script, car l'API pour les informations d'identification remplace l'objet d'informations d'identification par un nouvel objet au lieu de simplement le mettre à jour, et la liaison entre l'étape de construction Docker et la clé se fait par l'ID. Si vous utilisez la valeur nullde l'ID (comme dans la réponse que j'ai liée auparavant), un nouvel ID sera créé et le paramètre des informations d'identification dans l'étape de construction du docker sera perdu.

Et c'est tout - le script devrait pouvoir s'exécuter toutes les 12 heures et actualiser les informations d'identification ECR, et nous pouvons continuer à utiliser les plugins Docker.

Guss
la source
3

J'examinais également ce même problème. Je n'ai pas trouvé la réponse que nous cherchions, mais j'ai pu créer une solution de contournement avec les scripts shell. Jusqu'à ce qu'AWS propose une meilleure solution aux informations d'identification ECR, je prévois de faire quelque chose dans ce sens.

J'ai remplacé l'étape Docker Build and Publish du travail Jenkins par et Execute Shell. J'ai utilisé le script suivant (qui pourrait probablement être mieux écrit) pour créer et publier mon conteneur sur ECR. Remplacez les variables entre crochets <> si nécessaire:

#!/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
la source
Cela semble très raisonnable. le fait est que j'aime Docker Build and Publish, et je préfère continuer à l'utiliser, car cela me simplifie la vie. J'ai plusieurs versions de conteneur dans le système, et je veux en ajouter plus, et l'intégration de ce script à chaque version est plus compliquée que je ne suis prêt à vivre. J'ai une solution alternative que j'ajoute comme réponse.
Guss
2

L'utilisation de https://wiki.jenkins-ci.org/display/JENKINS/Amazon+ECR avec le plugin Docker Build and Publish fonctionne très bien.

Danilo
la source
Je l'ai installé - mais je n'ai pas pu comprendre quoi en faire: il n'a pas de configuration et pas d'interface utilisateur.
Guss
Installez le plugin. À l'étape Docker Build and Publish, vous avez un menu déroulant appelé "Identifiants de registre". Cliquez sur "Ajouter" à côté, sélectionnez comme type "AWS Credentials" dans la boîte de dialogue. Entrez la clé d'accès / clé secrète.
Danilo
Maintenant, je vois. Dommage qu'il ne supporte pas les profils d'instance.
Guss
Oui. Mais pour l'instant je préfère cette solution.
Danilo