Integrieren Sie die Amazon Elastic Container Registry in Jenkins

10

Ich versuche, die neue Elastic Container Registry (ECR) von Amazon in meinen Jenkins-Build-Service zu integrieren. Ich verwende das Cloudbees Docker Build & Publish-Plugin, um Container-Images zu erstellen und in einer Registrierung zu veröffentlichen.

Um ECR anstelle meiner privaten Registrierung zu verwenden, habe ich den AWS CLI-Befehl ausgeführt, aws --region us-east-1 ecr get-loginder einen auszuführenden Befehl ausgibt. Ich habe docker loginjedoch nur das Kennwort kopiert und aus diesem Kennwort Jenkins-Anmeldeinformationen vom Typ "Benutzername mit Kennwort" erstellt (der Benutzername lautet) immer "AWS").

Und das funktioniert gut! Das Problem ist, dass das von der AWS CLI generierte ECR-Kennwort nur 12 Stunden gültig ist. Im Moment muss ich das Kennwort zweimal täglich manuell neu generieren und den Jenkins-Bildschirm mit den Anmeldeinformationen manuell aktualisieren, da sonst meine Builds fehlschlagen.

Gibt es eine Möglichkeit, permanente ECR-Anmeldetoken zu generieren oder die Token-Generierung irgendwie zu automatisieren?

Guss
quelle

Antworten:

6

Dies ist jetzt mit amazon-ecr-credential-helper möglich, wie unter https://aws.amazon.com/blogs/compute/authenticating-amazon-ecr-repositories-for-docker-cli-with-credential-helper/ beschrieben .

Das kurze daran ist:

  • Stellen Sie sicher, dass Ihre Jenkins-Instanz über die richtigen AWS-Anmeldeinformationen verfügt, die Sie mit Ihrem ECR-Repository abrufen / pushen können. Diese können in Form von Umgebungsvariablen, einer gemeinsam genutzten Anmeldeinformationsdatei oder einem Instanzprofil vorliegen.
  • Platzieren Sie die Binärdatei docker-credential-ecr-login in einem der Verzeichnisse in $ PATH.
  • Schreiben Sie die Docker-Konfigurationsdatei in das Ausgangsverzeichnis des Jenkins-Benutzers, z. B. /var/lib/jenkins/.docker/config.json. mit dem Inhalt{"credsStore": "ecr-login"}
  • Installieren Sie das Docker Build and Publish-Plugin und stellen Sie sicher, dass der Jenkins-Benutzer den Docker-Dämon kontaktieren kann.
  • Erstellen Sie abschließend ein Projekt mit einem Erstellungsschritt, der das Docker-Image veröffentlicht
Klugscheißer
quelle
4

Wie @Connor McCarthy sagte, während wir darauf warteten, dass Amazon eine bessere Lösung für dauerhaftere Schlüssel findet, müssten wir die Schlüssel in der Zwischenzeit irgendwie selbst auf dem Jenkins-Server generieren.

Meine Lösung besteht darin, einen regelmäßigen Job zu haben, der die Jenkins-Anmeldeinformationen für ECR alle 12 Stunden mithilfe der Groovy-API automatisch aktualisiert. Dies basiert auf dieser sehr detaillierten Antwort , obwohl ich einige Dinge anders gemacht habe und das Skript ändern musste.

Schritte:

  1. Stellen Sie sicher, dass Ihr Jenkins-Master auf die erforderliche AWS-API zugreifen kann. In meinem Setup läuft der Jenkins-Master auf EC2 mit einer IAM-Rolle, daher musste ich ecr:GetAuthorizationTokender Serverrolle nur die Berechtigung hinzufügen . [ Update ] Um Pushs erfolgreich abzuschließen, müssen Sie außerdem die folgenden Berechtigungen erteilen : ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability, ecr:PutImage. Amazon verfügt über eine integrierte Richtlinie, die diese Funktionen bietet AmazonEC2ContainerRegistryPowerUser.
  2. Stellen Sie sicher, dass die AWS CLI auf dem Master installiert ist. In meinem Setup, in dem der Master in einem Debian-Docker-Container ausgeführt wird, habe ich gerade diesen Shell-Build-Schritt zum Schlüsselgenerierungsjob hinzugefügt: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. Installieren Sie das Groovy-Plugin , mit dem Sie das Groovy-Skript als Teil des Jenkins-Systems ausführen können.
  4. Suchen Sie im Bildschirm mit den Anmeldeinformationen nach Ihrem AWS ECR-Schlüssel, klicken Sie auf "Erweitert" und notieren Sie die "ID". In diesem Beispiel gehe ich davon aus, dass es "12345" ist.
  5. Erstellen Sie einen neuen Job mit einem regelmäßigen Start von 12 Stunden und fügen Sie einen Erstellungsschritt "System Groovy Script" mit dem folgenden Skript hinzu:

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

Bitte beachten Sie:

  • Die Verwendung der fest codierten Zeichenfolge "AWS"als Benutzername für die ECR-Anmeldeinformationen - so funktioniert ECR. Wenn Sie jedoch mehrere Anmeldeinformationen mit dem Benutzernamen "AWS" haben, müssen Sie das Skript aktualisieren, um die Anmeldeinformationen basierend auf dem zu finden Beschreibungsfeld oder so.
  • Sie müssen die reale ID Ihres realen ECR-Schlüssels im Skript verwenden, da die API für Anmeldeinformationen das Anmeldeinformationsobjekt durch ein neues Objekt ersetzt, anstatt es nur zu aktualisieren, und die Bindung zwischen dem Docker-Erstellungsschritt und dem Schlüssel durch die ID erfolgt. Wenn Sie den Wert nullfür die ID verwenden (wie in der Antwort, die ich zuvor verlinkt habe), wird eine neue ID erstellt und die Einstellung der Anmeldeinformationen im Docker-Erstellungsschritt geht verloren.

Und das war's - das Skript sollte alle 12 Stunden ausgeführt werden und die ECR-Anmeldeinformationen aktualisieren können, und wir können weiterhin die Docker-Plugins verwenden.

Guss
quelle
3

Ich habe mich auch genau mit diesem Thema befasst. Ich habe keine Antwort gefunden, nach der einer von uns gesucht hat, aber ich konnte eine Problemumgehung mit Shell-Skripten erstellen. Bis AWS eine bessere Lösung für ECR-Anmeldeinformationen herausbringt, habe ich vor, etwas in diese Richtung zu tun.

Ich habe den Schritt "Docker erstellen und veröffentlichen" des Jenkins-Jobs durch den Schritt "Shell ausführen" und "Shell ausführen" ersetzt. Ich habe das folgende Skript verwendet (könnte wahrscheinlich besser geschrieben werden), um meinen Container zu erstellen und in ECR zu veröffentlichen. Ersetzen Sie die Variablen in <> Klammern nach Bedarf:

#!/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
quelle
Klingt sehr vernünftig. Die Sache ist - ich mag Docker Build and Publish und benutze es lieber weiter, da es mein Leben vereinfacht. Ich habe mehrere Container-Builds im System und möchte mehr hinzufügen. Die Integration dieses Skripts in jeden Build ist mühsamer, als ich bereit bin, damit zu leben. Ich habe eine alternative Lösung, die ich als Antwort hinzufüge.
Guss
2

Die Verwendung von https://wiki.jenkins-ci.org/display/JENKINS/Amazon+ECR mit dem Docker Build and Publish-Plugin funktioniert einwandfrei.

Danilo
quelle
Ich habe es installiert - konnte aber nicht herausfinden, was ich damit anfangen soll: Es hat keine Konfiguration und keine Benutzeroberfläche.
Guss
Installieren Sie das Plugin. Im Schritt "Docker erstellen und veröffentlichen" befindet sich eine Dropdown-Liste mit dem Namen "Registrierungsdaten". Klicken Sie daneben auf "Hinzufügen" und wählen Sie im Dialogfeld als Typ "AWS-Anmeldeinformationen" aus. Geben Sie den Zugangsschlüssel / den geheimen Schlüssel ein.
Danilo
Jetzt sehe ich. Schade, dass Instanzprofile nicht unterstützt werden.
Guss
Ja. Aber im Moment bevorzuge ich diese Lösung.
Danilo