VMとKubernetesの最適なバランスを見つける
インフラ管理は通常、制御性と利便性の間のトレードオフになります。仮想マシン(VM)は完全な制御権を提供しますが、絶え間ないパッチ適用やOSのメンテナンスを必要とします。対照的に、Kubernetesは大規模なスケールを提供しますが、学習曲線が非常に険しく、小規模なチームではクラスター管理のために数ヶ月も足止めを食らうことがあります。私は、クラスターを管理するためのフルタイムのDevOpsエンジニアを雇うことなく、シンプルなマイクロサービスを実行したいと考えている数多くのエンジニアリングチームを見てきました。
Google Cloud Runは、ステートレスなコンテナ向けのフルマネージド環境を提供することで、この問題を解決します。コンテナイメージを渡すだけで、Googleがプロビジョニング、ネットワーキング、スケーリングをすべて処理します。これは現代の開発者にとって現実的な選択肢です。Dockerの柔軟性とPaaS(Platform-as-a-Service)のシンプルさを兼ね備えており、YAMLファイルのデバッグではなく、機能の開発に集中できるようになります。
クイックスタート:5分でコードを本番環境へ
サービスを公開するために必要なのは、アプリケーションとDockerfileだけです。この例ではPythonのFlaskアプリを使用していますが、Cloud Runは言語を問いません。アプリケーションが定義されたポートでHTTPリクエストを待機している限り、動作します。
1. アプリケーションコード (app.py)
from flask import Flask
import os
app = Flask(__name__)
@app.route('/')
def hello_world():
return "Cloud Runが稼働中。スケーリングも有効です!"
if __name__ == "__main__":
# Cloud RunはPORT環境変数を注入します
port = int(os.environ.get('PORT', 8080))
app.run(debug=False, host='0.0.0.0', port=port)
2. Dockerfile
FROM python:3.9-slim
ENV PYTHONUNBUFFERED True
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
3. コマンドひとつでデプロイ
手動でのイメージ作成やレジストリへのプッシュは不要です。Google Cloud SDKを使えば、パイプライン全体を一度に処理できます。ターミナルで以下のコマンドを実行してください:
gcloud run deploy my-service \
--source . \
--region us-central1 \
--allow-unauthenticated
このコマンドは、Google Cloud Buildをトリガーしてコンテナをパッケージ化し、Artifact Registryに保存して、本番用のURLにデプロイします。約60秒から90秒以内に、公開されたHTTPSリンクが発行されます。
Cloud Runのトラフィック制御とスケーリングの仕組み
Cloud Runは, KubernetesにサーバーレスパターンをもたらすオープンソースフレームワークであるKnative上に構築されています。しかし、Googleはその複雑さをすべて隠蔽しています。リクエストがエンドポイントに届くと、プラットフォームはアクティブなインスタンスがあるか確認します。存在しない場合は「コールドスタート」をトリガーし、軽量なアプリであれば約2秒でインスタンスを起動します。
コンカレンシー(同時実行数):効率的なリソース利用
AWS Lambdaのような従来のサーバーレス関数は、通常1インスタンスにつき1リクエストを処理します。Cloud Runは異なります。1つのコンテナで最大1,000件の同時リクエストを処理できます。これはI/Oバウンドなアプリケーションにとって大きな利点です。1つのコンテナで複数のリクエストを処理することで、必要な総インスタンス数を削減でき、1リクエスト1インスタンスのモデルと比較して月々のコストを30%以上削減できる場合があります。
ゼロダウンタイムリリースのためのトラフィック分割
安全なデプロイ機能がプラットフォームに組み込まれています。最初はトラフィックを一切送らずに、アプリの新しいバージョンをデプロイできます。おすすめは「カナリア」アプローチです。ユーザーの5%を新バージョンに誘導し、Cloud Loggingでエラーログを監視してから、100%に切り替えます。
gcloud run services update-traffic my-service --to-revisions=NEW_REVISION=5,OLD_REVISION=95
セキュリティとデータ:シークレットとデータベース
本番アプリにはコード以上のものが必要です。APIキーやデータベースの認証情報などです。これらをDockerイメージにハードコードするのはセキュリティ上の悪夢です。代わりに、Google Secret Managerを使用して、実行時に環境変数として機密データを直接注入します。
プライベートデータベースへの接続
アプリがCloud SQLインスタンスと通信する必要がある場合、データベースをパブリックインターネットに公開してはいけません。VPCコネクタを使用してください。これはプライベートな架け橋として機能し、サーバーレスコンテナがローカルネットワーク内にあるかのように、Virtual Private Cloud内の内部IPアドレスに到達できるようにします。
本番環境で得た教訓
Cloud Runで高トラフィックのサービスを管理してきた経験から、パフォーマンスとコストを最適化するためのいくつかの方法を特定しました。
- イメージを軽量に保つ: AlpineやSlimなどのベースイメージを使用してください。100MBのイメージは1GBのイメージよりも大幅に起動が早く、ユーザーへのコールドスタートの影響を軽減できます。
- 最小インスタンス数を設定する: レイテンシに敏感なアプリの場合は、
--min-instancesを1に設定します。これにより、常に1つのコンテナが「ウォーム」な状態に保たれ、その日最初のユーザーが遅延を感じることを防げます。 - メモリとCPUを調整する: Cloud Runのデフォルトは512MiBのRAMです。重いデータ処理を行う場合は、最大32GBおよび8 vCPUまでスケールアップできます。ただし、過剰なプロビジョニングは避けましょう。割り当てた分だけコストが発生します。
- ゼロへのスケール機能を活用する: Cloud Runはトラフィックがないときは無料です。これは開発環境に最適です。チームがオフラインの週末の間、コストを0ドルに抑えながらフル機能のステージングサイトをホストできます。
ローカルのDocker開発から本番のCloud Run環境への移行は、驚くほどスムーズです。コンテナのポータビリティとサーバーレスの運用負荷の低さを兼ね備えており、現代のWebアプリケーションをデプロイするための最も効率的な方法のひとつと言えるでしょう。

