第12章 API インフラストラクチャーに関するトラブルシューティング
本章の目的は、ユーザーが API インフラストラクチャーに関連する問題の原因を特定して修正できるように支援することです。
API インフラストラクチャーは、長く複雑なトピックです。ただし、少なくとも、インフラストラクチャーには 3 つの可動部分があります。
- API ゲートウェイ
- 3scale
- API
これらの 3 つの要素のいずれかでエラーが起こると、API の利用者は API にアクセスできなくなります。ただし、障害の原因となったコンポーネントを特定することは困難です。本章では、インフラストラクチャーのトラブルシューティングを行って問題を特定するためのヒントを紹介します。
以下のセクションを参照して、発生する可能性のある典型的な問題の特定および修正を行います。
12.1. インテグレーションに関する典型的な問題
3scale とのインテグレーションに関する非常に典型的な問題を示す症状がいくつかあります。これらは、API プロジェクトの最初の段階であるのか、インフラストラクチャーをセットアップしているのか、またはすでに実稼働環境に移行しているのかによって異なります。
12.1.1. インテグレーションの問題
以降のセクションで、3scale とのインテグレーションにおける初期段階 (Hosted APIcast 使用の初期段階および実稼働環境への移行前、ならびに Self-managed APIcast の稼働中) で、APIcast エラーログでよく見られる問題のいくつかについて概要を説明します。
12.1.1.1. Hosted APIcast
Service Integration 画面で API と Hosted APIcast を初めて統合する場合、以下のエラーのいずれかがページに表示されたり、インテグレーションの成功を確認するためのテストコールでエラーが返されたりする可能性があります。
Test request failed: execution expired
API が一般のインターネットからアクセス可能であることを確認します。Hosted APIcast は、プライベート API を扱うことができません。Hosted APIcast と統合する際に API を一般に公開したくない場合は、Hosted APIcast と API との間にプライベートシークレットを設定し、API ゲートウェイ以外からの呼び出しを拒否することができます。
設定可能なフォーマットは
protocol://address(:port)
です。API のプライベートベース URL の最後にあるパスを削除します。これらのパスは、マッピングルールのパターン、または API テスト GET リクエスト の最初に追加できます。
テストリクエストが失敗し HTTP コード XXX が返される
-
405
: エンドポイントが GET リクエストを受け入れることを確認します。APIcast は、インテグレーションをテストするための GET リクエストのみをサポートしています。 -
403: Authentication parameters missing
: API にすでに何らかの認証が設定されている場合は、APIcast はテストリクエストを送信することができません。 -
403: Authentication failed
: 3scale でこれ以前にサービスを作成したことがある場合は、テストリクエストを行うためのクレデンシャルが設定されたサービスでアプリケーションを作成していることを確認します。これが統合する最初のサービスである場合は、サインアップ時に作成したテストアカウントまたはアプリケーションを削除していないことを確認します。
-
12.1.1.2. Self-managed APIcast
Self-managed APIcast とのインテグレーションのテストが正常に終了したら、API ゲートウェイを独自にホストすることが望ましい場合があります。以下は、自己管理型ゲートウェイを初めてインストールし、これを介して API を呼び出す際に生じる可能性のあるエラーです。
upstream timed out (110: Connection timed out) while connecting to upstream
API ゲートウェイと一般のインターネットの間に、Self-managed APIcast ゲートウェイが 3scale に到達するのを妨げるファイアウォールまたはプロキシーがないことを確認します。
failed to get list of services: invalid status: 403 (Forbidden)
2018/06/04 08:04:49 [emerg] 14#14: [lua] configuration_loader.lua:134: init(): failed to load configuration, exiting (code 1) 2018/06/04 08:04:49 [warn] 22#22: *2 [lua] remote_v2.lua:163: call(): failed to get list of services: invalid status: 403 (Forbidden) url: https://example-admin.3scale.net/admin/api/services.json , context: ngx.timer ERROR: /opt/app-root/src/src/apicast/configuration_loader.lua:57: missing configuration
THREESCALE_PORTAL_ENDPOINT
の値に使用するアクセストークンが正しいこと、またスコープに Account Management API が含まれていることを確認します。そのためには、curl
コマンドを使用して確認します (curl -v "https://example-admin.3scale.net/admin/api/services.json?access_token=<YOUR_ACCESS_TOKEN>"
)。JSON ボディーでレスポンス 200 が返されるはずです。エラーステータスコードを返す場合は、レスポンスのボディーで詳細を確認します。
service not found for host apicast.example.com
2018/06/04 11:06:15 [warn] 23#23: *495 [lua] find_service.lua:24: find_service(): service not found for host apicast.example.com, client: 172.17.0.1, server: _, request: "GET / HTTP/1.1", host: "apicast.example.com"
このエラーは、公開ベース URL が正しく設定されていないことを示しています。設定された公開ベース URL は、Self-managed APIcast へのリクエストに使用するものと同じにする必要があります。正しい公開ベース URL を設定した後、以下を実行します。
-
APIcast が実稼働用に設定されていることを確認します (
THREESCALE_DEPLOYMENT_ENV
変数で上書きされていない場合のスタンドアロン APIcast のデフォルト設定)。必ず設定を実稼働環境にプロモートしてください。 -
環境変数
APICAST_CONFIGURATION_CACHE
とAPICAST_CONFIGURATION_LOADER
を使用して自動的に設定を再読み込みするように設定していなかった場合は、APIcast を再起動します。
-
APIcast が実稼働用に設定されていることを確認します (
以下は、Self-managed APIcast の誤ったインテグレーションを示すその他の症状の例です。
- マッピングルールの不一致/API コールの二重カウント: メソッドと API の実際の URL エンドポイント間のマッピングをどのように定義したかによって、場合により、メソッドが一致しない、またはリクエストごとに複数回カウントが増加することがあります。この問題のトラブルシューティングを行うには、3scale デバッグヘッダー を使用して API にテストコールを行います。これにより、API コールで一致したすべてのメソッドのリストが返されます。
- 認証パラメーターが見つからない: パラメーターを Service Integration 画面で指定した正しい場所に送信していることを確認します。クレデンシャルをヘッダーとして送信しない場合、GET リクエストについてはクエリーパラメーターとして、その他の HTTP メソッドについてはボディーパラメーターとして送信する必要があります。3scale デバッグヘッダーを使用して、API ゲートウェイによりリクエストから読み取られるクレデンシャルを再確認します。
12.1.2. 実稼働環境の問題
セットアップを完全にテストし、しばらくの間実際に API を運用した後に、API ゲートウェイに関連して問題が発生することはほとんどありません。ただし、実際の実稼働環境で発生しうる問題の一部をここに挙げます。
12.1.2.1. 可用性の問題
可用性の問題は、通常、nginx error.log に upstream timed out
エラーが表示されることが特徴です。以下に例を示します。
upstream timed out (110: Connection timed out) while connecting to upstream, client: X.X.X.X, server: api.example.com, request: "GET /RESOURCE?CREDENTIALS HTTP/1.1", upstream: "http://Y.Y.Y.Y:80/RESOURCE?CREDENTIALS", host: "api.example.com"
断続的に 3scale の可用性の問題が発生する場合、以下が原因の可能性があります。
使用されていない古い 3scale IP に解決しようとしている。
最新バージョンの API ゲートウェイ設定ファイルは、毎回強制的に IP を解決するために、変数として 3scale を定義します。応急処置として、NGINX インスタンスを再読み込みします。長期的な修正としては、アップストリームブロックで 3scale バックエンドを定義するのではなく、たとえば以下のように、各サーバーブロック内の変数として定義します。
server { # Enabling the Lua code cache is strongly encouraged for production use. Here it is enabled . . . set $threescale_backend "https://su1.3scale.net:443";
これを参照する場合は、以下のとおりです。
location = /threescale_authrep { internal; set $provider_key "YOUR_PROVIDER_KEY"; proxy_pass $threescale_backend/transactions/authrep.xml?provider_key=$provider_key&service_id=$service_id&$usage&$credentials&log%5Bcode%5D=$arg_code&log%5Brequest%5D=$arg_req&log%5Bresponse%5D=$arg_resp; }
すべての 3scale IP がホワイトリスト上に記載されていない。3scale が解決する IP の現在のリストを以下に示します。
- 75.101.142.93
- 174.129.235.69
- 184.73.197.122
- 50.16.225.117
- 54.83.62.94
- 54.83.62.186
- 54.83.63.187
54.235.143.255
上記の問題は、3scale の可用性の問題と考えられます。ただし、API が AWS ELB の背後に置かれている場合、API ゲートウェイからの API 可用性に同様の問題が発生する可能性があります。これは、デフォルトでは NGINX が起動時に DNS 解決を行ってから IP アドレスをキャッシュするためです。ただし、ELB は静的 IP アドレスを確保せず、頻繁に変わる可能性があります。ELB が別の IP に変わると、NGINX はその IP に到達できません。
この問題の解決方法は、強制的にランタイム DNS 解決を行う上述の修正と類似しています。
-
http
セクションの最上部にresolver 8.8.8.8 8.8.4.4;
という行を追加して、Google DNS などの特定の DNS リゾルバーを設定します。 -
server
セクションの最上部近くの任意の場所に、API のベース URL を変数として設定しますset $api_base "http://api.example.com:80";
-
location /
セクション内でproxy_pass
の行を探し、それをproxy_pass $api_base;
に置き換えます。
-
12.1.3. デプロイ後の問題
新しいエンドポイントを追加するなど、API に変更を加える場合、API ゲートウェイの新しい設定ファイルのセットをダウンロードする前に、必ず新しいメソッドおよび URL マッピングを追加する必要があります。
3scale からダウンロードした設定を変更した場合の最も典型的な問題は、Lua のコードエラーです。これにより、以下のような 500 - Internal server error
が発生します。
curl -v -X GET "http://localhost/" * About to connect() to localhost port 80 (#0) * Trying 127.0.0.1... connected > GET / HTTP/1.1 > User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3 > Host: localhost > Accept: */* > < HTTP/1.1 500 Internal Server Error < Server: openresty/1.5.12.1 < Date: Thu, 04 Feb 2016 10:22:25 GMT < Content-Type: text/html < Content-Length: 199 < Connection: close < <head><title>500 Internal Server Error</title></head> <center><h1>500 Internal Server Error</h1></center> <hr><center>openresty/1.5.12.1</center> * Closing connection #0
nginx error.log を見て、原因を確認することができます。以下に例を示します。
2016/02/04 11:22:25 [error] 8980#0: *1 lua entry thread aborted: runtime error: /home/pili/NGINX/troubleshooting/nginx.lua:66: bad argument #3 to '_newindex' (number expected, got nil) stack traceback: coroutine 0: [C]: in function '_newindex' /home/pili/NGINX/troubleshooting/nginx.lua:66: in function 'error_authorization_failed' /home/pili/NGINX/troubleshooting/nginx.lua:330: in function 'authrep' /home/pili/NGINX/troubleshooting/nginx.lua:283: in function 'authorize' /home/pili/NGINX/troubleshooting/nginx.lua:392: in function while sending to client, client: 127.0.0.1, server: api-2445581381726.staging.apicast.io, request: "GET / HTTP/1.1", host: "localhost"
access.log では、以下のようになります。
127.0.0.1 - - [04/Feb/2016:11:22:25 +0100] "GET / HTTP/1.1" 500 199 "-" "curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
上記のセクションでは、3scale 運用のいずれかのステージで発生する可能性のある最も典型的でよく知られた問題の概要を示します。
これらをすべて確認してもなお問題の原因と解決策が見つからない場合は、API へのリクエストに関する問題の特定 で説明する、より詳細なトラブルシューティングに進む必要があります。問題のある箇所の特定を試みるため、API から始めてクライアントまで遡って作業します。