web-dev-qa-db-ja.com

Amazon Elastic Container RegistryをJenkinsと統合する

Amazonの新しいElastic Container Registry(ECR)をJenkinsビルドサービスと統合しようとしています。 Cloudbees Docker Build&Publishプラグインを使用して、コンテナーイメージをビルドし、レジストリに公開しています。

プライベートレジストリの代わりにECRを使用するために、AWS CLIコマンドaws --region us-east-1 ecr get-loginを実行してdocker loginコマンドを実行しましたが、パスワードをコピーして、「ユーザー名」タイプのJenkins認証情報を作成しましたパスワード付き」(そのユーザー名は常に「AWS」です)。

そしてそれはうまくいきます!問題は、AWS CLIによって生成されるECRパスワードが12時間のみ有効であることです。現在、1日2回手動でパスワードを再生成し、Jenkinsの認証情報画面を手動で更新する必要があります。更新しないと、ビルドが失敗します。

永続的なECRログイントークンを生成する方法、またはトークンの生成を自動化する方法はありますか?

10
Guss

@Connor McCarthyが言ったように、Amazonがより永続的なキーのためのより良いソリューションを考え出すのを待つ間、当面はJenkinsサーバーでキーを自分で生成する必要があります。

私の解決策は、Groovy APIを使用して、12時間ごとにECRのJenkins資格情報を自動的に更新する定期的なジョブを持つことです。これは この非常に詳細な回答 に基づいていますが、いくつか異なることを行い、スクリプトを変更する必要がありました。

手順:

  1. Jenkinsマスターが必要なAWS APIにアクセスできることを確認してください。私のセットアップでは、JenkinsマスターがIAMロールを持つEC2で実行されているので、サーバーロールにecr:GetAuthorizationToken権限を追加する必要がありました。 [update]プッシュを正常に完了するには、次の権限も付与する必要があります:ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability, ecr:PutImage。 Amazonには、AmazonEC2ContainerRegistryPowerUserと呼ばれるこれらの機能を提供する組み込みポリシーがあります。
  2. AWS CLIがマスターにインストールされていることを確認してください。私のセットアップでは、マスターがdebian dockerコンテナーで実行されているので、次のシェルビルドステップをキー生成ジョブに追加しました: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. Jenkinsシステムの一部としてGroovyスクリプトを実行できるようにする Groovyプラグイン をインストールします。
  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)
}

ご注意ください:

  • eCR資格情報のユーザー名としてハードコードされた文字列"AWS"の使用-これはECRの仕組みですが、ユーザー名「AWS」の資格情報が複数ある場合は、スクリプトを更新して検索する必要があります。説明フィールドなどに基づく資格情報。
  • クレデンシャルのAPIは、クレデンシャルオブジェクトを単に更新するのではなく、新しいオブジェクトで置き換え、実際のECRキーの実際のIDをスクリプトで使用する必要があります。Dockerビルドステップとキーの間のバインディングはIDによるものです。 IDに値nullを使用すると(前にリンクした回答のように)、新しいIDが作成され、Dockerビルドステップでの資格情報の設定が失われます。

これで完了です。スクリプトは12時間ごとに実行され、ECR資格情報を更新できる必要があります。Dockerプラグインを引き続き使用できます。

4
Guss

これは、 Amazon-ecr-credential-helper を使用して可能になりました https://aws.Amazon.com/blogs/compute/authenticating- Amazon-ecr-repositories-for-docker-cli-with-credential-helper /

それの短いです:

  • Jenkinsインスタンスに、ECRリポジトリでプル/プッシュするための適切なAWS認証情報があることを確認してください。これらは、環境変数、共有認証情報ファイル、またはインスタンスプロファイルの形式にすることができます。
  • Docker-credential-ecr-loginバイナリを$ PATHのいずれかのディレクトリに配置します。
  • Docker構成ファイルをJenkinsユーザーのホームディレクトリ(/var/lib/jenkins/.docker/config.jsonなど)に書き込みます。コンテンツ{"credsStore": "ecr-login"}
  • Docker Build and Publishプラグインをインストールし、jenkinsユーザーがDockerデーモンにアクセスできることを確認します。
  • 最後に、Dockerイメージを公開するビルドステップでプロジェクトを作成します
6
Klugscheißer

私もこのまったく同じ問題を調査していました。どちらも探していた答えは思いつきませんでしたが、シェルスクリプトを使用して回避策を作成できました。 AWSがECRクレデンシャルに対するより優れたソリューションを提供するまで、これらの方針に沿って何かを行う予定です。

JenkinsジョブのDocker Build and PublishステップをExecute Shellステップに置き換えました。次のスクリプトを使用して(おそらくより適切に記述される可能性があります)、コンテナーをビルドして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}
3
Connor McCarthy

Docker Build and Publishプラグインで https://wiki.jenkins-ci.org/display/JENKINS/Amazon+ECR を使用しても問題なく機能します。

2
Danilo