Zintegruj rejestr elastycznych pojemników Amazon z Jenkins

10

Próbuję zintegrować nowy Rejestr Elastycznego Pojemnika (ECR) Amazon z moją usługą kompilacji Jenkins. Korzystam z wtyczki Cloudbees Docker Build & Publish do tworzenia obrazów kontenerów i publikowania ich w rejestrze.

Aby użyć ECR zamiast mojego prywatnego rejestru, uruchomiłem polecenie AWS CLI, aws --region us-east-1 ecr get-loginktóre wyrzuca docker loginpolecenie do uruchomienia - ale właśnie skopiowałem hasło i utworzyłem poświadczenia Jenkins typu „Nazwa użytkownika z hasłem” na podstawie tego hasła (nazwa użytkownika to zawsze „AWS”).

I to działa dobrze! Problem polega na tym, że hasło ECR generowane przez interfejs AWS CLI jest ważne tylko przez 12 godzin. Teraz muszę ręcznie ponownie wygenerować hasło dwa razy dziennie i ręcznie zaktualizować ekran poświadczeń Jenkins, w przeciwnym razie moje kompilacje zaczną się nie powieść.

Czy istnieje sposób na wygenerowanie trwałych tokenów logowania ECR lub w jakiś sposób zautomatyzować generowanie tokenów?

Guss
źródło

Odpowiedzi:

6

Jest to teraz możliwe za pomocą pomocnika amazon-ecr-credential-helper, jak opisano w https://aws.amazon.com/blogs/compute/authenticating-amazon-ecr-repositories-for-docker-cli-with-credential-helper/ .

Krótko mówiąc:

  • Upewnij się, że instancja Jenkins ma odpowiednie poświadczenia AWS do pobierania / przekazywania z repozytorium ECR. Mogą to być zmienne środowiskowe, udostępniony plik referencji lub profil instancji.
  • Umieść plik binarny docker-credential-ecr-login w jednym z katalogów w $ PATH.
  • Zapisz plik konfiguracyjny Docker w katalogu osobistym użytkownika Jenkins, na przykład /var/lib/jenkins/.docker/config.json. z zawartością{"credsStore": "ecr-login"}
  • Zainstaluj wtyczkę Docker Build and Publish i upewnij się, że użytkownik jenkins może skontaktować się z demonem Docker.
  • Na koniec utwórz projekt z krokiem kompilacji, który opublikuje obraz dokera
Klugscheißer
źródło
4

Jak powiedział @Connor McCarthy, czekając, aż Amazon wymyśli lepsze rozwiązanie dla bardziej trwałych kluczy, tymczasem musieliśmy sami wygenerować klucze na serwerze Jenkins.

Moim rozwiązaniem jest okresowe zadanie, które automatycznie aktualizuje poświadczenia Jenkins dla ECR co 12 godzin automatycznie, przy użyciu Groovy API. Jest to oparte na tej bardzo szczegółowej odpowiedzi , chociaż zrobiłem kilka rzeczy inaczej i musiałem zmodyfikować skrypt.

Kroki:

  1. Upewnij się, że twój mistrz Jenkins ma dostęp do wymaganego AWS API. W mojej konfiguracji mistrz Jenkins działa na EC2 z rolą IAM, więc musiałem tylko dodać uprawnienie ecr:GetAuthorizationTokendo roli serwera. [ Aktualizacja ] Aby uzyskać wszelkie popycha zakończy się pomyślnie, to trzeba także przyznać te uprawnienia: ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability, ecr:PutImage. Amazon ma wbudowane zasady, które oferują te możliwości, zwane AmazonEC2ContainerRegistryPowerUser.
  2. Upewnij się, że interfejs AWS CLI jest zainstalowany w systemie głównym. W moim ustawieniu, gdy master działa w kontenerze dokera Debiana, właśnie dodałem ten krok kompilacji powłoki do zadania generowania klucza: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. Zainstaluj wtyczkę Groovy, która pozwala na uruchomienie skryptu Groovy jako części systemu Jenkins.
  4. Na ekranie poświadczeń znajdź klucz AWS ECR, kliknij „Zaawansowane” i zapisz jego „ID”. W tym przykładzie założę, że jest to „12345”.
  5. Utwórz nowe zadanie z okresowym uruchamianiem 12 godzin i dodaj krok kompilacji „systemowy skrypt Groovy” za pomocą następującego skryptu:

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

Proszę zanotować:

  • użycie ciągu zakodowanego na stałe "AWS"jako nazwy użytkownika dla poświadczeń ECR - tak działa ECR, ale jeśli masz wiele poświadczeń z nazwą użytkownika „AWS”, musisz zaktualizować skrypt, aby zlokalizować poświadczenia na podstawie pole opisu czy coś takiego.
  • Musisz użyć prawdziwego identyfikatora swojego prawdziwego klucza ECR w skrypcie, ponieważ interfejs API dla poświadczeń zastępuje obiekt poświadczeń nowym obiektem zamiast po prostu go aktualizować, a powiązanie między krokiem kompilacji Dockera a kluczem odbywa się według tego identyfikatora. Jeśli użyjesz wartości nullidentyfikatora (jak w odpowiedzi, którą wcześniej podłączyłem), zostanie utworzony nowy identyfikator i ustawienie poświadczeń w kroku kompilacji dokera zostanie utracone.

I to wszystko - skrypt powinien być w stanie uruchamiać się co 12 godzin i odświeżać poświadczenia ECR, a my możemy nadal korzystać z wtyczek Docker.

Guss
źródło
3

Patrzyłem też na ten sam problem. Nie znalazłem odpowiedzi, której żadne z nas szukało, ale byłem w stanie stworzyć obejście ze skryptami powłoki. Dopóki AWS nie wyjdzie z lepszym rozwiązaniem poświadczeń ECR, planuję zrobić coś w tym kierunku.

Zastąpiłem krok Kompilacja i publikacja Dockera zadania Jenkins i krok Wykonaj powłokę. Użyłem następującego skryptu (prawdopodobnie można go lepiej napisać), aby zbudować i opublikować mój kontener do ECR. W razie potrzeby zamień zmienne w nawiasach <>:

#!/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
źródło
Brzmi bardzo rozsądnie. Chodzi o to, że lubię Docker Build and Publish i raczej go używam, ponieważ upraszcza to moje życie. Mam kilka kompilacji kontenerów w systemie i chcę dodać więcej, a integracja tego skryptu z każdą kompilacją jest bardziej kłopotliwa niż jestem gotów z tym żyć. Mam alternatywne rozwiązanie, które dodaję jako odpowiedź.
Guss,
2

Korzystanie z https://wiki.jenkins-ci.org/display/JENKINS/Amazon+ECR z wtyczką Docker Build and Publish działa dobrze.

Danilo
źródło
Zainstalowałem go - ale nie mogłem dowiedzieć się, co z nim zrobić: nie ma konfiguracji i interfejsu użytkownika.
Guss
Zainstaluj wtyczkę. W kroku Kompilacja i publikacja Dockera dostępna jest lista rozwijana o nazwie „Poświadczenia rejestru”. Kliknij „Dodaj” obok, wybierz jako „Poświadczenia AWS” w oknie dialogowym. Wprowadź klucz dostępu / klucz tajny.
Danilo
Teraz widzę. Szkoda, że ​​nie obsługuje profili instancji.
Guss
Tak. Ale na razie wolę to rozwiązanie.
Danilo