Elastic Load Balancing: ALB, NLB và Gateway Load Balancer

So sánh 3 loại load balancer, target groups, health checks và cross-zone load balancing. Thiết kế high availability.

Tại sao cần Load Balancer?

Khi bạn có nhiều servers, bạn cần một cách để phân phối traffic giữa chúng:

Không có Load Balancer:
User ──► Server 1 (quá tải, chậm)
User ──► Server 1 (crash!)
         Server 2 (idle, lãng phí)
         Server 3 (idle, lãng phí)

Có Load Balancer:
User ──► Load Balancer ──► Server 1 (33% traffic)
                       ├──► Server 2 (33% traffic)
                       └──► Server 3 (33% traffic)

3 Loại Load Balancer trong AWS

LoạiLayerUse CaseGiá
ALB (Application)7 (HTTP/HTTPS)Web apps, APIs, microservices$$
NLB (Network)4 (TCP/UDP)Gaming, IoT, extreme performance$$
GLB (Gateway)3 (IP)Firewalls, IDS/IPS, deep packet inspection$$$

Application Load Balancer (ALB)

ALB hoạt động ở Layer 7 - hiểu HTTP/HTTPS protocol.

Tính năng chính

  • Path-based routing: /api/* → API servers, /static/* → S3
  • Host-based routing: api.example.com → API, www.example.com → Web
  • HTTP/2, WebSocket, gRPC support
  • Authentication tích hợp (Cognito, OIDC)
  • Sticky sessions (session affinity)

Architecture

Internet ──► ALB ──► Target Group 1 (/api/*)

                         ├── EC2 Instance 1
                         ├── EC2 Instance 2
                         └── Lambda Function
                    
             ALB ──► Target Group 2 (/static/*)

                         └── S3 Bucket
                    
             ALB ──► Target Group 3 (default)

                         ├── ECS Container 1
                         └── ECS Container 2

Terraform: ALB

# Application Load Balancer
resource "aws_lb" "main" {
  name               = "${var.project_name}-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = var.public_subnet_ids

  enable_deletion_protection = var.environment == "prod"
  enable_http2               = true

  # Cross-zone load balancing (miễn phí cho ALB)
  enable_cross_zone_load_balancing = true

  # Access logs
  access_logs {
    bucket  = aws_s3_bucket.alb_logs.id
    prefix  = "alb"
    enabled = true
  }

  tags = {
    Name = "${var.project_name}-alb"
  }
}

# Target Group
resource "aws_lb_target_group" "app" {
  name        = "${var.project_name}-app-tg"
  port        = 80
  protocol    = "HTTP"
  vpc_id      = var.vpc_id
  target_type = "instance"  # hoặc "ip" cho Fargate, "lambda"

  # Health check
  health_check {
    enabled             = true
    healthy_threshold   = 2
    unhealthy_threshold = 3
    timeout             = 5
    interval            = 30
    path                = "/health"
    port                = "traffic-port"
    protocol            = "HTTP"
    matcher             = "200-299"
  }

  # Sticky sessions
  stickiness {
    type            = "lb_cookie"
    cookie_duration = 3600  # 1 hour
    enabled         = true
  }

  # Deregistration delay
  deregistration_delay = 30

  tags = {
    Name = "${var.project_name}-app-tg"
  }
}

# HTTPS Listener
resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.main.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = aws_acm_certificate.main.arn

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.app.arn
  }
}

# HTTP to HTTPS redirect
resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.main.arn
  port              = 80
  protocol          = "HTTP"

  default_action {
    type = "redirect"
    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}

# Path-based routing
resource "aws_lb_listener_rule" "api" {
  listener_arn = aws_lb_listener.https.arn
  priority     = 100

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.api.arn
  }

  condition {
    path_pattern {
      values = ["/api/*"]
    }
  }
}

# Host-based routing
resource "aws_lb_listener_rule" "admin" {
  listener_arn = aws_lb_listener.https.arn
  priority     = 50

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.admin.arn
  }

  condition {
    host_header {
      values = ["admin.${var.domain_name}"]
    }
  }
}

Network Load Balancer (NLB)

NLB hoạt động ở Layer 4 - chỉ xử lý TCP/UDP, không hiểu HTTP.

Khi nào dùng NLB?

  • Extreme performance: Millions of requests/second
  • Ultra-low latency: Microseconds vs milliseconds
  • Static IP required: NLB có static IP
  • Non-HTTP protocols: Gaming, IoT, custom protocols
  • AWS PrivateLink: Expose service cho customers

Terraform: NLB

# Network Load Balancer
resource "aws_lb" "nlb" {
  name               = "${var.project_name}-nlb"
  internal           = false
  load_balancer_type = "network"
  subnets            = var.public_subnet_ids

  # Static IP với Elastic IP
  enable_cross_zone_load_balancing = true  # Tốn phí cho NLB!

  tags = {
    Name = "${var.project_name}-nlb"
  }
}

# TCP Target Group
resource "aws_lb_target_group" "tcp" {
  name        = "${var.project_name}-tcp-tg"
  port        = 8080
  protocol    = "TCP"
  vpc_id      = var.vpc_id
  target_type = "instance"

  # Health check TCP
  health_check {
    enabled             = true
    healthy_threshold   = 3
    unhealthy_threshold = 3
    interval            = 10
    port                = "traffic-port"
    protocol            = "TCP"
  }

  # Connection termination
  connection_termination = true
  
  # Preserve client IP
  preserve_client_ip = true
}

# TCP Listener
resource "aws_lb_listener" "tcp" {
  load_balancer_arn = aws_lb.nlb.arn
  port              = 8080
  protocol          = "TCP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.tcp.arn
  }
}

# TLS termination at NLB
resource "aws_lb_listener" "tls" {
  load_balancer_arn = aws_lb.nlb.arn
  port              = 443
  protocol          = "TLS"
  certificate_arn   = aws_acm_certificate.main.arn
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.tcp.arn
  }
}

Gateway Load Balancer (GLB)

GLB dùng cho virtual appliances - firewalls, IDS/IPS.

Internet ──► GLB ──► Firewall Appliance ──► GLB ──► Application
                     (inspect traffic)

Terraform: GLB

resource "aws_lb" "glb" {
  name               = "${var.project_name}-glb"
  load_balancer_type = "gateway"
  subnets            = var.appliance_subnet_ids

  tags = {
    Name = "${var.project_name}-glb"
  }
}

resource "aws_lb_target_group" "appliances" {
  name        = "${var.project_name}-appliances"
  port        = 6081
  protocol    = "GENEVE"
  vpc_id      = var.vpc_id
  target_type = "instance"

  health_check {
    port     = 80
    protocol = "HTTP"
    path     = "/health"
  }
}

So sánh ALB vs NLB

FeatureALBNLB
Layer7 (HTTP)4 (TCP/UDP)
LatencyMillisecondsMicroseconds
ThroughputMillions RPSMillions RPS
Static IPKhông
Path routingKhông
WebSocket
SSL offload
Cross-zoneMiễn phíTốn phí
PricingPer LCUPer NLCU

Health Checks

Health checks quyết định target nào healthy để nhận traffic.

Best Practices

health_check {
  # Không check "/" - dùng dedicated health endpoint
  path = "/health"
  
  # Health endpoint nên kiểm tra:
  # - Database connection
  # - Critical dependencies
  # - Disk space
  
  # Tune thresholds dựa trên app
  healthy_threshold   = 2   # 2 successes = healthy
  unhealthy_threshold = 3   # 3 failures = unhealthy
  
  # Interval và timeout
  interval = 30  # Check mỗi 30s
  timeout  = 5   # Timeout sau 5s
  
  # Matcher cho ALB
  matcher = "200-299"  # Accept 2xx responses
}

Health Check Endpoint Example

# /health endpoint
from flask import Flask, jsonify
import psycopg2

app = Flask(__name__)

@app.route('/health')
def health():
    checks = {
        'database': check_database(),
        'redis': check_redis(),
        'disk': check_disk_space(),
    }
    
    all_healthy = all(c['status'] == 'ok' for c in checks.values())
    
    return jsonify({
        'status': 'healthy' if all_healthy else 'unhealthy',
        'checks': checks
    }), 200 if all_healthy else 503

def check_database():
    try:
        conn = psycopg2.connect(...)
        conn.execute('SELECT 1')
        return {'status': 'ok'}
    except Exception as e:
        return {'status': 'error', 'message': str(e)}

Cross-Zone Load Balancing

Không có Cross-Zone

AZ-a: ALB Node ──► Target 1 (50% traffic)
                 └► Target 2 (50% traffic)

AZ-b: ALB Node ──► Target 3 (100% traffic của AZ-b)

Nếu AZ-a có 2 targets và AZ-b có 1 target:
- Target 1: 25%
- Target 2: 25%
- Target 3: 50% ← Uneven!

Có Cross-Zone

AZ-a: ALB Node ───┬──► Target 1 (33%)
                  ├──► Target 2 (33%)
                  └──► Target 3 (33%)

AZ-b: ALB Node ───┬──► Target 1 (33%)
                  ├──► Target 2 (33%)
                  └──► Target 3 (33%)

Traffic phân phối đều!
resource "aws_lb" "main" {
  enable_cross_zone_load_balancing = true  # Khuyến nghị bật
}

Connection Draining (Deregistration Delay)

Khi target bị remove khỏi target group, connections hiện tại không bị cắt ngay:

resource "aws_lb_target_group" "app" {
  deregistration_delay = 30  # Đợi 30s cho connections hoàn thành
  
  # Đối với deployments, 30-60s thường đủ
  # Đối với long-running connections, có thể cần nhiều hơn
}

SSL/TLS Best Practices

Security Policy

resource "aws_lb_listener" "https" {
  # Chọn policy phù hợp
  ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  
  # Các policy thường dùng:
  # - ELBSecurityPolicy-TLS13-1-2-2021-06: TLS 1.3 + 1.2, modern ciphers
  # - ELBSecurityPolicy-TLS-1-2-2017-01: TLS 1.2 only
  # - ELBSecurityPolicy-FS-1-2-Res-2020-10: Forward Secrecy
}

Multiple Certificates (SNI)

# Primary certificate
resource "aws_lb_listener" "https" {
  certificate_arn = aws_acm_certificate.main.arn
}

# Additional certificates for other domains
resource "aws_lb_listener_certificate" "extra" {
  listener_arn    = aws_lb_listener.https.arn
  certificate_arn = aws_acm_certificate.extra.arn
}

Practice Questions (SAA style)

1. Một ứng dụng cần expose REST API và cần routing based on URL path. Load balancer nào phù hợp nhất?

A. Network Load Balancer
B. Application Load Balancer
C. Gateway Load Balancer
D. Classic Load Balancer

Đáp án: B - ALB hỗ trợ path-based routing ở Layer 7.


2. Công ty cần static IP cho TCP-based application để whitelist trong firewall của partner. Giải pháp nào phù hợp?

A. ALB với Elastic IP
B. NLB (có static IP by default)
C. CloudFront với origin ALB
D. Global Accelerator với ALB

Đáp án: B - NLB cung cấp static IP addresses per AZ.


3. Làm thế nào để đảm bảo traffic được phân phối đều giữa tất cả targets ngay cả khi số target khác nhau giữa các AZs?

A. Use sticky sessions
B. Enable cross-zone load balancing
C. Use weighted target groups
D. Configure health check thresholds

Đáp án: B - Cross-zone load balancing phân phối traffic đều giữa tất cả targets bất kể AZ.


Bài tiếp theo: Cost Optimization Strategies - Reserved, Spot và Savings Plans.