Cloud Run でウェブサイトをデプロイする

1. 始める前に

ウェブサイトの運用は容易ではありません。仮想マシン(VM)インスタンス、クラスタ、Pod、Service などを作成、管理するためのオーバーヘッドが発生するからです。これは大規模な多層アプリであれば問題ありませんが、ウェブサイトをデプロイして公開するだけの場合、こうしたオーバーヘッドは大きな負担です。

Google Cloud 上の Knative の実装である Cloud Run を使用すると、VM ベースや Kubernetes ベースのデプロイに伴うオーバーヘッドなしでウェブサイトを管理、デプロイできます。管理が簡素化されるだけでなく、ウェブサイトでリクエストを受信していないときは「ゼロにスケール」できます。

この Codelab では、Cloud Build で作成した Docker イメージを Cloud Shell でトリガーします。次に、Cloud Shell でコマンドを使用して、そのイメージを Cloud Run にデプロイします。

前提条件

学習内容

  • Cloud Build を使用して Docker イメージをビルドして gcr.io にアップロードする方法
  • Docker イメージを Cloud Run にデプロイする方法
  • Cloud Run デプロイメントを管理する方法
  • Cloud Run でアプリのエンドポイントを設定する方法

作成するアプリの概要

  • Docker コンテナ内で実行される静的ウェブサイト
  • Container Registry にあるこのコンテナのバージョン
  • 静的ウェブサイト用の Cloud Run デプロイメント

必要なもの

  • プロジェクトを作成するための管理者権限を持つ Google アカウント、またはプロジェクト オーナーのロールを持つプロジェクト

2. 環境設定

セルフペース型の環境設定

Google アカウントをお持ちでない場合は、アカウントを作成する必要があります。次に、Google Cloud コンソールにログインし、[プロジェクト] > [プロジェクトを作成] をクリックします。

53dad2cefdae71da.png

faab21976aabeb4c.png

プロジェクト ID をメモします。プロジェクト ID はプロジェクト名の下に自動的に入力されます。プロジェクト ID はすべての Google Cloud プロジェクトにおいて一意の名前であるため、スクリーンショットの名前はすでに使用されており、使用できません。後で PROJECT_ID とします。

次に、Google Cloud リソースを使用し、Cloud Run API を有効にするために、Cloud コンソールで課金を有効にする必要があります。

Cloud Run API を有効にする

ナビゲーション メニュー ☰ > [API とサービス] > [ダッシュボード] > [有効な API とサービス] をクリックします。.

5dbb2e6e27a55fcf.png

「Cloud Run API」を検索し、[Cloud Run API] > [有効にする] をクリックします。

f1fd486174a744cf.png

この Codelab の操作をすべて行って、費用が生じたとしても、少額です(最後に記載されているクリーンアップをご覧ください)。詳細については、料金をご覧ください。

Google Cloud の新規ユーザーは、300 ドル分の無料トライアルの特典があります。

Cloud Shell

Google Cloud と Cloud Run はノートパソコンからリモートで操作できますが、ここでは Cloud Shell(Google Cloud 上で動作するコマンドライン環境)を使用します。この環境には、必要なすべてのクライアント ライブラリとフレームワークが事前構成されています。

この Debian ベースの仮想マシンには、必要な開発ツールがすべて用意されています。仮想マシンは Google Cloud で稼働し、永続的なホーム ディレクトリが 5 GB 用意されているため、ネットワークのパフォーマンスと認証が大幅に向上しています。つまり、この Codelab に必要なのはブラウザだけです(Chromebook でも動作します)。

  1. Cloud Console から Cloud Shell を有効にするには、[Cloud Shell をアクティブにする] fEbHefbRynwXpq1vj2wJw6Dr17O0np8l-WOekxAZYlZQIORsWQE_xJl-cNhogjATLn-YxLVz8CgLvIW1Ncc0yXKJsfzJGMYgUeLsVB7zSwz7p6ItNgx4tXqQjag7BfWPcZN5kP-X3Q をクリックします(環境のプロビジョニングと接続に若干時間を要します)。

I5aEsuNurCxHoDFjZRZrKBdarPPKPoKuExYpdagmdaOLKe7eig3DAKJitIKyuOpuwmrMAyZhp5AXpmD_k66cBuc1aUnWlJeSfo_aTKPY9aNMurhfegg1CYaE11jdpSTYNNIYARe01A

Screen Shot 2017-06-14 at 10.13.43 PM.png

Cloud Shell に接続すると、すでに認証は完了しており、プロジェクトに各自の PROJECT_ID が設定されていることがわかります。

gcloud auth list

コマンド出力

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

コマンド出力

[core]
project = <PROJECT_ID>

なんらかの理由でプロジェクトが設定されていない場合は、次のコマンドを実行します。

gcloud config set project <PROJECT_ID>

PROJECT_ID が見つからない場合は、設定手順で使用した ID を確認するか、Cloud コンソール ダッシュボードで確認します。

R7chO4PKQfLC3bvFBNZJALLTUiCgyLEq_67ECX7ohs_0ZnSjC7GxDNxWrJJUaoM53LnqABYamrBJhCuXF-J9XBzuUgaz7VvaxNrkP2TAn93Drxccyj2-5zz4AxL-G3hzxZ4PsM5HHQ

Cloud Shell では、デフォルトで環境変数もいくつか設定されます。これらの変数は、以降のコマンドを実行する際に有用なものです。

echo $GOOGLE_CLOUD_PROJECT

コマンド出力

<PROJECT_ID>
  1. 最後に、デフォルトのゾーンとプロジェクト構成を設定します。
gcloud config set compute/zone us-central1-f

さまざまなゾーンを選択できます。詳細については、リージョンとゾーンをご覧ください。

3. ソース リポジトリのクローンを作成する

デプロイするウェブサイトはすでに存在するため、リポジトリからソースのクローンを作成するだけで、後は Docker イメージの作成と Cloud Run へのデプロイに集中できます。

次のコマンドを実行して、Cloud Shell インスタンスにリポジトリのクローンを作成し、適切なディレクトリに移動します。また、Node.js の依存関係もインストールして、デプロイ前にアプリをテストできるようにします。

cd ~
git clone https://github.com/googlecodelabs/monolith-to-microservices.git
cd ~/monolith-to-microservices
./setup.sh

これにより、リポジトリのクローンを作成し、ディレクトリに移動して、アプリをローカルで実行するために必要な依存関係をインストールします。スクリプトの実行には数分かかることがあります。

デューデリジェンスを行い、アプリをテストします。次のコマンドを実行してウェブサーバーを起動します。

cd ~/monolith-to-microservices/monolith
npm start

出力:

Monolith listening on port 8080!

アプリをプレビューするには、[ウェブでプレビュー] acc630712255c604.png をクリックし、[ポート 8080 でプレビュー] を選択します。

5869738f0e9ec386.png

新しいウィンドウが開き、動作中の Fancy Store が表示されます。

9ed25c3f0cbe62fa.png

このウィンドウは、ウェブサイトの確認後に閉じることができます。ウェブサーバー プロセスを停止するには、ターミナル ウィンドウで CONTROL+C(Macintosh の場合は Command+C)を押します。

4. Cloud Build を使用して Docker コンテナを作成する

ソースファイルの準備ができたので、次はアプリを Docker 化します。

通常、Docker コンテナを作成するには 2 ステップのアプローチを取る必要があります。具体的には、Docker コンテナをビルドするステップと、ビルドしたコンテナをレジストリに push してそのイメージを保管し、GKE がそこからイメージを pull できるようにするステップです。ただし、Cloud Build を使用して Docker コンテナをビルドし、1 つのコマンドでイメージを Container Registry に保存することで、作業を楽にできます。Dockerfile の作成と push の手動プロセスを確認するには、Container Registry のクイックスタートをご覧ください。

Cloud Build は、ディレクトリにあるファイルを圧縮して Cloud Storage バケットに移動します。次に、ビルドプロセスでそのバケットからすべてのファイルを取得し、同じディレクトリにある Dockerfile を使用して Docker ビルドプロセスを実行します。--tag フラグで Docker イメージのホストとして gcr.io を指定したため、ビルドされた Docker イメージは Container Registry に push されます。

まず、Cloud Build API が有効になっていることを確認する必要があります。次のコマンドを実行して有効にします。

gcloud services enable cloudbuild.googleapis.com

API が有効になったら、Cloud Shell で次のコマンドを実行してビルドプロセスを開始します。

gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0 .

このプロセスが完了するまでには数分かかります。完了すると、ターミナルに次のような結果が出力されます。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ID                                    CREATE_TIME                DURATION  SOURCE                                                                                  IMAGES                              STATUS
1ae295d9-63cb-482c-959b-bc52e9644d53  2019-08-29T01:56:35+00:00  33S       gs://<PROJECT_ID>_cloudbuild/source/1567043793.94-abfd382011724422bf49af1558b894aa.tgz  gcr.io/<PROJECT_ID>/monolith:1.0.0  SUCCESS

ビルド履歴を表示したり、プロセスをリアルタイムで確認したりするには、Cloud コンソールに移動し、ナビゲーション メニュー ☰ > [Cloud Build] > [履歴] をクリックします。過去のすべてのビルドのリストが表示されます。リストには、作成したばかりのビルドが 1 つだけ示されているはずです。

4c753ede203255f6.png

[ビルド ID] をクリックすると、ログ出力を含むそのビルドの詳細がすべて表示されます。[イメージ] の横にあるリンクをクリックすると、作成されたコンテナ イメージが表示されます。

6e88ed1643dfe629.png

5. コンテナを Cloud Run にデプロイする

ウェブサイトをコンテナ化して Container Registry に push したので、次はコンテナを Cloud Run にデプロイしましょう。

Cloud Run にデプロイするには次の 2 つの方法があります。

  • Cloud Run(フルマネージド)は、コンテナのライフサイクル全体が管理される PaaS モデルです。この Codelab では、この方法を使用します。
  • Cloud Run for Anthos は、制御が強化された Cloud Run で、GKE からクラスタと Pod を導入できます。詳細については、Cloud Run for Anthos on Google Cloud の設定をご覧ください。

コマンドライン サンプルは、前に設定した環境変数を使用して Cloud Shell で実行します。

コマンドライン

次のコマンドを実行して、アプリをデプロイします。

gcloud run deploy --image=gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0 --platform managed 

実行するリージョンを指定するよう求められます。最も近いリージョンを選択し、デフォルトで提案されたサービス名(monolith)を受け入れます。

d52d9419c5166674.png

テスト目的で、アプリへの未認証リクエストを許可します。プロンプトが表示されたら y と入力します。

3a57b32f133dad61.png

デプロイメントを確認する

デプロイメントが正常に作成されたことを確認するには、次のコマンドを実行します。Pod statusRunning になるまで少し時間がかかることがあります。

gcloud run services list

[1] Cloud Run(フルマネージド)を選択します。

出力:

SERVICE   REGION    URL  LAST DEPLOYED BY          LAST DEPLOYED AT
✔  monolith  us-east1 <your url>  <your email>  2019-09-16T21:07:38.267Z

出力には次の情報が表示されます。デプロイメント、デプロイしたユーザー(ユーザーのメールアドレス)、アプリにアクセスする際に使用する URL を確認できます。これらが示されていれば、デプロイメントは正常に作成されています。

ウェブブラウザでサービスのリストに示されている URL を開くと、ローカルでプレビューしたものと同じウェブサイトが表示されます。

6. 同時実行の値を小さくした新しいリビジョンを作成する

アプリを再度デプロイします。ただし、今回はパラメータのうちの 1 つを調整します。

デフォルトでは、Cloud Run アプリの同時実行の値は 80 に設定されます。つまり、各コンテナ インスタンスは一度に最大 80 件のリクエストを処理します。これは、1 つのインスタンスが一度に 1 件のリクエストを処理する Functions as a Service(FaaS)モデルとは大きく異なります。

同時実行の値を(テスト用に)1 に設定して同じコンテナ イメージを再デプロイし、どうなるかを確認します。

gcloud run deploy --image=gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0 --platform managed --concurrency 1

以降の質問には最初にデプロイしたときと同じように答えます。コマンドが正常に実行されたら、Cloud コンソールで結果を確認します。

Cloud Run ダッシュボードで、monolith サービスをクリックして詳細を表示します。

7d1eed2e4728a4f2.png

[変更内容] タブをクリックします。2 つのリビジョンが作成されていることを確認します。[monolith-00002] をクリックして詳細を確認します。同時実行の値が 1 に減らされていることがわかります。

217185c0eccc87dd.png]

4ad481b8bcd0343d.png

テストにはこの構成で十分ですが、本番環境でのほとんどのシナリオでは、コンテナで複数の同時リクエストをサポートすることになります。

再デプロイせずに同時実行の値を元に戻します。同時実行の値をデフォルトの 80 または 0 に設定します。後者の場合、同時実行の制限がすべて削除され、デフォルトの最大値(同じく 80)に設定されます。

Cloud Shell で次のコマンドを実行して、現在のリビジョンを更新します。

gcloud run deploy --image=gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0 --platform managed --concurrency 80

別のリビジョンが作成され、トラフィックがリダイレクトされ、同時実行数が 80 に戻ったことを確認します。

7. ウェブサイトに変更を加える

マーケティング チームから、会社のウェブサイトのホームページを変更するよう依頼されました。マーケティング チームは、会社の概要と販売している製品のより詳しい情報を追加する必要があると考えています。このセクションでは、マーケティング チームからの依頼に応じたテキストをホームページに追加します。

開発者の 1 人がすでに index.js.new というファイル名で変更を作成したようです。このファイルを index.js にコピーするだけで、変更内容を反映できます。手順に沿って適切な変更を行います。

次のコマンドを実行して、更新されたファイルを正しいファイル名にコピーし、その内容を出力して変更を確認します。

cd ~/monolith-to-microservices/react-app/src/pages/Home
mv index.js.new index.js
cat ~/monolith-to-microservices/react-app/src/pages/Home/index.js

変更後のコードは次のようになっています。

/*
Copyright 2019 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
const useStyles = makeStyles(theme => ({
  root: {
    flexGrow: 1
  },
  paper: {
    width: "800px",
    margin: "0 auto",
    padding: theme.spacing(3, 2)
  }
}));
export default function Home() {
  const classes = useStyles();
  return (
    <div className={classes.root}>
      <Paper className={classes.paper}>
        <Typography variant="h5">
          Fancy Fashion &amp; Style Online
        </Typography>
        <br />
        <Typography variant="body1">
          Tired of mainstream fashion ideas, popular trends and societal norms?
          This line of lifestyle products will help you catch up with the Fancy trend and express your personal style.
          Start shopping Fancy items now!
        </Typography>
      </Paper>
    </div>
  );
}

これで React コンポーネントは更新されましたが、React アプリをビルドして静的ファイルを生成する必要があります。次のコマンドを実行して React アプリをビルドし、monolith の公開ディレクトリにコピーします。

cd ~/monolith-to-microservices/react-app
npm run build:monolith

コードが更新されたので、Docker コンテナを再ビルドして Container Registry に公開する必要があります。前と同じコマンドを使用できますが、今回はバージョン ラベルを更新します。

次のコマンドを実行し、更新後のイメージ バージョン 2.0.0 を指定して新しい Cloud Build をトリガーします。

cd ~/monolith-to-microservices/monolith

#Feel free to test your application
npm start

gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:2.0.0 .

次のセクションでは、このイメージを使用してダウンタイムなしでアプリを更新します。

8. ダウンタイムなしでウェブサイトを更新する

変更が完了し、マーケティング チームも更新内容に満足してくれました。次は、ユーザーへのサービスを中断させずにウェブサイトを更新します。

Cloud Run は各デプロイメントを新しいリビジョンとして扱います。つまり、まずリビジョンをオンライン状態にして、トラフィックをそこにリダイレクトします。

次の手順に沿ってウェブサイトを更新してください。

コマンドライン

コマンドラインから、次のコマンドを使用してサービスを再デプロイし、イメージを新しいバージョンに更新できます。

gcloud run deploy --image=gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:2.0.0 --platform managed

デプロイメントを確認する

次のコマンドを実行して、Deployment の更新を検証します。

gcloud run services describe monolith --platform managed 

出力は次のようになります。

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  annotations:
    client.knative.dev/user-image: gcr.io/my-cloudrun-codelab/monolith:2.0.0
...

サービスが最新バージョンのイメージを使用するようになり、新しいリビジョンにデプロイされたことがわかります。

変更を確認するには、Cloud Run サービスの外部 URL に再度アクセスして、アプリのタイトルが更新されていることを確認します。

次のコマンドを実行してサービスを一覧表示し、IP アドレスを確認します(IP アドレスを忘れた場合は確認してください)。

gcloud run services list

ウェブサイトのホームページ コンポーネントに追加したテキストが表示されるようになりました。

451ca252acae6928.png

9. クリーンアップ

Container Registry イメージを削除する

# Delete the container image for version 1.0.0 of our monolith
gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0 --quiet

# Delete the container image for version 2.0.0 of our monolith
gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:2.0.0 --quiet

Cloud Storage から Cloud Build アーティファクトを削除する

# The following command will take all source archives from all builds and delete them from cloud storage

# Run this command to print all sources:
# gcloud builds list | awk 'NR > 1 {print $4}' 

gcloud builds list | awk 'NR > 1 {print $4}' | while read line; do gsutil rm $line; done

Cloud Run サービスの削除

gcloud run services delete monolith --platform managed

10.完了

Cloud Run でウェブサイトをデプロイ、スケーリング、更新しました。

その他の情報