AWS学びなおし(+TF)_ELB
AWSのELB(Elastic Load Balancing)は、受信トラフィックを複数のターゲット(EC2インスタンス、コンテナ、IPアドレス、Lambda関数など)に分散するサービスです。これにより、アプリケーションの可用性とスケーラビリティを向上させることができます。ELBは、単一障害点を排除し、トラフィックの急増に対応するために不可欠なコンポーネントです。
ELBには主に以下の4つのタイプがあります。
1. Classic Load Balancer (CLB)
- 特徴: 最も古いタイプのロードバランサー。HTTP、HTTPS、TCPプロトコルをサポートします。レイヤー4(トランスポート層)またはレイヤー7(アプリケーション層)で動作します。
- ルーティング: 基本的なラウンドロビンまたは最少接続ルーティング。高度なルーティング機能は限定的です。
- ユースケース: シンプルな負荷分散、HTTP/HTTPSアプリケーション、TCPベースのアプリケーション。
- 注意点: 機能が限定的で、後述のALBやNLBに比べて柔軟性に欠けます。新規構築には推奨されません。
2. Application Load Balancer (ALB)
- 特徴: レイヤー7(アプリケーション層)に特化したロードバランサー。HTTP/HTTPSプロトコルに最適化されています。高度なリクエストルーティング機能を提供します。
- ルーティング: コンテンツベースルーティング(パス、ホストヘッダー)、リダイレクト、固定レスポンスなど、柔軟なルーティングルールを設定可能。
- ユースケース: ウェブアプリケーション、マイクロサービスアーキテクチャ、コンテナ化されたアプリケーション。
- メリット: 高度なルーティング、WebSocketサポート、HTTP/2サポート、コンテナ化されたアプリケーションとの統合(ターゲットグループにIPアドレスを指定可能)。
- 注意点: TCP/UDPトラフィックの負荷分散には不向き。レイヤー4の機能は限定的。
3. Network Load Balancer (NLB)
- 特徴: レイヤー4(トランスポート層)に特化したロードバランサー。TCP、UDP、TLSプロトコルをサポートします。非常に高いパフォーマンスと低遅延を実現します。
- ルーティング: 静的IPアドレスを保持し、送信元IPアドレスに基づいてターゲットグループを選択するフローハッシュルーティング。
- ユースケース: TCP/UDPベースのアプリケーション、高パフォーマンスが必要なアプリケーション(ゲームサーバー、ストリーミングサービス)、TLS終端処理。
- メリット: 非常に高いスループットと低遅延、静的IPアドレス、ゾーン障害からの分離。
- 注意点: レイヤー7の機能は提供されない。コンテンツベースルーティングは不可。
4. Gateway Load Balancer (GWLB)
- 特徴: 仮想アプライアンス(ファイアウォール、侵入検知システムなど)のデプロイとスケーリングを容易にするロードバランサー。レイヤー3(ネットワーク層)で動作します。
- ルーティング: GENEVEプロトコルを使用してトラフィックを仮想アプライアンスにルーティングし、同一のアプライアンスにトラフィックを戻すスティッキーセッションを維持。
- ユースケース: ネットワーク仮想アプライアンスの統合、セキュリティインスペクション、ディープパケットインスペクション。
- メリット: 仮想アプライアンスのスケーラビリティと可用性の向上、透過的なトラフィックインスペクション。
- 注意点: 仮想アプライアンスとの連携が前提。ウェブアプリケーションの直接的な負荷分散には不向き。
ELB共通のメリット:
- 高可用性: 複数のアベイラビリティーゾーンに分散配置可能で、単一障害点を排除。
- スケーラビリティ: トラフィックの増減に応じて自動的にスケールアップ/ダウン。
- ヘルスチェック: ターゲットのヘルス状態を監視し、異常なターゲットへのトラフィックを自動的に停止。
- SSL/TLS終端: SSL/TLS証明書をELBで管理し、バックエンドサーバーの負荷を軽減。
- モニタリング: CloudWatchメトリクスを通じてパフォーマンスを監視可能。
【実務レベルの内容と重要事項】
1. セキュリティグループ:
- ELB自身とターゲットグループに適切なセキュリティグループを設定することが重要です。
- ELBのセキュリティグループは、クライアントからのアクセスを許可するポート(80, 443など)をインバウンドルールで許可します。
- ターゲットグループのセキュリティグループは、ELBからのアクセスを許可するポートと、必要に応じて他のリソースからのアクセスを許可します。
- 不要なポートは閉じ、最小限の許可設定にすることがセキュリティの基本です。
2. VPC設定:
- ELBはVPC内で動作します。パブリックサブネットに配置してインターネットからのアクセスを受け付けるか、プライベートサブネットに配置して内部トラフィックを処理するかを選択します。
- ALBやNLBは、複数のアベイラビリティーゾーンにまたがるサブネットに配置することで、ゾーン障害に対する耐性を高めることができます。
- サブネットのCIDRブロック設計、ルーティングテーブル設定もELBの動作に影響を与えるため、VPC全体の設計を考慮する必要があります。
3. ヘルスチェック:
- ヘルスチェックはELBの重要な機能です。ターゲットが正常にリクエストを処理できる状態にあるかを定期的に確認します。
- ヘルスチェックの設定(プロトコル、ポート、パス、タイムアウト、間隔、正常/異常の閾値)を適切に設定することが重要です。
- アプリケーションの状態を正確に反映するヘルスチェックエンドポイントを実装することが推奨されます。(例:
/health
エンドポイントでアプリケーションの状態を返す) - ヘルスチェックが失敗した場合の対処方法(自動復旧、アラート通知など)も事前に検討しておく必要があります。
4. スティッキーセッション(セッションパーシステンス):
- ALBとCLBは、スティッキーセッション(セッションパーシステンス)をサポートしています。特定のクライアントからのリクエストを常に同じターゲットにルーティングする機能です。
- CookieベースまたはIPアドレスベースのスティッキーセッションを選択できます。
- ステートフルなアプリケーションや、セッション情報をキャッシュしているアプリケーションで有効です。
- ただし、スティッキーセッションに依存しすぎると、ターゲットの負荷分散が偏る可能性があるため、注意が必要です。
5. クロスゾーンロードバランシング:
- ALBとNLBは、クロスゾーンロードバランシングをサポートしています。ロードバランサーが全てのアベイラビリティーゾーンのターゲットにトラフィックを均等に分散する機能です。
- デフォルトで有効になっていますが、無効にすることも可能です。
- 高可用性を最大限に高めるためには、クロスゾーンロードバランシングを有効にしておくことが推奨されます。
6. アクセスログ:
- ELBのアクセスログを有効にすることで、トラフィックの状況を詳細に把握できます。
- アクセスログはS3バケットに出力されます。
- ログ分析ツール(Athena、QuickSightなど)と連携することで、トラフィックの傾向分析、異常検知、セキュリティ監査などに活用できます。
- ログの保存期間、暗号化設定なども検討する必要があります。
7. WAF (Web Application Firewall) 連携:
- ALBはAWS WAFと連携できます。WAFをALBの前段に配置することで、SQLインジェクション、クロスサイトスクリプティングなどのウェブ攻撃からアプリケーションを保護できます。
- WAFルールを適切に設定し、誤検知を減らすためのチューニングも重要です。
8. 運用・監視:
- CloudWatchメトリクスを定期的に監視し、ELBのパフォーマンス(レイテンシ、リクエスト数、エラー率など)を把握します。
- CloudWatchアラームを設定し、異常値を検知した場合に通知を受け取れるようにします。
- アクセスログを分析し、トラフィックの傾向や異常なアクセスパターンを把握します。
- 定期的な負荷テストを実施し、ELBの性能限界やボトルネックを把握します。
9. パフォーマンスチューニング:
- ターゲットグループのインスタンスタイプ、Auto Scaling設定を適切に設定することで、ELB全体のパフォーマンスを向上させることができます。
- コネクションタイムアウト、アイドルタイムアウトなどの設定をアプリケーションの特性に合わせて調整します。
- HTTP/2、Keep-Aliveなどのプロトコル機能を有効にすることで、パフォーマンスを改善できる場合があります。
10. トラブルシューティング:
- ELBが正常に動作しない場合、CloudWatchメトリクス、アクセスログ、ヘルスチェックログなどを確認し、原因を特定します。
- セキュリティグループ、VPC設定、ルーティングテーブル設定などを再確認します。
- AWSのドキュメントやサポートフォーラムなどを参照し、解決策を探します。
【実務でどの程度使用されるのか】
ELBは、実務において非常に高い頻度で使用されるAWSの基本サービスの一つです。ウェブアプリケーション、APIサーバー、マイクロサービスアーキテクチャなど、インターネットに公開するシステムや、内部システムにおいても、可用性とスケーラビリティを確保するためにELBは不可欠な存在です。
- ほぼ全てのウェブアプリケーション: ウェブアプリケーションは、通常、ALBまたはCLBのいずれかを使用して負荷分散と高可用性を実現します。特にALBは、高度なルーティング機能とWAF連携により、ウェブアプリケーションに最適なロードバランサーとして広く利用されています。
- マイクロサービスアーキテクチャ: マイクロサービスアーキテクチャでは、多数のサービスが連携するため、サービス間のトラフィック分散、サービスディスカバリー、ルーティングにELBが活用されます。ALBのパスベースルーティングやホストベースルーティングは、マイクロサービス環境でのルーティングに非常に有効です。
- コンテナ化されたアプリケーション: ECS (Elastic Container Service) や EKS (Elastic Kubernetes Service) などのコンテナオーケストレーションサービスとELBは、非常に相性が良く、コンテナ化されたアプリケーションの負荷分散とスケーリングに広く利用されています。ALBは、コンテナのポートマッピングを自動的に検出し、ターゲットグループに登録する機能を提供します。
- 高トラフィックアプリケーション: NLBは、非常に高いスループットと低遅延が求められるアプリケーション(ゲームサーバー、ストリーミングサービス、広告配信システムなど)で利用されます。TCP/UDPベースのアプリケーションや、静的IPアドレスが必要な場合にもNLBが選択されます。
- セキュリティ要件の高いシステム: GWLBは、ファイアウォール、IDS/IPSなどの仮想アプライアンスを透過的に挿入し、トラフィックを検査する必要があるシステムで利用されます。セキュリティ要件の高いエンタープライズ環境や、コンプライアンス要件のあるシステムで採用されるケースが増えています。
代替技術との比較:
ELB以外にも、ロードバランシングを実現する技術は存在します。例えば、Nginx、HAProxyなどのソフトウェアロードバランサーや、Kubernetes Ingress Controllerなどがあります。
- Nginx/HAProxy: 柔軟性が高く、詳細な設定が可能ですが、自身で構築・運用・管理する必要があります。ELBと比較して運用負荷が高くなる場合があります。
- Kubernetes Ingress Controller: Kubernetes環境に特化したロードバランサー。Kubernetesのリソースとして管理でき、設定が容易ですが、Kubernetes環境外での利用はできません。
ELBは、AWSがマネージドサービスとして提供するため、運用・管理の負荷が低く、高可用性とスケーラビリティが保証されています。そのため、多くの企業やプロジェクトで、ロードバランサーの第一選択肢としてELBが採用されています。特に、AWS環境に特化している点、他のAWSサービスとの連携が容易な点も、ELBが広く利用される理由の一つです。
【terraformのコードで記述する場合の基本的内容と実務レベルの内容】
terraformのコードで記述する場合の基本的内容:
terraformでELBを記述する場合、主に以下のリソースを使用します。
-
aws_lb
: ロードバランサー本体を定義します。タイプ(application, network, gateway)、サブネット、セキュリティグループなどを設定します。 -
aws_lb_listener
: リスナーを定義します。ポート、プロトコル、デフォルトアクション(ターゲットグループへの転送など)を設定します。 -
aws_lb_target_group
: ターゲットグループを定義します。ターゲットタイプ(instance, ip, lambda)、ヘルスチェック設定などを設定します。 -
aws_lb_listener_rule
: ALBの場合、リスナールールを定義します。条件(パス、ホストヘッダーなど)、アクション(ターゲットグループへの転送、リダイレクトなど)を設定します。 -
aws_lb_target_group_attachment
: ターゲットグループにターゲット(EC2インスタンスなど)を登録します。
基本的なALBのterraformコード例:
resource "aws_lb" "alb" {
name = "example-alb"
internal = false # パブリックロードバランサー
load_balancer_type = "application"
subnets = [aws_subnet.public_subnet_1.id, aws_subnet.public_subnet_2.id]
security_groups = [aws_security_group.alb_sg.id]
}
resource "aws_lb_listener" "alb_listener" {
load_balancer_arn = aws_lb.alb.arn
port = 80
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.alb_tg.arn
}
}
resource "aws_lb_target_group" "alb_tg" {
name = "example-alb-tg"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.main.id
health_check {
path = "/health"
protocol = "HTTP"
matcher = "200"
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 5
interval = 10
}
}
resource "aws_lb_target_group_attachment" "alb_tg_attachment_1" {
target_group_arn = aws_lb_target_group.alb_tg.arn
target_id = aws_instance.example_instance_1.id
port = 80
}
resource "aws_lb_target_group_attachment" "alb_tg_attachment_2" {
target_group_arn = aws_lb_target_group.alb_tg.arn
target_id = aws_instance.example_instance_2.id
port = 80
}
実務レベルのterraformコードと重要事項:
実務レベルでは、上記の基本的なコードに加えて、以下の点を考慮する必要があります。
-
モジュール化: ELBの設定をモジュール化することで、コードの再利用性と可読性を高めます。例えば、ELBモジュールを作成し、VPC、サブネット、セキュリティグループなどの情報を変数として受け取るようにします。
-
変数化: ハードコードされた値を避け、変数を積極的に使用します。環境変数やterraform.tfvarsファイルなどを活用し、環境ごとに異なる設定を柔軟に適用できるようにします。
-
backend設定: terraform stateをリモートbackend(S3、Terraform Cloudなど)で管理することで、複数人での共同作業やstateの安全な管理を実現します。stateのロック機能も有効にすることが推奨されます。
-
provider設定: AWSプロバイダーのバージョンを明示的に指定し、terraform apply時の予期せぬ挙動を防ぎます。
-
タグ付け: 全てのリソースに適切なタグを付与することで、リソースの管理、コスト分析、監査を容易にします。
-
条件付きリソース:
count
やfor_each
を使用して、条件によってリソースの作成有無を制御したり、複数のリソースをまとめて作成したりします。 -
データソース: 既存のリソース(VPC、サブネット、セキュリティグループなど)を参照する場合、データソース (
data "aws_vpc" "example" {}
) を使用することで、情報を動的に取得できます。 -
IAMロール: terraformがAWSリソースを操作するためのIAMロールを適切に設定します。最小権限の原則に従い、必要な権限のみを付与します。
-
依存関係:
depends_on
を使用して、リソース間の依存関係を明示的に記述することで、リソース作成順序を制御し、エラーを回避します。 -
import機能: 既にAWS上に存在するELBをterraform管理下に置く場合、
terraform import
コマンドを使用します。
実務レベルのALBのterraformコード例(一部抜粋、モジュール化、変数化、タグ付けを考慮):
module "alb" {
source = "./modules/alb" # モジュールへのパス
name = var.alb_name
subnets = var.public_subnet_ids
security_groups = [module.security_group.alb_sg_id] # セキュリティグループモジュールからの出力
target_group_port = 80
target_group_protocol = "HTTP"
health_check_path = "/health"
instance_ids = var.instance_ids
tags = {
Environment = var.environment
Project = var.project_name
ManagedBy = "Terraform"
}
}
# modules/alb/main.tf (モジュールの中身の例)
resource "aws_lb" "alb" {
name = var.name
internal = false
load_balancer_type = "application"
subnets = var.subnets
security_groups = var.security_groups
tags = var.tags
}
resource "aws_lb_listener" "alb_listener" {
# ... (省略) ...
}
resource "aws_lb_target_group" "alb_tg" {
# ... (省略) ...
}
resource "aws_lb_target_group_attachment" "alb_tg_attachment" {
# ... (for_each で複数インスタンスを登録する例) ...
for_each = toset(var.instance_ids)
target_id = each.value
# ... (省略) ...
}
terraformコードの注意点:
- terraformコードは、実行前に
terraform plan
コマンドで変更内容を確認することを徹底します。 -
terraform apply
実行後は、AWSコンソールでリソースの状態を確認し、意図した通りに作成されているか検証します。 - stateファイルは機密情報を含む可能性があるため、安全に管理する必要があります。
- terraformのバージョンアップ時には、変更点を確認し、必要に応じてコードを修正する必要があります。
terraformを使用することで、ELBの設定をコードとして管理し、Infrastructure as Code (IaC) を実現できます。これにより、構成管理、変更管理、再現性、自動化が容易になり、実務におけるELBの運用効率を大幅に向上させることができます。
Discussion