HAProxyネットワークエラー:ソケットをバインドできません

提供:Dev Guides
移動先:案内検索

序章

HAProxy cannot bind socketエラーメッセージは、HAProxyが使用するように構成されている同じインターフェイスとTCPポートの組み合わせでリッスンしている別のプロセスがある場合、またはHAProxyがネットワークインターフェイスに割り当てられていないIPアドレスを使用しようとした場合に生成されます。 。 どちらのエラー状態も、基盤となるオペレーティングシステムのネットワークスタックに起因します。

最初のケースでは、HAProxyがバインドしようとしているインターフェイスとポートをすでに使用している別のプロセスがある場合、Linuxの根本的なエラーはEADDRINUSEです。 問題は、常に1つのプロセスのみをIPアドレスとポートの組み合わせにバインドできることです。

2番目のケースでは、HAProxyがシステムのインターフェースに割り当てられていないIPアドレスを使用しようとすると、Linuxの根本的なエラーはEADDRNOTAVAILです。 ここでの問題は、オペレーティングシステムで使用できないアドレスを使用してIPソケットを作成できないことです。

ただし、根本的なエラーは両方とも同じHAProxyエラーメッセージを生成するため、cannot bind socketエラーのトラブルシューティングでは、Linxシステムで現在使用されているソケットとIPアドレスのリストを調べる必要があります。

cannot bind socketエラーメッセージを検出するには、systemctljournalctlの出力を調べて、エラーの原因となっているIPアドレスとポートの組み合わせを特定する必要があります。 次に、実行中の他のプロセスとネットワークインターフェイスを調べて、サーバーの切り替え、HAProxyが使用するIPアドレスまたはポートの変更、またはこれらのオプションの任意の組み合わせによる問題の解決方法を決定できます。

systemctlを使用したトラブルシューティング

このシリーズの冒頭にある一般的なHAProxyエラーのトラブルシューティング方法チュートリアルのトラブルシューティング手順に従って、cannot bind socketエラーメッセージのトラブルシューティングを行う最初の手順は、systemctl

systemctl statusからの出力には、多くの場合、エラーを解決するために必要なすべての診断情報が含まれています。 これには、HAProxyが使用しているIPアドレスと、バインドしようとしているポートが含まれる場合があります。 出力には、HAProxyを開始できなかった期間も示されるため、問題がHAProxyに影響を及ぼしている期間を特定できます。

:UbuntuまたはDebianから派生したLinuxディストリビューションを使用している場合、systemctlには、問題を説明するcannot bind socketエラーメッセージを含むHAProxyからの出力は含まれません。 このチュートリアルの次のセクションであるjournalctlLogs を使用したトラブルシューティングにスキップして、systemdログを調べて競合するIPアドレスまたはポートを見つける方法を学習してください。


CentOS、Fedora、およびRedHatから派生したシステムでは、次のsystemctlコマンドを使用して、HAProxyのステータスを調べます。

CentOSとFedoraシステム

sudo systemctl status haproxy.service -l --no-pager

-lフラグは、systemctlが長い行を楕円()に置き換えるのではなく、行の内容全体を出力することを保証します。 --no-pagerフラグは、一度にコンテンツの画面のみを表示するlessのようなツールを呼び出さずに、ログ全体を画面に出力します。

cannot bind socketエラーメッセージのトラブルシューティングを行っているため、次のような出力が表示されます。

Output● haproxy.service - HAProxy Load Balancer
   Loaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Wed 2020-08-19 14:57:05 UTC; 3s ago
  Process: 138738 ExecStart=/usr/sbin/haproxy -Ws -f $CONFIG -p $PIDFILE (code=exited, status=1/FAILURE)
  Process: 138736 ExecStartPre=/usr/sbin/haproxy -f $CONFIG -c -q (code=exited, status=0/SUCCESS)
 Main PID: 138738 (code=exited, status=1/FAILURE)

Aug 19 14:57:05 92214d8ff5e2 systemd[1]: Starting HAProxy Load Balancer...
Aug 19 14:57:05 92214d8ff5e2 haproxy[138738]: [ALERT] 231/145705 (138738) : Starting frontend main: cannot bind socket [0.0.0.0:80]
. . .
Aug 19 14:57:05 92214d8ff5e2 systemd[1]: Failed to start HAProxy Load Balancer.

この例のsystemctl出力には、エラーを説明するsystemdジャーナルからの強調表示された行が含まれています。 これらの行は、さらにトラブルシューティングするために必要なエラーに関するすべての情報を提供します。 具体的には、cannot bind socket [0.0.0.0:80]の行は、HAProxyが使用しようとしているソケット(0.0.0.0:80)を示しているため、次のjournalctlの手順をスキップして、代わりにのトラブルシューティングに進むことができます。このチュートリアルの最後にあるssおよびpsUtilitiesセクションを使用します。 もう1つの強調表示された行は、HAProxyプロセスのステータスを示し、cannot bind socketエラーの場合はFailed to start HAProxy Load Balancer.と表示されます。

systemctlの出力で、エラーの原因となっているIPアドレスとポートに関する特定の情報が得られない場合(UbuntuまたはDebianを使用している場合は、これが適用されます)、[を調べる必要があります。 systemdログからのX215X]出力。 次のセクションでは、journalctlを使用してcannot bind socketエラーのトラブルシューティングを行う方法について説明します。

journalctlログを使用したトラブルシューティング

systemctl出力にcannot bind socketエラーの詳細が含まれていない場合は、journalctlコマンドを使用して、HAProxyのsystemdログを調べる必要があります。

UbuntuおよびDebianから派生したシステムでは、次のコマンドを実行します。

sudo journalctl -u haproxy.service --since today --no-pager

CentOS、Fedora、およびRedHatから派生したシステムでは、次のコマンドを使用してログを検査します。

sudo journalctl -u haproxy.service --since today --no-pager

--since todayフラグは、コマンドの出力を、当日の00:00:00から始まるエントリをログに記録するように制限します。 このオプションを使用すると、エラーをチェックするときに調べる必要のあるログエントリの量を制限するのに役立ちます。

HAProxyが使用中のポートにバインドできない場合は、出力を検索して、次のログエントリに類似した行、特にこの例で強調表示されているcannot bind socketエラーメッセージを含む行を探します。

Output-- Logs begin at Wed 2020-08-19 19:38:12 UTC, end at Wed 2020-08-19 19:53:53 UTC. --
. . .
Aug 19 19:39:21 92214d8ff5e2 systemd[1]: Starting HAProxy Load Balancer...
Aug 19 19:39:21 92214d8ff5e2 haproxy[135]: [ALERT] 231/193921 (135) : Starting frontend main: cannot bind socket [0.0.0.0:80]
Aug 19 19:39:21 92214d8ff5e2 haproxy[135]: [ALERT] 231/193921 (135) : Starting frontend main: cannot bind socket [:::80]
Aug 19 19:39:21 92214d8ff5e2 systemd[1]: haproxy.service: Main process exited, code=exited, status=1/FAILURE
Aug 19 19:39:21 92214d8ff5e2 systemd[1]: haproxy.service: Failed with result 'exit-code'.
Aug 19 19:39:21 92214d8ff5e2 systemd[1]: Failed to start HAProxy Load Balancer.
. . .

出力の最初の強調表示された行は、HAProxyが使用可能なすべてのIPv4インターフェイス(0.0.0.0 IPアドレスで示される)のポート80にバインドできないことを示しています。 システムの構成によっては、IPアドレスが異なり、個々のIPのみが表示される場合があります。

IPv6でHAProxyを使用している場合、出力には、IPv6固有のインターフェイスとポートエラー(この場合は:::80)で強調表示されている2番目の行のような行も含まれる場合があります。 最初の2つの::文字は、使用可能なすべてのIPv6インターフェースを示し、末尾の:80はポートを示します。

独自のシステムで競合するインターフェイスとポートが異なる場合でも、エラーはここに示す出力と同様になります。 journalctlからのこの出力では、このチュートリアルの次のセクションのssps、およびipコマンドを使用して問題を診断できます。

ssおよびpsユーティリティを使用したトラブルシューティング

cannot bind socketエラーのトラブルシューティングを行うには、HAProxyが使用しようとしているIPアドレスとポートでリッスンしている他のプロセス、またはHAProxyがIPアドレスを使用できるかどうかを判断する必要があります。

たとえば、Nginxなどの別のサーバーが利用可能なすべてのIPv4ネットワークインターフェイスのポート8080でリッスンするように構成されている場合、完全なソケットは0.0.0.0:8080になります。 HAProxyも0.0.0.0:8080を使用するように構成されている場合、オペレーティングシステムはEADDRINUSEエラーをスローし、HAProxyはそれ自体のソケットを要求できないため、cannot bind socketエラーメッセージを表示します。 。

前のjournalctlセクションでは、使用可能なすべてのIPv4アドレス(0.0.0.0:80で示される)に何かがすでにバインドされていました。 最新のLinuxディストリビューションのほとんどには、ssと呼ばれるユーティリティが含まれており、システムのネットワークソケットの状態に関する情報を収集するために使用できます。

次のコマンドは、ポート80でIPv4インターフェイスにすでにバインドされているプロセスの名前を判別します。 次のコマンドで80と異なる場合は、エラーメッセージのポートに置き換えてください。

sudo ss -4 -tlnp | grep 80

ssコマンドのフラグは、デフォルトの出力を次のように変更します。

  • -4は、ssがIPv4関連のソケット情報のみを表示するように制限します。
  • -tは、出力をtcpソケットのみに制限します。
  • -lは、-4および-tの制限を考慮したすべてのリスニングソケットを表示します。
  • -nは、「http or https」のようなプロトコル名ではなく、ポート番号が表示されるようにします。 HAProxyが非標準のポートにバインドしようとしている可能性があり、実際のポート番号ではなくサービス名が混乱する可能性があるため、これは重要です。
  • -pは、ポートにバインドされているプロセスに関する情報を出力します。
  • | grep 80は、出力を80の文字を含む行に制限するため、調べる必要のある行が少なくなります。

注:このIPv4および次のIPv6の例では、出力に一致するポートを持つ行がない場合、cannot bind socketエラーはEADDRNOTAVAILエラーに起因する可能性があります。 次のセクションipUtility のトラブルシューティングにスキップして、システムで使用可能なIPアドレスを調べてください。


これらのフラグをすべて使用すると、次のような出力を受け取るはずです。

OutputLISTEN   0         511                 0.0.0.0:80               0.0.0.0:*        users:(("nginx",pid=40,fd=6))

cannot bind socketエラーのトラブルシューティングを行う場合、最初の3つのフィールドは重要ではないため、無視してかまいません。 重要なフィールドは4番目(0.0.0.0:80)で、これは前に発見したjournalctlエラーと、最後のusers:(("nginx",pid=40,fd=6))、特にpid=40の部分と一致します。 。

IPv6インターフェースに関連するcannot bind socketエラーがある場合は、ss呼び出しを繰り返します。今回は、-6フラグを使用して、インターフェースをIPv6ネットワークスタックに制限します。これ:

sudo ss -6 -tlnp |grep 80

-6フラグは、ipコマンドをIPv6インターフェースに制限します。 HAProxyがIPv6ソケットにバインドできない場合は、次のような出力が必要です。

OutputLISTEN   0         511                    [::]:80                  [::]:*        users:(("nginx",pid=40,fd=7))

ここでも、強調表示されている80と異なる場合は、journalctl出力の問題のポート番号に置き換えてください。

IPv4エラーとIPv6エラーのどちらの場合も、ss出力は、0.0.0.0:80にバインドされたプロセスID40(出力のpid=40)を持つプログラムがあることを示します。 ]および[::]:80インターフェース。 このプロセスは、HAProxyがすでにポートを所有しているため、HAProxyの起動を妨げています。 プログラムの名前を判別するには、次のようなpsユーティリティを使用し、次の例で強調表示されている40値の代わりに、出力のプロセスIDを置き換えます。

sudo ps -p 40

次のような出力が表示されます。

OutputPID TTY          TIME CMD
40 ?        00:00:00 nginx

出力で強調表示されているnginxは、インターフェイスでリッスンしているプロセスの名前です。 これで、HAProxyの起動を妨げているプログラムの名前がわかったので、エラーを解決する方法を決定できます。 nginxプロセスを停止するか、nginxを再構成して別のインターフェイスとポートでリッスンするか、HAProxyを再構成してポートの衝突を回避することができます。

[を診断する場合、プロセスはnginxとは異なる場合があり、ポートアドレスとIPアドレスが常に0.0.0.0または[::]であるとは限らないことに注意してください。 X172X]エラー。 多くの場合、異なるWebサーバーとプロキシが同じサーバーで使用されます。 それぞれが、異なるWebトラフィックを処理するために異なるIPv4ポートおよびIPv6インターフェースにバインドしようとしている可能性があります。 たとえば、ポート8080でIPv4ループバックアドレス(localhostとも呼ばれる)をリッスンするHAProxyで構成されたサーバーは、次のようなss出力を表示します。

OutputLISTEN   0         2000              127.0.0.1:8080            0.0.0.0:*       users:(("haproxy",pid=545,fd=7))

systemctl出力、または特定のIPアドレスとポートを示すjournalctl出力を、ssからの診断データと組み合わせてから、psを組み合わせて絞り込むことが重要です。 HAProxyの起動に失敗する原因となっているプロセスをダウンさせます。

cannot bind socketエラーメッセージをssおよびpsでトラブルシューティングしているときに、出力がまったく表示されない場合があります。これは、エラーがソケットの競合によって引き起こされたものではない可能性があることを意味します。 。 このチュートリアルの次のセクションでは、ipユーティリティを使用してcannot bind socketエラーのトラブルシューティングを行う方法について説明します。

ipユーティリティを使用したトラブルシューティング

前のセクションでは、EADDRINUSEオペレーティングシステムエラーがcannot bind socketエラーメッセージを引き起こす可能性があることを説明しました。 ただし、ssおよびpsの出力を調べて、システムでソケットの競合がない場合は、代わりにEADDRNOTAVAILオペレーティングシステムエラーが原因で問題が発生している可能性があります。 この場合、HAProxyは、オペレーティングシステムで使用できないソケットにバインドしようとしている可能性があります。

cannot bind socketエラーの原因がEADDRNOTAVAILであるかどうかを判断するには、ipコマンドを使用して、システムのIPv4ネットワークインターフェイスとIPv6ネットワークインターフェイスの両方を調べます。

sudo ip -4 -c address show
  • -4は、ipがIPv4関連のインターフェース情報のみを表示するように制限します。
  • -cは、出力に色分けを追加して、視覚的に解析しやすくします。
  • address showは、-4および-cフラグを考慮して、インターフェイスのIPアドレスを表示します。

ipツールを含むLinuxディストリビューションでは、次のような出力が表示されます。

Output1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 203.0.113.1/24 brd 203.0.113.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.0.2.1/24 brd 192.0.2.255 scope global eth0
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 198.51.100.1/24 brd 198.51.100.255 scope global eth1
       valid_lft forever preferred_lft forever

この出力で強調表示されている例に対応するIPアドレスをメモします。 IPアドレスとネットワークインターフェイスは、ここに示す例とは異なります。 インターフェースが多かれ少なかれ、それぞれに割り当てられているアドレスが多かれ少なかれある場合があります。 重要な部分は、ipからのIPアドレスに注意することです。

システムに割り当てられているIPv6アドレスを調べるには、次のように-6フラグを指定してipコマンドを使用します。

sudo ip -6 -c address show

次のような出力を受け取るはずです。

Output1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2604:a880:400:d1::3d3:6001/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::a4ff:aaff:fec9:24f8/64 scope link
       valid_lft forever preferred_lft forever

この出力例で強調表示されている値に再度注意し、出力で対応するIPv6アドレスを探します。

システムに割り当てられているアドレスのリストを取得したら、cannot bind socket [x.x.x.x:80]エラーに対応する一致するIPアドレスを見つけることができます。 一致するIPアドレスがない場合、HAProxyはシステムで使用できないIPアドレスを使用するように構成されている可能性があり、cannot bind socketエラーは、オペレーティングシステムがEADDRNOTAVAILをスローすることによって発生します。エラー。

エラーを解決するには、/etc/haproxy/haproxy.cfgファイルを編集し、bindアドレスをipの出力に基づいてシステムで使用可能なIPアドレスに変更する必要があります。 ] 指図。

たとえば、/etc/haproxy/haproxy.cfg198.51.100.123をIPアドレスとして使用する次のようなbind行が含まれているが、システムに198.51.100.1が出力例に基づいて割り当てられている場合上記では、バインド行を編集する必要があります。

この架空の例に従って、このhaproxy.cfgスニペットは無効なIPアドレスを示しています。

/etc/haproxy/haproxy.cfg

. . .
frontend main
        bind 198.51.100.123:80

例のip出力のIPアドレスと一致する正しいbind行は、次のようになります。

/etc/haproxy/haproxy.cfg

. . .
frontend main
        bind 198.51.100.1:80

/etc/haproxy/haproxy.cfgを正しいIPアドレスで編集したら、systemctlコマンドを使用して再起動します。

sudo systemctl restart haproxy.service

次に、HAProxyのステータスを調べて、出力にactive (running)行が表示されていることを確認します。

sudo systemctl status haproxy.service
Output● haproxy.service - HAProxy Load Balancer
   Loaded: loaded (/lib/systemd/system/haproxy.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2020-08-19 21:31:46 UTC; 17h ago
     Docs: man:haproxy(1)
           file:/usr/share/doc/haproxy/configuration.txt.gz
  Process: 487 ExecStartPre=/usr/sbin/haproxy -f $CONFIG -c -q $EXTRAOPTS (code=exited, status=0/SUCCESS)
. . .
Aug 19 21:31:46 d6cdd0c71489 systemd[1]: Started HAProxy Load Balancer.

cannot bind socketエラーを解決した場合、出力はこの出力例のようになります。 HAProxyがアクティブであり、プロセスが正常に開始されたことを示す強調表示された行。

結論

このチュートリアルでは、IPv4インターフェイスとIPv6インターフェイスの両方でHAProxycannot bind socketエラーメッセージをトラブルシューティングする方法を学習しました。 systemctlを使用してHAProxyサーバーのステータスを調べ、エラーメッセージを見つけようとする方法を学びました。 また、journalctlを使用して、systemdログでcannot bind socketエラーに関する特定の情報を調べる方法も学習しました。

次に、systemdログからの適切なエラーメッセージを使用して、ssユーティリティと、それを使用してシステムのネットワークソケットの状態を調べる方法について学習しました。 その後、ssのプロセスID情報をpsユーティリティと組み合わせて、HAProxyを起動できなくなる原因となっているプロセスの名前を見つける方法を学びました。

最後に、使用できないIPv4またはIPv6アドレスに関連するcannot bind socketエラーの場合、ipユーティリティを使用してシステムで使用可能なネットワークインターフェイスを調べる方法を学習しました。