HAProxyネットワークエラー:ソケットをバインドできません
序章
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
エラーメッセージを検出するには、systemctl
とjournalctl
の出力を調べて、エラーの原因となっている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
からのこの出力では、このチュートリアルの次のセクションのss
、ps
、および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
は、「httpor
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.cfg
に198.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
ユーティリティを使用してシステムで使用可能なネットワークインターフェイスを調べる方法を学習しました。