このチュートリアルでは、サービス デベロッパーが Stackdriver ツールを使用して Cloud Run for Anthos サービスの問題を検出し、ローカル開発ワークフローで調査を行う方法を説明します。
このトラブル シューティング ガイドの詳細な「ケーススタディ」では、デプロイ時にランタイム エラーが発生するサンプル プロジェクトを使用して、問題を発見および修正します。
Google Cloud のオペレーション スイートのサポート制限により、このチュートリアルは Cloud Run for Anthos on VMware では使用できません。
目標
- サービスを作成、ビルドして、Cloud Run for Anthos にデプロイする
- Cloud Logging を使用してエラーを特定する
- 根本原因を分析するため Container Registry からコンテナ イメージを取得する
- 「本番環境」のサービスを修正し、今後の問題を軽減するためにサービスを改善する
費用
このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
始める前に
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
- Cloud Run for Anthos API を有効にする
- Google Cloud CLI をインストールして初期化します。
kubectl
コンポーネントをインストールします。gcloud components install kubectl
- コンポーネントを更新します。
gcloud components update
- Cloud Run for Anthos を使用している場合は、Cloud Run for Anthos の設定の手順に沿って新しいクラスタを作成します。
- Cloud Run for Anthos を使用している場合は、curl をインストールしてサービスをお試しください。
- 手順に沿って、Docker をローカルにインストールします。
gcloud のデフォルトを設定する
gcloud に Cloud Run for Anthos サービス用のデフォルトを構成するには、次のようにします。
デフォルト プロジェクトを設定します。
gcloud config set project PROJECT_ID
PROJECT_ID は、このチュートリアルで使用するプロジェクトの名前に置き換えます。
クラスタに gcloud を構成します。
gcloud config set run/platform gke gcloud config set run/cluster CLUSTER-NAME gcloud config set run/cluster_location REGION
以下のように置き換えます。
- CLUSTER-NAME は、クラスタに対して使用した名前に置き換えます。
- REGION は、選択したサポート対象のクラスタの場所に置き換えます。
コードを組み立てる
新しい Cloud Run for Anthos のサービスを段階的にビルドします。このサービスでは、トラブル シューティングの演習のためにランタイム エラーを発生させます。
新しいプロジェクトを作成します。
Node.js
サービス パッケージ、初期依存関係、および一般的なオペレーションを定義して、Node.js プロジェクトを作成します。hello-service
ディレクトリを新規作成します。mkdir hello-service cd hello-service
package.json
ファイルを生成して、Node.js プロジェクトを新規作成します。npm init --yes npm install --save express@4
エディタで新しい
package.json
ファイルを開き、node index.js
を実行するようにstart
スクリプトを構成します。完了すると、ファイルは次のような状態になります。{ "name": "hello-service", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "node index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "express": "^4.17.1" } }
このサービスをこのチュートリアルからさらに進化させる場合は、説明、作成者を入力してライセンスを評価します。詳しくは、package.json のドキュメントをご覧ください。
Python
hello-service
ディレクトリを新規作成します。mkdir hello-service cd hello-service
requirements.txt ファイルを作成し、依存関係をコピーします。
Go
hello-service
ディレクトリを新規作成します。mkdir hello-service cd hello-service
新しい go モジュールを初期化して Go プロジェクトを作成します。
go mod init example.com/hello-service
名前は必要に応じて更新できます。コードがウェブ到達可能なコード リポジトリに公開されている場合は、名前を更新する必要があります。
Java
新しい maven プロジェクトを作成します。
mvn archetype:generate \ -DgroupId=com.example \ -DartifactId=hello-service \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false
依存関係を
pom.xml
依存関係リストにコピーします(<dependencies>
要素間)。ビルド設定を
pom.xml
(<dependencies>
要素の下)にコピーします。
受信リクエストを処理する HTTP サービスを作成します。
Node.js
Python
Go
Java
Dockerfile
を作成して、サービスのデプロイに使用するコンテナ イメージを定義します。Node.js
Python
Go
Java
このサンプルでは、Jib を使用して一般的な Java ツールにより Docker イメージをビルドします。Jib は、Dockerfile や Docker をインストールせずにコンテナのビルドを最適化します。Jib を使用して Java コンテナを構築する方法の詳細を確認します。
コードの配布
コードの配布は、Cloud Build でコンテナ イメージをビルドする、Container Registry にコンテナ イメージをアップロードする、Cloud Run にコンテナ イメージをデプロイするという 3 ステップで構成されます。
コードを配布するには:
コンテナをビルドして、Container Registry に公開します。
Node.js
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
PROJECT_ID は、GCP のプロジェクト ID です。現在のプロジェクト ID は、
gcloud config get-value project
で確認できます。ビルドが成功すると、ID、作成時間、イメージ名を含む SUCCESS メッセージが表示されます。イメージが Container Registry に保存されます。このイメージは必要に応じて再利用できます。
Python
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
PROJECT_ID は、GCP のプロジェクト ID です。現在のプロジェクト ID は、
gcloud config get-value project
で確認できます。ビルドが成功すると、ID、作成時間、イメージ名を含む SUCCESS メッセージが表示されます。イメージが Container Registry に保存されます。このイメージは必要に応じて再利用できます。
Go
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
PROJECT_ID は、GCP のプロジェクト ID です。現在のプロジェクト ID は、
gcloud config get-value project
で確認できます。ビルドが成功すると、ID、作成時間、イメージ名を含む SUCCESS メッセージが表示されます。イメージが Container Registry に保存されます。このイメージは必要に応じて再利用できます。
Java
mvn compile jib:build -Dimage=gcr.io/PROJECT_ID/hello-service
PROJECT_ID は、GCP のプロジェクト ID です。現在のプロジェクト ID は、
gcloud config get-value project
で確認できます。ビルドが成功すると、BUILD SUCCESS メッセージが表示されます。イメージが Container Registry に保存されます。このイメージは必要に応じて再利用できます。
次のコマンドを実行して、アプリをデプロイします。
gcloud run deploy hello-service --image gcr.io/PROJECT_ID/hello-service
PROJECT_ID は実際の GCP プロジェクト ID に置き換えます。
hello-service
は、コンテナ イメージ名と Cloud Run for Anthos サービスの名前の両方です。コンテナ イメージは、gcloud の設定で構成したサービスとクラスタにデプロイされることに注意してください。デプロイが完了するまで待ちます。30 秒ほどかかる場合があります。成功すると、コマンドラインにサービス URL が表示されます。
試してみる
サービスを試してみて、サービスが正常にデプロイされたことを確認します。リクエストは HTTP 500 エラーまたは HTTP 503 エラー(クラス 5xx サーバーエラーのメンバー)で失敗します。このチュートリアルでは、このエラー レスポンスのトラブルシューティングについて説明します。
クラスタにルーティング可能なデフォルト ドメインが構成されている場合は、上記の手順をスキップして、URL をウェブブラウザにコピーします。
自動 TLS 証明書とドメイン マッピングを使用しない場合、サービスにナビゲーション可能な URL は提供されません。
その代わりに、指定された URL とサービスの入力ゲートウェイの IP アドレスを使用して、サービスにリクエストする curl
コマンドを作成します。
-
Istio Ingress ゲートウェイの外部 IP を取得するには:
kubectl get svc istio-ingress -n gke-system
次のような出力が生成されます。NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) istio-ingress LoadBalancer XX.XX.XXX.XX pending 80:32380/TCP,443:32390/TCP,32400:32400/TCP
ロードバランサの EXTERNAL-IP は、使用する必要がある IP アドレスです。 URL でこの
GATEWAY_IP
アドレスを使用して、curl
コマンドを実行します。curl -G -H "Host: SERVICE-DOMAIN" https://EXTERNAL-IP/
SERVICE-DOMAIN は、サービスにデフォルトで割り当てられているドメインに置き換えます。そのためにデフォルトの URL を取得し、プロトコル
http://
を削除します。HTTP 500 または HTTP 503 のエラー メッセージを確認してください。
問題の調査
前述の試してみるで発生した HTTP 5xx エラーが、本番環境ランタイム エラーとして発生したことを表示で確認してください。このチュートリアルでは、正式な処理プロセスを説明します。本番環境でのエラー解決プロセスは大きく異なりますが、このチュートリアルでは、有用なツールとテクニックを利用するための特定の手順を示します。
この問題を調査するには、以下のフェーズを実施します。
- 報告されたエラーの詳細を収集し、さらに調査を進め、軽減策を策定します。
- 修正を進めるか、既知の正常なバージョンにロールバックして、ユーザーへの影響を軽減させます。
- 正確な詳細が収集されたことと、1 回限りのエラーではないことを確認するために、エラーを再現します。
- バグの根本原因を分析して、このエラーの原因となったコード、構成、プロセスを特定します。
調査を開始すると、URL、タイムスタンプ、「Internal Server Error」というメッセージが表示されます。
詳細の収集
問題の詳細情報を収集して何が起きたのかを理解し、次のステップを決定します。
利用可能なツールを使用して詳細を収集します。
ログを表示して詳細を確認します。
Cloud Logging を使用して、エラー メッセージなど、問題につながる一連の操作を確認します。
正常なバージョンへのロールバック
動作していたことがわかっているリビジョンがある場合は、サービスをロールバックしてそのリビジョンを使用できます。たとえば、このチュートリアルでデプロイした新しい hello-service
サービスには 1 つのリビジョンしかないため、ロールバックはできません。
リビジョンを見つけてサービスをロールバックするには、次のようにします。
エラーを再現する
以前に取得した詳細を使用して、テスト条件で一貫して問題が発生していることを確認します。
同じ HTTP リクエストをもう一度試すことで送信し、同じエラーと詳細が報告されるかどうかを確認します。エラーの詳細が表示されるまでに時間がかかることがあります。
このチュートリアルのサンプル サービスは読み取り専用であり、複雑な副次的影響をトリガーしないため、本番環境でのエラーの再現は安全です。ただし、実際のサービスの多くには上記が当てはまりません。テスト環境でエラーを再現するか、ローカル調査に限定する必要があります。
エラーを再現することで、後続作業のコンテキストが明確になります。たとえば、デベロッパーがエラーを再現できない場合、サービスに対してインストゥルメンテーションの追加が必要になる場合があります。
根本原因の分析を行う
根本原因の分析は、効果的なトラブルシューティングにおいて、症状ではなく問題を解決するための重要なステップです。
このチュートリアルでは、Cloud Run for Anthos で問題を再現し、Cloud Run for Anthos でサービスがホストされているときに問題がアクティブであることを確認しました。次に、問題をローカルで再現させてみて、問題がコードに限定されているか、本番環境のホスティングでのみ発生しているかを判断します。
Container Registry で Docker CLI をローカルで使用していない場合は、gcloud で認証します。
gcloud auth configure-docker
別の方法については、Container Registry の認証方法をご覧ください。
最近使用したコンテナ イメージ名が利用できない場合、サービスの説明に最近デプロイしたコンテナ イメージの情報があります。
gcloud run services describe hello-service
spec
オブジェクト内部のコンテナ イメージ名を探します。よりターゲットを絞ったコマンドを使用すれば、直接取得することもできます。gcloud run services describe hello-service \ --format="value(spec.template.spec.containers.image)"
このコマンドは、
gcr.io/PROJECT_ID/hello-service
のようなコンテナ イメージ名を明らかにします。コンテナ イメージを Container Registry から環境に pull します。この手順では、コンテナ イメージをダウンロードするため、数分かかることがあります。
docker pull gcr.io/PROJECT_ID/hello-service
この名前を再利用するコンテナ イメージに対するその後の更新は、同じコマンドで取得できます。この手順をスキップすると、次の
docker run
コマンドはコンテナ イメージを pull します(ローカルマシンにない場合)。ローカルで実行して、Cloud Run for Anthos に固有の問題ではないことを確認します。
PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ gcr.io/PROJECT_ID/hello-service
上記のコマンドを要素に分解してみます。
PORT
環境変数は、コンテナ内でリッスンするポートを指定するためサービスが使用します。run
コマンドはコンテナを起動します。デフォルトでは、Dockerfile または親コンテナ イメージで定義されたエントリポイントのコマンドになります。--rm
フラグは、終了時にコンテナ インスタンスを削除します。-e
フラグは、環境変数に値を割り当てます。-e PORT=$PORT
は、PORT
変数をローカル システムから同じ変数名のコンテナに移動します。-p
フラグは、ローカルホストのポート 9,000 でコンテナをサービスとして公開します。localhost: 9000 へのリクエストは、ポート 8080 でコンテナにルーティングされます。つまり、使用中のポート番号に関するサービスからの出力は、サービスへのアクセス方法と一致しません。- 最後の引数
gcr.io/PROJECT_ID/hello-service
は、コンテナ イメージの最新バージョンを指すリポジトリパスです。ローカルで入手できない場合、Docker はリモート レジストリからイメージを取得しようとします。
ブラウザで http://localhost:9000 を開きます。ターミナルの出力で、Google Cloud のオペレーション スイートのエラー メッセージと一致するエラー メッセージをチェックします。
問題がローカルで再現できない場合は、Cloud Run for Anthos 環境固有の問題である可能性があります。Cloud Run for Anthos のトラブルシューティング ガイドで、調査する具体的な領域を確認します。
この場合、エラーはローカルで再現されます。
エラーが永続的なものとして二重に確認され、またホスティング プラットフォームではなくサービスコードが原因と判明したため、コードを詳しく調査します。
このチュートリアルでは、コンテナ内のコードとローカル システムのコードが同じであることを前提にしています。
Node.js
ログに表示されるスタック トレースで示されている行番号の近くにあるindex.js
ファイルで、エラー メッセージのソースを見つけます。
Python
ログに表示されるスタック トレースで示されている行番号の近くにあるmain.py
ファイルで、エラー メッセージのソースを見つけます。
Go
ログに表示されるスタック トレースで示されている行番号の近くにある main.go
ファイルで、エラー メッセージのソースを見つけます。
Java
ログに表示されるスタック トレースで示されている行番号の近くにある App.java
ファイルで、エラー メッセージのソースを見つけます。
このコードを調べると、NAME
環境変数が設定されていない場合、次のアクションが実施されます。
- エラーが Google Cloud のオペレーション スイートに記録される。
- HTTP エラー レスポンスが送信される。
問題の原因は変数がないことですが、根本的な原因はより具体的です。環境変数への強い依存関係を追加するコード変更で、デプロイ スクリプトおよびランタイム要件のドキュメントに対して関連する変更をしなかったからです。
根本原因の修正
これでコードを収集し潜在的な原因を特定できたので、修正の手順を行います。
サービスが、そこで利用できる
NAME
環境でローカルで動作するかどうかを確認します。環境変数を追加してコンテナをローカルで実行します。
PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ -e NAME="Local World!" \ gcr.io/PROJECT_ID/hello-service
ブラウザで http://localhost:9000 に移動します。
ページに「Hello Local World!」が表示されるのを確認します。
実行している Cloud Run for Anthos サービス環境を変更して、この変数を含めます。
--update-env-vars
パラメータを指定して services update コマンドを実行し、環境変数を追加します。gcloud run services update hello-service \ --update-env-vars NAME=Override
Cloud Run for Anthos が以前のリビジョンに基づき、追加された新しい環境変数を含む新しいリビジョンを作成するまで数秒待ちます。
サービスが修正されたことを確認します。
- ブラウザで Cloud Run for Anthos サービスの URL に移動します。
- ページに「Hello Override!」が表示されるのを確認します。
- Cloud Logging に予期しないメッセージまたはエラーが表示されないことを確認します。
今後のトラブルシューティングの改善
この本番環境の問題のサンプルでは、エラーは運用構成に関連していました。この問題による将来の影響を最小限に抑えるようなコード変更があります。
- エラーログを改善して、より具体的な情報を伝えます。
- エラーを返す代わりに、サービスを安全なデフォルトに戻します。デフォルトの使用が通常の機能への変更を意味する場合、モニタリングのため警告メッセージを使用します。
依存度が高い NAME
環境変数を削除する手順を説明します。
既存の
NAME
処理コードを削除します。Node.js
Python
Go
Java
フォールバック値を設定する新しいコードを追加します。
Node.js
Python
Go
Java
影響を受けた構成ケースからコンテナを再ビルドして実行し、ローカルでテストします。
Node.js
docker build --tag gcr.io/PROJECT_ID/hello-service .
Python
docker build --tag gcr.io/PROJECT_ID/hello-service .
Go
docker build --tag gcr.io/PROJECT_ID/hello-service .
Java
mvn compile jib:build
NAME
環境変数が引き続き機能することを確認します。PORT=8080 && docker run --rm -e $PORT -p 9000:$PORT \ -e NAME="Robust World" \ gcr.io/PROJECT_ID/hello-service
NAME
変数なしでサービスが機能することを確認します。PORT=8080 && docker run --rm -e $PORT -p 9000:$PORT \ gcr.io/PROJECT_ID/hello-service
サービスが結果を返さない場合、最初のステップでのコード削除で、レスポンスの書き込みに使用されるような余分な行まで削除していないか確認します。
コードをデプロイするセクションに戻ってこれをデプロイします。
サービスをデプロイするたびに、リビジョンが作成されます。準備ができると、トラフィックの送信が自動的に開始します。
前に設定した環境変数をクリアするには、次の手順を行います。
gcloud run services update hello-service --clear-env-vars
サービスの自動テスト カバレッジに、デフォルト値の新しい機能を追加します。
ログ内でその他の問題を検索
このサービスのログビューアには、その他の問題がある場合があります。たとえば、サポートされていないシステムコールは、「Container Sandbox Limitation」(コンテナ サンドボックスの制限)としてログに表示されます。
たとえば、Node.js サービスはこのようなログメッセージを残すことがあります。
Container Sandbox Limitation: Unsupported syscall statx(0xffffff9c,0x3e1ba8e86d88,0x0,0xfff,0x3e1ba8e86970,0x3e1ba8e86a90). Please, refer to https://gvisor.dev/c/linux/amd64/statx for more information.
この場合、サポート対象外でも hello-service サンプル サービスには影響ありません。
クリーンアップ
このチュートリアル用に新規プロジェクトを作成した場合は、そのプロジェクトを削除します。既存のプロジェクトを使用し、このチュートリアルで変更を加えずに残す場合は、チュートリアル用に作成したリソースを削除します。
プロジェクトを削除する
課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。
プロジェクトを削除するには:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
チュートリアル リソースを削除する
このチュートリアルでデプロイした Cloud Run for Anthos サービスを削除します。
gcloud run services delete SERVICE-NAME
SERVICE-NAME は、選択したサービス名です。
Google Cloud コンソールから Cloud Run for Anthos のサービスを削除することもできます。
チュートリアルを設定したときに追加した gcloud のデフォルト構成を削除します。
gcloud config unset run/platform gcloud config unset run/cluster gcloud config unset run/cluster_location
プロジェクト構成を削除します。
gcloud config unset project
このチュートリアルで作成した他の Google Cloud リソースを削除します。
gcr.io/<var>PROJECT_ID</var>/hello-service
という名前のコンテナ イメージを Container Registry から削除します。- このチュートリアル用にクラスタを作成した場合は、クラスタを削除します。
次のステップ
- Cloud Logging を使用して本番環境での動作を分析する方法を学習する。
- Cloud Run for Anthos のトラブルシューティングの詳細については、[/anthos/run/archive/docs/troubleshooting#sandbox] をご覧ください。
- Google Cloud に関するリファレンス アーキテクチャ、図、チュートリアル、ベスト プラクティスを確認する。Cloud Architecture Center を確認します。