Google Compute Engine 아키텍처 심화 및 실전 구축·운영 가이드
온프레미스 데이터센터와 멀티 클라우드 인프라를 운영하는 인프라 엔지니어, 네트워크 엔지니어, SRE를 위한 심화 기술 포털입니다. 기초적인 콘솔 사용법은 생략하고, 3시간(180분) 본 과정 동안 Andromeda SDN, GFE, Maglev, 분산 Envoy 프록시 기반의 내부 아키텍처와 Regional/Stateful MIG 무중단 운영, Keep-alive 502 에러 방지 튜닝 및 Day-2 트러블슈팅을 심도 있게 다룹니다.
3시간 본 과정 상세 아젠다 및 시간 배분
본 과정 180분 + 선택형 실습 60분| 구분 / 시간 | 소요 시간 | 세션명 | 상세 아젠다 및 핵심 다룸 내용 |
|---|---|---|---|
| Session 1 00:00 ~ 00:45 |
45분 | GCE 코어 아키텍처 및 엔터프라이즈 구축 가이드 |
|
| Session 2 00:45 ~ 01:35 |
50분 | Instance Group (UMIG/MIG) 구조 및 라이프사이클 운영 |
|
| Session 3 01:35 ~ 02:30 |
55분 | Cloud Load Balancing 아키텍처 및 트래픽 제어 |
|
| Session 4 02:30 ~ 03:00 |
30분 | Day-2 운영, 트러블슈팅 가이드 및 아키텍처 Q&A |
|
| [별도 추가 세션] 본 과정 외 선택 옵션 |
+60분 | [Optional Add-on] 실전 구축 및 502 디버깅 Hands-on Lab |
|
Session 1 GCE 코어 아키텍처 및 엔터프라이즈 구축 가이드
소요 시간: 45분 (00:00 ~ 00:45)1.1 Compute & Machine Family 선택 기준 및 고대역폭 네트워킹
온프레미스 x86 서버나 타 클라우드의 인스턴스 패밀리를 운영하던 엔지니어가 Google Compute Engine을 설계할 때 가장 먼저 정립해야 할 기준은 세대별 하드웨어 오프로딩 아키텍처(Titanium), 네트워크 인터페이스 드라이버(gVNIC), 그리고 호스트 유지보수 시의 Live Migration 동작입니다.
| 머신 시리즈 | 프로세서 및 아키텍처 기반 | 지원 스토리지 유형 | 네트워크 드라이버 / 최대 대역폭 | 적합한 엔터프라이즈 워크로드 |
|---|---|---|---|---|
| E2 | 환경에 따른 동적 CPU 할당 (Intel / AMD) | Persistent Disk | virtio-net 또는 gVNIC / 최대 16Gbps | 개발/테스트 환경, 트래픽 변동이 적은 경량 백오피스 및 배치 |
| N2 / N2D | Intel Ice Lake / AMD EPYC Milan | Persistent Disk, Hyperdisk | virtio-net, gVNIC / Tier 1 시 최대 100Gbps | 표준 엔터프라이즈 웹/WAS, 일반 마이크로서비스 클러스터 |
| N4 | Intel Emerald Rapids + Titanium 오프로딩 | Hyperdisk 전용 (Hyperdisk Balanced 기본) | gVNIC 필수 / 최대 50Gbps | 높은 가격 대비 성능과 균일한 I/O 응답 시간이 요구되는 차세대 표준 API 서버 |
| C3 / C3D / C4 | Intel Sapphire/Emerald Rapids, AMD Genoa + Titanium IPU | Hyperdisk 중심 (Local SSD 옵션 제공) | gVNIC 필수 / Tier 1 시 최대 200Gbps | 초저지연 코어 트랜잭션, 암호화/패킷 처리, 고성능 API 게이트웨이 및 DB 엔진 |
- Titanium IPU 하드웨어 오프로딩: 3세대 이후 머신(N4, C3, C4)은 네트워크 가상화(Andromeda SDN 패킷 처리)와 스토리지 암호화/I/O 연산을 호스트 CPU에서 분리하여 전용 하드웨어인 Titanium 어댑터에서 처리합니다. 이를 통해 이웃 VM으로 인한 성능 간섭(Noisy Neighbor)을 방지하고 일관된 클럭 성능을 제공합니다.
- gVNIC (Google Virtual NIC): 3세대 이상 VM에서는 레거시
virtio-net드라이버가 지원되지 않으며,gVNIC드라이버가 포함된 OS 이미지를 사용해야 합니다. - vCPU당 이그레스 대역폭 상한 주의: 기본 네트워크 구성을 사용할 경우 VM의 아웃바운드 대역폭은 vCPU 코어당 2Gbps(머신 타입별 기본 상한 32~50Gbps)로 제한됩니다. 대용량 트래픽을 중계하는 프록시나 미디어/데이터 노드는 반드시
gVNIC과 함께 Tier 1 네트워킹 옵션을 활성화하여 최대 100~200Gbps 대역폭을 확보해야 합니다.
- Live Migration 기본 동작: 물리 서버 펌웨어 패치나 하드웨어 예방 점검 시, 일반 GCE VM은 재부팅 없이 실행 중인 메모리 페이지와 활성 TCP 세션을 유지한 채 인접 물리 호스트로 이동합니다.
- 클러스터 하트비트 튜닝 포인트: Live Migration 최종 전환 순간에 수십~수백 밀리초 수준의 짧은 프리징(Blackout window)이 발생할 수 있습니다. 온프레미스용으로 설계된 자체 HA 솔루션이나 BFD에서 하트비트 타임아웃을 1초 미만으로 극단적으로 짧게 설정하면 오탐 페일오버가 발생할 수 있으므로 최소 3~5초 이상으로 설정하는 것이 안전합니다.
- Terminate 대상 인스턴스 대응: GPU 인스턴스, 대용량 Local SSD 장착 VM, 베어메탈 인스턴스는 Live Migration이 불가하여
TERMINATE정책이 적용됩니다. 이 경우 메타데이터 서버의maintenance-event속성을 주기적으로 폴링하여 사전 드레이닝을 수행해야 합니다.
#!/usr/bin/env bash
# 메타데이터 서버에서 호스트 유지보수 예고(MIGRATE_ON_HOST_MAINTENANCE 또는 TERMINATE_ON_HOST_MAINTENANCE) 감지
EVENT=$(curl -s -H "Metadata-Flavor: Google" \
"http://metadata.google.internal/computeMetadata/v1/instance/maintenance-event")
if [ "$EVENT" != "NONE" ]; then
logger -t gce-maintenance "Host maintenance event detected: ${EVENT}. Starting graceful drain..."
# 로컬 헬스체크 상태를 Unready로 전환하여 로드 밸런서 신규 유입 차단
touch /tmp/unready
fi
1.2 Storage & Image 엔지니어링: Hyperdisk와 Golden Image 파이프라인
스토리지 설계에서 가장 중요한 변화는 디스크 크기(GB)와 성능(IOPS/Throughput)의 결합을 해체한 Hyperdisk의 도입이며, 프로비저닝 속도 및 안정성 측면에서는 부팅 시 패키지 설치를 배제한 Golden Image 파이프라인 구축이 핵심입니다.
| 비교 항목 | Persistent Disk (pd-balanced, pd-ssd) |
Google Cloud Hyperdisk (hyperdisk-balanced, hyperdisk-extreme) |
|---|---|---|
| 성능 결정 구조 | 디스크 할당 용량(GB) 및 VM vCPU 수에 비례하여 IOPS와 처리량이 선형적으로 고정됨 | 용량(GB)과 성능(IOPS, MB/s)이 완전히 분리됨 (소용량 디스크에도 고성능 IOPS 독립 할당 가능) |
| 비용 효율성 | 높은 IOPS를 얻기 위해 실제로는 쓰지 않는 수 TB의 디스크 용량을 과다 할당해야 하는 비용 낭비 발생 | 필요한 용량(예: 100GB)만 할당하고 원하는 IOPS(예: 20,000 IOPS)와 처리량만 정밀하게 프로비저닝 가능 |
| 운영 중 성능 변경 | 성능을 높이려면 디스크 크기를 영구 증설해야 함 (축소 불가) | VM 무중단 상태에서 API / CLI / Terraform으로 IOPS 및 처리량 수치를 동적으로 상향 및 하향 조정 가능 |
| 스토리지 풀 공유 | 개별 디스크 단위로만 프로비저닝 | Hyperdisk Storage Pools를 통해 여러 VM이 사전 확보된 용량과 IOPS 풀을 씬 프로비저닝으로 공유 가능 |
[CI/CD: Cloud Build + HashiCorp Packer]
Base OS Image (Debian/RHEL)
+ OS 보안 패치 및 커널 파라미터(sysctl) 튜닝
+ Google Cloud Ops Agent 사전 설치
+ 런타임(JDK/Node/Python) 및 애플리케이션 아티팩트 내장
===> Custom Golden Image 생성 및 Image Family (예: prod-was-family) 등록
[Runtime: Instance Template + MIG]
Image Family 최신 이미지 참조하여 부팅 (외부 apt/yum/pip 패키지 다운로드 0건)
+ Startup Script: 메타데이터/환경변수 읽기 → 설정 파일 렌더링 → systemctl start (30초 내 기동 완료)
+ Shutdown Script: ACPI 종료 신호 수신 시 최대 90초 내 로컬 큐 드레이닝 및 로그 플러시
apt-get update, 외부 패키지 저장소 다운로드, 빌드 작업을 넣으면 VM 기동에 3~5분 이상 소요될 뿐 아니라 외부 저장소 순단 시 스케일아웃 전체가 실패합니다. 모든 바이너리와 에이전트는 반드시 Golden Image에 사전 베이킹(Baking)해야 합니다.
# VM 재부팅이나 마운트 해제 없이 피크 타임 전에 IOPS와 Throughput을 즉시 상향
gcloud compute disks update prod-db-data-disk \
--zone=asia-northeast3-a \
--provisioned-iops=15000 \
--provisioned-throughput=600
1.3 네트워크 및 보안 베이스라인: Global VPC, 방화벽 설계, OS Login + IAP
타 클라우드의 VPC가 리전(Region) 단위에 귀속되고 서브넷이 가용 영역(AZ)에 종속되는 것과 달리, Google Cloud의 VPC는 글로벌 리소스이며 서브넷(Subnet)은 리전 리소스입니다.
[타 클라우드 VPC 모델] [Google Cloud Global VPC & Regional Subnet 모델]
VPC (Region 종속) Global VPC (전 세계 단일 라우팅 평면, 28-bit VNID 격리)
├── Subnet A (AZ-a 전용: 10.0.1.0/24) └── Regional Subnet (서울 리전: 10.10.0.0/20)
├── Subnet B (AZ-b 전용: 10.0.2.0/24) ├── Zone a VM (10.10.0.12) ─┐
└── Subnet C (AZ-c 전용: 10.0.3.0/24) ├── Zone b VM (10.10.0.13) ─┼─ 동일 /20 대역에서
(존마다 CIDR을 쪼개야 하며 AZ 간 이동 시 IP 변경 필요) └── Zone c VM (10.10.0.14) ─┘ 라우팅 테이블 없이 직결 통신
엔터프라이즈 환경에서는 중앙 네트워크 운영팀이 Shared VPC Host Project에서 서브넷, 방화벽 정책, Cloud Router, Dedicated Interconnect / HA VPN을 통합 통제하고, 각 개발 조직의 Service Project에는 지정된 서브넷에 VM을 배포할 수 있는 roles/compute.networkUser 권한만 위임하여 네트워크 거버넌스와 프로젝트별 IAM 격리를 동시에 달성합니다.
방화벽 식별자 아키텍처 비교: Network Tags vs Service Account vs IAM Tags
| 구분 | Network Tags | Service Account 기반 방화벽 | IAM Tags + Network Firewall Policy |
|---|---|---|---|
| 식별 메커니즘 | VM 인스턴스의 단순 문자열 배열 속성 | VM에 할당된 IAM Service Account 이메일 식별자 | Resource Manager 계층의 키-값 태그 바인딩 (예: env=prod, tier=was) |
| 보안 통제 강도 | 낮음: VM 수정 권한(setTags)이 있는 사용자가 임의로 태그를 부착해 방화벽 우회 가능 |
높음: 해당 Service Account에 대한 iam.serviceAccounts.actAs 권한이 있어야 부여 가능 |
매우 높음 (권장 표준): 태그 값 생성 및 바인딩 권한(resourcemanager.tagUser)을 보안팀이 독점 통제 |
| 운영 제약 및 범위 | 실시간 변경 가능하나 감사 및 강제 통제 불가 | VM의 SA 변경 시 인스턴스 중지(Stop) 필요, VPC Peering 구간 미지원 | 무중단 실시간 변경 가능, 조직/폴더 계층 상속, VPC Peering 및 NGFW 정책 전반 지원 |
Metadata Server 보호 및 OS Login과 IAP Tunneling 접근 통제
- 모든 GCE VM은
169.254.169.254(metadata.google.internal)를 통해 인스턴스 속성과 연결된 Service Account의 단기 OAuth2 토큰을 조회합니다. - 애플리케이션의 SSRF(Server-Side Request Forgery) 취약점을 통한 토큰 탈취를 막기 위해, Google Cloud 메타데이터 서버는 HTTP 요청 헤더에
Metadata-Flavor: Google이 명시되지 않은 모든 요청을 즉시 거부합니다. - 또한 VM 생성 시 레거시
cloud-platform전체 스코프에 과도한 기본 편집자 권한을 주지 않고, 워크로드별 최소 권한 전용 Service Account를 생성해 연결해야 합니다.
- 프로덕션 VM에는 공인 IP를 할당하지 않으며, 별도의 Bastion Host VM도 운영하지 않습니다.
- Google의 Identity-Aware Proxy(IAP) TCP Forwarding 대역인
35.235.240.0/20에서의 인바운드 TCP 22번만 방화벽에서 허용합니다. - 프로젝트 또는 인스턴스 메타데이터에
enable-oslogin=TRUE(필요 시enable-oslogin-2fa=TRUE)를 설정하면, 수동 SSH 키 배포 없이 Cloud Identity 계정 및 IAM 역할(roles/compute.osLogin또는roles/compute.osAdminLogin)이 리눅스 PAM/NSS와 실시간 연동됩니다. 퇴사자 발생 시 IAM 권한만 회수하면 전체 서버 접근이 즉시 차단됩니다.
# 1. Google IAP TCP Forwarding 전용 대역(35.235.240.0/20)에 대해서만 SSH(22) 인바운드 허용
gcloud compute firewall-rules create allow-ssh-from-iap \
--network=prod-vpc \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:22 \
--source-ranges=35.235.240.0/20
# 2. 프로젝트 전체에 OS Login 및 2단계 인증(2FA) 강제 활성화
gcloud compute project-info add-metadata \
--metadata enable-oslogin=TRUE,enable-oslogin-2fa=TRUE
# 3. 공인 IP가 없는 Private VM에 IAP 터널을 통해 안전하게 SSH 접속
gcloud compute ssh prod-was-vm-01 \
--zone=asia-northeast3-a \
--tunnel-through-iap
Session 2 Instance Group 구조 및 라이프사이클 운영
소요 시간: 50분 (00:45 ~ 01:35)2.1 UMIG vs MIG 아키텍처 및 Regional MIG 멀티존 분산 알고리즘
Compute Engine의 인스턴스 그룹은 비관리형(UMIG)과 관리형(MIG)으로 나뉩니다. 프로덕션 환경에서는 단일 존 장애(Zone Outage) 시에도 서비스 연속성을 보장하기 위해 단일 서브넷 위에서 3개 존에 걸쳐 동작하는 Regional MIG를 기본 아키텍처로 채택합니다.
| 비교 항목 | Unmanaged Instance Group (UMIG) | Zonal MIG | Regional MIG (엔터프라이즈 표준) |
|---|---|---|---|
| 구성 방식 | 수동 생성된 이기종 VM들을 임의로 묶은 그룹 | 단일 존 내부에 동일한 Instance Template으로 배포 | 리전 내 복수 존(기본 3개 존)에 걸쳐 동일한 Instance Template으로 자동 분산 배포 |
| 자동화 기능 | Autoscaling, Autohealing, Rolling Update 전부 미지원 | Autoscaling, Autohealing, Rolling/Canary Update 지원 | Autoscaling, Autohealing, Rolling/Canary Update + 존 간 자동 분산 및 장애 격리 지원 |
| 권장 사용처 | 레거시 리프트 앤 시프트 과도기 외에는 사용 지양 | 특정 존에 고정된 단일 데이터베이스와의 초저지연 통신이 필수인 특수 배치 워크로드 | 모든 무상태(Stateless) 웹/WAS, API 서버, 프록시 계층 및 고가용성 클러스터 |
Regional MIG의 Target Distribution Shape 3가지 모드
리전 내 선택된 모든 존에 인스턴스 대수를 정확히 동일하게 유지합니다. 특정 존에 일시적인 하드웨어 용량 부족이 발생하더라도 타 존에 대체 생성하지 않고 해당 존 할당량을 고수합니다. 존별 예약이 100% 확보된 환경에 적합합니다.
기본적으로 존 간 균등 배치를 유지하지만, 특정 존에 장애나 용량 부족이 발생하면 가용한 다른 존에 인스턴스를 우선 프로비저닝하여 전체 목표 대수(Target Size)를 지키는 데 최우선 순위를 둡니다. 미션 크리티컬 서비스에 가장 권장되는 설정입니다.
존 간 균등성보다 가용 용량 확보나 Spot VM 활용, 특정 존의 미사용 예약 리소스 소진을 우선시합니다. 대규모 배치 처리나 단일 존 몰아주기(지연 시간 최소화)가 필요한 워크로드에 사용합니다.
--instance-redistribution-type=NONE으로 비활성화해야 합니다.
2.2 무중단 배포 메커니즘과 Rolling 및 Canary 필수 파라미터
Instance Template은 한 번 생성하면 수정할 수 없는 불변(Immutable) 리소스입니다. 애플리케이션 버전이나 커널 설정을 변경하려면 신규 템플릿(v2)을 생성한 뒤 MIG의 updatePolicy를 통해 무중단 교체를 수행합니다.
[단일 Regional MIG 내 Canary 배포 (다중 템플릿 버전 분할)]
├── versions[0] (Primary): instance-template-v1 (90% 트래픽 처리)
└── versions[1] (Canary) : instance-template-v2 (targetSize: fixed=1 또는 percent=10%)
* 별도의 카나리용 MIG를 추가 생성하거나 LB 설정을 건드릴 필요 없이 단일 MIG 내부에서 카나리 검증 완료!
[검증 완료 후 100% 무중단 Rolling Update (type = PROACTIVE, replacementMethod = SUBSTITUTE)]
1. maxSurge=3 (존당 1대씩 신규 v2 VM 3대 선제 프로비저닝, 기존 v1 VM은 100% 정상 가동 유지)
2. v2 VM 부팅 완료 → Load Balancer Health Check HEALTHY 판정
3. minReadySec=60 (헬스체크 통과 후에도 JVM/애플리케이션 캐시 워밍업을 위해 60초간 추가 대기)
4. maxUnavailable=0 원칙에 따라, 신규 v2 VM이 완전히 준비된 후에만 기존 v1 VM의 Connection Draining 시작
| 업데이트 파라미터 | 권장 프로덕션 설정값 | 내부 동작 원리 및 설계 주의사항 |
|---|---|---|
type |
PROACTIVE |
템플릿 변경 즉시 롤링 교체를 시작합니다. (반면 OPPORTUNISTIC은 즉시 교체하지 않고 추후 스케일아웃이나 Autohealing으로 새 VM이 생성될 때만 새 템플릿을 적용하므로 피크 타임 중 변경 사항만 먼저 반영해 둘 때 유용합니다.) |
replacementMethod |
SUBSTITUTE |
새 이름을 가진 신규 VM을 먼저 생성하여 트래픽을 넘긴 뒤 구버전 VM을 삭제합니다. (RECREATE는 기존 VM을 먼저 종료하고 동일 이름으로 다시 생성하므로 maxSurge=0이 강제되며 다운타임이나 용량 감소가 발생합니다.) |
maxUnavailable |
0 (필수) |
업데이트 도중 목표 대수 대비 감소해도 되는 인스턴스 수입니다. 무중단 배포를 위해서는 반드시 0으로 설정하여 신규 인스턴스가 완전히 준비되기 전에는 기존 인스턴스가 절대 내려가지 않도록 강제해야 합니다. |
maxSurge |
3 이상 (또는 20%) |
업데이트 중 목표 대수를 초과해 임시로 더 생성할 수 있는 인스턴스 수입니다. 3개 존을 사용하는 Regional MIG에서는 최소 3 이상으로 설정해야 3개 존에서 동시에 병렬 교체가 진행되어 배포 속도가 빨라집니다. |
minReadySec |
30 ~ 120초 |
신규 VM이 부팅되고 헬스체크가 HEALTHY로 통과한 직후에도, 다음 배치 교체를 진행하기 전에 추가로 대기할 워밍업 시간(초)입니다. |
# 1단계: 기존 v1을 유지한 채 10% 인스턴스에만 v2 템플릿을 적용하는 Canary 업데이트 시작
gcloud compute instance-groups managed rolling-action start-update prod-was-rmig \
--region=asia-northeast3 \
--version=template=prod-was-tpl-v1 \
--canary-version=template=prod-was-tpl-v2,target-size=10% \
--type=proactive \
--replacement-method=substitute \
--max-surge=3 \
--max-unavailable=0 \
--min-ready=60s
# 2단계: 메트릭 및 에러율 정상 확인 후 전체 인스턴스를 v2로 100% 롤링 전환
gcloud compute instance-groups managed rolling-action start-update prod-was-rmig \
--region=asia-northeast3 \
--version=template=prod-was-tpl-v2 \
--type=proactive \
--replacement-method=substitute \
--max-surge=3 \
--max-unavailable=0 \
--min-ready=60s
2.3 Autoscaling 제어 및 Health Check 이원화 아키텍처
| 구분 | Load Balancer Health Check (Readiness 역할) | Autohealing Health Check (Liveness 역할) |
|---|---|---|
| 검증 목적 | 이 인스턴스가 지금 당장 클라이언트 요청을 정상 처리할 수 있는가? | 이 인스턴스의 데몬이나 OS가 완전히 데드락/크래시되어 VM 자체를 폐기하고 새로 찍어내야 하는가? |
| 실패 시 시스템 동작 | Load Balancer의 라우팅 풀에서만 즉시 제외됨 (VM은 삭제되지 않고 유지되며, 헬스체크가 다시 성공하면 즉시 트래픽 재투입) | MIG가 해당 VM을 강제 삭제(Delete)하고 신규 VM을 처음부터 다시 프로비저닝 (복구에 최소 수 분 소요) |
| 권장 엔드포인트 설계 | /healthz/ready (로컬 캐시 준비 상태, 다운스트림 의존성 상태 및 Graceful Shutdown 시 의도적 503 반환 포함) |
/healthz/live (외부 DB나 타 API 의존성을 배제하고, 오직 로컬 웹/WAS 프로세스 자체의 생존 여부만 가볍게 확인) |
| 권장 주기와 임계치 | 민감하게 설정: 주기 5초, 타임아웃 3초, 연속 실패 2회 (10초 내 장애 노드 트래픽 격리) |
보수적으로 설정: 주기 10~15초, 타임아웃 5초, 연속 실패 3~5회 (30~75초 이상 완전 불능 시에만 재구축) + initialDelaySec=300 |
Autoscaling Scale-in Control 및 Graceful Shutdown
트래픽 피크가 끝난 직후 Autoscaler가 인스턴스를 급격하게 축소(Scale-in)하면, 남은 인스턴스의 로컬 캐시 미스가 급증하거나 짧은 시간 뒤 다시 찾아온 2차 트래픽 스파이크에 대응하지 못합니다. 이를 방지하기 위해 scaleInControl을 설정하여 일정 시간 동안 줄어들 수 있는 최대 인스턴스 수 또는 비율을 제한합니다.
resource "google_compute_region_autoscaler" "was_autoscaler" {
name = "prod-was-autoscaler"
region = "asia-northeast3"
target = google_compute_region_instance_group_manager.was_rmig.id
autoscaling_policy {
min_replicas = 6
max_replicas = 30
cooldown_period = 90
cpu_utilization {
target = 0.65
predictive_method = "OPTIMIZE_AVAILABILITY"
}
# 급격한 축소 방지: 최근 10분(600초) 동안 피크 대수 대비 최대 20%까지만 축소 허용
scale_in_control {
time_window_sec = 600
max_scaled_in_replicas {
percent = 20
}
}
}
}
2.4 Stateful MIG 아키텍처와 3대 구조적 한계
레거시 금융 솔루션, 라이선스가 호스트명/IP에 귀속되는 상용 소프트웨어, 또는 카프카/엘라스틱서치처럼 개별 노드의 고유 디스크와 식별자가 유지되어야 하는 워크로드를 위해 MIG는 Stateful Policy와 Per-instance Configuration(인스턴스별 개별 구성)을 제공합니다.
- 인스턴스 이름 보존: 재생성 후에도 동일한 VM 이름 유지
- 영구 디스크(PD/Hyperdisk) 보존: VM이 Autohealing으로 삭제 후 재생성되더라도 기존 부팅/데이터 디스크를 지우지 않고 새 VM에 그대로 재마운트 (
autoDelete=false자동 관리) - 내부 및 외부 고정 IP 보존: 장애 복구 시에도 동일한 사설/공인 IP 주소 재할당
- 인스턴스별 고유 메타데이터 보존:
node_id=broker-01등 개별 노드의 설정값 유지
- 1. Autoscaling 동시 사용 불가: 각 인스턴스가 고유한 상태와 디스크를 가지므로 자동 수평 확장(Autoscaling)을 활성화할 수 없습니다.
- 2. 교차 존(Cross-Zone) 자동 페일오버 미지원: Stateful MIG의 Autohealing은 장애가 발생한 바로 그 존(Zone) 내부에서만 VM을 재생성하고 Zonal 디스크를 재부착합니다. 특정 존 전체 장애 시 타 존으로 자동 이동하지 않습니다.
- 3. 롤링 업데이트 시
RECREATE강제: 동일한 이름, IP, 디스크를 새 VM에 다시 물려야 하므로 기존 VM을 먼저 내렸다가 올리는RECREATE방식만 사용할 수 있습니다.
gcloud compute instances delete(단일 VM API)로 직접 삭제하면, MIG 컨트롤러는 이를 "예기치 않은 장애로 인한 인스턴스 유실"로 판단하여 즉시 동일한 VM을 다시 생성합니다. 특정 인스턴스를 그룹에서 제거하거나 재구축할 때는 반드시 gcloud compute instance-groups managed delete-instances 또는 recreate-instances(MIG API)를 호출해야 합니다.
Session 3 Cloud Load Balancing 아키텍처 및 트래픽 제어
소요 시간: 55분 (01:35 ~ 02:30)3.1 GCP Load Balancing 내부 아키텍처: GFE, Andromeda SDN, Maglev, Envoy
타 클라우드의 로드 밸런서가 고객의 VPC 서브넷 내부에 네트워크 인터페이스를 가진 가상 어플라이언스(노드)를 프로비저닝하는 방식인 것과 달리, Google Cloud Load Balancing은 고객 VPC 안에 생성되는 개별 장비가 아닙니다. 전 세계 80개 이상의 엣지 PoP에 상시 가동 중인 Google Front End(GFE), Maglev 및 호스트 하이퍼바이저에 내장된 Andromeda SDN에 라우팅 구성을 배포하는 완전한 소프트웨어 정의 아키텍처입니다.
[인터넷 클라이언트 트래픽]
│
(단일 글로벌 Anycast VIP 진입)
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Google Edge PoP (전 세계 80+ 거점 상시 가동 인프라) │
│ • L4 External Passthrough NLB : Maglev (Consistent Hashing + 연결 추적)│
│ • L7 Global External ALB : 1차 GFE 종료 + 분산 Envoy Proxy 계층 │
└─────────────────────────────────────────────────────────────────────────┘
│
(Google 전용 광케이블 백본 - Premium Tier 최단 진입)
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Google Cloud Region & Andromeda SDN (물리 호스트 하이퍼바이저 계층) │
│ • Regional / Internal ALB : 관리형 Envoy 프록시 풀 (Proxy Subnet) │
│ • Internal Passthrough NLB : 프록시 홉 없음! 호스트 가상 스위치 직결│
└─────────────────────────────────────────────────────────────────────────┘
│
▼
[Backend Regional MIG VMs (gVNIC)]
- 사전 워밍(Pre-warming)이 불필요한 이유: 로드 밸런서를 생성하는 것은 새로운 VM 노드를 띄우는 것이 아니라, 이미 초당 수억 건의 글로벌 트래픽을 처리 중인 GFE 및 Maglev 클러스터의 라우팅 테이블에 VIP와 백엔드 엔드포인트 규칙을 등록하는 작업입니다. 따라서 0 RPS에서 100만 RPS로 트래픽이 급증해도 LB 계층의 스케일업 지연이 발생하지 않습니다.
- External Passthrough NLB (Maglev): Google의 분산 소프트웨어 L4 로드 밸런서인 Maglev가 일관된 해싱(Consistent Hashing)과 연결 추적을 통해 패킷을 백엔드 호스트로 분배합니다.
- Internal Passthrough NLB (Andromeda 직결): 중간에 어떤 프록시나 LB 장비도 거치지 않습니다. Andromeda SDN 컨트롤 플레인이 가상 스위치에 직접 매핑 정보를 내려보내어, 클라이언트 VM이 위치한 물리 호스트에서 타겟 백엔드 VM이 위치한 물리 호스트로 패킷이 직접 캡슐화되어 날아갑니다.
- Classic ALB (
EXTERNAL) vs Envoy 기반 ALB (EXTERNAL_MANAGED,INTERNAL_MANAGED): Classic ALB는 기존 GFE 단독 스택에서 동작하며, 신규 표준인 Global/Regional/Internal ALB는 오픈소스 Envoy 프록시 데이터 플레인 위에서 동작합니다. 가중치 기반 카나리 스플리팅, 정규표현식 라우팅, 헤더 조작, 양방향 mTLS, Service Extensions를 사용하려면 반드시 Envoy 기반 스킴(EXTERNAL_MANAGED/INTERNAL_MANAGED)을 선택해야 합니다. - Proxy-only Subnet (
--purpose=REGIONAL_MANAGED_PROXY)의 정체: Regional ALB나 Internal ALB를 생성할 때 VPC 내에/23이상의 Proxy-only Subnet 구성이 필수입니다. 이는 Google이 관리하는 Envoy 프록시 인스턴스들이 고객 VPC 내부의 백엔드 VM으로 새로운 TCP 연결을 맺을 때 출발지 IP(SNAT 주소)로 할당받아 사용하는 전용 주소 풀입니다.
3.2 Proxy LB vs Passthrough LB 패킷 흐름 및 Direct Server Return 원리
네트워크 운영팀이 방화벽 정책, tcpdump 패킷 분석, 클라이언트 원천 IP 보존 아키텍처를 설계할 때 가장 명확히 구분해야 하는 두 가지 데이터 플레인 동작 방식입니다.
| 비교 항목 | Proxy Load Balancer (L7 ALB, L4 Proxy NLB) | Passthrough Load Balancer (External/Internal Passthrough NLB) |
|---|---|---|
| TCP / TLS 세션 종료 | LB(GFE/Envoy)에서 클라이언트의 TCP/TLS 세션을 완전히 종료하고, 백엔드 VM과 별도의 새로운 TCP 연결을 수립함 | LB는 세션을 종료하지 않고 클라이언트가 보낸 원본 패킷(IP/Port 헤더 변조 없음)을 그대로 백엔드 VM에 전달함 |
| 백엔드가 보는 Source IP | Google 프록시/헬스체크 대역 (35.191.0.0/16, 130.211.0.0/22) 또는 VPC 내 Proxy-only Subnet 대역 |
클라이언트의 실제 원본 Source IP가 L3 헤더에 그대로 보존됨 |
| 클라이언트 원천 IP 확인 | L7은 HTTP X-Forwarded-For 헤더, L4 Proxy는 PROXY protocol v1/v2 헤더를 파싱하여 확인 |
별도 헤더 파싱 없이 소켓의 L3 Source IP에서 직접 확인 |
| 백엔드가 보는 Destination IP | 백엔드 VM 자신의 Private NIC IP (예: 10.10.0.15) |
Load Balancer(Forwarding Rule)의 VIP (예: 10.10.0.99 또는 공인 VIP) |
| 응답 패킷 경로 | 백엔드 VM → LB 프록시 → 클라이언트 (대칭 경로) | Direct Server Return (DSR): 백엔드 VM이 LB를 거치지 않고 클라이언트에게 직접 응답 패킷 전송 |
심화 해부: Passthrough LB에서 왜 백엔드 VM은 자기 NIC IP가 아닌 LB VIP 패킷을 드롭하지 않는가?
패스스루 로드 밸런서는 목적지 IP(Destination IP)를 백엔드 VM의 사설 IP로 변환(DNAT)하지 않고, Forwarding Rule의 VIP가 찍힌 상태 그대로 백엔드 호스트에 전달합니다. 일반적인 리눅스 커널이라면 자신의 네트워크 인터페이스 IP가 아닌 패킷을 수신했을 때 이를 즉시 폐기(Drop)해야 정상입니다. GCE에서 이 패킷이 정상 수신되고 DSR 응답이 나가는 원리는 다음과 같습니다:
- 1단계 (Andromeda 캡슐화 전달): Maglev 또는 Andromeda 가상 스위치는 안쪽 패킷의 L3/L4 헤더(Src: 클라이언트 IP, Dst: LB VIP)를 전혀 수정하지 않은 채, 바깥쪽에 Andromeda SDN 터널 헤더만 씌워 타겟 백엔드 VM이 실행 중인 물리 호스트로 전달합니다.
- 2단계 (
google-guest-agent의 로컬 라우트 자동 주입): GCE 표준 OS 이미지 내부에서 실행되는google-guest-agent데몬이 메타데이터 서버를 상시 감시하다가, 해당 VM이 Passthrough LB의 백엔드로 등록되면 리눅스 커널의local라우팅 테이블에 LB VIP를 프로토콜 식별자proto 66으로 자동 등록합니다. - 3단계 (로컬 소켓 수신 및 DSR 직접 응답): 커널의
local테이블에 LB VIP가 등록되어 있으므로 리눅스 커널은 해당 패킷을 자기 자신에게 온 패킷으로 인식하여 애플리케이션 소켓으로 전달합니다. 응답 패킷을 보낼 때도 출발지 IP를 LB VIP로 달아서 클라이언트로 직접 반환(Direct Server Return)합니다.
# google-guest-agent가 리눅스 커널 local 라우팅 테이블에 자동 주입한 LB VIP(proto 66) 확인
ip route show table local proto 66
# [출력 예시]
# local 10.10.0.99 dev eth0 proto 66 scope host
# local 34.64.xxx.xxx dev eth0 proto 66 scope host
google-guest-agent가 비활성화되어 있으면, Passthrough LB 뒤에 연결했을 때 proto 66 로컬 라우트가 생성되지 않아 패킷이 100% 드롭됩니다. 이 경우 루프백(lo)이나 인터페이스에 LB VIP를 수동으로 바인딩해야 합니다.
3.3 L7 ALB & L4 NLB 모듈 구조 해부 및 엔터프라이즈 하이브리드 연동
Google Cloud의 로드 밸런서는 단일 모놀리식 객체가 아니라, 진입점부터 백엔드까지 각 계층이 독립된 리소스로 모듈화되어 조립됩니다.
[L7 Application Load Balancer (Proxy 아키텍처)]
Forwarding Rule (VIP + 수신 포트 + Global Access 설정)
└──> Target HTTP(S) Proxy (TLS 종료, SSL 인증서 및 SSL Policy 매핑)
└──> URL Map (Host/Path/Header 기반 라우팅, 가중치 기반 카나리 트래픽 스플리팅)
└──> Backend Service (Balancing Mode, Timeout, Cloud Armor, Session Affinity, Health Check)
├──> Regional MIG (VM 그룹 단위 부하 분산)
└──> Network Endpoint Group (Zonal/Hybrid/Serverless NEG)
[L4 Passthrough Network Load Balancer (DSR 아키텍처)]
Forwarding Rule (VIP + 프로토콜/포트 또는 --ports=ALL)
└──> Backend Service (CONNECTION Balancing Mode, Health Check) *Target Proxy 및 URL Map 없음!
└──> Regional MIG / Zonal NEG
네트워크 운영팀을 위한 하이브리드 연동 및 Cloud NAT 핵심 아키텍처 3가지
Dedicated Interconnect나 HA VPN 너머의 온프레미스 데이터센터 서버에서 GCP 내부의 Internal ALB/NLB VIP를 호출하려면, Internal Forwarding Rule에 반드시 --allow-global-access 플래그를 활성화해야 합니다. 기본값은 동일 리전 내 클라이언트로만 제한됩니다.
서드파티 보안 장비(Palo Alto, Fortinet 등 NVA)를 MIG로 구성한 뒤 앞단에 Internal Passthrough NLB를 배치하고, VPC 라우팅 테이블의 Next-hop(--next-hop-ilb)으로 지정하면 BGP 수렴 지연 없는 무중단 인라인 보안 구간과 대칭 해싱(Symmetric Hashing)을 구현할 수 있습니다.
Private VM이 외부 단일 목적지(예: 외부 결제/오픈뱅킹 API VIP:443)로 동시 다발적인 연결을 맺을 때 기본 정적 포트(64개)는 즉시 고갈(OUT_OF_RESOURCES)됩니다. 반드시 Dynamic Port Allocation(minPortsPerVm=256~1024, maxPortsPerVm=65536)을 켜고 복수의 공인 NAT IP를 할당해야 합니다.
3.4 LB + MIG 연동 실전 운영: Balancing Mode와 Keep-alive 502 방지 공식
1. Balancing Mode 선택 기준: UTILIZATION vs RATE vs CONNECTION
| Balancing Mode | 적용 가능 LB | 동작 특징 및 프로덕션 설계 가이드 |
|---|---|---|
UTILIZATION |
L7 ALB, L4 Proxy | 백엔드 MIG의 CPU 사용률을 기준으로 트래픽을 배분합니다. 단, 백엔드 애플리케이션이 DB 쿼리나 외부 API 응답 대기로 인해 CPU 사용률은 10%인데 워커 스레드 풀이 고갈된 경우(I/O Bound), LB는 여유가 있다고 판단해 계속 트래픽을 밀어넣어 장애를 확대시킬 수 있습니다. |
RATE (권장) |
L7 ALB 전용 | 인스턴스당 초당 최대 HTTP 요청 수(maxRatePerInstance)를 기준으로 제어합니다. L7 ALB와 MIG 연동 시 가장 예측 가능하고 안전한 모드입니다. 주의할 점은 maxRatePerInstance를 MIG Autoscaler의 목표치보다 1.5~2배 여유 있게 설정하여, 스케일아웃이 완료되기 전에 LB가 트래픽을 과도하게 드롭(503)하거나 타 존으로 스필오버시키지 않도록 설계해야 합니다. |
CONNECTION |
L4 Proxy / Passthrough NLB | 동시 활성 TCP 연결 수를 기준으로 트래픽을 분배합니다. |
2. LB-Backend 간 Keep-alive 타임아웃 미스매치와 502 Bad Gateway 방지 황금 공식
프로덕션 환경에서 간헐적으로 발생하는 502 Bad Gateway 에러의 90% 이상은 로드 밸런서와 백엔드 웹/WAS 서버 간의 HTTP Keep-alive 유휴 타임아웃(Idle Timeout) 불일치로 인한 TCP Race Condition 때문에 발생합니다.
[L7 Application Load Balancer (GFE / Envoy)] [Backend VM (Nginx / Tomcat / Node.js / Gunicorn)]
* 백엔드 Keep-Alive 유휴 타임아웃 = 600초 고정! * 기본 Keep-Alive 타임아웃 = 2초 ~ 65초 (LB보다 짧음!)
│ │
│ <══════════════ HTTP/1.1 Keep-Alive 유휴 소켓 유지 ═══════════════> │
│ │
(유휴 만료 시점)│ ────────────── 1. 백엔드가 유휴 소켓 종료를 위해 TCP FIN 전송 ───── │ (예: 5초/60초 경과)
│ ───── 2. 같은 찰나에 LB가 해당 소켓으로 신규 HTTP POST 요청 전송 ─> │ (네트워크 비행 중 교차!)
│ <───────────── 3. 백엔드 커널이 이미 닫힌 소켓이므로 TCP RST 응답 ── │
✕
[클라이언트에게 502 Bad Gateway 반환!]
Cloud Logging statusDetails: "backend_connection_closed_before_data_sent_to_client"
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ [502 원천 차단 황금 공식] │
│ Backend HTTP Keep-Alive Timeout (권장: 620초) > Load Balancer Keep-Alive Timeout (600초 고정) │
│ * 언제나 백엔드 서버가 아닌 Load Balancer가 먼저 유휴 연결을 정리하도록 백엔드 타임아웃을 더 길게 설정!│
└──────────────────────────────────────────────────────────────────────────────────────────────────────────┘
http {
# GCP L7 ALB의 고정 유휴 타임아웃(600초)보다 길게 설정
keepalive_timeout 620s;
# 단일 Keep-Alive 연결에서 처리할 최대 요청 수 충분히 확보
keepalive_requests 10000;
}
// [Node.js] 기본값 5초(5000ms) -> 620초로 상향 필수!
const server = app.listen(8080);
server.keepAliveTimeout = 620 * 1000; // 620,000 ms
server.headersTimeout = 625 * 1000; // keepAliveTimeout보다 크게
# [Spring Boot application.yml]
# server.tomcat.keep-alive-timeout: 620s
# server.tomcat.max-keep-alive-requests: 10000
Session 4 Day-2 운영, 트러블슈팅 가이드 및 아키텍처 Q&A
소요 시간: 30분 (02:30 ~ 03:00)4.1 Observability 표준화 및 Load Balancer 로그 기반 병목 구간 특정
하이퍼바이저 기본 메트릭만으로는 VM 외부에서 보이는 CPU 사용률과 디스크 I/O만 파악할 수 있습니다. 실제 게스트 OS 내부의 가용 메모리(memory/percent_used), 스왑 사용량, 파일시스템 파티션 여유 공간, 프로세스별 상태를 수집하려면 OpenTelemetry와 Fluent Bit가 통합된 단일 Google Cloud Ops Agent를 Golden Image에 기본 탑재해야 합니다.
네트워크 병목 vs 백엔드 애플리케이션 병목 3초 판별법
간헐적인 응답 지연이 발생했을 때 Cloud Load Balancing 로그의 두 가지 지연 시간 필드를 비교하면 원인이 네트워크/클라이언트 구간인지 백엔드 서버 구간인지 즉시 판별할 수 있습니다:
httpRequest.latency: 전체 왕복 지연 시간클라이언트가 보낸 요청의 첫 번째 바이트가 Google LB(GFE/Envoy)에 도착한 순간부터, LB가 클라이언트에게 응답의 마지막 바이트를 전송 완료할 때까지 걸린 전체 왕복 처리 시간(total_latencies)입니다.
jsonPayload.backend_target_latency: 순수 백엔드 처리 시간LB 프록시가 백엔드 MIG VM으로 요청을 전달하기 시작한 시점부터 백엔드 VM으로부터 응답을 모두 수신할 때까지 걸린 순수 백엔드 처리 시간(backend_latencies)입니다.
- 케이스 A (
total_latencies = 3.05s,backend_latencies = 3.01s): 100% 백엔드 WAS 애플리케이션 또는 뒷단 DB 슬로우 쿼리 병목입니다. - 케이스 B (
total_latencies = 3.20s,backend_latencies = 0.04s): 백엔드 VM은 40ms 만에 응답을 마쳤으나, 클라이언트의 무선 네트워크 품질 저하로 대용량 응답 페이로드 수신이 지연되었거나 클라이언트의 요청 본문 업로드 자체가 느렸던 케이스입니다.
실전 트러블슈팅 치트시트: jsonPayload.statusDetails 핵심 시그니처
jsonPayload.statusDetails 값 |
HTTP 상태 | 정확한 발생 원인 및 엔지니어링 조치 방안 |
|---|---|---|
response_sent_by_backend |
2xx ~ 5xx | LB 및 네트워크 구간 이상 없음. 백엔드 서버가 직접 생성하여 반환한 HTTP 응답 코드입니다 (백엔드 애플리케이션 자체가 500/502/504를 반환한 경우 포함). |
backend_connection_closed_before_data_sent_to_client |
502 | Keep-alive 타임아웃 미스매치 시그니처. LB가 재사용한 유휴 TCP 소켓을 백엔드 서버가 먼저 닫아버림(FIN/RST) → 백엔드 Keep-alive 타임아웃을 620초로 상향합니다. |
failed_to_connect_to_backend |
502 | LB 프록시가 백엔드 VM과 TCP 3-way handshake 수립 자체에 실패함 → 방화벽에서 프록시/헬스체크 대역(35.191.0.0/16, 130.211.0.0/22, Proxy-only Subnet)이 차단되었거나 백엔드 데몬 리스닝 포트가 내려가 있는지 확인합니다. |
backend_timeout |
504 | 백엔드와 TCP 연결은 맺었으나 Backend Service에 설정된 timeoutSec(기본 30초) 이내에 응답 헤더를 받지 못함 → 백엔드 타임아웃 병목을 해결하거나 장기 실행 API인 경우 timeoutSec를 상향합니다. |
failed_to_pick_backend |
502 / 503 | 트래픽을 전달할 수 있는 건강한(Healthy) 백엔드 인스턴스가 0대임 → Health Check 경로/포트/응답 코드 및 인바운드 방화벽 규칙을 즉시 점검합니다. |
client_disconnected_after_partial_response |
499 / - | 백엔드 응답을 모두 전달하기 전에 클라이언트(앱/브라우저)가 자체 타임아웃으로 연결을 먼저 종료함. |
4.2 부팅/네트워크 디버깅 및 Terraform 무중단 코드 패턴
- Serial Console: 커널 패닉,
/etc/fstab오타, 방화벽 실수로 SSH 접속이 불가할 때 하이퍼바이저의 시리얼 포트(ttyS0) 부팅 로그를 실시간 스트리밍하거나 대화형 콘솔(enable-serial-port=TRUE)로 직접 진입해 복구합니다. - Network Intelligence Center (Connectivity Tests): 실제 패킷을 발생시키지 않고도 Andromeda SDN의 제어 플레인 라우팅 테이블과 방화벽 정책을 정적 분석 및 라이브 프로빙하여, 어느 방화벽 규칙이나 라우트 홉에서 패킷이 드롭되는지 수 초 내에 찾아냅니다.
- Terraform의 기본 리소스 교체 순서는
Destroy(기존 삭제) → Create(신규 생성)입니다. - 하지만 현재 MIG가 사용 중인
google_compute_instance_template을 먼저 삭제하려고 하면 GCP API가resourceInUseByAnotherResource에러를 반환하며 배포가 실패합니다. - 따라서 반드시
name_prefix와create_before_destroy = true를 함께 선언하여신규 템플릿 생성 → MIG 롤링 업데이트 참조 변경 → 구버전 템플릿 삭제순서로 동작하도록 강제해야 합니다.
resource "google_compute_instance_template" "was_tpl" {
# 고정 name 대신 name_prefix를 사용하여 변경 시마다 고유한 이름의 새 템플릿 생성
name_prefix = "prod-was-tpl-"
machine_type = "n4-standard-4"
disk {
source_image = "projects/debian-cloud/global/images/family/debian-12"
auto_delete = true
boot = true
disk_type = "hyperdisk-balanced"
disk_size_gb = 50
provisioned_iops = 3600
}
network_interface {
subnetwork = google_compute_subnetwork.was_subnet.id
nic_type = "GVNIC"
# access_config 블록을 생략하여 공인 IP 원천 차단 (Private VM 베이스라인)
}
# 필수: 새 템플릿을 먼저 생성해 MIG에 연결한 뒤 기존 템플릿을 삭제하도록 강제
lifecycle {
create_before_destroy = true
}
}
4.3 아키텍처 & 실무 운영 핵심 Q&A
GCP VPC의 서브넷은 특정 존에 묶이지 않는 리전(Regional) 리소스입니다. 또한 GCP에는 물리적인 인터넷 게이트웨이 객체가 별도로 존재하는 것이 아니라 기본 라우트(0.0.0.0/0 → default-internet-gateway)가 논리적으로 존재하며, VM에 외부 IP가 부여되어 있거나 해당 서브넷에 Cloud NAT가 연결되어 있을 때만 인터넷 아웃바운드 통신이 작동합니다. 따라서 존마다 서브넷 CIDR을 쪼갤 필요가 없어 IP 대역 단편화가 사라지고, Regional MIG가 3개 존에 걸쳐 유연하게 스케일링할 수 있습니다.
바뀌지 않습니다. Global External ALB나 Regional External ALB의 Forwarding Rule에 예약된 고정 외부 IP(Static External IP)를 바인딩하면 해당 Anycast 또는 Regional VIP는 영구적으로 고정됩니다. 하이브리드 전용선으로 연동되는 Internal ALB 역시 지정한 서브넷 내의 특정 고정 사설 IP를 영구 할당할 수 있습니다.
충분히 가능합니다. 단일 Regional MIG의 다중 템플릿 버전 기능(--version + --canary-version)을 사용하여 인스턴스 대수 비율로 카나리를 수행하거나, Envoy 기반 L7 ALB(EXTERNAL_MANAGED / INTERNAL_MANAGED)의 URL Map에서 두 개의 MIG Backend Service 간 가중치 기반 트래픽 스플리팅(Weight-based Traffic Splitting, 예: 95:5)을 설정하면 GKE나 서비스 메시 없이도 요청 단위 비율 제어와 1초 만의 즉시 롤백을 수행할 수 있습니다.
별도 추가 세션 · Optional Add-on 실전 구축, 무중단 배포 및 502 장애 디버깅 Hands-on Lab
본 3시간 과정 외 선택 실습 (+60분)본 핸즈온 랩은 3시간(180분) 본 과정(Session 1~4 이론 및 아키텍처 심화)에는 포함되지 않는 별도 추가 세션(+60분)입니다. 실습 세션을 추가로 편성하거나 교육 종료 후 샌드박스 프로젝트에서 직접 아키텍처를 검증할 때 활용하실 수 있습니다. 리소스 생성 대기로 시간을 소모하지 않도록 Step 1에서는 Terraform으로 전체 베이스라인 인프라를 3분 만에 일괄 구축하고, Step 2~4에서는 보안 접속 검증, 무중단 롤링 업데이트, Keep-alive 502 장애 재현 및 로그 분석에 집중합니다.
Cloud Shell 또는 로컬 터미널에서 실습 레포지토리를 클론하고, Global VPC, 동적 포트 할당이 적용된 Cloud NAT, Private Regional MIG, Envoy 기반 Global External ALB를 한 번에 배포합니다.
git clone https://github.com/hajekim/gcp-infra.git
cd gcp-infra/terraform
export PROJECT_ID=$(gcloud config get-value project)
export REGION="asia-northeast3"
gcloud services enable compute.googleapis.com iap.googleapis.com \
networkmanagement.googleapis.com logging.googleapis.com --project=$PROJECT_ID
terraform init
terraform apply -var="project_id=${PROJECT_ID}" -var="region=${REGION}" -auto-approve
export ALB_VIP=$(terraform output -raw alb_vip)
echo "ALB VIP: http://${ALB_VIP}/"
생성된 MIG 인스턴스는 공인 IP가 전혀 없습니다. IAP TCP Forwarding을 통해 SSH 접속이 이루어지는지 확인하고, Network Intelligence Center의 Connectivity Tests로 Google Health Check 대역에서 백엔드 VM 8080 포트로의 방화벽 및 라우팅 정합성을 검증합니다.
# 1. MIG 내 첫 번째 인스턴스 이름 및 존 확인
VM_INFO=$(gcloud compute instance-groups managed list-instances gce-ws-rmig \
--region=$REGION --format="value(instance.basename(),instance.scope().segment(0))" | head -n 1)
VM_NAME=$(echo $VM_INFO | awk '{print $1}')
VM_ZONE=$(echo $VM_INFO | awk '{print $2}')
# 2. 공인 IP 없이 IAP Tunneling으로 내부 상태 및 Keep-Alive 설정 확인
gcloud compute ssh "$VM_NAME" --zone="$VM_ZONE" --tunnel-through-iap \
--command="systemctl status workshop-app --no-pager && curl -s localhost:8080 | jq ."
# 3. Connectivity Test 생성 및 실행 (Health Check Prober -> Private VM:8080)
gcloud network-management connectivity-tests create hc-to-vm-test \
--source-ip-address=35.191.0.1 \
--destination-instance="projects/${PROJECT_ID}/zones/${VM_ZONE}/instances/${VM_NAME}" \
--destination-port=8080 \
--protocol=TCP
gcloud network-management connectivity-tests describe hc-to-vm-test \
--format="yaml(reachabilityDetails)"
터미널 창 하나에서 실시간 모니터링 스크립트를 실행해 둔 상태로, app_version="v2"를 적용하여 create_before_destroy와 maxUnavailable=0 기반의 무중단 교체가 일어나는 과정을 확인합니다.
# [터미널 1] 실시간 응답 및 버전 모니터링 실행
../scripts/watch_rollout.sh "$ALB_VIP"
# [터미널 2] v2 템플릿 무중단 롤링 업데이트 실행 (create_before_destroy 동작 확인)
terraform apply -var="project_id=${PROJECT_ID}" -var="app_version=v2" -auto-approve
# 롤링 업데이트 진행 상태 실시간 조회
gcloud compute instance-groups managed list-instances gce-ws-rmig --region=$REGION
# [선택] Readiness와 Liveness 분리 확인: 특정 VM만 LB 트래픽에서 즉시 제외(/tmp/unready 생성)
gcloud compute ssh "$VM_NAME" --zone="$VM_ZONE" --tunnel-through-iap \
--command="touch /tmp/unready"
# -> VM은 삭제되지 않고 유지되면서 LB 백엔드에서만 제외됨을 확인 후 복구:
gcloud compute ssh "$VM_NAME" --zone="$VM_ZONE" --tunnel-through-iap \
--command="rm -f /tmp/unready"
백엔드 Keep-Alive 타임아웃을 의도적으로 2초로 낮추어 LB(600초)와의 Race Condition을 유발하고, Cloud Logging에서 backend_connection_closed_before_data_sent_to_client 시그니처를 확인한 뒤 620초로 복구합니다.
# 1. 백엔드 Keep-Alive 타임아웃을 2초로 단축하여 취약한 템플릿 배포
terraform apply -var="project_id=${PROJECT_ID}" -var="app_version=v2-buggy" -var="keepalive_timeout_sec=2" -auto-approve
# 2. 롤링 업데이트 완료 대기
gcloud compute instance-groups managed wait-until --stable gce-ws-rmig --region=$REGION
# 3. 2초 유휴 경계 타이밍에 POST 요청을 보내 502 Bad Gateway 재현
python3 ../scripts/trigger_502_race.py "$ALB_VIP" 1.98
# 4. Cloud Logging에서 502 에러의 정확한 원인(statusDetails) 및 지연 시간 쿼리
gcloud logging read \
'resource.type="http_load_balancer" AND httpRequest.status>=500' \
--limit=5 \
--format="table(timestamp, httpRequest.status, jsonPayload.statusDetails, httpRequest.latency, jsonPayload.backend_target_latency)"
# 5. 황금 공식(Keep-Alive 620초 > LB 600초)으로 복구 후 502 소멸 검증
terraform apply -var="project_id=${PROJECT_ID}" -var="app_version=v2-fixed" -var="keepalive_timeout_sec=620" -auto-approve
gcloud network-management connectivity-tests delete hc-to-vm-test -q || true
terraform destroy -var="project_id=${PROJECT_ID}" -auto-approve