Masayan tech blog.

  1. ブログ記事一覧>
  2. Google Cloud Buildを使用してCI/CDパイプラインをサクッと構築する

Google Cloud Buildを使用してCI/CDパイプラインをサクッと構築する

公開日

Google Cloud Buildとは

Googleが提供するクラウドコンピューティングサービス。

本記事では、nodeアプリケーションをGoogle App Engine (GAE)にデプロイするためのパイプラインをGoogle Cloud Buildで構築する

手順

リポジトリ作成

事前にgithubのリポジトリを用意しておくこと。また、Google App Engine (GAE)のプロジェクト作成の方法はこちらの記事を参考されたし

Cloud Build

トリガー作成

GCPのコンソールから、Cloud Buildを選択し、トリガーを作成をクリック

名前、リージョン、イベントを入力。イベントは今回、ブランチにpushするを選択

リポジトリの項目で、新しいリポジトリに接続をクリック

プロバイダはGithubを選択。認証が完了したら、リポジトリを選択し、接続。ブランチを指定。

構成で、形式は自動検出もしくはCloud Build構成ファイルを選択し、ロケーションはリポジトリを選択。最後に選択をクリック

Cloud Build サービスアカウントに権限追加

トリガーの設定でサービスアカウントを特に指定しなかった場合、Cloud Build サービス アカウント ( xxxxx@cloudbuild.gserviceaccount.com )で処理が実行されるが、このアカウントには、AppEngineへのデプロイに必要なロールを追加する必要がある。(必要なロールが付与されていない場合は以下のようなエラーが出る)

ERROR: (gcloud.app.deploy) Permissions error fetching application [apps/projectid]. Please make sure that you have permission to view applications on the project and that XXXXXXXXXX@cloudbuild.gserviceaccount.com has the App Engine Deployer (roles/appengine.deployer) role.

AppEngineへのデプロイに必要なロールはこちらに書いてあるので、App Engine Admin API を有効化した上で、設定から「App Engine管理者」と「サービスアカウントユーザー」を有効化

必要なファイルを用意

今回はcloud-build-testというディレクトリの中にapp.yamlとcloudbuild.yaml、app.jsとpackage.jsonを作成して配置した

cloudbuild.yaml

steps:
- name: 'node:18'
  entrypoint: 'npm'
  args: ['install']
- name: 'gcr.io/cloud-builders/gcloud'
  args: ['app', 'deploy', 'app.yaml', '--project', 'your projectId']

app.yaml

runtime: nodejs
service: sample-node-app
entrypoint: npm start

env: flex
runtime_config:
  operating_system: ubuntu22
manual_scaling:
  instances: 1
resources:
  cpu: 1
  memory_gb: 0.5
  disk_size_gb: 10

app.js

'use strict';

const express = require('express');

const app = express();

app.get('/', (req, res) => {
  res.status(200).send('Hello, world!').end();
});

const PORT = parseInt(process.env.PORT) || 8080;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
  console.log('Press Ctrl+C to quit.');
});

module.exports = app;

package.json

{
  "name": "appengine-hello-world",
  "description": "Simple Hello World Node.js sample for Google App Engine Flexible Environment.",
  "version": "0.0.2",
  "private": true,
  "license": "Apache-2.0",
  "author": "Google Inc.",
  "repository": {
    "type": "git",
    "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
  },
  "engines": {
    "node": ">=16.0.0"
  },
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "^4.17.1"
  }
}

これで対象のリポジトリにpushするとビルドが走り、AppEngineにデプロイされる。ちなみに、Cloud Buildのトリガーから「実行」をクリックすると手動で実行させることも可能

おまけ

app.yamlのシークレット値

Cloud BuildでデプロイするリソースがAppEngineで、かつapp.yamlにシークレット値が含まれている場合、うまく取り扱う必要がある(app.yaml上からシークレットマネージャーにアクセスする機能がないため ※2024/1/7時点)

これを実現するためにかなり調べたが、現状は以下の2通りのいずれかの方法になると思われる

  • app.yamlのシークレット値は仮の値を設定しておき、CI/CD時に、シークレットマネージャーから値を取得し、app.yamlの該当の箇所を置換してデプロイする
  • シークレット値は別のapp.env.ymlなどに出力し、CI/CD時に、app.yamlのincludesを使用して、app.env.ymlをapp.yamlに取り込む

色々検討し、1つ目の方法を使うことにしたので、その際の設定値のサンプルを示しておく

cloudbuild.yaml

# gcloud app deploy前にapp.yamlの該当の箇所を置換する
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    id: "Deploy"
    entrypoint: '/bin/bash'
    args:
      - -c
      - |
        sed -i "s|%SERVICE_ACCOUNT_PRIVATE_KEY%|$$SERVICE_ACCOUNT_PRIVATE_KEY|g" ${_APP_YAML_FILE}
        gcloud app deploy --project=${_PROJECT_ID} ${_APP_YAML_FILE}
    secretEnv: ['SERVICE_ACCOUNT_PRIVATE_KEY']

# シークレットマネージャーから値を取得する
availableSecrets:
  secretManager:
  - versionName: ${_SERVICE_ACCOUNT_PRIVATE_KEY_SECRET_VERSION_NAME}
    env: SERVICE_ACCOUNT_PRIVATE_KEY

app.yaml

env_variables:
  SERVICE_ACCOUNT_PRIVATE_KEY: "%SERVICE_ACCOUNT_PRIVATE_KEY%"

まとめ

いかがでしたでしょうか。本記事では、Google Cloud Buildを使用してCI/CDパイプラインをサクッと構築するための手順について紹介しました。ぜひ参考にしてみて下さい。