11. 回避すべき既知の落とし穴
システムの再起動後にhaproxyサービスが起動せず、手動で起動すると動く、という報告をときどき受けます。多くの場合、keepalivedなどのクラスターIPアドレス管理機構を使い、マスターノードだけにサービスのIPアドレスを割り当てています。haproxyを0.0.0.0にバインドしていたときは動作していたものが、仮想IPアドレスにバインドするように変更すると動かなくなります。これは、サービスの起動時点ではローカルノードが仮想IPアドレスをまだ所有しておらず、HAProxyがそのアドレスにバインドしようとすると、ローカルのIPアドレスではないためシステムが拒否することが原因です。解決策はhaproxyサービスの起動を遅らせることではありません。それでは再起動に対応できません。ローカルに存在しないアドレスへのバインドを許可するよう、システムを正しく設定します。Linuxでは、net.ipv4.ip_nonlocal_bind sysctlを1に設定するだけです。この設定は、特定の宛先アドレスに向けてHAProxyを通過するIPトラフィックを透過的に捕捉する場合にも必要です。
送信元ポートの範囲を使用するマルチプロセス構成は、一見動作しているようでも、高負荷時にランダムな障害を起こします。複数のプロセスが同じ送信元ポートを使って同じサーバーに接続しようとする可能性があり、それはできないためです。システムがエラーを返し、別のポートを選んで再試行します。“retries” パラメーターに大きな値を設定すれば影響をある程度隠せますが、CPU使用量と処理時間も増加します。ログにも一定数の再試行が記録されます。このため、マルチプロセス構成ではポート範囲の使用を避けてください。
HAProxyはSO_REUSEPORTを使用し、複数の独立したプロセスを同じIP:portにバインドできます。このため、トラブルシューティング中に古いプロセスを停止しないまま新しいプロセスを起動してしまうことがあります。その結果、設定の変更がすべて無視されているかのような、不可解なテスト結果が得られます。新しいプロセスを新しい設定で再起動しても、古いプロセスが受信接続の一部を処理し、想定外の結果を返すためです。疑わしい場合は新しいプロセスを停止し、もう一度試してください。それでも動作するなら、古いプロセスが残っていて停止する必要がある可能性が非常に高いと考えられます。Linuxの “netstat -lntp” が調査に役立ちます。
コマンドラインからACLにエントリーを追加する場合、たとえば送信元アドレスをブラックリストに登録する場合は、これらのエントリーがファイルに同期されないことに注意してください。誰かが設定をリロードすると、更新内容は失われます。ブラックリストへの登録ではこの動作が望ましいことも多いものの、問題を修正するための変更であれば、期待どおりとは限りません。CLIインターフェースの “add acl” アクションを参照してください。