GKE大好きマン、SREチームの吉村と申します。
今回は少し浮気して、GCPにある古参のコンテナ実行環境のCloudBuildをご紹介します。
Cloud Build
CloudBuildの実行トリガーの少なさに涙を流したことはありませんか?
リポジトリ連携できないけどCloudBuildを動かしたい!
そんなご要望にCloudFunctionsがお応え致します。
GCSへのファイル更新をトリガーに、GCSのバケットへアップロードされたzipファイルをコンテナにマウントしてサーバーレス処理を試してみます。
1日120分無料のCloudBuildを使って、手軽にコンテナを利用したサーバーレス処理を体験しましょう。
CloudBuildAPIの利用方法
CloudBuildはRESTのAPIを持ってます。
REST リファレンス
curlコマンドを使ってCloudBuildを走らせてみましょう。
以下のリクエス文を書きます
※この例ではdockerコンテナをPullしてコマンド”ls -l”を実行します
req.json
{
"steps": [
{
"name": "gcr.io/cloud-builders/docker",
"entrypoint": "bash",
"args": [
"-c",
"ls -l"
]
}
]
}
リクエストを送信します
以下のコマンドを実行してください
curl -X POST -T req.json -H "Authorization: Bearer $(gcloud config config-helper --format='value(credential.access_token)')" https://cloudbuild.googleapis.com/v1/projects/[プロジェクト名]/builds\?alt\=json
動きましたか?
ローカルでgcloudコマンドを利用すると簡単にGoogleAPIへのアクセストークンを取得できます。
実行した環境に正しいIAM権限があれば、リポジトリ連携しなくてもCloudBuildは起動します。
※CloudBuildのログ確認方法はこちらの記事をご参照ください
Node.jsからGoogleAPIを利用する方法
googleapisを利用するとgcloudコマンドと同様に、プログラムの中でGoogleAPIへのアクセストークンが取得できます。
NodeJS API Client
以下のコマンドを実行してください。
#認証トークンの取得に利用
npm install googleapis
#REST送信に利用
npm install request
以下のコードを書きます。
test.js
var googleapis = require("googleapis");
var request = require("request");
var APIURL = "https://cloudbuild.googleapis.com/v1/projects/[プロジェクト名]/builds?alt=json"
async function main() {
const token = await googleapis.google.auth.getAccessToken();
console.log(token);
var options = {
url: APIURL,
method: 'POST',
headers:{Authorization: ' Bearer ' + token},
body: {
"steps": [
{
"name": "gcr.io/cloud-builders/docker",
"entrypoint": "bash",
"args": [
"-c",
"ls -l"
]
}
]
},
json: true
};
request(options, function (error, response, body) {
if (error) {
console.error('Error: ' + error.message);
return;
};
console.log(body);
});
};
main()
コードを実行します。
node test.js
動きましたか?
crulコマンドで実行した結果と同じになったと思います。
CloudFunctionsからCloudBuildを利用する方法
それではCloudFunctionsからCloudBuildを実行してみましょう!
これまでのローカル実行と異なり、実行するユーザはCloudFunctionsのサービスアカウントになります。
CloudFunctionsのサービスアカウントにCloudBuildの権限付与してください。
※デフォルトのサービスアカウントを利用する場合は、プロジェクトの編集権限が付いてるので、権限設定不要です。
処理フローを下記に示します。
デプロイ準備をします。
mkdir test-function
cd test-function
準備した環境へ以下のコードを書きます。
[プロジェクト名],[バケット名],[ファイル名]はご自身の環境に合わせてください。※ファイルは.tar.gz、.zipで圧縮してください
Build Request仕様
index.js
var googleapis = require("googleapis");
var request = require("request");
var APIURL = "https://cloudbuild.googleapis.com/v1/projects/[プロジェクト名]/builds?alt=json"
exports.helloGCS = (event, context) => {
const gcsEvent = event;
console.log(`Processing file: ${gcsEvent.name}`);
async function main() {
const token = await googleapis.google.auth.getAccessToken();
console.log(token);
var options = {
url: APIURL,
method: 'POST',
headers:{Authorization: ' Bearer ' + token},
body: {
"source": {
"storageSource": {
"bucket": "[バケット名]",
"object": "[ファイル名]"
}
},
"steps": [
{
"name": "gcr.io/cloud-builders/docker",
"entrypoint": "bash",
"args": [
"-c",
"ls -l"
]
}
]
},
json: true
};
request(options, function (error, response, body) {
if (error) {
console.error('Error: ' + error.message);
return;
};
console.log(body);
});
};
main()
};
packege.json
{
"name": "sample",
"version": "0.0.1",
"dependencies": {
"request": "2.88.0",
"googleapis":"39.2.0"
}
}
functionsをデプロイします。
以下のコマンドを実行してください。
gcloud functions deploy helloGCS --runtime nodejs8 --trigger-bucket [バケット名]
GCSへファイルアップロードしてfunctionsを実行してみましょう。
zip test.zip *
gsutil cp test.zip gs:// [バケット名]
CloudBuildのログを確認してみましょう。
ログの末尾に以下の記載があれば成功です!お疲れ様でした。
省略......
Archive: /tmp/source-archive.zip
inflating: /workspace/index.js
inflating: /workspace/package.json
BUILD
Already have image (with digest): gcr.io/cloud-builders/docker
total 8
-rw-r--r-- 1 root root 1116 May 15 10:36 index.js
-rw-r--r-- 1 root root 122 May 15 10:37 package.json
PUSH
DONE
いかがでしてたでしょうか?
GCPではフルマネージドなサービスを組み合わせ、簡単にコンテナを利用したサーバーレス処理が可能です。
常駐するアプリケーション構成は不可能ですが、CloudBuildの利便性とCloudFunctionsの接着力で様々な処理が可能になります。
しかもサービス間の通信はGCP内部でのgoogleapi認証が透過的に行われており、外部からの脅威を防ぎます。
コスト・パフォーマンス・セキュリティと三拍子揃ったGCPを利用してシステムを構築してみませんか?
GKE上で常駐してくれるコンテナ達も素敵ですが、CloudBuild上に来てくれるコンテナ達も魅力的です。
それではGCPで良いコンテナ開発を!