AWSの3種類のLBの比較と使い分け (ALB, NLB, CLB)

AWSのELB(Elastic Load Balancing)にある3つのLBの使い分けについてまとめました。

- ALB (Application Load Balancer)
- NLB (Network Load Balancer)
- CLB (Classic Load Balancer)

CLBが最初(2009年)にリリースされたELBで、当時はCLBという名称はなくELBといえばいまのCLBでした。2016年と2017年にALBとNLBがリリースされました。後発のALBとNLBのほうがCLBよりも高機能で高性能です。


# 3つのLBの選択方法

CLBの機能のほとんどはALBとNLBでカバーされていますので、基本的には後発のALB, NLBの2つを使い分けます。CLBでしか実現できない要件がどうしても外せない場合にのみCLBを使います。CLBだけの機能はわずかです。

以下は、要件に応じてどれを使うべきかの大雑把な基準です。

- EC2-Classicの環境
    - → **CLB**
- EC2-Classicの環境ではない
    - プロトコルはHTTP(S)以外のTCPまたはUDP
        - → **NLB**
    - プロトコルはHTTP(S)
        - 以下の要件に該当しなければHTTP(S)向けに特化した **ALB** が無難
        - 以下の複数の要件で違うLBが選択されてしまう場合はいずれかの要件をあきらめる
        - 要件
            - アプリが生成するCookieでSticky Sessionsを使用したい
                - → **CLB** (アプリサーバに状態をもたせるのは本来はよくない)
            - SSLはカスタムセキュリティポリシーが必要
                - → **CLB**
            - URLやリクエストヘッダなどでターゲットを切り替えたい
                - → **ALB**
            - リクエスト元IPでターゲットを切り替えたい
                - → **ALB**
            - ターゲットはLambdaも使いたい
                - → **ALB**
            - HTTP(S)のリクエストログを取りたい
                - → **ALB**
            - リダイレクトや固定レスポンスをLBだけで処理したい
                - → **ALB**
            - 事前の予告なき負荷のスパイク（負荷急増）に耐えられる必要がある
                - → **NLB** (事前にわかっていればALBでも暖機運転をすればよい)
            - LBのIPを固定したい
                - → **NLB**
            - リクエスト元IPをLBに書き換えないでほしい
                - → **NLB** (ALBでもX-Forwarded-Forヘッダを見ればよい)
            - 2AZでの運用でAZ障害時に障害AZを切り離し正常な1AZのみでも運用できるようにしたい
                - → **NLB** (ALBでも3AZ構成にすればAZ障害時に2AZにできる)


# 比較軸別の特徴整理

## プロトコル

- ALB: HTTP(S)
- NLB: TCP, UDP
- CLB: HTTP(S), TCP

## ルーティングアルゴリズム

- ALB: ラウンドロビンまたは The least outstanding requests routing algorithm
- NLB: フローハッシュアルゴリズム
- CLB
    - HTTP(S): The least outstanding requests routing algorithm
    - TCP: ラウンドロビン

## ターゲットの指定方法

- ALB: インスタンスID、IPアドレス、Lambda関数
- NLB: インスタンスID、IPアドレス
- CLB: インスタンスID

## 同一インスタンスの複数ポートへの分散

- ALB: 可
- NLB: 可
- CLB: 不可

## Sticky Sessionsの機能

- ALB: LBが生成するCookieで可能
- NLB: 不可
- CLB: LBが生成するCookie、またはアプリが生成するCookieで可能

## 負荷のスパイク

- ALB: 暖気運転が必要
- NLB: 問題なし
- CLB: 暖気運転が必要

## マルチAZ

- ALB: 2AZ以上必要（AZ障害時でも臨時に1AZとするのは不可）
- NLB: 1AZまたは複数AZが可能
- CLB: 1AZまたは複数AZが可能

## ターゲットの柔軟な設定

- ALB: URL、リクエストヘッダー、リクエスト元IPでターゲットグループを切り替えられる
- NLB: ALBのような柔軟な設定は不可
- CLB: ALBのような柔軟な設定は不可

## ターゲットから見たリクエスト元

- ALB: LBのIPからパケットが来る。リクエスト元はHTTP(S)ではX-Forwarded-Forヘッダに書かれる
- NLB: リクエスト元から直接パケットが来ているように見える。
- CLB: LBのIPからパケットが来る。リクエスト元はHTTP(S)ではX-Forwarded-Forヘッダに書かれる

## LBのIP

- ALB: IP固定できない
- NLB: IP固定できる
- CLB: IP固定できない

# LB別の特徴整理

## ALB

- L7(HTTP(S))で動作する
- 対応プロトコル
    - HTTP(S)
- クロスゾーン負荷分散はデフォルトで有効 (CLBと同様)
- 同一インスタンスの複数ポートへの分散も可能 (NLBと同様)
- マネジメントコンソールでは「ターゲットグループ」のメニューでターゲットを設定 (NLBと同様)
- ルーティングアルゴリズムはラウンドロビンまたは The least outstanding requests routing algorithm
    - https://aws.amazon.com/jp/about-aws/whats-new/2019/11/application-load-balancer-now-supports-least-outstanding-requests-algorithm-for-load-balancing-requests/
- 負荷のスパイク（負荷急増）は自動スケーリングが間に合わず503を返す可能性がある (CLBと同様)
    - 対策は暖機運転の申請または自前で負荷を段階的に上昇させること
- 2AZ以上で設定することが必須
    - 2AZ構成から1つAZをマニュアルで切り離すことができない
    - AZ障害時の運用に問題があるので3AZ構成が望ましい (2019年8月23日の障害の事例参照)
- ターゲットの指定方法
    - インスタンスID
    - IPアドレス
    - Lambda関数
- ターゲットグループを選択するルールを設定できる
    - URLのパス
    - URLのホスト
    - クエリ文字列
    - HTTPヘッダ
        - User-Agent など
    - HTTPメソッド
    - リクエスト元IPアドレス(CIDR)
- アクション
    - ターゲットグループにリクエストを転送
    - リダイレクト
    - 固定レスポンス
    - Cognito認証
    - OpenID Connectによる認証
- Sticky Sessionsの機能あり
    - 対応Cookie
        - LBが生成するCookie
        - アプリが生成するCookieは不可
- ターゲットから見たときのIPアドレスはLBのIPになってしまう (CLBと同様)
    - HTTP(S)ではX-Forwarded-Forヘッダにリクエスト元IPが書かれる
- HTTP(S)リクエストのログを取れる (CLBと同様)
- IPは固定できない (CLBと同様)
- EC2-Classicの環境に非対応 (NLBと同様)

## NLB

- L4(TCP, UDP)で動作する
- 対応プロトコル
    - TCP
    - TLS
    - UDP
    - TCP_UDP
- セキュリティグループの設定ができない
- クロスゾーン負荷分散はデフォルトで無効
- 同一インスタンスの複数ポートへの分散も可能 (ALBと同様)
- AZ冗長化をしない1AZでの設定も可能 (CLBと同様)
- マネジメントコンソールでは「ターゲットグループ」のメニューでターゲットを設定 (ALBと同様)
- ルーティングアルゴリズムはフローハッシュアルゴリズム
- 暖機運転不要で負荷のスパイク（負荷急増）にも耐えられる
- ターゲットの指定方法
    - インスタンスID
    - IPアドレス
- IPをAZごとに固定できる
- 送信元IPとポート番号を保持
    - ターゲットから見たらクライアントと直接通信しているように見える
    - しかしDSR(Direct Serve Return)ではない（仕組みは不明）
    - ターゲットをIPで指定した場合やPrivateLinkの場合はNLBとの通信になる
- HTTP(S)リクエストとしてのログは取れない
- EC2-Classicの環境に非対応 (ALBと同様)

## CLB

- L4(TCP)またはL7(HTTP(S))で動作する
- 対応プロトコル
    - HTTP(S)
    - TCP
    - SSL
- クロスゾーン負荷分散はデフォルトで有効 (ALBと同様)
- 同一インスタンスの複数ポートへの分散は不可
- AZ冗長化をしない1AZでの設定も可能 (NLBと同様)
- マネジメントコンソールでは「ロードバランサー」のメニューでターゲットを設定
- ルーティングアルゴリズムはTCPはラウンドロビン、HTTP(S)は The least outstanding requests routing algorithm
- 負荷のスパイク（負荷急増）は自動スケーリングが間に合わず503を返す可能性がある (ALBと同様)
    - 対策は暖機運転の申請または自前で負荷を段階的に上昇させること
- ターゲットの指定方法
    - インスタンスID
- Sticky Sessionsの機能あり
    - 対応Cookie
        - LBが生成するCookie
        - アプリが生成するCookie
- ターゲットから見たときのIPアドレスはLBのIPになってしまう (ALBと同様)
    - HTTP(S)ではX-Forwarded-Forヘッダにリクエスト元IPが書かれる
- IPは固定できない (ALBと同様)
- HTTP(S)リクエストのログを取れる (ALBと同様)
- EC2-Classicの環境に対応
- CLBが必要なケースはほとんどなく、ALBまたはNLBでよい
    - CLBが必要なケース
        - EC2-Classic
        - アプリが生成するCookieでSticky Sessionsを使用したい
        - カスタムセキュリティポリシー
    - CLBはALB、NLBに比べてコストが高い

# 3つのLBで共通の特徴（注意点）

- 2段階の負荷分散
    - LB自体が複数
    - ターゲットが複数
- クロスゾーン負荷分散を無効にして、AZ間でターゲット数が異なると、ターゲットの負荷が偏ってしまう