CLBでのConnection Drainingの有効化手順

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。

この記事では、Classic Load Balancer (CLB) のConnection Drainingが有効化されていない状態について、リスクと対策を解説します。

ポリシーの説明

Elastic Load Balancing の Security Hub コントロール – AWS Security Hub

このコントロールは、Classic Load Balancers で Connection Draining が有効になっているかどうかをチェックします。

リスク

Amazon Elastic Load Balancing (ELB) のClassic Load Balancer (CLB) は、トラフィックを複数のEC2インスタンスに分散する役割を担います。しかし、CLBでConnection Draining(接続のドレイン)が有効になっていない場合、以下のような運用上および可用性に関するリスクが発生します。

  • サービス停止やエラーの発生: ロードバランサーからインスタンスを登録解除する際(例えば、インスタンスの停止、置き換え、デプロイ、スケールダウンなど)、Connection Drainingが有効でないと、CLBは即座にそのインスタンスへの新規リクエストのルーティングを停止しますが、既存の確立された接続は強制的に切断してしまいます。これにより、そのインスタンスで処理中だったユーザーのリクエストが途中で中断され、エラーレスポンスが返されたり、ユーザー体験が損なわれたりする可能性があります。
  • データ損失の可能性: 特に、時間がかかるリクエスト(ファイルのアップロード、データベーストランザクションなど)が処理中に強制終了されると、データが完全に処理されず、損失につながる恐れがあります。
  • デプロイメントの不安定化: アプリケーションの新しいバージョンをデプロイする際、古いインスタンスから新しいインスタンスへのスムーズな切り替えができません。これにより、デプロイプロセスが不安定になり、ダウンタイムが発生しやすくなります。
  • スケーリングイベントの悪影響: オートスケーリンググループがインスタンスを終了させる際、Connection Drainingがなければ、終了対象のインスタンスが既存の接続を適切に終了させることなく強制的にシャットダウンされ、サービスに悪影響を与えることがあります。

対策

CLBのConnection Drainingを有効化することは、インスタンスの登録解除やヘルスチェック失敗時におけるユーザー体験の維持、およびアプリケーションの可用性向上に不可欠です。

  • Connection Drainingの有効化: CLBの設定において、Connection Draining(最新のELBでは「登録解除の遅延」と表現されることもあります)を有効にします。
  • 適切なタイムアウト期間の設定: Connection Drainingのタイムアウト期間をアプリケーションの最大リクエスト処理時間に合わせて設定します。例えば、最大で60秒かかるリクエストがある場合、タイムアウトを60秒以上に設定することで、そのリクエストが完了するまで待機するようにします。ただし、タイムアウトが長すぎると、インスタンスの終了が遅れ、スケーリングやデプロイの効率が低下する可能性もあります。
  • ヘルスチェックとの連携: Connection Drainingは、ヘルスチェックに失敗したインスタンスからの接続をドレインする際にも機能します。これにより、問題のあるインスタンスがトラフィックを処理している間に接続が強制的に切断されることを防ぎます。
  • デプロイ戦略への組み込み: CI/CDパイプラインやデプロイ戦略にConnection Drainingの考慮を組み込み、アプリケーションの更新やインスタンスの置き換えがスムーズに行われるように設計します。

修復方法

AWSコンソールでの修復手順

AWSコンソールを使用して、Classic Load BalancerのConnection Drainingを有効にします。

  1. EC2サービスへ移動:
    • AWSコンソールにログインし、EC2サービスを開きます。
  2. ロードバランサーの選択:
    • 左側のナビゲーションペインで「ロードバランサー」を選択します。
    • Connection Drainingを有効にしたい「Classic Load Balancer」を選択します。
  3. 属性の編集:
    • ロードバランサーの詳細ページで、「説明」タブ(または「Attributes」タブ)を選択します。
    • 「Connection Draining」の項目を見つけ、「編集」をクリックします。
  1. Connection Drainingの有効化とタイムアウト設定:
    • 「Connection Draining の有効化」にチェックを入れます。
    • タイムアウト (ドレーニング間隔)」に、アプリケーションの最大リクエスト処理時間に合わせて適切な秒数を入力します(例: 300秒 = 5分)。
    • 「変更内容の保存」をクリックして変更を適用します。

Terraformでの修復手順

TerraformでClassic Load BalancerのConnection Drainingを有効にするには、aws_elb リソースの connection_draining および connection_draining_timeout パラメータを設定します。

# Classic Load Balancer (CLB) の定義
resource "aws_elb" "my_clb" {
  name               = "my-classic-load-balancer"
  security_groups    = [aws_security_group.clb_sg.id]
  subnets            = [aws_subnet.public_a.id, aws_subnet.public_c.id] # あなたのサブネットIDに置き換えてください
  internal           = false # 内部ロードバランサーの場合 true

  listener {
    instance_port     = 80
    instance_protocol = "HTTP"
    lb_port           = 80
    lb_protocol       = "HTTP"
  }

  health_check {
    healthy_threshold   = 2
    unhealthy_threshold = 2
    timeout             = 3
    target              = "HTTP:80/"
    interval            = 30
  }

  # Connection Draining の有効化とタイムアウト設定
  connection_draining         = true
  connection_draining_timeout = 300 # 秒単位 (例: 300秒 = 5分)

  tags = {
    Name = "MyClassicLoadBalancer"
  }
}

# 関連リソースの定義例 (VPC, Subnet, Security Group など)
# これらのリソースは、あなたの環境に合わせて定義または参照してください。

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "main-vpc"
  }
}

resource "aws_subnet" "public_a" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "ap-northeast-1a" # あなたのリージョンに合わせて変更
  tags = {
    Name = "public-subnet-a"
  }
}

resource "aws_subnet" "public_c" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "ap-northeast-1c" # あなたのリージョンに合わせて変更
  tags = {
    Name = "public-subnet-c"
  }
}

resource "aws_security_group" "clb_sg" {
  name        = "clb-security-group"
  description = "Allow HTTP traffic to CLB"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # 適切なIP範囲に制限してください
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "clb-sg"
  }
}

# EC2インスタンスをCLBにアタッチする場合 (例)
/*
resource "aws_instance" "web" {
  count         = 2
  ami           = "ami-0abcdef1234567890" # あなたのAMI IDに置き換えてください
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.public_a.id # いずれかのパブリックサブネット
  vpc_security_group_ids = [aws_security_group.clb_sg.id] # CLBからのアクセスを許可するSG

  lifecycle {
    create_before_destroy = true
  }

  # ここでCLBにインスタンスを登録します
  depends_on = [aws_elb.my_clb] # CLBが作成されてからインスタンスが作成されるように依存関係を追加
  
  # インスタンスがCLBに登録されるように設定 (ELBに直接インスタンスIDを渡すか、Target Groupを使用)
  # CLBの場合は、`instances`パラメータでインスタンスIDのリストを指定します
  # aws_elb.my_clb.instances = [aws_instance.web[0].id, aws_instance.web[1].id]
}
*/

上記の例では、aws_elb リソースブロック内で connection_draining = true を設定することでConnection Drainingを有効化し、connection_draining_timeout = 300 でタイムアウト期間を300秒(5分)に設定しています。

subnetsamiyour-email@example.com など、あなたの環境に合わせたプレースホルダーは適切に修正してください。

最後に

この記事では、CLBのConnection Drainingが有効化されていない状態について、リスクと対策を解説しました。Connection Drainingを有効にすることは、ロードバランサー配下のインスタンスが安全にトラフィックから切り離されることを保証し、ユーザーへの影響を最小限に抑える上で非常に重要です。これにより、アプリケーションの可用性と安定性を向上させることができます。

この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。

運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。

最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです

この記事をシェアする

クラウドセキュリティ対策実践集一覧へ戻る

貴社の利用状況に合わせた見積もりを作成します。

料金プランを詳しく見る