NLBのヘルスチェックの挙動を調べてみた

記事タイトルとURLをコピーする

こんにちは!こんばんは! 現在テクサポ課でOJT中の日高と、営業でOJT中の末廣です!

NLBのヘルスチェックの挙動について知りたかったのですが、ヘルスチェックの挙動について書いているサイトやブログがなかったので
同期の末廣君と一緒に調べました。
その結果を本記事で書いていきたいと思います!

NLBのネットワーク設定などについて弊社の山下がブログを書いているので、気になる方は目を通して頂けると幸いです!

blog.serverworks.co.jp

NLB(Network Load Balancer) について

AWSの負荷分散サービスであるElastic Load Balancingの1種でOSI参照モデルの第4層(トランスポート層)で機能します。

docs.aws.amazon.com

NLBの特徴

簡単にNLBの特徴を以下に箇条書きで書かせていただきます。

  • TCP(L4)のバランサとして機能
  • ELBの中で唯一固定IPアドレスを持つことができる
  • 送信元IPアドレスの保持
  • 暖機運転なしに急激なスパイクにも対応可能
  • セキュリティグループの設定がない
  • VPCエンドポイントサービスのサポート

固定IPアドレスをもちたい場合、送信元IPアドレスを保持したい場合にNLBを検討するのがいいと考えています。
今回検証するヘルスチェックはTCP、HTTP、HTTPSに対応しています。

検証

ITの基礎を振り返りながら、検証した結果を見ていきます。

ターゲットとヘルスチェック

ロードバランサーはクライアントからリクエストを受け取り、 EC2 インスタンスなどのターゲットグループのターゲット間でリクエストを割り当てます。
ターゲットがリクエストを処理できるかどうかは、新しく登録したターゲットへのヘルスチェックを使用して判断しています。

docs.aws.amazon.com

NLBのヘルスチェックはデフォルトでTCP プロトコルが使用されます。 よって、本記事ではTCPによるヘルスチェックの動作についての検証についてまとめたものとなります。

TCPプロトコルの通信と検証のきっかけ

TCPはトランスポート層のプロトコルです。
TCP通信では、接続相手とコネクションを確立するために、スリーウェイハンドシェイクという3段階の通信を行います。

ヘルスチェックの成功例として、Apacheが動作しているEC2インスタンス上でtsharkコマンドを実行しました。

$ sudo tshark port 80
Capturing on 'eth0'
  1 0.000000000 10.0.132.180 -> 10.0.4.187   TCP 74 6340 > http [SYN] Seq=0 Win=8961 Len=0 MSS=8361 SACK_PERM=1 TSval=1993022496 TSecr=0 WS=1
  2 0.000031832   10.0.4.187 -> 10.0.132.180 TCP 74 http > 6340 [SYN, ACK] Seq=0 Ack=1 Win=62643 Len=0 MSS=8961 SACK_PERM=1 TSval=304827147 TSecr=1993022496WS=128
  3 0.000759064 10.0.132.180 -> 10.0.4.187   TCP 66 6340 > http [ACK] Seq=1 Ack=1 Win=8961 Len=0 TSval=1993022497 TSecr=304827147
  4 0.000759171 10.0.132.180 -> 10.0.4.187   TCP 66 6340 > http [FIN, ACK] Seq=1 Ack=1 Win=8961 Len=0 TSval=1993022497 TSecr=304827147
  5 0.000859652   10.0.4.187 -> 10.0.132.180 TCP 66 http > 6340 [FIN, ACK] Seq=1 Ack=2 Win=62720 Len=0 TSval=304827148 TSecr=1993022497
  6 0.001202048 10.0.132.180 -> 10.0.4.187   TCP 66 6340 > http [ACK] Seq=2 Ack=2 Win=8960 Len=0 TSval=1993022498 TSecr=304827148

スリーウェイハンドシェイクで80番ポートにTCPコネクションを確立し、すぐにコネクションを切断していることがわかります。
つまり、NLBのターゲットのヘルスチェックの成功には、スリーウェイハンドシェイクの成功が条件かと予想できます。
まだまだIT初心者の私には、これがApacheなどのWebサーバソフトウェアの動作がヘルスチェックには必要なのかどうか気になったため、今回の検証を行うこととしました。

検証条件と結果

今回の検証条件は上記を含めて以下の4つです。

  1. ターゲットのEC2インスタンスにApacheがインストールされており、動作している ← 成功
  2. Apacheがインストールされているが動作していない
  3. Apacheを動作させず、80番ポートを開放する
  4. Apacheを動作させず、80番ポートを Listen 状態にする

1 の結果は上記で検証したものになるので、2 からの検証内容と結果をまとめていきます。

Apacheがインストールされているが動作していない

1 の状態からApacheを停止してtsharkを実行すると、以下の結果になりました。

$ sudo systemctl stop httpd
$ sudo tshark port 80
Capturing on 'eth0'
  1 0.000000000 10.0.132.180 -> 10.0.4.187   TCP 74 23268 > http [SYN] Seq=0 Win=8961 Len=0 MSS=8361 SACK_PERM=1 TSval=519489787 TSecr=0 WS=1
  2 0.000025993   10.0.4.187 -> 10.0.132.180 TCP 54 http > 23268 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0
  3 9.999944091 10.0.132.180 -> 10.0.4.187   TCP 74 43683 > http [SYN] Seq=0 Win=8961 Len=0 MSS=8361 SACK_PERM=1 TSval=1986022148 TSecr=0 WS=1
  4 9.999972035   10.0.4.187 -> 10.0.132.180 TCP 54 http > 43683 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0

SYNフラグの通信への応答がRSTとなっており、スリーウェイハンドシェイクが失敗しています。
この状態でマネジメントコンソールのヘルスチェックの状態を確認すると、ヘルスチェックは失敗していました。

予想通りスリーウェイハンドシェイクに失敗するとヘルスチェックが失敗することがわかりました。

  1. ターゲットのEC2インスタンスにApacheがインストールされており、動作している ← 成功
  2. Apacheがインストールされているが動作していない ←失敗
  3. Apacheを動作させず、80番ポートを開放する
  4. Apacheを動作させず、80番ポートを Listen 状態にする

Apacheを動作させず、80番ポートを開放する

3 からの検証を行った理由としては、TCPプロトコルでヘルスチェックを行っているということは、HTTPのWebサーバソフトウェアである Apacheが動作していなくても80番ポートが応答できればできるのではと考えたからです。
ここでは、iptablesを編集して80番ポートの通信を許可してみます。

$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
$ sudo iptables -A INPUT -p tcp --sport 80 -j ACCEPT

結果としては、tsharkの結果は2 と同じで、ヘルスチェックも当然失敗となりました。

  1. ターゲットのEC2インスタンスにApacheがインストールされており、動作している ← 成功
  2. Apacheがインストールされているが動作していない ←失敗
  3. Apacheを動作させず、80番ポートを開放する ←失敗
  4. Apacheを動作させず、80番ポートを Listen 状態にする

Apacheを動作させず、80番ポートを Listen 状態にする

3 で立てたApacheが動作していなくてもTCPプロトコルでのヘルスチェックは成功する方法あるのではないかという仮説に対して色々調べた結果、スリーウェイハンドシェイクにはポートがListen状態になっている必要があるということがわかりました。

ネットワークの疎通確認で使用されるncatコマンドを使用することでこれが実現できました。
実行するにはnmapをインストールする必要があります。

$ sudo yum install nmap
$ sudo ncat -vklp 80
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on :::80
Ncat: Listening on 0.0.0.0:80
Ncat: Connection from 10.0.132.180.
Ncat: Connection from 10.0.132.180:13530.
Ncat: Connection from 10.0.132.180.
Ncat: Connection from 10.0.132.180:7965.
Ncat: Connection from 10.0.132.180.
Ncat: Connection from 10.0.132.180:56775.
Ncat: Connection from 10.0.132.180.
Ncat: Connection from 10.0.132.180:45306.

-kオプションでListen状態をキープすることができ、コマンドの実行中のみヘルスチェックが成功していました。

最終結果

今回の検証の結果になります。

  1. ターゲットのEC2インスタンスにApacheがインストールされており、動作している ← 成功
  2. Apacheがインストールされているが動作していない ←失敗
  3. Apacheを動作させず、80番ポートを開放する ←失敗
  4. Apacheを動作させず、80番ポートを Listen 状態にする ←成功

検証のまとめ

TCPプロトコルでのヘルスチェックと書いてるのだからApacheを動作させなくてもいけるだろ、といった興味本位から始まった内容でしたが、なんとか我々の中ではスッキリする結果が出たのではないかと思います。
Listen状態はOSカーネルのシステムコールやソケットなどと関わってくる話で私にはまだまだ理解が及んでいないので、動いたらいいや、ではなく様々な視点から理解を深めることが必要だと思い知らされました。

まとめ

今回の検証でNLBのヘルスチェックでは、スリーウェイハンドシェイクが確立するかどうかを確認していることが分かりました。
このように同期と2人でブログを書いてみるのは面白かったので、また機会があれば末廣君とブログを書いてみたいと思います!!
本記事が誰かの助けになれば幸いです。

日高 僚太(執筆記事の一覧)

EC部ソリューションアーキテクト2課 / AWS認定資格 12冠

2022年IT未経験で新卒入社しました。
最近はダーツとサウナが気になっています!
記事に関するお問い合わせや修正依頼⇒ hidaka@serverworks.co.jp

末廣 満希(執筆記事の一覧)

2022年新卒入社です。ここに何かかっこいい一言を書くことができるエンジニアになれるように頑張ります。