CircleCIでCloudFunctionsにデプロイする

公開:2020/12/29
更新:2020/12/30
4 min読了の目安(約4400字TECH技術記事

ゴール

GitHubリポジトリで管理するCloudFunctionsで動かすコード(python)について、
masterにプッシュまたはマージされたときに、CircleCIのJobとして、CloudFunctionsにzipをデプロイするようにする。

TL;DR

  1. サービスアカウントを作成する
  2. サービスアカウントキーを取得する
  3. サービスアカウントキーをパイプラインの環境変数に設定する
  4. CircleCIの設定ファイルを作成する
  5. デプロイする

サービスアカウントを作成する

  • サービスアカウントの作成に関しては、gcloudやTerraformでもできますが、今回はコンソールからやります。
  • プロジェクトは予め作成して、選択されていることが前提です。
  1. ID > サービスアカウント を選択する
  2. サービスアカウントを作成 を選択する
  3. サービスアカウント名 を入力し、作成 を押す
  4. サービスアカウントに付与するロールを選択する
    • CloudFunctions開発者
    • サービスアカウントユーザー

  5. 完了(ユーザーのサービスアカウントへのアクセスはしない)

サービスアカウントキーを取得する

  1. 作成したサービスアカウントについて、鍵を作成する

  2. (ダウンロードした鍵でプロジェクトのCloudFunctionsの操作ができることを確認する)

# サービスアカウントをアクティベートにする
~$ gcloud auth activate-service-account --key-file $HOME/Downloads/project-abcdefgh.json
Activated service account credentials for: [circleci-to-gcf@project.iam.gserviceaccount.com]

# デプロイ用のzip
~$ ls $HOME/Desktop/gcf/
sample.zip

# デプロイを試行する。
# サービスアカウントでCloudFunctionsにdeploy操作することが確認できれば良いので403等のアクセス制限による失敗でなければ、ここでの目的は果たしたとみなしてよい
~$ gcloud functions deploy sample --trigger-http --runtime=python38 --source=$HOME/Desktop/gcf/
WARNING: Function created with limited-access IAM policy. To enable unauthorized access consider "gcloud alpha functions add-iam-policy-binding sample --member=allUsers --role=roles/cloudfunctions.invoker"
Deploying function (may take a while - up to 2 minutes)...WARNING: Setting IAM policy failed, try "gcloud alpha functions add-iam-policy-binding sample --member=allUsers --role=roles/cloudfunctions.invoker"

サービスアカウントキーをパイプラインの環境変数に設定する

  1. CircleCIから対象のプロジェクトのProject Settings を選択する

  2. Add Environment Variable を選択する

  3. サービスアカウントキー(jsonファイル)をbase64エンコードする

    ~$ cat ~/Downloads/project-abcdefgh.json | base64
    hogefuga
    
  4. base64エンコードしたサービスアカウントキーを環境変数として設定する

CircleCIの設定ファイルを作成する

  • yamlではなくymlとすること
# .circleci/config.yml
version: 2.1

jobs:
  deploy:
    docker:
    - image: google/cloud-sdk:alpine
    environment:
      PROJECT: ""
      FUNCTION_NAME: ""
      ENTRY_POINT: ""
      RUNTIME: "python37"
      TRIGGER_EVENT: "providers/cloud.pubsub/eventTypes/topic.publish"
      TRIGGER_RESOURCE: ""
      REGION: "us-central1"
      MEMORY: "256MB"
      TIMEOUT: "60s"
    steps:
    - checkout
    - run:
        name: Prepare
        command: |
          apk --no-cache add zip
    - run:
        name: Zip scripts
        command: |
          zip functions -r ./app
    - run:
        name: Authorize gcloud
        command: |
          echo $SERVICE_ACCOUNT_KEY | base64 -d | \
            gcloud auth activate-service-account --key-file=-
    - run:
        name: Deploy to Google Cloud Functions
        command: |
          echo $ENV_FILE | base64 -d > .env.yaml
          gcloud functions deploy $FUNCTION_NAME \
            --entry-point $ENTRY_POINT \
            --runtime $RUNTIME \
            --trigger-event $TRIGGER_EVENT \
            --trigger-resource $TRIGGER_RESOURCE \
            --source ./app/ \
            --env-vars-file .env.yaml \
            --project $PROJECT \
            --region $REGION \
            --memory $MEMORY \
            --timeout $TIMEOUT
workflows:
  version: 2
  build-test-and-deploy:
    jobs:
      - deploy:
        filters:
          branches:
            only:
              - master

デプロイする

  • config.ymlをコミットに含めて、git push origin master すると、パイプラインが始まる
  • 成功例