😺

はじめてみよう Google Cloud ハンズオン Cloud Run編を試す(gcloud設定、Cloud Runデプロイ)

2023/08/02に公開

はじめに

この記事では、以下の、「はじめてみよう Google Cloud ハンズオン Cloud Run 編」のgcloud設定やCloud Runへのデプロイを試します。

https://github.com/google-cloud-japan/gcp-getting-started-cloudrun

環境

実行したMacbook Proのスペックは以下のとおりです。

メモリ:64GB
プロセッサ:Intel Core i9 8コア
OS:Ventura 13.4.1(c) 

リポジトリのクローン

はじめに該当のリポジトリをクローンしておきます。

git clone git@github.com:google-cloud-japan/gcp-getting-started-cloudrun.git

gcloudコマンドのインストール

はじめにgcloudコマンドを利用可能にするため、以下のコマンドを実行します。

brew install --cask google-cloud-sdk

~/.zshrcに以下を追記します。

source "/usr/local/share/google-cloud-sdk/completion.zsh.inc"
source "/usr/local/share/google-cloud-sdk/path.zsh.inc"

~/.zshrcを再読み込みします。

source ~/.zshrc

gcloudのバージョンを確認します。

gcloud --version

Google Cloud SDK 439.0.0
beta 2023.07.14
bq 2.0.94
core 2023.07.14
gcloud-crc32c 1.0.0
gsutil 5.25

Google Cloud プロジェクトの設定

対象の Google Cloud プロジェクトを設定

Google Cloudプロジェクトを作成し、プロジェクトIDを環境変数に設定します。

export PROJECT_ID=[PROJECT_ID]

プロジェクトIDは、ダッシュボードに進み、左上のプロジェクト情報から確認します。

プロジェクトの課金が有効化されていることを確認する

gcloud beta billing projects describe ${PROJECT_ID} | grep billingEnabled

有効化できていれば、以下の表示になりました。

billingEnabled: true

gcloudの設定

gcloud から利用する Google Cloud のデフォルトプロジェクトを設定

gcloud config set project ${PROJECT_ID}

gcloud からの Cloud Run のデフォルト設定

gcloud config set run/region asia-northeast1
gcloud config set run/platform managed

利用する機能の有効化

gcloud services enable artifactregistry.googleapis.com run.googleapis.com cloudbuild.googleapis.com sourcerepo.googleapis.com container.googleapis.com

サンプルアプリケーション

ハンズオンで利用するアプリケーションはsumserviceと呼び、REST APIで公開します。

固定文字列を返すHello Challenger APIと数値の合計を返す数値合計 APIがあります。

フォルダ、ファイル構成は以下となっています。

.
└─ src
    └─ sumservice
        ├─ .dockerignore    # コンテナに含めないファイル群を指定するファイル
        ├─ Dockerfile       # Docker コンテナ作成定義ファイル
        ├─ Procfile         # 起動方法が記載されているファイル、Buildpacks でビルドするときに利用
        ├─ main.py          # メイン関数ソースファイル
        └─ requirements.txt # 利用ライブラリ一覧

Dockerfile

 Use the official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.9-slim

# Allow statements and log messages to immediately appear in the Knative logs
ENV PYTHONUNBUFFERED True

# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./

# Install dependencies.
RUN pip install -r requirements.txt

# Run the web service on container startup. Here we use the gunicorn
# webserver, with one worker process and 8 threads.
# For environments with multiple CPU cores, increase the number of workers
# to be equal to the cores available.
# Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling.
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

main.py

main.pyはFlaskを用いてAPIサーバとして実装されています。


import os
import json
import requests

from flask import Flask, request, jsonify

app = Flask(__name__)


@app.route("/")
def hello_world():
    name = os.environ.get("NAME", "Challenger01")
    return "Hello {}!".format(name)


@app.route("/sum", methods=["POST"])
def sum_numbers():
    try:
        json_data = request.get_json()
    except:
        return jsonify({'error': 'Bad Request', 'message': 'Invalid request: {}'.format(request.get_data(as_text=True))}), 400
    if not 'numbers' in json_data:
        return jsonify({'error': 'Bad Request', 'message': 'Request format error: {}'.format(request.get_data(as_text=True))}), 400
    try:
        ans = sum(json_data['numbers'])
    except TypeError:
        return jsonify({'error': 'Bad Request', 'message': 'Request format error: {}'.format(request.get_data(as_text=True))}), 400
    return jsonify({'sum': ans}), 200




def retrieve_token(target_url):
    # Set up metadata server request
    metadata_server_token_url = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience='

    token_request_url = metadata_server_token_url + target_url
    token_request_headers = {'Metadata-Flavor': 'Google'}

    # Fetch the token
    token_response = requests.get(
        token_request_url, headers=token_request_headers)
    return token_response.content.decode("utf-8")


if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))

詳細は、サンプルアプリケーションの章をご確認ください。

Cloud Runへのデプロイ

Cloud Runへのデプロイは2種類あります。

  • Dockerfileを使い、ローカルでコンテナを作成、レジストリにプッシュしてからデプロイ
  • Buildpacks、Cloud Build を使い、Dockerfile 無し、かつリポジトリの指定無しにデプロイ

今回は前者を試します。

Dockerfileを使い、ローカルでコンテナを作成、レジストリにプッシュしてからデプロイ

アーキテクチャ図は、以下です。
まず、Artifact Registryを作成します。
次に、ソースファイルとDockerfileを元にイメージを作成し、そのイメージを元にしたコンテナをArtifact Registryへpushします。その後、そのコンテナを元にCloud Runへデプロイされます。

https://raw.githubusercontent.com/google-cloud-japan/gcp-getting-started-cloudrun/main/images/step_by_step_deployment.png

Artifact Registryにリポジトリを作成

gcloud artifacts repositories create cloudrun-handson --repository-format=docker --location=asia-northeast1 --description="Docker repository for Cloud Run hands-on"
Create request issued for: [cloudrun-handson]
Waiting for operation [projects/${PROJECT_ID}/locations/asia-northeast1/operations/18c4a96d-296e-4c11-8e5c-cf3164fff021] to complete...done.                                 
Created repository [cloudrun-handson].

Artifact Registryにリポジトリが作成できたことを確認します。

docker コマンドの認証設定

gcloud auth configure-docker asia-northeast1-docker.pkg.dev --quiet
...
Adding credentials for: asia-northeast1-docker.pkg.dev

ローカルにコンテナを作成

(cd src/sumservice && docker build -t asia-northeast1-docker.pkg.dev/${PROJECT_ID}/cloudrun-handson/sumservice:v1 .)

docker imagesコマンドでイメージが作成できたかを確認します。

docker images

REPOSITORY                                                                        TAG             IMAGE ID       CREATED         SIZE
asia-northeast1-docker.pkg.dev/${PROJECT_ID}/cloudrun-handson/sumservice   v1              b500b7ef15cc   6 seconds ago   161MB

作成したコンテナをArtifact Registryへpushします

docker push asia-northeast1-docker.pkg.dev/${PROJECT_ID}/cloudrun-handson/sumservice:v1
The push refers to repository [asia-northeast1-docker.pkg.dev/noted-ability-320105/cloudrun-handson/sumservice]
ba457e788bff: Pushed 
a5e3673b9369: Pushed 
8cc7b56b32c3: Pushed 
9bfcb9ca631e: Pushed 
ba4397078275: Pushed 
91c4ec8027b7: Pushed 
5f77f286226c: Pushed 
c6e34807c2d5: Pushed 
v1: digest: sha256:d6c2f5ced0e41fbdb5506e7dd6654d64a3cc2e1cc6d0b8156833fa0a5651f831 size: 1995

リポジトリにpushできたことを確認します。

Cloud Runへデプロイします

Artifact Registryへ登録されたイメージからCloud Runを認証なしで起動します。

gcloud run deploy sumservice --image=asia-northeast1-docker.pkg.dev/${PROJECT_ID}/cloudrun-handson/sumservice:v1 --allow-unauthenticated
Enabling service [run.googleapis.com] on project [xxxxxxxxxxxxxx]...
Operation "operations/acf.p2-xxxxxxxxxxxxxx-f116d24a-e537-4139-8dac-0419b160a73f" finished successfully.
Deploying container to Cloud Run service [sumservice] in project [${PROJECT_ID}] region [asia-northeast1]
✓ Deploying new service... Done.                                                                         
  ✓ Creating Revision...                                                                                 
  ✓ Routing traffic...                                                                                   
  ✓ Setting IAM Policy...                                                                                
Done.                                                                                                    
Service [sumservice] revision [sumservice-00001-qaq] has been deployed and is serving 100 percent of traffic.
Service URL: https://xxxxxxxxxx.a.run.app

動作確認

SUM_URL=$(gcloud run services describe sumservice --format json | jq -r '.status.address.url')
curl -s -H "Content-Type: application/json" -d '{"numbers": [10, 20, 30, 300, 100]}' ${SUM_URL}/sum | jq

以下が返ってくれば、成功です。

{
  "sum": 460
}

サービスの削除

デプロイしたサービスを削除します。

gcloud run services delete sumservice --quiet

おわりに

この記事では、「はじめてみよう Google Cloud ハンズオン Cloud Run 編」のgcloudコマンドのインストールからCloud Runへのデプロイまでを試しました。

GitHubで編集を提案

Discussion