この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Google Cloud Deployment ManagerでCloud Functionsのデプロイをやってみました。Cloud Functionsにコードをデプロイするため、Pythonテンプレートを利用してCloud BuildでCloud StorageへのZIPファイルのアップロードを実装しています。
事前準備
Cloud Deployment Managerでリソースをデプロイする際にgcloudコマンドを使用します。gcloud CLIはCloud SDKをインストールすることで利用できるようになります。Cloud SDKの導入方法は次のブログが参考になりました。
環境
項目 | 内容 |
---|---|
OS | macOS Catalina 10.15.4(19E287) |
Python | 3.7.0 |
Cloud SDK | 280.0.0 |
ディレクトリ構成
ディレクトリ構成は以下の通りです。Cloud Functionsのソースコードと構成ファイルやPythonテンプレートを分けています。
・
├─ src
│ ├─ hello-world
│ │ └─ index.js
│ └─ welcome
│ └─ index.js
└─ templates
├─ cloud-functions.py
└─ cloud-functions.yaml
Cloud Functionsのソースコード
シンプルなメッセージを返す2つの関数を実装します。
src/hello-world/index.js
exports.handler = (req, res) => {
res.status(200).send({
message: "Hello World!",
time: new Date(),
});
};
src/welcome/index.js
exports.handler = (req, res) => {
res.status(200).send({
message: "Welcome!",
time: new Date(),
});
};
Pythonテンプレート
Pythonテンプレートは各リソース定義の雛形です。Cloud FunctionsのデプロイではソースコードをZIPファイルにまとめて、Cloud Storageのバケットにアップロードする必要があります。これをPythonテンプレートで実装します。
templates/cloud-functions.py
import zipfile
import io
import base64
import hashlib
def GenerateConfig(context):
in_memory_output_file = io.BytesIO()
zip_file = zipfile.ZipFile(
in_memory_output_file, mode='w', compression=zipfile.ZIP_DEFLATED)
for imp in context.imports:
if imp.startswith(context.properties['codeLocation']):
zip_file.writestr(
imp[len(context.properties['codeLocation']):], context.imports[imp])
zip_file.close()
content = base64.b64encode(in_memory_output_file.getvalue())
m = hashlib.md5()
m.update(content)
source_archive_url = 'gs://%s/%s' % (
context.properties['codeBucket'], m.hexdigest() + '.zip')
cmd = "echo '%s' | base64 -d > /function/function.zip;" % (
content.decode('ascii'))
volumes = [{'name': 'function-code', 'path': '/function'}]
upload_function_code = {
'action': 'gcp-types/cloudbuild-v1:cloudbuild.projects.builds.create',
'name': context.properties['function'] + '-upload-function-code',
'properties': {
'steps': [{
'name': 'ubuntu',
'args': ['bash', '-c', cmd],
'volumes': volumes,
}, {
'name': 'gcr.io/cloud-builders/gsutil',
'args': ['cp', '/function/function.zip', source_archive_url],
'volumes': volumes
}],
'timeout': '120s'
},
'metadata': {
'runtimePolicy': ['UPDATE_ON_CHANGE']
}
}
cloud_function = {
'type': 'gcp-types/cloudfunctions-v1:projects.locations.functions',
'name': context.properties['function'] + '-cloud-function',
'properties': {
'parent': f"projects/{context.env['project']}/locations/{context.properties['location']}",
'function': context.properties['function'],
'sourceArchiveUrl': source_archive_url,
'entryPoint': context.properties['entryPoint'],
'httpsTrigger': {},
'timeout': context.properties['timeout'],
'availableMemoryMb': context.properties['memory'],
'runtime': context.properties['runtime']
},
'metadata': {
'dependsOn': [context.properties['function'] + '-upload-function-code']
}
}
return {
'resources': [upload_function_code, cloud_function]
}
Pythonテンプレートでは、GenerateConfig
またはgenerate_config
という名前のメソッドを定義します。context
オブジェクトには、環境に関するメタデータや構成ファイルのプロパティが渡されます。
再利用可能なテンプレートについて | Google Cloud
構成ファイル
構成ファイルではPythonテンプレートを読み込んでリソースを定義します。resources
のtype
にPythonテンプレートを指定できます。なお、使用するファイルは全てimports
に書く必要があります。
templates/cloud-functions.yaml
imports:
- path: ../src/hello-world/index.js
- path: ../src/welcome/index.js
- path: cloud-functions.py
resources:
- type: cloud-functions.py
name: hello-world
properties:
function: hello-world
codeLocation: ../src/hello-world/
codeBucket: [ソースコードをアップロードするバケットの名前]
location: asia-northeast1
timeout: 60s
runtime: nodejs8
memory: 256
entryPoint: handler
- type: cloud-functions.py
name: welcome
properties:
function: welcome
codeLocation: ../src/welcome/
codeBucket: [ソースコードをアップロードするバケットの名前]
location: asia-northeast1
timeout: 60s
runtime: nodejs8
memory: 256
entryPoint: handler
properties
に定義した値はPythonテンプレートに渡されます。例えばcodeLocation
はPythonテンプレートでcontext.properties['codeLocation']
のように取得できます。
codeBucket
は後でソースコードのアップロード先のバケットを作成した際にバケットの名前に変更します。
デプロイ
Cloud Buildを使いますので有効になっていない場合は有効化します。
Cloud StorageでCloud Functionsのソースコードをアップロードするバケットを作成します。
デプロイ先のプロジェクトを gcloud コマンドで指定します。
gcloud config set project [PROJECT_ID]
作成した構成ファイルを使用して gcloud コマンドでデプロイします。
gcloud deployment-manager deployments create cloud-functions --config templates/cloud-functions.yaml
Cloud Deployment Managerのコンソールでデプロイの詳細を確認できます。
デプロイが完了するとCloud Functionsのコンソールに表示されます。
Cloud Functionsのテストを実行して「Hello World!」が出力されることを確認します。
後片付け
作成したリソースに対しては課金が発生するため、忘れずに削除します。
gcloud deployment-manager deployments delete cloud-functions
Cloud StorageのバケットはGCPのコンソールから手動で削除します。
まとめ
Cloud Deployment ManagerではPythonテンプレートを利用することで、構成ファイルでリソースをシンプルに定義できることがわかりました。次はCloud APIなど他のリソースとCloud Functionsを組み合わせた使い方について学習したいと考えています。
構成ファイルやPythonテンプレートはGitHubでもソースコードを公開しています。