はじめに
ALB配下のリバースプロキシサーバからべつのALBに接続するという構成で、たびたび503エラーが発生することがあり、対処した事例をまとめていきます。
構成
上記のような構成で、リバースプロキシをApacheで実装しており、特定のURLを別のALBにリダイレクトするような構成をとっていました。この構成において、ユーザが503エラーを観測しており原因を調査しました。
原因
結論から見ると、上記のようなエラーになっていました。まず、前段のリバースプロキシを担うApacheはデフォルトで、接続先の名前解決を実施し、一定期間キャッシュを持ちます。ALBは、スケーリングなどの任意のタイミングでENIを置き換えるため、同じIPアドレスでの接続が保証されません。今回は一度名前解決を行って返却されたIPアドレスを保持するALBのENIが置き換えられたことにより、リバースプロキシが対象のIPアドレスに接続できず503エラーを引き起こしてしまいました。
ログ
Apacheのログ上では以下のようなエラーが出力されます。
[XXXX][proxy:error][pid xxxx:tidxxxx](xxx)Connection timed out:XXX:HTTP:attempt to connect XXXX (ALBのFQDN)failed
エラーが出力された時間帯で、CloudTrailのログを確認します。
以下のようなイベントが該当時間帯に出力されていれば、ENIが置き換わっていることが裏付け可能です。
Event name:CreateNetworkInterface
Source IP address:elasticloadbalancing.amazonaws.com
対策
前段にNLBを挟む
本構成をとるとIPアドレスが固定化可能です。対象のドメインに対してNLBのIPアドレスを割り当てる(Route53等による名前解決)もしくは、NLBのIPアドレスに直接送信すればよいです。この構成を取った場合IPアドレスをキャッシュしても、固定IPであるため問題ありません。
Apacheのコネクションプーリングを無効化する。
Apacheでは上記の様に、コネクションプーリングにより、1つのプロセスが接続を保持します。プロセスが接続を保持するため、接続がタイムアウトするまでは、同一IPでの接続をスレッドで繰り返します。
そのため、この仕組みを無効化してしまい、必ずリクエストごとに名前解決する仕組みに変更します。
リバースプロキシにおいて以下のような設定を行います。
ProxyPass /xxxx ALBのFQDN diisablereuse=On
この場合、コネクションがリクエストごとに生成されるため、リバースプロキシ側に多少なりとも負荷がかかることになるため注意が必要です。
まとめ
クラウドではやはり名前解決に注意です。ALBやRDSなど名前解決でしか接続をサポートしないサービスが多いです。
安易にIPアドレスをキャッシュしないことはもちろんですが、切り替え時にキャッシュがどの程度影響するかなどは考慮しておくのがよいでしょう。