CFアプリ開発と管理#16 アプリのデプロイとトラブルシューティング

Cloud Foundryでアプリケーションを展開して実行する際の一般的な問題の診断と解決に関するヘルプについては、このトピックを参照してください。

*注意事項: この記事は、Cloud Foundry Documentaion [Troubleshooting Application Deployment and Health](https://docs.cloudfoundry.org/devguide/deploy-apps/troubleshoot-app-health.html) (last updated: June 23, 2017) の独自の翻訳とコメントです。内容を保証するものではありません。*

*コメント: Bluemixの拡張機能に関するトラブルシューティングのガイドは、「[Bluemix資料 トラブルシューティング](https://console.bluemix.net/docs/troubleshoot/troubleshoot.html#troubleshoot_overview)」に資料があります。*

## 共通の問題
以下のセクションでは、アプリケーションのデプロイおよび実行時に発生する可能性のある一般的な問題と、解決方法について説明します。

### cf pushタイムアウト
アップロードまたはステージングフェーズでデプロイメントがタイムアウトすると、次のいずれかのエラーメッセージが表示されることがあります。

* `504 Gateway Timeout`
* `Error uploading application`
* `Timed out waiting for async job JOB-NAME to finish`


このような場合は、次の操作を行います。

* **ネットワーク速度を確認してください。** アプリケーションのサイズによっては、アップロードに時間がかかりすぎるため、cf pushがタイムアウトする可能性があります。アップロードには少なくとも768 KB/s（6 Mb/s）のインターネット接続速度をお勧めします。

* **必要なファイルだけをプッシュしていることを確認してください。** デフォルトでは、cf pushは現在の作業ディレクトリのすべての内容をプッシュします。アプリケーションのディレクトリのみをプッシュしていることを確認してください。アプリケーションが大きすぎる場合、または小さなファイルが多い場合、アップロード中にCloud Foundryがタイムアウトすることがあります。プッシュしているファイルの数を減らすには、アプリケーションのディレクトリだけをプッシュし、不要なファイルを削除するか、.cfignoreファイルを使用して除外ファイルを指定するようにしてください。

* **CF_STAGING_TIMEOUTおよびCF_STARTUP_TIMEOUT環境変数を設定します。** デフォルトでは、アプリは15分、開始は5分です。 `CF_STAGING_TIMEOUT`と`CF_STARTUP_TIMEOUT`を設定することで、これらの時間を増やすことができます。詳細については、コマンドラインで`cf help`と入力してください。

* **アプリに多数のファイルが含まれている場合は、アプリを繰り返し押してみてください。** 各プッシュはいくつかのファイルをアップロードします。最終的に、すべてのファイルがアップロードされ、プッシュは成功します。これは、あなたのアプリに小さなファイルがたくさんある場合にはうまくいかない可能性があります。


### アプリが大きすぎます
アプリケーションが大きすぎる場合、cf pushで次のエラーメッセージのいずれかが表示されることがあります。

* `413 Request Entity Too Large`
* `You have exceeded your organization's memory limit`


このような場合は、次の操作を行います。

* **組織に、アプリのすべてのインスタンスに十分なメモリがあることを確認します。** あなたの組織に割り当てられているメモリより多くのメモリを使用することはできません。組織のメモリクォータを表示するには、`cf org ORG_NAME`を使用します。
総メモリ使用量は、組織内のすべてのスペースですべてのアプリケーションが使用しているメモリの合計です。 各アプリケーションのメモリ使用量は、それに割り当てられたメモリにインスタンス数を掛けたものです。スペース内のすべてのアプリケーションのメモリ使用量を表示するには、`cf apps`を使用します。

* **アプリケーションが1GB未満であることを確認してください。** 既定では、Cloud Foundryは現在の作業ディレクトリのすべてのコンテンツを展開します。プッシュしているファイルの数を減らすには、アプリケーションのディレクトリだけをプッシュし、不要なファイルを削除するか、.cfignoreファイルを使用して[除外ファイルを指定](https://docs.cloudfoundry.org/devguide/deploy-apps/prepare-to-deploy.html#exclude)するようにしてください。次の制限が適用されます。

  * プッシュするアプリファイルは1GBを超えることはできません。
  * これらのファイルをコンパイルした結果のdropletは1.5 GBを超えることはできません。dropletは通常、プッシュされたファイルよりも3分の1です。
  * アプリケーションファイル、コンパイルされたdroplet、および buildpackキャッシュ の合計サイズは、ステージング中に合計4GBを超えることはできません。


### サポートされているアプリケーションタイプを検出できません

Cloud Foundryがアプリケーションの[適切なビルドパックを特定できない](https://docs.cloudfoundry.org/buildpacks/detection.html)場合、`Unable to detect a supported application type`というエラーメッセージが表示されます。

`cf buildpacks`コマンドを使用して、使用可能なビルドパックを表示できます。

あなたのアプリケーションをサポートすべきだと思うビルパックがある場合は、そのビルドパックがサポートしているアプリケーションをどのように検出するかについて、[buildpackのマニュアル](https://docs.cloudfoundry.org/buildpacks/)を参照してください。

アプリケーション用のビルドパックが表示されない場合でも、ビルドパックへのパスとともに`cf push -b`を使用して[カスタムビルドパック](https://docs.cloudfoundry.org/buildpacks/custom.html)を使用してアプリケーションをプッシュすることができます。



### デプロイが失敗する

デプロイが失敗した場合でも、Cloud Foundryにアプリが存在する可能性があります。 `cf apps` を実行して、現在ターゲットとしている組織とスペースのアプリを確認します。 CLIを使用して問題を解決できる場合や、アプリを削除して再デプロイする必要がある場合があります。

アプリのデプロイに失敗する一般的な理由には、次のものがあります。

* PostgreSQLやMongoDBのサービスインスタンスなど、必要なサービスインスタンスをアプリケーションに正常に作成してバインドしていませんでした。 「Step 3: Create and Bind a Service Instance for a RoR Application」を参照してください。
* アプリの一意のURLを正常に作成できませんでした。「Refer to the troubleshooting tip App Requires Unique URL」を参照してください。


### アプリケーションの起動に失敗する

`cf push` がアプリをステージングしてdropletをアップロードした後、アプリが起動に失敗することがあります。
 
 次の例のように、起動パターンとクラッシュ・パターンが共通しています。

~~~
 -----> Uploading droplet (23M)
...
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 down
...
0 of 1 instances running, 1 failing
FAILED
Start unsuccessful
~~~

この様な問題がおきたら、以下を試してください。

* **アプリが失敗した理由を探し、コードを修正します。**  `cf events APP-NAME`と `cf logs APP-NAME --recent`を実行し、次のようなメッセージを探します。

~~~
2014-04-29T17:52:34.00-0700   app.crash          index: 0, reason: CRASHED,
exit_description: app instance exited, exit_status: 1
~~~

これらのメッセージは、メモリまたはポートの問題を識別することができます。 そうした場合は、アプリケーションコードを再検討して修正する際に、これを出発点にしてください。

* **アプリケーションコードがPORT環境変数を使用していることを確認してください。** 間違ったポートでリッスンしているため、アプリケーションが失敗する可能性があります。 アプリケーションがリッスンするポートをハードコーディングする代わりに、PORT環境変数を使用します。
たとえば、このRubyスニペットは、ポート値を`listen_here`変数に割り当てます。
`listen_here = ENV ['PORT']`

アプリケーションフレームワーク固有のサンプルについては、アプリケーションの言語に関する適切な[ビルドパックのドキュメント](https://docs.cloudfoundry.org/buildpacks/)を参照してください。

* **あなたのアプリが [Tweleve-Factor App](https://12factor.net)の原則に従っていることを確認し、[アプリケーションのデプロイの準備をしてください。](https://docs.cloudfoundry.org/devguide/deploy-apps/prepare-to-deploy.html)** これらのテキストは、アプリがローカルに構築されているがクラウドに構築できない状況を防ぐ方法を説明しています。

* **アプリのタイムアウト設定を確認します。** アプリケーションのヘルスチェックでは、アプリの初回起動時にタイムアウト設定が使用されます。 [Using Application Health Checks](https://docs.cloudfoundry.org/devguide/deploy-apps/healthchecks.html)を参照してください。 ヘルスチェックタイムアウトのためにアプリケーションの起動に失敗した場合は、ログに次のようなメッセージが表示されることがあります。

~~~
2017-01-30T14:07:20.39-0800 [CELL/0]     OUT Creating container
2017-01-30T14:07:20.65-0800 [CELL/0]     OUT Successfully created container
2017-01-30T14:07:22.30-0800 [CELL/0]     OUT Starting health monitoring of container
2017-01-30T14:08:23.52-0800 [CELL/0]     ERR Timed out after 1m0s: 
health check never passed.
2017-01-30T14:08:23.57-0800 [CELL/0]     OUT Destroying container
2017-01-30T14:08:23.59-0800 [API/0]      OUT Process has crashed with type: "web"
2017-01-30T14:08:23.59-0800 [CELL/0]     OUT Creating container
2017-01-30T14:08:23.60-0800 [API/0]      OUT App instance exited with guid 91086440-bac0-44f0-808f-a034a1ec2ed0 
payload: {"instance"=>"", "index"=>0, "reason"=>"CRASHED",
"exit_description"=>"2 error(s) occurred:\n\n* 1 error(s) 
occurred:\n\n* Exited with status 6\n* 2 error(s) 
occurred:\n\n* cancelled\n* cancelled", "crash_count"=>1,
"crash_timestamp"=>1485814103565763172,
"version"=>"3e6e4232-7e19-4168-9583-1176833d2c71"}
2017-01-30T14:08:23.83-0800 [CELL/0]     OUT Successfully destroyed container
2017-01-30T14:08:23.84-0800 [CELL/0]     OUT Successfully created container
2017-01-30T14:08:25.41-0800 [CELL/0]     OUT Starting health monitoring of container
~~~


## アプリが過剰にメモリを消費してクラッシュする
`cf push`がアップロードして起動したアプリケーションは、あまりにも多くのメモリを使用すると後でクラッシュする可能性があります。

**あなたのアプリが必要以上のメモリを消費していないことを確認してください。** `cf push` と` cf scale`を実行すると、アプリで使用するメモリ量が制限されてしまいました。 アプリの実際のメモリ使用量を確認してください。 制限を超えている場合は、メモリを少なくするようにアプリを変更してください。


## ルーティングの競合

Cloud Foundryでは、複数のアプリまたは同じアプリのバージョンを同じルートにマッピングできます。 この機能により、Blue-Greenの導入が可能になります。 詳細については、[Blue-Green展開を使用したダウンタイムとリスクの削減]()を参照してください。

複数のアプリを同じルートにルーティングすると、受信したリクエストを共有ルート上のいずれかのアプリにランダムにルーティングすることによって、状況によっては望ましくない動作が発生することがあります。

ルーティングの競合が疑われる場合は、`cf routes`を実行して、インストール内のルートを確認してください。

2つのアプリがBlue-Greenの導入方針外のルートを共有している場合は、別のルートに再割り当てするアプリを1つ選択し、以下の手順に従います。

1. `cf unmap-route YOUR-APP-NAME OLD-ROUTE`を実行して、そのアプリから既存のルートを削除します。
2. `cf map-route YOUR-APP-NAME NEW-ROUTE`を実行して、アプリを新しい一意のルートにマップします。


## 診断情報を収集する

このセクションの手法を使用して、診断情報を収集し、アプリのデプロイメントに関する問題のトラブルシューティングを行います。


### 環境変数を調べる
`cf push`はアプリケーションをサーバー上のコンテナにデプロイします。 コンテナ内の環境変数がアプリケーションを制御します。

デプロイする前に作成したマニフェストで環境変数を設定できます。 「[アプリケーションマニフェストを使用したデプロイメント](https://docs.cloudfoundry.org/devguide/deploy-apps/manifest.html)」を参照してください。

また、`cf set-env`コマンドと`cf push`コマンドで環境変数を設定することもできます。 変数をコンテナ環境で有効にするには、`cf push`を実行する必要があります。

`cf env`コマンドを使用して、`cf set-env`コマンドとコンテナ環境の変数を使用して設定した環境変数を表示します。

~~~
$ cf env my-app
 Getting env variables for app my-app in org My-Org / space development as admin...
 OK

 System-Provided:
 {
   "VCAP_SERVICES": {
     "p-mysql-n/a": [
       {
         "credentials": {
           "uri":"postgres://lrra:e6B-X@p-mysqlprovider.example.com:5432/lraa
         },
         "label": "p-mysql-n/a",
         "name": "p-mysql",
         "syslog_drain_url": "",
         "tags": ["postgres","postgresql","relational"]
       }
     ]
   }
 }

 User-Provided:
 my-env-var: 100
 my-drain: http://drain.example.com
~~~
 

### ログを見る

リアルタイムでストリーミングされたアプリログを表示するには、`cf logs APP-NAME`コマンドを使用します。

アプリ履歴を集計してログ履歴を表示するには、アプリをSyslogドレインサービスにバインドします。 詳細については、「[アプリケーションログをログ管理サービスにストリーミングする](https://docs.cloudfoundry.org/devguide/services/log-management.html)」を参照してください。

注： The Diego architectureは`cf files`コマンドをサポートしていません。


### Cloud Controller REST APIコールのトレース

コマンドが失敗したり予期しない結果が発生した場合は、HTTPトレースを有効にしてコマンドを再実行して、cf CLIとCloud Controller REST API間のリクエストと応答を表示します。

例えば：

* `cf push`を`-v`で再実行する：
`cf push APP-NAME -v`


*`cf push`を再実行しながら、API要求診断をログファイルに追加します。
`CF_TRACE=PATH-TO-TRACE.LOG; cf push APP-NAME`


これらの例では、単一のコマンドに対してのみHTTPトレースを有効にしています。 シェルセッション全体で有効にするには、最初に変数を設定します。

`export CF_TRACE=true`
`export CF_TRACE=PATH-TO-TRACE.LOG`

注：CF_TRACEは、cf CLIの動作を変更するローカル環境変数です。 CF_TRACEとアプリケーションが動作するコンテナ環境の変数を混同しないでください。


### ZipkinトレースIDを分析する

Cloud FoundryでZipkin機能が有効な場合、Gorouterは、ZipkinトレースIDとスパンIDをHTTPヘッダーに追加または転送します。 HTTPヘッダーにGorouterが提供するものの詳細については、「HTTPルーティング」トピックの「[HTTPヘッダー](https://docs.cloudfoundry.org/concepts/http-routing.html#http-headers)」セクションを参照してください。

アプリケーションログにZipkin HTTPヘッダーを追加した後、開発者は`cf logs myapp`を使用して、Gorouterによって記録されたトレースとスパンIDを、アプリケーションによって記録されたトレースIDと相関させることができます。 要求のトレースIDを複数のアプリケーションで相互に関連付けるには、各アプリケーションが、要求のあるヘッダーに適切な値を他のアプリケーションに転送する必要があります。



## トラブルシューティングコマンドの利用

cf CLIを使用して、アプリのデプロイメントと健全性を調べることができます。

一部のcf CLIコマンドは接続資格情報を返すことがあります。 アウトプットをパブリックなフォーラムに投稿する前には、コマンド出力から資格情報およびその他の機密情報を削除してください。

* `cf apps`: 名前、現在の状態、インスタンス数、メモリとディスク割り当て、各アプリケーションのURLなど、デプロイメントオプションを使用して、現在のスペースにデプロイされているアプリケーションのリストを返します。

* `cf app APP-NAME`: インスタンスID番号、現在の状態、実行されている時間、および使用しているCPU、メモリ、およびディスクの量など、現在の領域内の特定のアプリケーションの各インスタンスの正常性とステータスを返します。

注：cf appによって返されるCPU値は、各コアが100％活動するホストVM上のすべてのCPUコア上の各アプリケーション・インスタンスの合計使用率を示します。たとえば、1つのコアを持つ Diegoセル のシングルスレッド・アプリケーションインスタンスのCPUは100％を超えることはできず、セルを共有する4つのインスタンスは平均CPUの25％を超えることはできません。 8つのコアを持つセル上で単独で実行されるマルチスレッドのアプリケーションインスタンスは、最大800％のCPUを利用できます。

* `cf env APP-NAME`: `cf set-env`とコンテナ環境に存在する変数を使用して設定された環境変数を返します。
* `cf events APP-NAME`: エラー・コードを含むアプリケーション・クラッシュに関する情報を戻します。アプリ・インスタンスが終了したことを示します。詳細については、アプリケーションログを参照してください。 Cloud Foundryのエラーのリストについては、https://github.com/cloudfoundry/errorsを参照してください。
* `cf logs APP-NAME --recent`: 最近のログをダンプします。 「[コマンドラインインターフェイスでのログの表示](https://docs.cloudfoundry.org/devguide/deploy-apps/streaming-logs.html#view)」を参照してください。
* `cf logs APP-NAME`: アプリケーションSTDOUTおよびSTDERRのリアルタイムストリームを返します。 Ctrl+C（^ C）を使用して、リアルタイムストリームを終了します。
* `cf files APP-NAME`: アプリケーションディレクトリ内のファイルを一覧表示します。与えられたファイルへのパスは、そのファイルの内容を出力します。サブディレクトリへのパスを指定すると、その中のファイルが一覧表示されます。これを使用して個々のログを調べます。

注：アプリケーションはログをSTDOUTおよびSTDERRに指示する必要があります。また、`cf logs`コマンドは、ログをSTDOUTに送信するように設定した[log4j](https://logging.apache.org/log4j/2.x/)機能からのメッセージも返します。


## SSHでアプリケーションにアクセス
アプリのインスタンスのトラブルシューティングが必要な場合は、SSHプロキシとデーモンを使用してアプリにSSHアクセスできます。 詳細については、[アプリケーションSSHの概要](https://docs.cloudfoundry.org/devguide/deploy-apps/app-ssh-overview.html)のトピックを参照してください。


## リクエストをアプリケーションインスタンスに送信する
SSHのないデバッグデータを取得するには、`X-CF-APP-INSTANCE` HTTPヘッダーを使用して、アプリケーションの特定のインスタンスにHTTP要求を行うことができます。 詳細については、「HTTPルーティング」トピックの「[App Instance Routing](https://docs.cloudfoundry.org/concepts/http-routing.html#app-instance-routing)」を参照してください。