🐧

Cloud Build 入門:YAML を使った CI/CD パイプライン構築

2024/09/04に公開

はじめに

こんにちは、クラウドエースの SRE 部の梶尾です。
この記事では、YAML ファイルを用いて Cloud Build を利用した CI/CD パイプラインの構築方法を、初心者向けにわかりやすく解説します。

今回行うこととそのメリット

GitHub と Cloud Build を連携し、terraform initterraform apply を自動で実行するパイプラインを構築します。これにより、コードが GitHub に push されると同時に、Terraform による初期化と変更の適用が自動的に行われます。

これを行うことで、コードの変更が自動的に環境に反映される仕組みを実現することができ、手間が省けると同時に変更のミスを減らすことができます。さらに、変更が自動で適用されるため、環境が常に最新の状態を保つことができます。

Cloud Build の概要と利点

まず、Cloud Build は何ができるのかというところを説明します。
Cloud Build は、主にソフトウェア開発の自動化をサポートします。特に、CI/CD と呼ばれる仕組みを簡単に実現することができます [1]
CI/CD とは、コードの変更を自動でビルドし、テストし、問題がなければ自動的にデプロイするプロセスのことを指します。これにより、手動で行う必要がなくなり、開発スピードが向上し、品質を維持しながらリリース頻度を高めることができます [2]

ただし、リリースという段階においては、特に大きな変更や節目のリリースの場合、チームの判断で手動で行うこともあります。

YAML ってなに

構造化データを表現するためのデータフォーマットの一つであり、JSON や XML と比較して、構文がシンプルで人間が読みやすく書きやすいことが特徴です。
YAML は、主にインフラストラクチャの自動化や CI/CD の設定ファイルで使われることが多く、Cloud Build でも YAML ファイルを使ってパイプラインを構築できます。
今回は、YAML の基本的な構文や使用例を解説し、Cloud Build での実践的な活用方法に焦点を当てていきます。

GitHub と Cloud Build を連携

まずは、対象プロジェクトの Cloud Build API を有効にする必要があります。
次に、Cloud Build からリポジトリの接続とトリガーの作成をしていく必要があります。
サービスアカウントの作成方法は以下のとおりです。

  1. Cloud Console にアクセスし、ナビゲーションメニューから「IAM と管理」→「サービスアカウント」を選択します。
  2. 「サービスアカウントを作成」をクリックし、サービスアカウント名を入力します(例: cloud-build-service-account)。
  3. 「作成と続行」をクリックします。
  4. 「IAM」→「アクセス権を付与」を選択します。
  5. 「ロール」に Cloud Build を使用するにあたり、必要となる権限(cloudbuild.builds.builder, cloudbuild.serviceAgent, ※storage.objectAdmin )を付与します。
    ※logsBucket で Cloud Storage のバケット名を指定する場合に必要になります。

Cloud Console からのリポジトリ接続方法は以下のとおりです [3]

  1. Cloud Console にアクセスし、ナビゲーションメニューから「Cloud Build」→「リポジトリ」を選択します。
  2. 「リポジトリを接続」を選択します。
  3. 任意のリージョンを選択する。(例:asia-northeast1 (東京))
  4. GitHub (Cloud Build GitHub アプリ)を選択します。
  5. 自分の GitHub アカウントと GitHub リポジトリを選択します。

Cloud Console からのトリガー作成方法は以下のとおりです [4]

  1. Cloud Console にアクセスし、ナビゲーションメニューから「Cloud Build」→「トリガー」を選択します。
  2. 「トリガーを作成」を選択します。
  3. イベントの選択を「ブランチに push する」に設定すると、git push origin [ブランチ名]を実行した際にトリガーが実行されます。
    新しいタグを push する場合は、リリース バージョンを更新した際にトリガーが実行されます。
    「pull リクエスト」を選択すると、新しい pull リクエストを作成した際やgit push origin [ブランチ名]を実行した際にトリガーが実行されます。
  4. 構成の形式として、YAML ファイルを作成し Cloud Build が読み込んで実行するため、「Cloud Build 構成ファイル(yaml または json)」を選択します(今回は YAML を作成します)。
  5. 「ロケーション」→「リポジトリ」を選択し、「Cloud Build 構成ファイルの場所」の中にファイル名(例:cloudbuild.yaml)を記載します。
  6. 上記で作成したサービスアカウントを選択します。

YAML ファイルの作成

さて、今回の本題である YAML ファイルの作成方法について説明していきます [5]
この YAML ファイルは、対応したトリガーが起動された際に、Cloud Build が terraform init と terraform apply を自動的に実行するように設定します。

steps を分けることは必須ではありませんが、エラーが起こった場合にどこでエラーが発生したのかを把握しやすくなるため、分けることをお勧めします。

以下に、steps を分けない場合と分ける場合の 2 種類の YAML 記述例を示します。

stepsを分けない記述
steps:
  - name: "hashicorp/terraform:1.6.0" 	# 使用する Docker イメージ(この場合は Terraform のバージョン1.6.0)
    entrypoint: "sh" 			# シェルを指定('sh'はシェルスクリプトを実行する)
    args:
      - "-c" 				# 'sh'の引数として'-c'を指定(シェルでコマンドを実行)
      - | 				# 複数行のコマンドを実行するための記号(pipe記号)
        terraform init
        terraform plan
        terraform apply -auto-approve

logsBucket: "ログを保存する Cloud Storage 名" # ビルドログを保存する Cloud Storage のバケット名を指定

serviceAccount: "サービスアカウント名" 	# Cloud Build が使用するサービスアカウントを指定
stepsを分ける記述
steps:
  - name: "hashicorp/terraform:1.6.0"
    entrypoint: "sh"
    args:
      - "-c"
      - terraform init

  - name: "hashicorp/terraform:1.6.0"
    entrypoint: "sh"
    args:
      - "-c"
      - terraform plan

  - name: "hashicorp/terraform:1.6.0"
    entrypoint: "sh"
    args:
      - "-c"
      - terraform apply -auto-approve

logsBucket: "ログを保存する Cloud Storage 名 "

serviceAccount: "サービスアカウント名"

name は必須のフィールドであり、実行する Docker イメージを指定しています。この場合は、Terraform のバージョン 1.6.0 を含む Docker イメージを使うということになります。他には、Python や Node.js をここで指定することができます。

entrypoint は、実行されるコマンドやスクリプトを指定するためのもので、必須のフィールドではありませんが、特定のシェルやスクリプトを使いたい場合は必要になってきます。この場合は、sh というシェルを使用しています。他には、bash や zsh 等をここで指定することができます。
terraform apply -auto-approve の -auto-approve は、terraform apply コマンドを実行する際に、ユーザーの確認を求めることなく、自動的に適用を実行するために必要な記述です。
-auto-approve を使わないとき、CI/CD を構築して自動化しているにも関わらず、確認が入るため自動ではなくなってしまいます。
使用することで、Terraform による環境変更が自動で適用されるため、CI/CD パイプライン内で手動の確認を必要とせず、スムーズに進めることができます。

args は、実行するコマンドのオプションや引数を指定するために使用します。例えば、特定のオプションをコマンドに渡す場合に便利です。
実際の運用では頻繁に使用され、コマンドを柔軟に制御するために欠かせないフィールドです。entrypoint だけで実行したいコマンドが完結する場合は、args を省略することもできますが、複雑なコマンドを実行する場合には args を使用します。

logsBucket は、ビルドログの保存場所を指定するフィールドです。省略した場合、ログは Cloud Build のデフォルトのログバケットに保存されます。デフォルトでは、ログは Cloud Logging に自動的に保存されますが、特定の Cloud Storage バケットを指定することで、任意の場所に保存することができます。ログの保存先を明確にしておきたい場合や、複数のプロジェクトで一貫してログ管理を行いたい場合は、このフィールドを設定するのが有用です。

serviceAccount は、Cloud Build が使用するサービスアカウントを指定する任意のフィールドです。このフィールドを設定する際には、必ず最小権限の原則を遵守してください。これにより、サービスアカウントに不要な権限が付与されることを防ぎ、セキュリティリスクを最小限に抑えることができます。
Compute Engine をデプロイする場合は、compute.instanceAdmin.v1 を付与する必要があります。これは、Compute Engine のインスタンスを作成、管理することができる権限です。
Cloud SQL  をデプロイする場合は、cloudsql.admin を付与する必要があります。これは、Cloud SQL のインスタンスを作成、管理することができる権限です。
その他デプロイするリソースに応じて権限を付与する必要があります。権限はデプロイ先のプロジェクトに付与する必要があります。
権限を適切に設定することで、サービスアカウントに必要な最小限の権限だけを付与し、セキュリティを強化できます。デフォルトのサービスアカウントを使用すると、必要以上の権限が与えられてしまう可能性があるため、注意が必要です。
また、serviceAccount を明確に指定しないと、存在しないか間違ったサービスアカウントを参照してしまい、権限エラーが発生する可能性があります。そのようなエラーを防ぐためにも、適切なサービスアカウントを設定しておくことをお勧めします。

エラーの対処法

Cloud Build が YAML ファイルを読み込み、実行するにあたり、起きたエラーを私がどう対処したか解説します [6]

権限エラー
権限を付与しているはずなのに、付与されていないというエラーが発生する可能性があります。terraform で権限を付与している場合、反映のタイミングや状態管理の差異が原因でエラーが起きることがあります。この場合、まずは terraform apply を再実行してエラーが解消されるか確認してください。

generic::not_found: Unknown service account というエラー
デフォルトのサービスアカウントを使用したことによって表示されたエラーです。Cloud Build 用のサービスアカウントを作り、必要な権限を付与することによって解決することができます [7]

Step failed: Build failed: "name" is not a valid Docker image というエラー
指定した Docker イメージの名前が存在していないか、間違っている場合に表示されたエラーです。正しい Docker イメージ名やバージョンを指定することで解決します。

SERVICE_DISABLED というエラー
Cloud Build が必要とする API が無効になっている場合に表示されたエラーです。Cloud Console で必要な API を有効化することで解決することができます [8]

まとめ

今回は、Cloud Build を利用して、GitHub と連携した CI/CD パイプラインを構築する方法について解説しました。特に、初心者の方でもわかりやすいように、YAML ファイルの基本的な書き方と、それを Cloud Build でどのように活用するかに焦点を当てました。
YAML ファイルを使うことで、インフラストラクチャの自動化や CI/CD の設定を簡単に行うことができます。
この記事で紹介した手順を参考に、皆さんもぜひ自分のプロジェクトで CI/CD パイプラインを構築してみてください。

参考 URL

脚注
  1. Cloud Build の概要: https://cloud.google.com/build/docs/overview?hl=ja ↩︎

  2. データ処理用の CI/CD パイプライン設計ガイド: https://cloud.google.com/architecture/cicd-pipeline-for-data-processing?hl=ja ↩︎

  3. Cloud Build を自分のリポジトリに接続する: https://cloud.google.com/build/docs/automate-builds?hl=ja#connect_to_your_repository ↩︎

  4. トリガーを作成する: https://cloud.google.com/build/docs/automate-builds?hl=ja#create_a_trigger ↩︎

  5. ビルド構成の作成: https://cloud.google.com/build/docs/configuring-builds/create-basic-configuration?hl=ja#creating_a_build_config ↩︎

  6. Cloud Build のトラブルシューティングガイド: https://cloud.google.com/build/docs/troubleshooting?hl=ja ↩︎

  7. サービスアカウント: https://cloud.google.com/build/docs/securing-builds/configure-user-specified-service-accounts?hl=ja ↩︎

  8. Cloud Build の API: https://cloud.google.com/build/docs/securing-builds/configure-user-specified-service-accounts?hl=ja#before_you_begin ↩︎

Discussion