ALB(Application Load Balancer)を使ったコンテナ負荷分散

はじめに

現代のクラウドネイティブアプリケーションでは、高可用性とスケーラビリティを確保するために複数のコンテナインスタンスを実行するのが一般的になっています。しかし、これらのコンテナに効率的にトラフィックを分散させるには、信頼性の高い負荷分散ソリューションが必要です。AWSのApplication Load Balancer(ALB)は、コンテナ化されたアプリケーションの負荷分散に最適なサービスです。

この記事では、ALBを使用してDockerコンテナへのトラフィックを効率的に分散させる方法について詳しく解説します。

ALBとは?

Application Load Balancer(ALB)は、AWSが提供するロードバランサーサービスの一つで、レイヤー7(HTTPおよびHTTPS)レベルで動作します。以下のような特徴があります:

  • コンテンツベースのルーティング
  • パスベースのルーティング
  • ホストベースのルーティング
  • コンテナ化されたアプリケーションのサポート
  • WebSocketプロトコルのサポート
  • HTTP/2のサポート
  • 統合された証明書管理

従来のELB(現在はClassic Load Balancerと呼ばれる)と比較して、ALBはより高度なルーティング機能と、コンテナ環境との優れた統合性を提供します。

アーキテクチャ概要

ALBを使用したコンテナ負荷分散の基本的なアーキテクチャは次のようになります:

ユーザー → ALB → ターゲットグループ → EC2インスタンス上のコンテナ(ECS/Kubernetes)

ALBは以下のコンポーネントから構成されています:

  1. リスナー: ALBがトラフィックを受け付けるプロトコルとポート
  2. ルール: リスナーに関連付けられ、着信リクエストをどのターゲットグループに転送するかを決定
  3. ターゲットグループ: トラフィックの転送先となるインスタンスやコンテナの集合
  4. ヘルスチェック: ターゲットの健全性を確認するための設定

ALBでのコンテナ負荷分散設定手順

ステップ1: ロードバランサーの作成

  1. AWSマネジメントコンソールにログインし、EC2ダッシュボードを開きます
  2. 左側のナビゲーションペインから「ロードバランサー」を選択します
  3. 「ロードバランサーの作成」ボタンをクリックします
  4. 「Application Load Balancer」を選択し、「作成」をクリックします
  5. 基本的な設定を行います:
    • 名前を入力(例:my-container-alb)
    • スキームは「インターネット向け」または「内部」を選択
    • IPアドレスタイプは「IPv4」を選択
  6. リスナーを設定します(通常はHTTP:80またはHTTPS:443)
  7. 可用性ゾーンを選択します(最低2つの異なるAZを選択することをお勧めします)
  8. 「次へ: セキュリティ設定の構成」をクリックします

HTTPS使用時は、AWSの証明書マネージャー(ACM)で発行された証明書を選択するか、既存の証明書をインポートします。

ステップ2: セキュリティグループの設定

  1. 新しいセキュリティグループを作成するか、既存のものを選択します
  2. 以下のインバウンドルールを設定します:
    • HTTP (80) または HTTPS (443): ソースを「0.0.0.0/0, ::/0」(全てのトラフィック)または必要に応じて制限
  3. 「次へ: ルーティングの設定」をクリックします

ステップ3: ターゲットグループの設定

  1. 新しいターゲットグループを作成します:
    • 名前を入力(例:my-container-targets)
    • ターゲットタイプを選択:
      • インスタンス: EC2インスタンスを直接ターゲットにする場合
      • IP: 特定のIPアドレスをターゲットにする場合(例:Fargateタスク)
      • Lambda関数: サーバーレス関数をターゲットにする場合
    • プロトコルとポートを設定(例:HTTP:80 or HTTP:8080など、コンテナが公開しているポート)
  2. ヘルスチェックを設定します:
    • プロトコル: HTTP
    • パス: アプリケーションの健全性を確認できるエンドポイント(例:/health)
    • 高度なヘルスチェック設定を必要に応じて調整
  3. 「次へ: ターゲットの登録」をクリックします

ステップ4: ターゲットの登録

注意: コンテナ化されたアプリケーションを使用する場合は、この段階でターゲットを手動で登録しないことが多いです。特にECSやKubernetesを使用している場合は、これらのサービスがターゲットの登録/登録解除を自動的に処理します。

手動で登録する場合は、該当するインスタンスまたはIPアドレスを選択し、ポートを指定して「登録済みに追加」をクリックします。

「次へ: 確認」をクリックし、設定を確認して「作成」をクリックします。

Amazon ECSとALBの統合

Amazon ECSはDockerコンテナのオーケストレーションサービスです。ECSとALBを統合することで、コンテナの動的なスケーリングと負荷分散を実現できます。

ECSサービスとALBの連携設定

  1. ECSクラスターを作成します(既存のクラスターを使用することもできます)
  2. タスク定義を作成/更新し、コンテナのポートマッピングを設定します:
"portMappings": [
  {
    "containerPort": 80,
    "hostPort": 0,  // 動的ポートマッピングを使用
    "protocol": "tcp"
  }
]
  1. ECSサービスを作成:
    • クラスターを選択
    • タスク定義とリビジョンを選択
    • サービス名を入力
    • 起動タイプ(EC2またはFargate)を選択
    • タスク数を設定
    • デプロイタイプを選択(通常は「ローリング更新」)
  2. ロードバランシングを設定:
    • 「ロードバランサータイプ」で「Application Load Balancer」を選択
    • 既存のALBを選択するか、新しいALBを作成
    • コンテナとポートを選択
    • ターゲットグループ名を入力
    • ヘルスチェックの猶予期間を設定(コンテナの起動時間に応じて調整)
  3. 自動スケーリングを必要に応じて設定
  4. サービスを作成

これにより、ECSサービスはタスク(コンテナ)を起動すると自動的にALBのターゲットグループに登録します。またタスクが終了すると、ターゲットグループからの登録も解除されます。

Amazon EKS(Kubernetes)とALBの統合

AWSで実行されるKubernetesクラスター(EKS)との統合には、AWS Load Balancer Controllerを使用します。

AWS Load Balancer Controllerのインストール

  1. Helm(Kubernetesパッケージマネージャー)がインストールされていることを確認します
  2. 以下のコマンドでAWS Load Balancer Controllerをインストールします:
# Helmリポジトリを追加
helm repo add eks https://aws.github.io/eks-charts
helm repo update

# IAMポリシーをダウンロード
curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json

# IAMポリシーを作成
aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam-policy.json

# ServiceAccountを作成
eksctl create iamserviceaccount \
  --cluster=my-cluster \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --attach-policy-arn=arn:aws:iam::<AWS_ACCOUNT_ID>:policy/AWSLoadBalancerControllerIAMPolicy \
  --approve

# AWS Load Balancer Controllerをインストール
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=my-cluster \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller

IngressリソースでALBを使用する

Kubernetes IngressリソースでALBを使用するには、以下のように設定します:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-app-service
                port:
                  number: 80

また、Serviceリソースは通常のClusterIPタイプで構成します:

apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  ports:
    - port: 80
      targetPort: 8080
  selector:
    app: my-app
  type: ClusterIP

これにより、AWS Load Balancer Controllerが自動的にALBを作成し、Kubernetesサービスに関連付けます。

パスベースのルーティング

ALBの強力な機能の一つは、URLパスに基づいて異なるサービスにリクエストをルーティングできることです。これにより、単一のALBで複数のマイクロサービスをホストできます。

例えば、次のような設定が可能です:

  • /api/* → APIサービスコンテナ
  • /admin/* → 管理パネルコンテナ
  • /* → フロントエンドWebアプリケーションコンテナ

パスベースルーティングの設定方法

  1. ALBに複数のターゲットグループを作成します(例:api-targets, admin-targets, frontend-targets)
  2. リスナールールを設定します:
    • パスパターン /api/* → api-targets
    • パスパターン /admin/* → admin-targets
    • デフォルト(正確な一致なし) → frontend-targets

ECSの場合は、サービス作成時に「追加のルーティング設定」でパスパターンを指定します。

Kubernetesの場合は、Ingressリソースで複数のパスを定義できます:

spec:
  rules:
    - http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80
          - path: /admin
            pathType: Prefix
            backend:
              service:
                name: admin-service
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80

ヘルスチェック

ALBは定期的にターゲットに対してヘルスチェックを実行し、正常に応答しないターゲットにはトラフィックを送信しません。これにより、アプリケーションの可用性が向上します。

効果的なヘルスチェックの設定

  1. 専用のヘルスチェックエンドポイントを実装します(例:/health
  2. ヘルスチェックエンドポイントは以下を確認すべきです:
    • アプリケーション自体の健全性
    • 依存サービス(データベースなど)への接続
    • 十分なリソース(メモリ、ディスク容量など)
  3. ヘルスチェックの間隔と閾値を適切に設定:
    • 間隔: 健全性チェックの頻度(例:30秒)
    • 不健全しきい値: 不健全と判断するまでの失敗回数(例:2回)
    • 正常しきい値: 正常と判断するまでの成功回数(例:3回)
    • タイムアウト: 応答を待機する時間(例:5秒)

ALBのモニタリングとログ記録

ALBの動作を監視し、問題を迅速に検出するために、以下の機能を活用できます:

CloudWatchメトリクス

ALBは以下のような重要なメトリクスをCloudWatchに自動的に送信します:

  • RequestCount: 処理されたリクエスト数
  • TargetResponseTime: ターゲットからの応答時間
  • HTTPCode_ELB_4XX: ALBが生成した4XXエラーの数
  • HTTPCode_ELB_5XX: ALBが生成した5XXエラーの数
  • HTTPCode_Target_4XX: ターゲットが生成した4XXエラーの数
  • HTTPCode_Target_5XX: ターゲットが生成した5XXエラーの数

これらのメトリクスを使用して、CloudWatchダッシュボードやアラームを作成できます。

アクセスログ

ALBのアクセスログを有効にすると、ALBを介して送信されたリクエストの詳細情報がS3バケットに保存されます:

  1. S3バケットを作成します(または既存のバケットを使用)
  2. ALBのアクセスログを有効にします:
    • ALBの「説明」タブを選択
    • 「属性の編集」をクリックします
    • 「アクセスログ」を有効にします
    • S3バケットを選択し、必要に応じてプレフィックスを指定します
    • 保存をクリックします

X-Ray統合

AWS X-Rayを使用すると、ALBを経由するリクエストのエンドツーエンドの追跡が可能になります:

  1. X-Ray SDKをアプリケーションに統合します
  2. ALBのリスナーまたはターゲットグループでX-Ray追跡を有効にします

コスト最適化のためのベストプラクティス

ALBに関連するコストを最適化するためのベストプラクティスを紹介します:

  1. 適切なターゲットグループタイプの選択:
    • インスタンスタイプ: EC2インスタンスを直接使用する場合
    • IPタイプ: Fargateタスクや他のIPベースのターゲットを使用する場合
  2. 削除保護の有効化: 誤って負荷分散器を削除しないように保護します
  3. アイドル状態のALBのクリーンアップ: 使用していないALBは削除してコストを節約します
  4. SSL証明書の管理: ACMを使用して証明書を管理し、更新を自動化します
  5. ゾーンシフト: 特定のAZで問題が発生した場合、ALBのクロスゾーンロードバランシング機能を活用します

セキュリティのベストプラクティス

ALBを使用する際のセキュリティベストプラクティスを紹介します:

  1. HTTPS使用の強制:
    • HTTPSリスナーを設定し、HTTPS使用を強制するようにリダイレクトルールを設定します
    • セキュリティポリシーでTLS 1.2以上を要求します
  2. WAF(Web Application Firewall)との統合:
    • クロスサイトスクリプティング(XSS)やSQLインジェクションなどの一般的な脆弱性から保護します
    • AWS WAF Web ACLをALBに関連付けます
  3. セキュリティグループの制限:
    • ALBのセキュリティグループでは、必要なポートのみ許可します
    • ターゲットのセキュリティグループでは、ALBからのトラフィックのみを許可します
  4. アクセスログの暗号化:
    • S3バケットポリシーとサーバーサイド暗号化を使用してアクセスログを保護します

一般的な問題のトラブルシューティング

ALBを使用する際に発生する可能性のある一般的な問題とその解決方法を紹介します:

  1. ヘルスチェックの失敗:
    • セキュリティグループがヘルスチェックのポートへのアクセスを許可しているか確認
    • ターゲットでヘルスチェックエンドポイントが正しく応答しているか確認
    • ヘルスチェックのタイムアウト設定が適切か確認
  2. 504 Gateway Timeout:
    • ターゲットのタイムアウト設定を確認
    • アプリケーションのパフォーマンスを確認
    • ALBのアイドルタイムアウト設定を調整(デフォルトは60秒)
  3. 403 Forbidden:
    • WAFルールを確認
    • セキュリティグループの設定を確認
    • バケットポリシーを確認(S3バケットをホストする場合)
  4. 接続ドレイン問題:
    • 接続ドレインのタイムアウト設定を確認(デフォルトは300秒)
    • 長時間実行されるリクエスト処理の方法を見直す

まとめ

AWS Application Load Balancer(ALB)は、コンテナベースのアプリケーションに最適な負荷分散ソリューションを提供します。パスベースのルーティング、コンテナ統合、ヘルスチェック、モニタリング機能により、スケーラブルで高可用性のアプリケーションを構築できます。

この記事で紹介したベストプラクティスとヒントを活用して、ALBを使ったコンテナ環境を最適化し、信頼性の高いサービスを提供してください。

参考リソース

コメント

タイトルとURLをコピーしました