朝日ネット 開発者ブログ

朝日ネットのエンジニアによるリレーブログ。今、自分が一番気になるテーマで書きます。

たのしいCloud Build

開発部のmuratamです。 今回はGoogle CloudのサービスのひとつであるCloud Buildについて書きます。

Cloud Buildについて

cloud.google.com

Google Cloud上で、コンテナベースでビルドやテスト、デプロイができるサービスです。 一部の社内プロジェクトでも利用しており、ビルド方法をコーディングすることでCIを回すことができます。 社内ではJenkinsも使っていますが、Jenkinsと比較した場合、Jenkinsのメンテナンス(バージョンアップなど)をしなくていいのが個人的には嬉しいポイントだと思っています。その作業がどうしてもJenkinsに詳しい人に集中して本来の仕事が中断してしまうのも辛いところです。

Cloud Buildの料金ですが、通常のインスタンスを使っている場合は1日ごとに120分の無料枠があり、超えた分は1分あたり$0.003となっています (2019年1月現在)。 小規模で試してみる分にはまず料金が発生することはないでしょう。

やってみる

Hello Worldレベルの単純なものですがGitHubに置いたGoプログラムをビルドすることにします。

Google Cloud Platformの設定

Cloud Build APIを有効にする必要があります。 https://console.cloud.google.com/cloud-build/builds で "Cloud Build APIを有効にする"ボタンをクリックします。 課金が有効でないとできませんのでご注意ください。

ビルドの構成

ビルドの手順はYAMLまたはJSONでビルドステップを並べることによって定義します。 各ビルドステップではビルドに必要なツールを入れたコンテナを使って処理を実行していきます。 Cloud Buildの設定はcloudbuild.yaml1という名前のファイルに置いておきます。 これをレポジトリで管理すればビルド手順のバージョン管理もできます。

steps:
  - name: '<container for step1>'
    args: ['<arg1>', '<arg2>']
  - name: '<container for step2>'
    args: ['<arg1>', '<arg2>']
...

ビルドに使えるコンテナイメージ(クラウドビルダー)が既にいくつか用意されています(公式, コミュニティ)。 逆に、自分でコンテナイメージを用意すればかなり柔軟なことができます。

まずgitが動くコンテナイメージ gcr.io/cloud-builders/git が用意されているのでそれを使ってレポジトリからソースコードを取得します。

/workspace/ がデフォルトの作業ディレクトリとして用意されており、そのディレクトリ以下に加えた変更は次のステップに引き継がれます。

Goが動くイメージ gcr.io/cloud-builders/go も用意されているのでそれを使ってテスト、成功したらビルドします2

steps:
  - name: 'gcr.io/cloud-builders/git'
    args: ['clone', '-b', 'master', '--single-branch', '--depth', '1', 'https://github.com/AsahiNetMuratam/sample-build.git', 'src/sample-build/']
  - name: 'gcr.io/cloud-builders/go'
    args: ['test', 'sample-build']
  - name: 'gcr.io/cloud-builders/go'
    args: ['install', 'sample-build']

ここまででビルドを定義したのでCloud Buildで実行してみます。 コマンドラインからgcloudを使って実行できます。

% gcloud builds submit --config=./cloudbuild.yaml --no-source

ビルド履歴を見に行くと先ほど実行したビルドが追加されています。

f:id:anmrtm:20190118122310j:plain

ビルドにはCloud Buildのサービスアカウントが使用され、プロジェクト内のサービスであればほぼ問題なく利用することができます。 また、ビルドステップで設定できる項目は他にもあるので公式のドキュメント(ビルド構成の概要)を参照してください。

成果物をCloud Storageに置く

このままではせっかくビルドした成果物を利用することができないので、バイナリをCloud Storageに置いてみます。

cloudbuild.yamlにartifactsフィールドを記述するとビルド終了後に自動でCloud Storageに保存されます。 locationにCloud Storageのパスを、pathsにCloud Storageに保存したいファイルを記述します。

artifacts:
  objects:
    location: 'gs://${_BUCKET_NAME}/'
    paths: ['bin/sample-build']

"$"ではじまる変数はsubmitのときに--substitutionsで定義することができます。(変数値の置換)

% gcloud builds submit --config=./cloudbuild.yaml --no-source --substitutions='_BUCKET_NAME=<your bucket name>'

ビルドが成功するとファイルと保存結果を表すマニフェスト(jsonファイル)がCloud Storageに保存されます。 マニフェストはビルド履歴からも確認できます。

f:id:anmrtm:20190118122814j:plain

成果物をContainer Registryに登録する

成果物のバイナリが動くコンテナイメージをContainer Registryにpushしてみます。 /workspace/image というディレクトリを作成しそこにレポジトリのルートにあるDockerfileとバイナリをコピーしてコンテナイメージを作ります。 ${PROJECT_ID}はデフォルトでBuildを実行しているプロジェクト名が設定されます。 dirフィールドで、/workspaceからの相対的な実行ディレクトリを指定できます。

  - name: 'alpine'
    args: ['mkdir', 'image']
  - name: 'alpine'
    args: ['cp', 'bin/sample-build', 'image/']
  - name: 'alpine'
    args: ['cp', 'src/sample-build/Dockerfile', 'image/']
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'gcr.io/${PROJECT_ID}/sample-build', '.']
    dir: 'image'

imagesフィールドにコンテナイメージを書いておくとビルドの終了後にpushされます。 もちろん明示的にdocker pushするstepを記述することもできます。

images: ['gcr.io/${PROJECT_ID}/sample-build']

トリガー

レポジトリへのpushにあわせて自動でビルドを走らせるトリガー機能も用意されています3。 GoogleがホストしているSource Repositoriesのほか、GitHub, BitBucketにも対応しています。

設定はコンソールから行います。 まず"トリガーを追加"ボタンを押し、ソースを選択します。 今回はGitHubを選択します。 選択するとGitHubの認証トークンをGoogleが保存することに同意を求めるチェックボックスが現れるのでチェックして"続行"ボタンを押します。 続いてGitHubにログインし、OAuthの許可を求められるので許可します。 Cloud Buildの画面に戻ってきたらレポジトリを選択し、トリガー設定をすれば完了です。

トリガー設定では ビルド設定にcloudbuild.yamlを選択しておきます。 cloudbuid.yamlはレポジトリにあるものを参照します。 代入変数の欄で、コマンドラインから実行していた時は--substitutionsで設定していた変数をセットできます。

f:id:anmrtm:20190118123205j:plain

トリガー一覧で"トリガーを実行"を押して、ブランチを選ぶとトリガー発生時の挙動を試すことができます。

f:id:anmrtm:20190118125653j:plain

通知

Cloud Buildはビルドに関する通知をGoogle Cloud Pub/Subに流しており、それをsubscribeすることでビルドの失敗などイベントの通知をすることができます。 この記事ではあまり深く触れませんが、公式のドキュメントCloud Functionsを通してSlackへの投稿やメール送信をする方法が紹介されています。

まとめ

今回触れていない機能もありますが、Cloud Buildでそこそこお手軽かつ柔軟なCIが実現できます。 現在も小規模ながら使用していますが特に問題なく働いてくれているので、今後も引き続き使っていけたらよいなと考えています。

採用情報

朝日ネットでは新卒採用・キャリア採用を行っております。


  1. YAMLで書く場合。また、ファイル名は任意です。

  2. GOPATHはカレントディレクトリにsrcというディレクトリがあるとそこをGOPATHとして使う挙動があるのでそれを利用しています。もちろんenvを使って環境変数で明示的にGOPATHを与えてもよいです。

  3. この記事を書いている段階ではまだベータ版です。