Skip to content

Envoy-based Regional & Internal ALB — Proxy nằm trong VPC của bạn

Why this matters in production

Phần lớn traffic trong một hệ thống production không phải đi ra internet — nó là traffic đông-tây (east-west) giữa các microservice, hoặc traffic từ on-prem vào qua VPN/Interconnect. Cho những luồng này, bạn không dùng Global External ALB (GFE/anycast) mà dùng Envoy-based load balancer: Regional Internal ALB cho L7 routing nội bộ, Regional External ALB khi cần proxy external nhưng giới hạn region, Cross-region Internal ALB khi cần internal LB trải nhiều region.

Sự khác biệt với GFE không phải tiểu tiết — nó thay đổi cách bạn thiết kế mạng:

  • Envoy LB cần một proxy-only subnet trong VPC. Quên tạo nó → LB không thể được tạo. Tạo sai kích thước → Envoy hết IP và LB ngừng scale. Đây là nguồn gốc của một class lỗi mà GFE LB không bao giờ gặp.
  • Backend của bạn thấy source IP từ proxy-only subnet, không phải từ dải GFE toàn cầu. Firewall rule phải khác. Đặt sai → health check pass nhưng traffic thật bị chặn, hoặc ngược lại.
  • Envoy là regional: một regional internal ALB chỉ sống trong một region. Hiểu sai scope dẫn tới kỳ vọng "global" không bao giờ thành.

File này giải thích đúng cơ chế đó, và vì sao nó khác GFE ở mức kiến trúc chứ không phải mức cấu hình.

Internal model — Envoy managed proxy fleet trong VPC

Envoy là gì ở đây, và "managed" nghĩa là gì

Envoy là một L7 proxy mã nguồn mở (do Lyft tạo, nay thuộc CNCF). GCP dùng Envoy làm engine cho toàn bộ họ load balancer "managed proxy" hiện đại: Regional External/Internal ALB, Cross-region Internal ALB, và các Proxy NLB regional/internal. "Managed" nghĩa là: bạn không vận hành Envoy — Google triển khai, scale, vá lỗi, và giám sát fleet Envoy thay bạn. Bạn chỉ khai báo mô hình resource (forwarding rule → target proxy → URL map → backend service), và Google biên dịch cấu hình đó thành cấu hình Envoy rồi đẩy xuống fleet.

Điểm khác biệt cốt lõi so với GFE: GFE sống ở biên mạng toàn cầu của Google (control plane của Google, ngoài VPC bạn). Envoy fleet ở đây sống trong region và lấy IP từ VPC của bạn. Theo tài liệu internal ALB, internal ALB chạy "Envoy proxy" trên "Andromeda network virtualization stack" — tức Envoy là tiến trình proxy, còn Andromeda là datapath ảo hóa đưa packet tới/từ Envoy. Hai lớp này phối hợp: Andromeda lái packet từ client tới một Envoy proxy; Envoy terminate connection, đọc HTTP, chọn backend, mở connection mới tới backend.

Proxy-only subnet — trái tim của mô hình Envoy

Đây là khái niệm bạn phải hiểu đúng, vì nó là nguồn gốc của khác biệt vận hành lớn nhất so với GFE.

Theo tài liệu proxy-only subnet: "Proxy-only subnet cung cấp một pool địa chỉ IP được dành riêng exclusively cho các Envoy proxy do Google Cloud load balancer sử dụng." Cơ chế cụ thể:

                 Proxy-only subnet (ví dụ 10.129.0.0/23)
                 ┌─────────────────────────────────────┐
   Client ─────► │  Envoy proxy   Envoy proxy   ...     │
   (trong VPC)   │  10.129.0.5    10.129.0.6           │
                 └──────────────┬──────────────────────┘
                                │ source IP = 10.129.0.x
                                │ (LẤY TỪ proxy-only subnet)

                          Backend VM / Pod
                          (firewall phải allow 10.129.0.0/23)

Ba điểm cơ chế phải nắm:

  1. Mỗi Envoy proxy nhận một IP nội bộ từ proxy-only subnet. Khi Envoy mở connection tới backend, source IP của packet đó là một IP trong proxy-only subnet. Tài liệu nói rõ: "packet gửi từ proxy tới backend VM hoặc endpoint có source IP từ proxy-only subnet". Đây là điều backend thực sự thấy — không phải IP client, không phải dải GFE, mà là proxy-only subnet của chính VPC bạn.

  2. Subnet này có purpose đặc biệt, không phải subnet thường. Hai purpose: REGIONAL_MANAGED_PROXY (cho regional external/internal ALB, regional proxy NLB, Secure Web Proxy) và GLOBAL_MANAGED_PROXY (cho cross-region internal ALB và cross-region internal proxy NLB). Một subnet purpose này không chứa được VM thường — nó dành riêng cho Envoy. Bạn không gán instance vào nó.

  3. Một proxy-only subnet active mỗi purpose mỗi region mỗi VPC. Tài liệu: "trong một VPC network và region cho trước, chỉ một proxy-only subnet với purpose GLOBAL_MANAGED_PROXY có thể active". Và: "bạn phải tạo một proxy-only subnet trong mỗi region của VPC" nơi bạn triển khai Envoy LB. Nghĩa là: trong một region, mọi Envoy LB cùng VPC chia sẻ chung một proxy-only subnet. Đây là điểm gây ngạc nhiên: bạn không tạo subnet riêng cho từng LB; bạn tạo một subnet dùng chung cho cả region.

Sizing. Subnet phải có tối thiểu 64 IP (/26). Google khuyến nghị bắt đầu với /23 (512 IP). Lý do: vì mọi Envoy LB trong region chia sẻ subnet này, và Envoy fleet scale theo traffic, một subnet quá nhỏ sẽ cạn IP khi traffic tăng — và khi Envoy không lấy được IP mới, fleet không scale được, gây nghẽn. Đây là một capacity planning thật, không phải con số tùy tiện.

Datapath một request qua internal ALB

So với two-tier GFE của Global ALB, datapath Envoy đơn giản hơn vì nó regional (một tầng proxy, không phải hai):

   Client (VM trong VPC, hoặc on-prem qua VPN/Interconnect)
        │  kết nối tới internal VIP (ví dụ 10.0.0.50, từ subnet thường)

   Andromeda lái packet tới một Envoy proxy trong proxy-only subnet


   Envoy proxy (10.129.0.x):
     1. Terminate TCP/TLS
     2. Đọc HTTP, parse URL map → chọn backend service
     3. Áp dụng locality LB policy + outlier detection → chọn backend
     4. Mở connection MỚI tới backend, source IP = 10.129.0.x


   Backend (VM trong IG, hoặc Pod qua NEG)
     - thấy source IP = proxy-only subnet (KHÔNG phải client IP)
     - client IP thật trong X-Forwarded-For

Vì chỉ có một tầng proxy regional, internal ALB không có khái niệm "first-layer/second-layer GFE". Envoy proxy vừa terminate vừa chọn backend tại chỗ. Đổi lại, nó không có anycast global — VIP là một địa chỉ internal trong region (hoặc, với cross-region internal ALB, một VIP global internal được phục vụ bởi Envoy ở nhiều region).

Locality LB policy và outlier detection — "thông minh" của Envoy

Vì engine là Envoy, internal/regional ALB thừa hưởng các cơ chế phân phối tải tinh vi của Envoy, cấu hình qua backend service:

  • Locality LB policy: ROUND_ROBIN (mặc định), LEAST_REQUEST (chọn backend ít request đang xử lý nhất — tốt cho request thời lượng không đều), RING_HASHMAGLEV (consistent hashing theo một khóa, cho affinity), RANDOM, ORIGINAL_DESTINATION. Đây là quyết định trong một locality (zone/region) sau khi đã chọn được nhóm backend.

  • Outlier detection: Envoy chủ động eject (loại tạm) một backend khỏi pool khi nó trả về quá nhiều lỗi 5xx liên tiếp, dù health check vẫn pass. Đây là cơ chế mạnh hơn health check thuần: health check kiểm tra "backend còn sống không"; outlier detection kiểm tra "backend có đang trả lỗi cho traffic thật không". Một backend có thể pass health check (endpoint /healthz trả 200) nhưng vẫn lỗi 500 cho mọi request thật — outlier detection bắt được trường hợp này, health check thì không.

Đây là một khác biệt năng lực thực sự giữa Envoy-based LB và GFE-based LB: Envoy phơi bày nhiều control L7 chi tiết hơn (circuit breaking, outlier detection, retry policy chi tiết) vì nó là Envoy. Khi bạn cần các control này cho east-west traffic, internal ALB là công cụ đúng.

Constraints, trade-offs & failure modes

Regional scope — và vì sao "cross-region internal ALB" tồn tại

Regional internal ALB chỉ phục vụ trong một region. Nếu app của bạn chạy đa region và bạn muốn một internal endpoint duy nhất route tới region gần nhất, regional internal ALB không làm được — bạn cần Cross-region Internal ALB, vẫn dựa trên Envoy nhưng dùng GLOBAL_MANAGED_PROXY subnet ở mỗi region và một VIP global internal. Mental model: cross-region internal ALB = "internal ALB nhưng VIP global, Envoy ở mỗi region terminate tại chỗ". Nó cho bạn tính chất gần-anycast cho traffic nội bộ mà không phải lộ ra internet.

Failure mode: proxy-only subnet cạn IP

Triệu chứng: LB đang chạy ổn, traffic tăng đột biến, rồi xuất hiện lỗi 502/503 rời rạc hoặc LB không scale kịp. Nguyên nhân gốc thường bị bỏ qua: proxy-only subnet (/26 = 64 IP) đã cạn vì Envoy fleet cần thêm proxy để xử lý traffic nhưng không lấy được IP. Vì mọi Envoy LB trong region chia sẻ subnet này, một LB "ngốn IP" có thể làm cạn subnet và ảnh hưởng mọi LB khác cùng region cùng VPC. Phòng tránh: cấp /23 (512 IP) từ đầu như khuyến nghị, và giám sát mức sử dụng subnet. Đây là class lỗi đặc thù của Envoy LB mà GFE LB không có (GFE không tốn IP VPC).

Failure mode: firewall chặn proxy-only subnet

Vì backend thấy source IP từ proxy-only subnet, firewall của backend phải allow ingress từ dải proxy-only subnet. Lỗi điển hình: kỹ sư mở firewall cho dải health-check của Google (35.191.0.0/16, 130.211.0.0/22) — health check pass, backend báo healthy — nhưng quên mở cho proxy-only subnet, nên traffic thật từ Envoy bị chặn. Kết quả khó hiểu: "health check xanh nhưng client nhận 502". Quy tắc: với Envoy LB, mở firewall cho cả hai — dải prober proxy-only subnet.

Trade-off so với GFE

Envoy regional/internal ALBGFE Global External ALB
ScopeRegional (hoặc cross-region)Global (anycast)
IP consumptionTốn proxy-only subnet trong VPCKhông tốn IP VPC
Source IP backend thấyProxy-only subnet (VPC bạn)Dải GFE của Google
TLS terminationTại Envoy trong regionTại GFE edge gần client
Control L7 chi tiếtCao (outlier detection, circuit break)Tiêu chuẩn
Internal trafficCó (internal scheme)Không (external)
Firewall cần mởProber + proxy-only subnetProber (cho traffic GFE)

Quy tắc chọn: traffic internal/east-west hoặc cần control L7 Envoy → Envoy LB. Traffic public toàn cầu → GFE Global ALB.

Real-world scenario: L7 routing cho microservice mesh nội bộ

Một hệ thống microservice trong một VPC, nhiều service (orders, payments, inventory), muốn một endpoint nội bộ duy nhất internal-api.corp route theo path tới đúng service, có mTLS, và circuit breaking khi một service lỗi:

  • Dựng Regional Internal ALB: forwarding rule với internal VIP, URL map route /orders/* → backend-service-orders, /payments/* → backend-service-payments, v.v.
  • Tạo proxy-only subnet /23 purpose REGIONAL_MANAGED_PROXY trong region — dùng chung cho cả mesh.
  • Backend là NEG container-native trỏ thẳng Pod IP (xem file 05).
  • Bật outlier detection trên backend service: khi payments trả 5xx liên tiếp, Envoy eject pod đó, traffic dồn sang pod khỏe — không cần health check phát hiện.
  • Firewall: allow ingress từ proxy-only subnet /23 tới Pod range, và allow dải prober cho health check.

Lý do cơ chế của từng lựa chọn: internal (không lộ ra ngoài), Envoy (cần outlier detection + path routing), proxy-only subnet dùng chung (một subnet cho cả region), container-native NEG (bỏ hop kube-proxy). Đây là kiến trúc đông-tây điển hình mà GFE không phục vụ được.

Common mistakes / anti-patterns

Anti-pattern 1 — Tạo proxy-only subnet /26 rồi quên nó. Hiểu lầm: coi proxy-only subnet như subnet cấu hình một lần. Hậu quả: traffic tăng, Envoy cạn IP, LB nghẽn, và vì subnet dùng chung, mọi LB cùng region bị ảnh hưởng. Sửa: cấp /23 từ đầu, giám sát mức dùng.

Anti-pattern 2 — Chỉ mở firewall cho dải prober, quên proxy-only subnet. Hiểu lầm: nghĩ health check pass nghĩa là traffic sẽ tới được. Hậu quả: health xanh nhưng client nhận 502, vì traffic thật từ Envoy (source = proxy-only subnet) bị firewall chặn. Sửa: allow cả prober proxy-only subnet.

Anti-pattern 3 — Mong regional internal ALB hoạt động "global". Hiểu lầm: tưởng internal ALB tự route đa region. Hậu quả: client ở region khác không reach được, hoặc phải hack DNS. Sửa: dùng Cross-region Internal ALB (GLOBAL_MANAGED_PROXY) khi cần internal đa region.

References