Cloud Runの「Failed to start and then listen on the port」原因を切り分ける

Cloud Runサービスの起動失敗をrevision、processログ、PORTとbind先、startup probeから調べ、起動と業務応答を分けて確認します。

AIものさし編集部

Cloud Runサービスで「Failed to start and then listen on the port」が出たら、portの数字だけを変更せず、失敗したrevisionの起動ログを確認します。アプリがlistenする前に例外で終了した場合も、PORTやbind先が違う場合も、入口では似たエラーとして見えることがあります。

この記事はHTTP要求を受けるCloud Runサービスのingress containerを扱います。Jobsやworker poolsへ同じlisten要件を適用しません。以下は架空の診断表で、Cloud Runへの接続、image build、container実行、deploy、probe変更は行っていません。

対象revisionと失敗段階を固定する

Cloud Runのservice、project、region、失敗revision、image識別、作成時刻を対応付けます。稼働中の旧revisionと、新しくreadyになれなかったrevisionのログを混ぜないようにします。tagが同じでも、意図したimageの内容が同じとは限りません。

表は横にスクロールできます

観測した状態最初に確認するもの別問題として扱うもの
image取得前に失敗image参照・取得権限appのlisten設定
processがすぐ終了起動直後の例外・exitport変更だけの対応
processは動くがlistenしないentrypoint・初期化・bindHTTP要求の処理timeout
ready後に応答が失敗要求ログ・業務依存起動時のport不一致

GoogleのCloud Run troubleshooting(新しいタブで開く)は、まずcontainer imageをローカルでも実行できるか確かめる流れを示しています。試験する場合は実サービスへの副作用やsecretの扱いを管理した検証環境を使い、ローカル成功をCloud Runでも成功した証拠にはしません。

listenより前のprocess終了を調べる

revisionの起動時刻付近のstdout/stderrで、module不在、起動commandの誤り、設定不足、依存サービス接続失敗などを確認します。これは原因候補の例で、portエラーから特定の一つを断定するものではありません。

entrypointやcommandの上書きが、imageの既定動作と一致しているかを見ます。HTTP サーバーではなく一回限りの処理を実行して終了する設定なら、portを合わせてもlistenは始まりません。起動時に重いdownloadやmigrationを行う場合は、どこで止まったかをログの段階で区別します。

imageの実行形式も確認します。container runtime contract(新しいタブで開く)はLinux x86_64 ABIやmulti-architecture imageのlinux/amd64を説明しています。開発端末で動いた別architectureのimageを、そのまま同条件と考えないようにします。

PORTとbind先を組み合わせて照合する

公式contractでは、ingress containerは要求先portで0.0.0.0へlistenし、127.0.0.1へ限定しないよう定めています。Cloud Runはingress containerへPORT環境変数を注入します。既定portだけを暗記するより、対象revisionに設定されたcontainer portと、processが実際に使う値を照合します。

表は横にスクロールできます

設定の架空例processの状態確認する差分
PORT=80800.0.0.0:8080へlistenport・bindの基本条件は合う
PORT=8080127.0.0.1:8080だけbind先の限定
PORT=80800.0.0.0:3000へlistenportの読込・固定値
PORT=8080listen前にprocess終了port以外の起動失敗

表は成功保証ではありません。DockerfileのEXPOSEなどの宣言と、processがsocketを開くことも別です。frameworkのhost/port設定、環境変数の読込時点、起動引数を確認します。multi-container構成では、どれがingressで、どれがsidecarかも分けます。

startup probeと要求timeoutを混同しない

Cloud Runのhealth check資料(新しいタブで開く)はstartup、liveness、readinessの役割を分けています。起動準備が終わったかを確認するprobeと、起動後の一件のHTTP要求に許す時間は別です。要求timeoutを延ばせば起動失敗も直る、とは扱いません。

表は横にスクロールできます

probeの確認確認する事実不適切な成功判定
TCP対象portで接続を受けるか必要な業務処理まで保証
HTTP設定pathと応答条件が一致するか別pathの200だけで判断
gRPC対応health checkを実装しているかHTTP用設定をそのまま流用
起動が遅い初期化の進行と必要時間例外終了を待機延長で隠す

遅いだけなのか、永久に待つ・失敗するのかを区別してからprobe設定を検討します。health endpointには秘密や内部状態を過剰に返さず、意味のある準備状態を返す設計にします。probeだけ無条件成功へ変えて、準備前のアプリへtrafficを流す方法にはしません。

修正後は起動と応答を別々に確認する

変更候補は一つずつにし、image、entrypoint、PORT、bind、probeのどれを変えたか記録します。新revisionがreadyになったこと、そのrevisionへ意図した要求が届いたこと、必要最小限の応答が返ることを分けて確認します。旧revisionの成功応答を、新revisionの検証結果へ流用しません。

うまくいかなければ、変更前のimageと設定へ戻すための識別を保ちます。本番traffic変更を診断の最初の手順にせず、検証用の経路と運用の復旧手順を決めてから実施します。実施していない経路は未確認として残します。

確認した公式資料