Compute Engine で Ruby Bookshelf アプリを実行する

このチュートリアルでは、Compute EngineRuby Bookshelf サンプルアプリを実行する方法を説明します。このチュートリアルに沿って、既存の Ruby ウェブアプリを Compute Engine にデプロイします。App Engine スタンダード環境のチュートリアルの一部として、Bookshelf アプリのドキュメントを参照することをおすすめします。

目標

  • 単一の Compute Engine インスタンスに Bookshelf サンプルアプリをデプロイします。
  • マネージド インスタンス グループを使用して、アプリの水平スケーリングを行います。
  • HTTP 負荷分散を使用して、トラフィックを処理します。
  • 自動スケーリングを使用して、トラフィックの変化に対応します。

費用

このチュートリアルでは、以下の課金対象の Google Cloud Platform コンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを出すことができます。 GCP を初めてご利用の場合は、無料トライアルをご利用いただけます。

このチュートリアルを終了した後、作成したリソースを削除すると、それ以降課金は発生しません。詳しくは、クリーンアップをご覧ください。

始める前に

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. GCP Console のプロジェクト セレクタのページで、GCP プロジェクトを選択または作成します。

    プロジェクト セレクタのページに移動

  3. Google Cloud Platform プロジェクトに対して課金が有効になっていることを確認します。 プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  4. Cloud Datastore API、Cloud Storage API、Cloud Pub/Sub APIAPIs を有効にします。

    API を有効にする

  5. Cloud SDK をインストールして初期化します。
  6. Ruby 2.3 以降Ruby on Rails をインストールします。Ruby に含まれている Ruby Gems も必要になります。

Cloud Datastore の初期化

Bookshelf サンプルアプリは Cloud Datastore を使用して書籍情報を格納します。プロジェクトの Cloud Datastore を初めて初期化する場合には、次の操作を行います。

  1. Google Cloud Platform Console で、Cloud Datastore を開きます。

    Cloud Datastore を開く

  2. データストアのリージョンを選択し、[続行] をクリックします。

    [エンティティの作成] ページが表示されたらウィンドウを閉じます。これで、Bookshelf アプリから Cloud Datastore にエンティティを作成する準備ができました。

Cloud Storage バケットの作成

Cloud Storage バケットを作成する手順は次のとおりです。バケットは、Cloud Storage でデータを格納する基本的なコンテナです。

  1. ターミナル ウィンドウで次のコマンドを入力します。

    gsutil mb gs://[YOUR-BUCKET-NAME]

    [YOUR-BUCKET-NAME] は、Cloud Storage バケットの名前を表します。

  2. Bookshelf アプリでアップロードした画像を表示するには、バケットのデフォルトのアクセス制御リスト(ACL)を public-read に設定します。

    gsutil defacl set public-read gs://[YOUR-BUCKET-NAME]

サンプルアプリのクローン作成

サンプルアプリは GitHub の GoogleCloudPlatform/getting-started-ruby からダウンロードできます。

  1. リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/getting-started-ruby.git
    
  2. サンプル ディレクトリに移動します。

    cd getting-started-ruby/7-compute-engine
    

アプリの構成

  1. 依存関係をインストールします。

    bundle install
    
  2. 提供されている例をコピーして、構成ファイルを作成します。構成ファイルのパスは .gitignore に含まれており、バージョン コントロールに commit されることはありません。

    cp config/database.example.yml config/database.yml
    cp config/settings.example.yml config/settings.yml
    
  3. config/settings.yml を編集のために開き、次の値を置き換えます。

    • @@PROJECT_ID@@ には実際のプロジェクト ID を指定します。
    • @@BUCKET_NAME@@ には前の手順で作成したストレージ バケットの名前を指定します。
    • @@CLIENT_ID@@ には実際の OAuth クライアント ID を指定します。
    • @@CLIENT_SECRET@@ には実際の OAuth クライアント シークレットを指定します。
  4. settings.yml を保存して閉じます。

  5. config/database.yml を編集のために開き、@@PROJECT_ID@@ を実際のプロジェクト ID に置き換えます。

  6. database.yml を保存して閉じます。

ローカル パソコン上でのアプリの実行

  1. ローカルのウェブサーバーを起動します。

    rails server
    
  2. ウェブブラウザに「http://localhost:3000」と入力します。

    ローカル ウェブサーバーを停止するには、Ctrl+C キーを押します。

ローカル コンピュータでワーカーの実行

ワーカーは Resque キューイング サービスを使用します。Resque はバックエンドとして Redis を使用するため、Redis サーバーをローカルで実行し、ポート 6379 でワーカーを接続する必要があります。詳しくは、Redis のクイックスタートをご覧ください。

Redis を起動した後、新しいコマンド ウィンドウで次のコマンドを入力します。

TERM_CHILD=1 QUEUE=* rake environment resque:work

次に、Bookshelf アプリに書籍を追加します。アプリとワーカー インスタンスの両方がローカルで実行されている場合、バックグラウンドでワーカーが書籍情報を更新するのを確認できます。

Resque のインターフェースは次のアドレスでアクセスできるように構成されており、これを使用してワーカーのステータスをチェックできます。

http://localhost:3000/resque

単一インスタンスへのデプロイ

単一インスタンスのデプロイ

このセクションでは、Compute Engine 上でアプリの単一インスタンスを実行する手順について説明します。

コードをリポジトリに push する

Cloud Source Repositories を使用してプロジェクトに Git リポジトリを作成し、このリポジトリにアプリのコードをアップロードできます。そうすると、起動時にリポジトリから最新バージョンのアプリのコードを pull できます。Git リポジトリを使用すると、アプリの更新時に新しいイメージやインスタンスを構成する必要がないため便利です。既存のインスタンスを再起動するか、インスタンスを作成するだけで済みます。

Git を初めて使用する場合は、git config --global を使用して自分の ID を設定します。

  1. GCP Console で、リポジトリを作成します。

    リポジトリを作成

  2. アプリのコードをプロジェクトのリポジトリに push します。

    git commit -am "Updating configuration"
    git config credential.helper gcloud.sh
    git remote add cloud https://source.developers.google.com/p/[YOUR_PROJECT_ID]/r/[YOUR_REPO]
    git push cloud master
    

    [YOUR_PROJECT_ID] はプロジェクト ID、[YOUR_REPO] はリポジトリの名前を表します。

起動スクリプトを使用してインスタンスを初期化する

Compute Engine インスタンスからコードにアクセスできるようになったので、次は、コードのダウンロードと実行をインスタンスに指示します。インスタンスには起動スクリプトを設定できます。起動スクリプトはインスタンスの起動時または再起動時に常に実行されます。

Bookshelf サンプルアプリに含まれている起動スクリプトを次に示します。

set -e

# Talk to the metadata server to get the project id
PROJECTID=$(curl -s "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google")
REPO_NAME="[YOUR_REPO_NAME]"

# Get the source code
export HOME=/root
git config --global credential.helper gcloud.sh
# Change branch from master if not using master
git clone https://source.developers.google.com/p/$PROJECTID/r/$REPO_NAME /opt/app -b master

pushd /opt/app/7-compute-engine

pushd config

cp database.example.yml database.yml
chmod go-rwx database.yml
cp settings.example.yml settings.yml
chmod go-rwx settings.yml

# Add your GCP project ID here
sed -i -e 's/@@PROJECT_ID@@/[YOUR_PROJECT_ID]/' settings.yml
sed -i -e 's/@@PROJECT_ID@@/[YOUR_PROJECT_ID]/' database.yml

# Add your cloud storage config here
sed -i -e 's/@@BUCKET_NAME@@/[YOUR_BUCKET_NAME]/' settings.yml

# Add your OAuth config here
sed -i -e 's/@@CLIENT_ID@@/[YOUR_CLIENT_ID]/' settings.yml
sed -i -e 's/@@CLIENT_SECRET@@/[YOUR_CLIENT_SECRET]/' settings.yml
popd # config

./gce/configure.sh

popd # /opt/app
set -e

curl -s "https://storage.googleapis.com/signals-agents/logging/google-fluentd-install.sh" | bash
cat >/etc/google-fluentd/config.d/railsapp.conf << EOF
<source>
  type tail
  format none
  path /opt/app/7-compute-engine/log/*.log
  pos_file /var/tmp/fluentd.railsapp.pos
  read_from_head true
  tag railsapp
</source>
EOF
service google-fluentd restart &

# Install dependencies from apt
apt-get update
apt-get install -y git ruby ruby-dev build-essential libxml2-dev zlib1g-dev nginx libmysqlclient-dev libsqlite3-dev redis-server

gem install bundler --no-ri --no-rdoc

useradd -m railsapp
chown -R railsapp:railsapp /opt/app

mkdir /opt/gem
chown -R railsapp:railsapp /opt/gem

sudo -u railsapp -H bundle install --path /opt/gem
sudo -u railsapp -H bundle exec rake assets:precompile

systemctl enable redis-server.service
systemctl start redis-server.service

cat gce/default-nginx > /etc/nginx/sites-available/default
systemctl restart nginx.service

cat gce/railsapp.service > /lib/systemd/system/railsapp.service
systemctl enable railsapp.service
systemctl start railsapp.service

cat gce/resqworker.service > /lib/systemd/system/resqworker.service
systemctl enable resqworker.service
systemctl start resqworker.service

この起動スクリプトは、次のタスクを実行します。

  1. Cloud Source Repositories にあるアプリのソースコードのクローンを作成し、シークレットを使用して構成ファイルを設定します。

  2. Logging エージェントをインストールし、アプリのログをモニタリングするよう構成します。つまり、前のチュートリアルで構成したログは、あたかも App Engine を使用しているかのように GCP Console のロギング セクションにアップロードされます。

  3. Ruby、Rails、NGINX をインストールして構成します。

起動スクリプトをカスタマイズする

サンプルアプリには起動スクリプトのテンプレートが含まれており、これを変更して実際のシークレットを追加できます。シークレットはソース管理にチェックインしないでください。

  1. 起動スクリプトのテンプレートをコピーします。このスクリプト ファイルに変更を加えますが、チェックインはしないでください。

    cp gce/startup-script.sh gce/my-startup.sh
    
  2. my-startup.sh ファイルを編集します。

    データベースと Cloud Storage にシークレットを追加します。これらのシークレットは、以前に database.ymlsettings.yml に追加したものと同じです。[YOUR_* プレースホルダを実際の値に置き換えます。

    次に例を示します。

    # Add your GCP project ID here
    sed -i -e 's/PROJECT_ID/your-project-id/' settings.yml
    sed -i -e 's/PROJECT_ID/your-project-id/' database.yml
    
    # Add your Cloud Storage config here
    sed -i -e 's/BUCKET_NAME/your-bucket-name/' settings.yml
    
    # Add your OAuth config here
    sed -i -e 's/CLIENT_ID/1234/' settings.yml
    sed -i -e 's/CLIENT_SECRET/1234/' settings.yml
    

Compute Engine インスタンスの作成と構成

  1. Compute Engine インスタンスを作成します。

    次のコマンドでインスタンスを作成し、GCP サービスへのアクセスを許可し、起動スクリプトを実行します。インスタンス名は my-app-instance です。

    Linux と macOS

    gcloud compute instances create my-app-instance \
        --machine-type=g1-small \
        --scopes logging-write,storage-rw,datastore,https://www.googleapis.com/auth/projecthosting \
        --metadata-from-file startup-script=gce/my-startup.sh \
        --zone us-central1-f \
        --tags http-server \
        --image-family ubuntu-1604-lts \
        --image-project ubuntu-os-cloud
    

    Windows

    gcloud compute instances create my-app-instance ^
        --machine-type=g1-small ^
        --scopes logging-write,storage-rw,datastore,https://www.googleapis.com/auth/projecthosting ^
        --metadata-from-file startup-script=gce/my-startup.sh ^
        --zone us-central1-f ^
        --tags http-server ^
        --image-family ubuntu-1604-lts ^
        --image-project ubuntu-os-cloud
    

  2. インスタンス作成の進行状況を確認します。

    gcloud compute instances get-serial-port-output my-app-instance --zone us-central1-f
    

    起動スクリプトが完了すると、コマンド出力の最後の近くに「Finished running startup script」と表示されます。

  3. インスタンスへのトラフィックを許可するファイアウォール ルールを作成します。

    Linux / MacOS

    gcloud compute firewall-rules create default-allow-http-80 \
        --allow tcp:80 \
        --source-ranges 0.0.0.0/0 \
        --target-tags http-server \
        --description "Allow port 80 access to http-server"
    

    Windows

    gcloud compute firewall-rules create default-allow-http-80 ^
        --allow tcp:80 ^
        --source-ranges 0.0.0.0/0 ^
        --target-tags http-server ^
        --description "Allow port 80 access to http-server"
    

  4. インスタンスの外部 IP アドレスを取得します。

    gcloud compute instances list
    
  5. 実行中のアプリを確認するため、http://[YOUR_INSTANCE_IP] に移動します。

    [YOUR_INSTANCE_IP] は、実際のインスタンスの外部 IP アドレスに置き換えてください。

インスタンスの管理とモニタリング

GCP Console を使用して、インスタンスのモニタリングと管理を行うことができます。

  • 実行中のインスタンスを表示して ssh で接続するには、GCP Console で [VM インスタンス] ページに移動します。

    [VM インスタンス] ページに移動

  • Compute Engine リソースによって生成されたすべてのログを GCP Console で表示するには、[ログ] ページに移動します。

    [ログ] ページに移動

    Logging は、syslog を含むさまざまな共通サービスからログを収集するように自動的に構成されます。

複数のインスタンスによる水平スケーリング

マネージド インスタンスによる複数インスタンスのデプロイメント

Compute Engine は水平方向にスケールできます。マネージド インスタンス グループと Compute Engine Autoscaler を使用することにより、Compute Engine は、必要なときに自動的にアプリの新しいインスタンスを作成し、要求が少ない場合はインスタンスをシャットダウンできます。HTTP ロードバランサをセットアップすると、マネージド インスタンス グループ内の各インスタンスにトラフィックを分散できます。

デプロイメント スクリプト

サンプルアプリには、後続のデプロイメント手順を自動化するスクリプトが含まれています。deploy.sh という名前のスクリプトは、完全に自動スケールされた負荷分散アプリのリソースをデプロイします。詳細については、複数のインスタンスによる水平スケーリングをご覧ください。

次の各ステップを自分で実行することも、gce/deploy.shgce ディレクトリから実行することもできます。

マネージド インスタンス グループの作成

マネージド インスタンス グループは、同じインスタンス テンプレートに基づく同種のインスタンスのグループです。インスタンス テンプレートは、ソースイメージやディスクサイズ、スコープ、メタデータ(例: 起動スクリプト)など、インスタンスの構成を定義します。

  1. テンプレートを作成します。

    gcloud compute instance-templates create my-app-tmpl \
        --machine-type=g1-small \
        --scopes logging-write,storage-rw,datastore,https://www.googleapis.com/auth/projecthosting \
        --metadata-from-file startup-script=gce/my-startup.sh \
        --image-family ubuntu-1604-lts \
        --image-project ubuntu-os-cloud \
        --tags http-server
    
  2. インスタンス グループを作成します。

    gcloud compute instance-groups managed create my-app-group \
        --base-instance-name my-app \
        --size 2 \
        --template my-app-tmpl \
        --zone us-central1-f
    

    --size パラメータはグループ内のインスタンスの数を指定します。すべてのインスタンスで起動スクリプトの実行が終了したら、外部 IP アドレスとポート 8080 を使用して、個別にインスタンスにアクセスできます。インスタンスの外部 IP アドレスを調べるには、「gcloud compute instances list」と入力します。マネージド インスタンスには、同じプレフィックス my-app で始まる名前が付きます。これは --base-instance-name パラメータで指定したものです。

ロードバランサを作成する

テストやデバッグであれば単独のインスタンスでも十分ですが、ウェブ トラフィックを処理するのであれば、ロードバランサを使用して、利用できる複数のインスタンスの間で自動的にトラフィックを分配することをおすすめします。ロードバランサを作成する手順は次のとおりです。

  1. ヘルスチェックを作成します。

    ロードバランサは、ヘルスチェックを使用して、トラフィックを処理できるインスタンスを判断します。

    gcloud compute http-health-checks create bookshelf-health-check \
        --request-path / \
        --port 8080
    
  2. 名前付きポートを作成します。

    HTTP ロードバランサは http サービスを検索して、トラフィックの送信先ポートを判別します。既存のインスタンス グループで、ポート 8080 に名前 http を指定します。

    gcloud compute instance-groups managed set-named-ports my-app-group \
        --named-ports http:8080 \
        --zone us-central1-f
    
  3. バックエンド サービスを作成します。

    バックエンド サービスは、負荷分散されたトラフィックのターゲットとして機能します。バックエンド サービスにより、トラフィックの送信先となるインスタンス グループと使用するヘルスチェックが定義されます。

    gcloud compute backend-services create my-app-service \
        --http-health-check bookshelf-health-check
    
  4. バックエンド サービスを追加します。

    gcloud compute backend-services add-backend my-app-service \
        --group my-app-group \
        --zone us-central1-f
    
  5. URL マップとプロキシを作成します。

    URL マップは、どの URL がどのバックエンド サービスにつながるのかを定義します。今回のサンプルでは、1 つのバックエンド サービスですべてのトラフィックを処理しています。複数のリージョンやグループ間でリクエストを負荷分散する場合は、複数のバックエンド サービスを作成します。プロキシは、トラフィックを受信し、URL マップを使用してトラフィックをバックエンド サービスに転送します。

    1. URL マップを作成します。

      gcloud compute url-maps create my-app-service-map \
          --default-service my-app-service
      
    2. プロキシを作成します。

      gcloud compute target-http-proxies create my-app-service-proxy \
          --url-map my-app-service-map
      
  6. グローバル転送ルールを作成します。グローバル転送ルールは、公開 IP アドレスとポートをプロキシに関連付けます。

    gcloud compute forwarding-rules create my-app-service-http-rule \
        --global \
        --target-http-proxy my-app-service-proxy \
        --port-range 80
    

オートスケーラーを構成する

ロードバランサにより、すべての正常なインスタンス間でトラフィックが分散されます。では、これらのインスタンスで処理できないほど、トラフィックが過剰に発生した場合はどうなるでしょうか。インスタンスを手動で追加することもできます。しかし、より良い方法として Compute Engine Autoscaler があります。Compute Engine Autoscaler を構成すると、トラフィックの需要に応じてインスタンスの作成と削除を自動的に行うことができます。

  1. オートスケーラーを作成します。

    gcloud compute instance-groups managed set-autoscaling my-app-group \
        --max-num-replicas 10 \
        --target-load-balancing-utilization 0.5 \
        --zone us-central1-f
    

    上記のコマンドにより、マネージド インスタンス グループにオートスケーラーが作成され、最大 10 個のインスタンスまで自動的にスケールされます。ロードバランサの使用率が 50% を超えるとインスタンスが追加され、使用率が 50% を下回るとインスタンスが削除されます。

  2. 少なくとも 1 つのインスタンスが HEALTHY を報告するまで、進行状況を確認します。

    gcloud compute backend-services get-health frontend-web-service --global
    

アプリの表示

  1. ロードバランサの転送 IP アドレスを取得します。

    gcloud compute forwarding-rules list --global
    

    転送ルールの IP アドレスは IP_ADDRESS 列に表示されます。

  2. リストから取得した IP アドレスをブラウザに入力します。

    負荷分散型の自動スケーリング アプリが Compute Engine 上で動作していることを確認します。

デプロイメントの管理とモニタリング

負荷分散、自動スケーリング、マネージド インスタンス グループをモニタリングするには、GCP Console を使用します。

  • GCP Console の [インスタンス グループ] ページで、インスタンス グループと自動スケーリング構成をモニタリングして管理できます。

    [インスタンス グループ] ページに移動

  • GCP Console の [負荷分散] ページで、URL マップやバックエンド サービスなどの負荷分散構成をモニタリングして管理できます。

    [負荷分散] ページに移動

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

破棄スクリプトを実行する

deploy.sh スクリプトを実行した場合、teardown.sh スクリプトを実行すると、deploy.sh スクリプトによって作成されたリソースをすべて削除できます。これにより、プロジェクトが deploy.sh スクリプトを実行する前の状態に戻るため、以降の課金を回避できます。チュートリアルの開始時に作成した単一インスタンスとストレージ バケットを削除するには、次のセクションの手順に従ってください。

手動でリソースを削除する

このチュートリアルの手順を手動で進めてきた場合は、作成したクラウド リソースを手動で削除できます。

ロードバランサの削除

  1. GCP Console で [負荷分散] ページに移動します。

    [負荷分散] ページに移動

  2. 削除するロードバランサの横にあるチェックボックスをオンにして、[削除]delete をクリックします。

  3. [ロードバランサの削除] ダイアログで、関連するバックエンド サービスとヘルスチェックのリソースを選択し、[削除]delete をクリックします。ロードバランサとその関連リソースが削除されます。

Compute Engine マネージド インスタンス グループの削除

Compute Engine インスタンス グループを削除するには:

  1. GCP Console で、[インスタンス グループ] ページに移動します。

    [インスタンス グループ] ページに移動

  2. 次のチェックボックスをオンにします。 削除するインスタンス グループ。
  3. インスタンス グループを削除するには、ページの上部にある [削除]()をクリックします。

1 つの Compute Engine インスタンスの削除

Compute Engine インスタンスを削除するには:

  1. GCP Console の [VM インスタンス] ページに移動します。

    [VM インスタンス] ページに移動

  2. 次のチェックボックスをオンにします。 削除するインスタンス。
  3. インスタンスを削除するには、[削除] () をクリックします。

Cloud Storage バケットの削除

Cloud Storage バケットを削除するには:

  1. GCP Console で、Cloud Storage ブラウザページに移動します。

    Cloud Storage ブラウザページに移動

  2. 削除するバケットのチェックボックスをクリックします。
  3. バケット削除するには、[削除]()をクリックします。

次のステップ