ALB と NLB のヘルスチェックの違い ── HTTP のパスと成功コードで見るか、TCP の接続で見るか

目次

概要

ロードバランサーの配下にあるサーバーが 1 台おかしくなっても、そのサーバーにリクエストを送らずに済むのは ヘルスチェック のおかげです。ロードバランサーは、ターゲットグループに登録したターゲットへ定期的に確認のリクエストを送り、合格したターゲットだけにトラフィックを流します。

ただし、何をもって「正常」とみなすかは、ロードバランサーの種類で変わります。Application Load Balancer(ALB) はレイヤー 7 で動き、HTTP / HTTPS で決めたパスにリクエストを送って、返ってきたステータスコードで判定します。Network Load Balancer(NLB) はレイヤー 4 で動き、既定は TCP の接続 ができるかどうかで判定します(HTTP / HTTPS のヘルスチェックも選べます)。そのため、アプリが 404 や 500 を返していても、ポートさえ開いていれば NLB の TCP ヘルスチェックは合格してしまいます。

この記事では、ALB と NLB のヘルスチェックの設定項目と既定値、ターゲットが unhealthy になったときの理由の見方を整理します。実践では、同じ 2 台の EC2 を ALB と NLB の両方に登録し、片方のヘルスチェック用ページを消したときに、それぞれのロードバランサーがどう判定するかを比べます。

同じ 2 台の EC2 を、ALB(HTTP)と NLB(TCP)の両方でヘルスチェックする
同じ 2 台の EC2 を、ALB(HTTP)と NLB(TCP)の両方でヘルスチェックする
クラウドおさる

猿山の監視当番には、倉庫番に「今日の在庫は?」と聞いて答えの中身まで確かめる当番と、戸を叩いて返事があれば良しとする当番がいるのでござる。ALB と NLB のヘルスチェックも、この違いでござるな。

この記事のメリット

  • ALB と NLB のヘルスチェックで、使えるプロトコルと「正常」の判定方法の違いを説明できるようになる
  • パス・成功コード・しきい値・間隔・タイムアウトの意味と既定値が分かる
  • ターゲットが unhealthy になったとき、理由コードから原因を切り分けられるようになる
  • TCP ヘルスチェックではアプリの異常を見逃すことがある、という落とし穴を実機で確かめられる

執筆者とキャラクター紹介

執筆者:土肥(とひ)

株式会社ジェニュインの代表であり元エンジニア。これまでオンプレミスと AWS 環境のインフラ業務を担当。AWS 認定資格の学習で得た知識を、ハンズオンとともに解説するのが得意。直近では新人の教育も行っており、これから技術を学ぶ方が納得できる解説を心がけています。基礎編・Cloud Practitioner の記事では、解説役としても登場します。

土肥

クラウドおさる

クラウドおさる

はじめましてでござる。弊猿はクラウドおさる。IT インフラが異常に発達した猿山から、雲に乗って地上の AWS を学びに降りてきたのでござる。

クラウドおさる

基礎編や Cloud Practitioner の記事では、とひさんに素朴な疑問をぶつける役でござるな。Security - Specialty などの記事では、要所でワンポイントや注意点をひとこと添えるでござる。

クラウドおさる

猿山にもデータセンターや監視当番があって、地上で起きることはだいたい猿山にも同じ仕組みがあるのでござる。例え話がつい猿山に寄るのは、弊猿の癖でござる。

技術解説

ヘルスチェックはターゲットグループに設定する

ヘルスチェックの設定は、ロードバランサー本体ではなく ターゲットグループ に持たせます。ロードバランサーは、リスナー(またはリスナールール)から参照されているターゲットグループに登録されたターゲットへ、決めた間隔で確認を送ります。

  • 連続して 非正常のしきい値 の回数だけ失敗すると unhealthy になり、そのターゲットへのルーティングが止まる
  • unhealthy のターゲットが連続して 正常のしきい値 の回数だけ合格すると healthy に戻り、ルーティングが再開する
  • ターゲットグループがどのリスナーからも使われていないと、ヘルスチェックは行われない(状態は unused、理由は Target.NotInUse)

ALB と NLB の設定項目の違い

項目ALBNLB
動くレイヤーレイヤー 7(HTTP / HTTPS)レイヤー 4(TCP / UDP / TLS)
ヘルスチェックのプロトコルHTTP / HTTPS(既定 HTTP)TCP / HTTP / HTTPS(既定 TCP)
パス既定 /HTTP / HTTPS のときだけ。既定 /
成功コード200〜499 から指定。既定 200HTTP / HTTPS のときだけ。200〜599 から指定。既定 200-399
正常のしきい値2〜10。既定 52〜10。既定 5
非正常のしきい値2〜10。既定 22〜10。既定 2
タイムアウト2〜120 秒。既定 5 秒(インスタンス / IP)2〜120 秒。既定 HTTP 6 秒、TCP / HTTPS 10 秒
間隔5〜300 秒。既定 30 秒(インスタンス / IP)5〜300 秒。既定 30 秒

ALB のヘルスチェックに TCP はありません。逆に NLB の既定の TCP ヘルスチェックは、ターゲットのポートに接続できれば合格です。Web サーバーのプロセスが生きていてポートが開いていれば、アプリがエラーを返していても NLB は気づきません。アプリの中身まで見たいなら、NLB でもヘルスチェックのプロトコルを HTTP / HTTPS にして、パスを指定します。

クラウドおさる

ALB は「答えの中身」を、NLB の TCP は「戸を叩いて返事があるか」を見るのでござる。大量の通信を低遅延でさばく API 層には NLB、パスで振り分けたい Web 層には ALB、と役割で選び、確かめたい深さに合わせてヘルスチェックを決めるのでござるな。

ALB と NLB のヘルスチェックは「何をもって正常とするか」が違う
ALB と NLB のヘルスチェックは「何をもって正常とするか」が違う

unhealthy の原因は理由コードで見る

ターゲットグループの「ターゲット」タブには、ターゲットごとのヘルスステータスと、その理由(詳細)が表示されます。CLI の aws elbv2 describe-target-health でも同じ理由コードが返ります。Elb で始まるコードはロードバランサー側、Target で始まるコードはターゲット側の理由です。

ヘルスステータス主な理由コード見るところ
initialElb.RegistrationInProgress / Elb.InitialHealthChecking登録直後。最初のヘルスチェックに 1 回合格すれば healthy になる
unhealthyTarget.ResponseCodeMismatch(ALB)アプリが成功コード以外(404・500 など)を返している。パスと成功コードの設定も確認
unhealthyTarget.Timeout(ALB)応答がタイムアウトした。ターゲットのセキュリティグループ、アプリの応答時間
unhealthyTarget.FailedHealthChecksヘルスチェックに失敗した。NLB ではこのコードにまとまる
unusedTarget.NotInUse / Target.NotRegistered / Target.InvalidStateリスナーから使われていない、未登録、インスタンスが停止している
クラウドおさる

ターゲットがすべて unhealthy になると、ロードバランサーは「フェイルオープン」して、全部のターゲットにリクエストを送るのでござる。全部倒れたから全部止まる、とはならぬので、ヘルスチェックの設定ミスで全滅していないかも気にしておくでござるぞ。

ヘルスチェックの通信は、ターゲットのセキュリティグループで許可しておく必要があります。ALB・NLB ともに、ロードバランサーのセキュリティグループをターゲット側のインバウンドルールの送信元に指定するのが確実です。NLB はセキュリティグループを付けずに作成すると後から関連付けられない点(作成時に付けておけば、あとで入れ替えられます)と、ヘルスチェックには NLB のアウトバウンドルールが適用される点に注意します。

新卒・未経験の方へ
クラウドおさる

AWS を仕事にしたい方へ ── 新卒・未経験から

この記事を書いているのは、AWS の設計・構築を仕事にしている現役エンジニアです。運営元の株式会社ジェニュインでは、新卒・未経験の方も募集しています。異業種や文系からインフラエンジニアになり活躍しているメンバーもいます。

  • ✓システム開発・WEB エンジニア / インフラ構築などの職種で、未経験から応募できます
  • ✓未経験から入社した社員の声を含む社員アンケートを掲載
  • ✓応募フォームから 1 分で応募できます

実践

ハンズオンガイド8 ステップ画面 7 枚

コンソールの横に開いて、チェックしながら進めましょう。

ガイドを開く

別タブで開きます。チェックはこのブラウザに保存されます。

同じ 2 台の EC2(soa-hc-web-a / soa-hc-web-b)を、ALB 用と NLB 用のターゲットグループに登録します。どちらの EC2 も /health.html で ok を返します。途中で soa-hc-web-b の /health.html だけを消し、アプリの一部が壊れた状態を作ったときに、ALB(HTTP ヘルスチェック)と NLB(TCP ヘルスチェック)の判定がどう変わるかを比べます。

前提条件

  • リージョン: ap-northeast-1(東京)
  • 以下のリソースが作成済みであること

まだ用意していない場合は、「作り方の参考」の記事の手順で作れます。リソース名は、この記事の名前に読み替えてください。

リソース種別リソース名内容作り方の参考
EC2 インスタンスsoa-hc-web-a(ap-northeast-1a)Apache で / に web-a、/health.html に ok を返すAmazon EC2 でインスタンスを起動しSSH接続する
EC2 インスタンスsoa-hc-web-b(ap-northeast-1c)同上(/ は web-b)同上
IAM ロールsoa-hc-ec2-role2 台の EC2 に付与。AmazonSSMManagedInstanceCore をアタッチ(Run Command 用)AWS IAM でユーザー・ロール・ポリシーを作成しアクセス制御する
セキュリティグループsoa-hc-web-sgEC2 用。TCP 80 を soa-hc-alb-sg と soa-hc-nlb-sg から許可
Application Load Balancersoa-hc-albインターネット向け、ap-northeast-1a / 1c、soa-hc-alb-sg(HTTP 80 を許可)。リスナーはまだ無い
Network Load Balancersoa-hc-nlbインターネット向け、ap-northeast-1a / 1c、soa-hc-nlb-sg(TCP 80 を許可)。リスナーはまだ無い

作成するリソース一覧

リソース種別リソース名用途
ターゲットグループsoa-hc-alb-tgALB 用。HTTP で /health.html を確認する
ターゲットグループsoa-hc-nlb-tgNLB 用。TCP の接続を確認する(後で HTTP に変える)
リスナーsoa-hc-alb の HTTP:80soa-hc-alb-tg へ転送
リスナーsoa-hc-nlb の TCP:80soa-hc-nlb-tg へ転送

手順 1: ALB 用のターゲットグループを作る

AWS マネジメントコンソールにログインし、リージョンが ap-northeast-1(東京)であることを確認します。上部の検索バーに EC2 と入力し、「EC2」を選択します。

左側ナビゲーションの「ロードバランシング」→「ターゲットグループ」を選択し、「ターゲットグループの作成」をクリックします。以下を設定します。

  • ターゲットタイプの選択: 「インスタンス」
  • ターゲットグループ名: soa-hc-alb-tg
  • プロトコル : ポート: HTTP : 80
  • VPC: soa-lab-vpc
  • ヘルスチェックプロトコル: HTTP
  • ヘルスチェックパス: /health.html

「ヘルスチェックの詳細設定」を開き、確認が早く進むように以下へ変更します。

  • 正常のしきい値: 2
  • 非正常のしきい値: 2
  • タイムアウト: 5
  • 間隔: 10
  • 成功コード: 200

その他の項目はデフォルトのままにします。

soa-hc-alb-tg のヘルスチェック設定(プロトコル HTTP・パス /health.html・しきい値・間隔・成功コード)
soa-hc-alb-tg のヘルスチェック設定(プロトコル HTTP・パス /health.html・しきい値・間隔・成功コード)

「次へ」をクリックし、「ターゲットを登録」で soa-hc-web-a と soa-hc-web-b にチェックを入れ、「保留中として以下を含める」をクリックします。「ターゲットグループの作成」をクリックします。

手順 2: ALB にリスナーを追加する

左側ナビゲーションの「ロードバランサー」を選択し、soa-hc-alb を開きます。「リスナーとルール」タブで「リスナーの追加」をクリックし、以下を設定して「追加」をクリックします。

  • プロトコル: HTTP、ポート: 80
  • デフォルトアクション: 「ターゲットグループへ転送」→ soa-hc-alb-tg

リスナーから参照されたことで、soa-hc-alb-tg のヘルスチェックが始まります。ターゲットグループ soa-hc-alb-tg の「ターゲット」タブを開き、しばらく待って(画面右上の更新ボタンで再読み込み)2 台とも「ヘルスステータス」が Healthy になったことを確認します。

soa-hc-alb-tg のターゲットタブ(soa-hc-web-a / soa-hc-web-b が Healthy)
soa-hc-alb-tg のターゲットタブ(soa-hc-web-a / soa-hc-web-b が Healthy)

手順 3: NLB 用のターゲットグループとリスナーを作る

「ターゲットグループ」に戻り、「ターゲットグループの作成」をクリックします。以下を設定します。

  • ターゲットタイプの選択: 「インスタンス」
  • ターゲットグループ名: soa-hc-nlb-tg
  • プロトコル : ポート: TCP : 80(ポートは自動では入らないので入力します)
  • VPC: soa-lab-vpc
  • ヘルスチェックプロトコル: TCP(プロトコルを TCP にしても、ここは HTTP のまま残ることがあるので選び直します)

「ヘルスチェックの詳細設定」を開き、以下へ変更します。TCP では、パスと成功コードの項目がありません。タイムアウトは既定の 10 秒のままにします。

  • 正常のしきい値: 2
  • 非正常のしきい値: 2
  • 間隔: 10
soa-hc-nlb-tg のヘルスチェック設定(プロトコル TCP。パスと成功コードの項目が無い)
soa-hc-nlb-tg のヘルスチェック設定(プロトコル TCP。パスと成功コードの項目が無い)

「次へ」をクリックし、手順 1 と同じく 2 台を登録して「ターゲットグループの作成」をクリックします。

「ロードバランサー」から soa-hc-nlb を開き、「リスナー」タブで「リスナーの追加」をクリックします。プロトコル TCP、ポート 80、デフォルトアクションの転送先に soa-hc-nlb-tg を選んで「追加」をクリックします。soa-hc-nlb-tg の「ターゲット」タブで、2 台とも Healthy になるまで待ちます。

手順 4: web-b のヘルスチェック用ページを消す

soa-hc-web-b のアプリの一部が壊れた状態を作ります。上部のツールバーの CloudShell アイコンをクリックして AWS CloudShell を開き、次のコマンドで Run Command を実行します。soa-hc-web-b の /health.html だけが消え、/(トップページ)と Apache のプロセスはそのまま動き続けます。

aws ssm send-command \
  --document-name AWS-RunShellScript \
  --targets Key=tag:Name,Values=soa-hc-web-b \
  --parameters 'commands=["rm -f /var/www/html/health.html"]' \
  --query Command.CommandId --output text

手順 5: ALB と NLB の判定を比べる

20〜30 秒ほど待ってから、soa-hc-alb-tg の「ターゲット」タブを再読み込みします。soa-hc-web-b の「ヘルスステータス」が Unhealthy になり、「ヘルスステータスの詳細」に Health checks failed with these codes: [404] のように、成功コード(200)以外が返ったことが表示されます。

soa-hc-alb-tg のターゲットタブ(soa-hc-web-b が Unhealthy・詳細に 404)
soa-hc-alb-tg のターゲットタブ(soa-hc-web-b が Unhealthy・詳細に 404)

次に soa-hc-nlb-tg の「ターゲット」タブを開きます。こちらは 2 台とも Healthy のままです。TCP ヘルスチェックはポート 80 に接続できるかだけを見ているので、/health.html が 404 を返していることには気づきません。

soa-hc-nlb-tg のターゲットタブ(2 台とも Healthy のまま)
soa-hc-nlb-tg のターゲットタブ(2 台とも Healthy のまま)

CloudShell で理由コードも確認しておきます。<ALB 用ターゲットグループの ARN> は、soa-hc-alb-tg の詳細に表示される ARN に置き換えます。

aws elbv2 describe-target-health \
  --target-group-arn <ALB 用ターゲットグループの ARN> \
  --query 'TargetHealthDescriptions[].[Target.Id,TargetHealth.State,TargetHealth.Reason]' \
  --output table

soa-hc-web-b のインスタンス ID の行に unhealthy と Target.ResponseCodeMismatch が表示されます。コンソールの表には詳細の文だけが出て、この理由コードは出ません。

CloudShell の describe-target-health の結果(Target.ResponseCodeMismatch)
CloudShell の describe-target-health の結果(Target.ResponseCodeMismatch)
クラウドおさる

戸を叩けば返事はあるので、NLB の当番は「元気でござる」と帳面に書いてしまうのでござるな。中身まで確かめる当番でないと、このずれは見つからぬのでござる。

手順 6: NLB のヘルスチェックを HTTP に変える

soa-hc-nlb-tg の「ヘルスチェック」タブで「編集」をクリックし、以下に変更して「変更内容の保存」をクリックします。

  • ヘルスチェックプロトコル: HTTP
  • ヘルスチェックパス: /health.html
  • 「ヘルスチェックの詳細設定」を開き、成功コード: 200

成功コードは空のままだと「ヘルスチェック http コードマッチャーを空にすることはできません。」と表示されて保存できないので、必ず入力します。

soa-hc-nlb-tg のヘルスチェックの編集画面(プロトコル HTTP・パス /health.html・成功コード 200)
soa-hc-nlb-tg のヘルスチェックの編集画面(プロトコル HTTP・パス /health.html・成功コード 200)

ヘルスチェックの設定を変えると、ターゲットはいったん initial(初期のヘルスチェック中)に戻ります。3 分ほど待って「ターゲット」タブを再読み込みすると、NLB でも soa-hc-web-b が Unhealthy になります。NLB の理由は Target.FailedHealthChecks(ヘルスチェックに失敗)としてまとめて表示されます。

クラウドおさる

Web 層は ALB でパスと成功コード、大量のリクエストを低遅延でさばく層は NLB。どの層に何を使い、ヘルスチェックで何を確かめるかを組み合わせで問われると、TCP が使えるのはどちらかで迷いやすいのでござる。

まとめ

比べるところALBNLB
ヘルスチェックのプロトコルHTTP / HTTPS(TCP は無い)TCP(既定)/ HTTP / HTTPS
「正常」の判定パスへのリクエストのステータスコードが成功コードに入るかTCP は接続できるか。HTTP / HTTPS ならステータスコード
成功コード200〜499 から指定(既定 200)200〜599 から指定(既定 200-399)
unhealthy の理由Target.ResponseCodeMismatch / Target.Timeout などTarget.FailedHealthChecks
  • ヘルスチェックはターゲットグループに設定する。リスナーから使われていないターゲットグループはチェックされない(unused)
  • 非正常のしきい値の回数だけ続けて失敗すると unhealthy、正常のしきい値の回数だけ続けて合格すると healthy に戻る
  • NLB の TCP ヘルスチェックはポートが開いていれば合格する。アプリの異常まで検知したいなら HTTP / HTTPS にしてパスを指定する
  • 全ターゲットが unhealthy になるとフェイルオープンし、全ターゲットにトラフィックを送る
  • ターゲットのセキュリティグループは、ロードバランサーのセキュリティグループからのヘルスチェックを許可する

参照先

キャリア相談
クラウドおさる

独学の先に、AWS の仕事がある ── ジュニアおさるのキャリア相談

CLF には受かったけれど、次に何をすればいいのか分からない。独学で AWS を学ぶジュニアおさるの相談に、株式会社ジェニュイン代表の土肥が答えています。

  • ✓資格はゴールか、CLF の次に何から手を付けるか
  • ✓EC2 の次に作ってみる構成と、IaC・コスト管理
  • ✓実務経験ゼロでも、面接で話せる「これまで」の作り方
新卒・未経験の方へ
クラウドおさる

AWS を仕事にしたい方へ ── 新卒・未経験から

この記事を書いているのは、AWS の設計・構築を仕事にしている現役エンジニアです。運営元の株式会社ジェニュインでは、新卒・未経験の方も募集しています。異業種や文系からインフラエンジニアになり活躍しているメンバーもいます。

  • ✓システム開発・WEB エンジニア / インフラ構築などの職種で、未経験から応募できます
  • ✓未経験から入社した社員の声を含む社員アンケートを掲載
  • ✓応募フォームから 1 分で応募できます

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

株式会社ジェニュイン(https://genuine-pt.jp)の代表取締役.

2018年〜インフラエンジニアとしてキャリアをスタートし、オンプレミスのネットワーク・サーバ環境で3年半、クラウド環境で4年半の8年間エンジニアとして従事。
2021年に佐藤氏の創業した株式会社Luxyを引き継ぎ、代表に就任。
その後アガルートグループ内の株式会社ジェニュインと合併。
合併後同社代表に就任。

目次