🤖

Cloud Functions のデプロイまとめ

2021/12/02に公開

最近超小規模の案件があり、先方の運用費も含めてとにかく低予算で収めたいという要望と機能・非機能の要件も満たしていたので Cloud Functions + Cloud Firestore で開発を行いました。今回は一桁程度の関数しか作成しなかったのですが、大規模になった時を見越して Cloud Functions のデプロイについて調査・検証しましたのでまとめてみたいと思います。

デプロイ方法の概要

Deploying Cloud Functions | Cloud Functions Documentation

  • GCP コンソールを使う
  • gcloud コマンドを使う
  • Cloud Functions API を使う

方法としては上記の 3 つあり、どの方法を使ったとしても以下の 3 つのステップで行います。

  1. ソースコードのアップロード
  2. ソースコードからコンテナイメージのビルド
  3. コンテナイメージのデプロイ

これらを踏まえて自身で CI&CD を構築する場合に各方法でどうすれば良さそうかを説明します。GCP コンソールは Cloud Functions をお試しで利用する際ぐらいしか利用しないと思いますので触れません。

gcloud コマンドを使う

gcloud functions deploy | Cloud SDK Documentation | Google Cloud

gcloud functions deploy Hello \
--entry-point=HelloWorld \
--region=asia-northeast1 \
--runtime=go113 \
--memory=256MB \
--security-level=secure-always \
--env-vars-file=env.yaml \
--trigger-http \
--allow-unauthenticated

各オプションの説明は公式に委ねて省略しますが、よく使うオプションを並べるとこんな感じですね。このコマンドを実行するとカレントディレクトリにあるものが GCS にアップロードされビルド&デプロイが行われます。

gcloud topic gcloudignore | Cloud SDK Documentation | Google Cloud

GCS にアップロードされたくないファイルがある時は .gcloudignore というファイルを作成して下さい。構文は .gitignore と同じです。

gcloud functions deploy のリファレンスを見て頂いてもわかりますが、1 コマンド: 1 関数のデプロイになっており、実行する度にソースコードのアップロードが行われますので、これを避けたい場合についても紹介しておきます。

Uploads and downloads | Cloud Storage | Google Cloud

gcloud functions deploy には --source というオプションがあり、GCS にある zip ファイルを指定する事が出来ます(一応 Cloud Source Repository も指定可)。手動で zip ファイル化したものを gsutil を使ってアップロードして --source で指定すれば都度アップロードを防ぐ事ができます。

Cloud Functions API を使う

Deploying from the Google Cloud Functions API

公式ドキュメントにも紹介されている通り、以下の順で API を叩きます。

  1. projects.locations.functions.generateUploadUrl を叩いて uploadUrl を生成する
  2. 生成された uploadUrl にソースコードを固めた zip ファイルをアップロードする
  3. projects.locations.functions.createsourceUploadUrluploadUrl を指定して叩く

generateUploadUrl で生成される URL は都度ユニークなものが生成されるので、並列に走ったジョブによって上書きされる心配はありません。が、デプロイ先が同じだと結局問題になるので並列実行させない方がいいです。

Resumable uploads | Cloud Storage | Google Cloud

アップロードは curl 等でも行えますが、API を叩く一連の流れや最後に叩く create のリクエストボディの JSON の作りやすさなどから、クライアントライブラリの用意された言語等で実装する方がやりやすいと思います。

アップロードしたソースコードを使いまわして複数の関数をデプロイしたい場合は、create API の sourceUploadUrl に共通のものを使いつつ、 name のパラメータだけ変えれば実現できます。

GitHub Actions

Cloud Functions Deploy - GitHub Marketplace

on:
  push:
    branches:
      - main

concurrency: gcf-deploy

jobs:
  build-and-deploy:
    name: Deploy Functions
    runs-on: ubuntu-20.04

    strategy:
      matrix:
        functions: [Hello, Echo]

    steps:
      - uses: actions/checkout@v2
      - name: auth
        uses: google-github-actions/auth@v0.4.0
        with:
          credentials_json: ${{ secrets.GCP_CREDENTIALS }}

      - name: deploy
        uses: google-github-actions/deploy-cloud-functions@v0.6.0
        with:
          name: ${{ matrix.functions }}
          runtime: go113

GitHub Actions を使ってデプロイしたい場合は Google 公式の Action があります。 Cloud Functions 開発者 の権限を持ったサービスアカウントを作成し、発行したサービスアカウントキーの JSON ファイルの内容を Github の Secrets に保存して上記のような設定を書けば動きます。(例だと GCP_CREDENTIALS に保存している)

上記の例だと Hello と Echo という関数が並列にビルド&デプロイされます。Action の実装は設定された内容の関数を Cloud Functions API で説明した手順を TypeScript で 1 つずつデプロイする形式になっており、複数の関数をデプロイしたい場合は strategy.matrix を使う必要があります。

もしソースコードのアップロードを 1 度のみにしたいのであれば、前述の gcloud もしくは Cloud Functions API で説明した方法を自前で実装する必要があります。

Discussion