GeekFactory

int128.hatenablog.com

AWS CodeBuildとJenkinsの連携

TL;DR

AWS CodeBuildとJenkinsを連携させると、これまでJenkins Agentで実行していたビルド処理をAWS CodeBuildに置き換えることができます。以下のメリットがあります。

  • AWS CodeBuildは無限に*1スケールするので、ビルドキューの待ち行列がなくなる
  • ビルド単位で課金されるので、Jenkins AgentのEC2インスタンスを待機させておくコストが不要になる
  • コンテナでビルド処理が実行されるので、ビルドに必要なOSやミドルウェアを管理する手間がなくなる
  • JenkinsのUIやユーザ管理をそのまま使い続けられるので導入しやすい

AWS CodeBuildとJenkinsを連携させるには公式の AWS CodeBuild Plugin を利用します。

AWS CodeBuildとJenkinsの連携はGitHubだけでなくGitBucketやGitLabでも利用できます。

Getting Started

ここではGitHub→Jenkins→AWS CodeBuildを連携させる例を説明します。ビルドのトリガーは下図のようになります。

+----------------------------------+
| 開発者
+----------------------------------+
  ↓ git push
+----------------------------------+
| GitHub
+----------------------------------+
  ↓ webhook
+----------------------------------+
| Jenkins
+----------------------------------+
  ↓ ビルド実行
+----------------------------------+
| AWS CodeBuild
+----------------------------------+

GitHubの設定

GitHubで新しいリポジトリを作成します。

Jenkinsfile という名前で下記のファイルを作成します。

node {
  stage('codebuild') {
    awsCodeBuild(
      projectName: 'sandbox',
      region: 'ap-northeast-1',
      sourceControlType: 'project',
      sourceVersion: env.BRANCH_NAME,
      // CodeBuildにブランチ名を環境変数で渡すため
      envVariables: "[{BRANCH_NAME,${env.BRANCH_NAME}}]",
    )
  }
}

buildspec.yml という名前で下記のファイルを作成します。

version: 0.2
phases:
  build:
    commands:
      - echo "Current branch is $BRANCH_NAME."

Jenkinsの設定

AWS CodeBuild Pluginをインストールしておきます。

Multibranch Pipelineジョブを作成し、先ほど作成したGitHubリポジトリをビルドするように設定します。詳しい手順は https://go.cloudbees.com/docs/cloudbees-documentation/cje-user-guide/index.html#github-branch-source を参照してください。

JenkinsからAWS CodeBuildを操作できるようにするため、Jenkinsを実行しているEC2インスタンスにIAMロールを付与します。IAMロールを利用できない場合は代わりにIAMユーザを作成し、アクセスキーとシークレットキーをJenkinsの認証情報に登録しておきます。

IAMロールにアタッチするポリシーは https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/jenkins-plugin.html を参照してください。とりあえず下記のポリシーをアタッチすれば動きますが、本来はもう少し絞った方がよいでしょう。

f:id:int128:20180420132556p:plain

AWS CodeBuildの設定

マネジメントコンソールからAWS CodeBuildを開き、新しいプロジェクトを作成します。

  • ソースプロバイダ: GitHub
  • リポジトリ: 先ほど作成したGitHubリポジトリを指定します
  • Webhook: オフ
  • 環境イメージ: AWS CodeBuild によって管理されたイメージの使用
  • ランタイム: Java
  • ランタイムバージョン: aws/codebuild/java:openjdk-8
  • ビルド仕様: ソースコードのルートディレクトリの buildspec.yml を使用
  • サービスロール: アカウントでサービスロールを作成

ここではJavaのアプリケーションをビルドする設定としましたが、他の言語も利用できます。

新しいプロジェクトを作成したら、ビルドの開始 をクリックしてビルドが成功するか確認しておきます。

f:id:int128:20180420130121p:plain

動作確認

GitHubに新しいコミットをpushします。まず、Jenkinsで新しいビルドが実行されることを確認します。ビルドが実行されない場合はJenkinsの設定からログを確認してみてください。Webhookやアクセストークンの設定に問題があることが多いです。

次に、AWS CodeBuildで新しいビルドが実行されることを確認します。ビルドが実行されない場合はビルドログにエラーメッセージが出ていると思います。IAMロールの権限不足やプロジェクト名の誤りなどが考えられます。

ビルドした成果物のS3へのアップロード

AWS CodeBuildにはビルドした成果物をS3バケットにアップロードする機能があります。S3バケットからEC2インスタンスにアプリをリリースしている場合に有用です。

まず、成果物をアップロードするためのS3バケットを作成します。ここではバケット名を s3-release とします。

AWS CodeBuildのプロジェクトで以下を設定します。

buildspec.yml に以下を書きます。

version: 0.2
phases:
  build:
    commands:
      - echo "Current branch is $BRANCH_NAME." > result.txt
artifacts:
  files:
    - result.txt

AWS CodeBuildでビルドを実行してみましょう。S3バケットresult.txt という名前のファイルが配置されていれば成功です。

S3パスの動的な指定

ブランチ名に応じてS3バケットのパスを変えたいといった場合は、Jenkinsfileの artifactPathOverride を利用してパスを指定します。

// Jenkinsfile
node {
  stage('codebuild') {
    awsCodeBuild(
      projectName: 'sandbox',
      region: 'ap-northeast-1',
      sourceControlType: 'project',
      sourceVersion: env.BRANCH_NAME,
      envVariables: "[{BRANCH_NAME,${env.BRANCH_NAME}}]",
      // S3に成果物をアップロードする
      artifactLocationOverride: 's3-release',
      artifactNameOverride: '/',
      artifactPathOverride: "/releases/${env.BRANCH_NAME}/",
      artifactPackagingOverride: 'NONE',
      artifactTypeOverride: 'S3',
    )
  }
}

Gitリポジトリにコミットをpushし、Jenkins経由でビルドを実行してみましょう。master ブランチをpushした場合は /releases/master/result.txt というファイルが配置されているはずです。

GitHub以外のリポジトリとの連携

GitBucket

GitBucketはGitHub Enterpriseとして振る舞うことができるので、特別な対応は不要です。Jenkinsの設定ではGitHubをGitBucketに読み替えて設定してください。AWS CodeBuildの設定ではGitHub Enterpriseを指定します。詳しくは以下を参考にしてください。

GitLab

JenkinsとGitLabを連携させるにはJenkins GitLab Pluginが必要です。詳しい手順は JenkinsとGitLabを連携する方法 を参照してください。

(2018-06-28追記)GitBucketと同様の方法で、AWS CodeBuildがGitLabからソースコードを取得できるようになります。

以下は古い内容です。

AWS CodeBuildはGitLabに対応していないため、S3経由でソースコードを渡す必要があります。

+----------------------------------+
| 開発者
+----------------------------------+
  ↓ git push
+----------------------------------+
| GitLab
+----------------------------------+
  ↓ webhook
+----------------------------------+
| Jenkins (Jenkins GitLab Plugin)
+----------------------------------+
  ↓ ソースコードを保存
+----------------------------------+
| S3バケット
+----------------------------------+
  ↓ ソースコードをビルド
+----------------------------------+
| AWS CodeBuild
+----------------------------------+

まず、ソースコードを配置するためのS3バケットを作成します。オブジェクトバージョニングを有効にしておきます(有効にしないとJenkins AWS CodeBuild Pluginがエラーになります)。

AWS CodeBuildのプロジェクトの設定でS3からソースコードを取得するようにします。

Jenkinsfileでは sourceControlTypejenkins に設定します。これにより、Jenkinsが取得したソースコードがS3バケットに配置されるようになります。

// Jenkinsfile
node {
  stage('codebuild') {
    awsCodeBuild(
      projectName: 'sandbox',
      region: 'ap-northeast-1',
      sourceControlType: 'jenkins',
      sourceVersion: env.BRANCH_NAME,
      envVariables: "[{BRANCH_NAME,${env.BRANCH_NAME}}]",
    )
  }
}

Jenkinsのビルドログを開き、下記のようなS3バケットへのアップロードのログが表示されていれば成功です。

[Pipeline] awsCodeBuild
[AWS CodeBuild Plugin] Uploading code to S3 at location sandbox/jenkins. MD5 checksum is ...
[AWS CodeBuild Plugin] S3 object version id for uploaded source is ...
[AWS CodeBuild Plugin] Starting build with 
    > project name: jenkins-docker
    > source version: ...
[AWS CodeBuild Plugin] Build id: jenkins:895c9eba-b455-4f70-a83a-babe3d50fa39
[AWS CodeBuild Plugin] CodeBuild dashboard: https://ap-northeast-1.console.aws.amazon.com/codebuild/home?region=ap-northeast-1#builds/jenkins:...
[AWS CodeBuild Plugin] CloudWatch dashboard: https://console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#logEvent:group=/aws/codebuild/jenkins;...
[AWS CodeBuild Plugin] 2018/04/12 03:33:00 Waiting for agent ping
[AWS CodeBuild Plugin] 2018/04/12 03:33:00 Waiting for DOWNLOAD_SOURCE
[AWS CodeBuild Plugin] 2018/04/12 03:33:08 Phase is DOWNLOAD_SOURCE
[AWS CodeBuild Plugin] 2018/04/12 03:33:08 CODEBUILD_SRC_DIR=/codebuild/output/src896775218/src
[AWS CodeBuild Plugin] 2018/04/12 03:33:08 YAML location is /codebuild/output/src896775218/src/buildspec.yml
[AWS CodeBuild Plugin] 2018/04/12 03:33:08 Processing environment variables
[AWS CodeBuild Plugin] 2018/04/12 03:33:08 Moving to directory /codebuild/output/src896775218/src
[AWS CodeBuild Plugin] 2018/04/12 03:33:08 Registering with agent
[AWS CodeBuild Plugin] 2018/04/12 03:33:08 Phases found in YAML: 1
[AWS CodeBuild Plugin] 2018/04/12 03:33:08  BUILD: 1 commands
[AWS CodeBuild Plugin] 2018/04/12 03:33:08 Phase complete: DOWNLOAD_SOURCE Success: true

まとめ

ビルドキューの待ち行列やJenkins Agentインスタンスのメンテナンスで疲弊している場合はAWS CodeBuildを試してみましょう。

*1:デフォルトでは同時実行数は20に制限されています。