๐ง Multi-Region Infrastructure ๊ด๋ฆฌ ๊ฐ์ด๋
๐ ๊ฐ์โ
Multi-Region Infrastructure์ ์ผ์์ ์ธ ๊ด๋ฆฌ, ์ค์ ๋ณ๊ฒฝ, ๊ทธ๋ฆฌ๊ณ ์ด์ ๋ฐฉ๋ฒ์ ๋ํ ๊ฐ์ด๋์ ๋๋ค.
๐๏ธ ์ค์ ํ์ผ ๊ตฌ์กฐโ
๊ณ์ธต์ ์ค์ ์์โ
shared/common.hcl (์ ์ญ ๊ณตํต)
โฌ๏ธ
`[env]`/env.hcl (ํ๊ฒฝ๋ณ)
โฌ๏ธ
regions/`[region]`/region.hcl (์ง์ญ๋ณ)
โฌ๏ธ
`[service]`/terragrunt.hcl (์๋น์ค๋ณ)
์ค์ ๋ก๋ฉ ํจํดโ
# ๋ชจ๋ ์๋น์ค์์ ํ์ค์ผ๋ก ์ฌ์ฉํ๋ ํจํด
locals {
# ์์ ์ค์ ๋ค ๋ก๋
env_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))
region_vars = read_terragrunt_config("../region.hcl")
# ๋์ ๊ฐ ์ถ์ถ
project_id = local.region_vars.locals.project_id
region = local.region_vars.locals.region
zone = local.region_vars.locals.zone
}
๐ฏ ์๋ก์ด Region ์ถ๊ฐโ
1๋จ๊ณ: ๊ณตํต ์ค์ ์ ๋ฐ์ดํธโ
shared/regions.hcl์ ์ region ์ถ๊ฐโ
locals {
regions = {
# ๊ธฐ์กด regions...
# ์๋ก์ด US Region
"us-central1" = {
region = "us-central1"
zone = "us-central1-a"
timezone = "America/Chicago"
url_suffix = "us"
services = {
cloud_run_region = "us-central1"
cloudsql_region = "us-central1"
redis_region = "us-central1"
scheduler_region = "us-central1"
}
}
}
}
2๋จ๊ณ: ํ๊ฒฝ๋ณ ํ๋ก์ ํธ ๋งคํโ
[env]/env.hcl ์
๋ฐ์ดํธโ
locals {
projects = {
europe = { ... } # ๊ธฐ์กด
asia = { ... } # ๊ธฐ์กด
# ์๋ก์ด US region ์ถ๊ฐ
us = {
project_id = "dta-cloud-us-dev" # ๋๋ ์ ์ ํ naming
project_name = "dta-cloud-us-dev"
region = "us-central1"
zone = "us-central1-a"
timezone = "America/Chicago"
url_suffix = "us"
}
}
# ์๋น์ค URL ์ถ๊ฐ
services = {
europe = { ... } # ๊ธฐ์กด
asia = { ... } # ๊ธฐ์กด
us = {
dta_wide_api_url = "https://dta-wide-api-${local.environment}-us-xxxxxxxx-uc.a.run.app"
}
}
}
3๋จ๊ณ: Region ๋๋ ํ ๋ฆฌ ์์ฑโ
# ์ region ๋๋ ํ ๋ฆฌ ์์ฑ
mkdir -p infrastructure/terragrunt/dev/regions/us-central1
# ๊ธฐ์กด region์์ ๋ณต์ฌ
cp -r infrastructure/terragrunt/dev/regions/europe-west3/* \
infrastructure/terragrunt/dev/regions/us-central1/
# region.hcl ์์
regions/us-central1/region.hclโ
locals {
# ๋ถ๋ชจ ์ค์ ๋ก๋
env_vars = read_terragrunt_config("../../env.hcl").locals
regions_vars = read_terragrunt_config("../../../shared/regions.hcl").locals
# US region ์ค์
current_region = "us-central1"
region_config = local.regions_vars.regions[local.current_region]
# US region ํ๋ก์ ํธ ์ ๋ณด
project_id = local.env_vars.projects.us.project_id
region = local.region_config.region
zone = local.region_config.zone
}
4๋จ๊ณ: ๋ฐฐํฌ ๋ฐ ๊ฒ์ฆโ
# ์๋ก์ด region ๊ฒ์ฆ
terragrunt validate --terragrunt-working-dir dev/regions/us-central1/
# ๋จ๊ณ๋ณ ๋ฐฐํฌ
terragrunt apply --terragrunt-working-dir dev/regions/us-central1/network/
terragrunt apply --terragrunt-working-dir dev/regions/us-central1/cloudsql/
# ... ๊ธฐํ ์๋น์ค๋ค
๐ ํ๊ฒฝ ๊ด๋ฆฌโ
์๋ก์ด Environment ์ถ๊ฐโ
1. ํ๊ฒฝ ๋๋ ํ ๋ฆฌ ์์ฑโ
# ์๋ก์ด ํ๊ฒฝ (์: staging2) ์์ฑ
cp -r infrastructure/terragrunt/dev infrastructure/terragrunt/staging2
2. env.hcl ์ ๋ฐ์ดํธโ
locals {
environment = "staging2"
projects = {
europe = {
project_id = "dta-cloud-de-staging2"
}
asia = {
project_id = "dta-cloud-staging2"
}
}
}
Environment๊ฐ ์ค์ ๋๊ธฐํโ
# Dev์์ Stage๋ก ์ค์ ๋๊ธฐํ
./scripts/sync-env-config.sh dev stage
# ๋ชจ๋ ํ๊ฒฝ์ ๊ณตํต ๋ณ๊ฒฝ์ฌํญ ์ ์ฉ
./scripts/apply-global-changes.sh
๐ ํ๋ก์ ํธ ๊ด๋ฆฌโ
ํ๋ก์ ํธ ์์ฑโ
์๋ ์์ฑ (๊ถ์ฅ)โ
# EU region ํ๋ก์ ํธ
gcloud projects create dta-cloud-de-dev \
--organization=778204568675 \
--name="DTA Cloud DE Dev"
# Asia region ํ๋ก์ ํธ
gcloud projects create dta-cloud-dev \
--organization=778204568675 \
--name="DTA Cloud Dev"
# Billing ๊ณ์ ์ฐ๊ฒฐ
gcloud billing projects link dta-cloud-de-dev \
--billing-account=01A3DE-04193F-06C496
Terragrunt ๊ธฐ๋ฐ ์์ฑโ
# Global project-creation ๋ชจ๋ ์ฌ์ฉ
terragrunt apply --terragrunt-working-dir dev/global/project-creation/
ํ๋ก์ ํธ ๊ถํ ์ค์ โ
# DevOps ํ ๊ถํ ๋ถ์ฌ
gcloud projects add-iam-policy-binding dta-cloud-dev \
--member="user:bok@weltcorp.com" \
--role="roles/editor"
# Service Account ๊ถํ ๋ถ์ฌ
gcloud projects add-iam-policy-binding dta-cloud-dev \
--member="serviceAccount:terraform@dta-cloud-de-dev.iam.gserviceaccount.com" \
--role="roles/editor"
๐ง ์๋น์ค๋ณ ๊ด๋ฆฌโ
Cloud SQL ๊ด๋ฆฌโ
Region๋ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ธ์คํด์คโ
# Europe region
instance_name = "db-dta-wide-${local.environment}-eu"
region = "europe-west3"
# Asia region
instance_name = "db-dta-wide-${local.environment}-asia"
region = "asia-northeast3"
๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ง์ด๊ทธ๋ ์ด์ โ
# Asia region์ ์ด๊ธฐ ์คํค๋ง ์ค์
psql -h <asia-db-ip> -U admin -d dta_wide_0_1_0 < schema.sql
# ๊ธฐ์กด EU ๋ฐ์ดํฐ๋ฅผ Asia๋ก ๋ง์ด๊ทธ๋ ์ด์
(์ ํ์ )
pg_dump -h <eu-db-ip> -U admin dta_wide_0_1_0 | \
psql -h <asia-db-ip> -U admin dta_wide_0_1_0
Redis ์บ์ ๊ด๋ฆฌโ
Region๋ณ ์บ์ ์ ๋ตโ
# ๊ฐ region๋ณ ๋
๋ฆฝ์ ์ธ ์บ์
locals {
redis_configs = {
europe = {
memory_size_gb = 2 # EU ์ฌ์ฉ์ ๋ง์
tier = "STANDARD_HA"
}
asia = {
memory_size_gb = 1 # ์ด๊ธฐ ๋จ๊ณ
tier = "BASIC"
}
}
}
๋คํธ์ํฌ ๊ด๋ฆฌโ
CIDR ๋ฒ์ ๊ด๋ฆฌโ
# Region๋ณ ๊ฒน์น์ง ์๋ IP ๋ฒ์
vpc_cidrs = {
europe = "10.8.0.0/16" # EU VPC
asia = "10.9.0.0/16" # Asia VPC
us = "10.10.0.0/16" # ๋ฏธ๋ US VPC
}
# VPC Connector CIDR
connector_cidrs = {
europe = "10.8.0.0/28" # EU Connector
asia = "10.9.0.0/28" # Asia Connector
us = "10.10.0.0/28" # ๋ฏธ๋ US Connector
}
๐ ์ผ์์ ์ธ ์ด์ ์์ โ
์ค์ ๋ณ๊ฒฝโ
๊ณตํต ์ค์ ๋ณ๊ฒฝโ
# 1. shared/common.hcl ์์
# 2. ๋ชจ๋ ํ๊ฒฝ์ ์ ์ฉ
for env in dev stage prod; do
terragrunt run-all apply --terragrunt-working-dir $env/
done
ํน์ Region ์ค์ ๋ณ๊ฒฝโ
# Asia region CloudSQL ๋ฉ๋ชจ๋ฆฌ ์ฆ๊ฐ
terragrunt apply --terragrunt-working-dir dev/regions/asia-northeast3/cloudsql/
# ํน์ ์๋น์ค๋ง ์
๋ฐ์ดํธ
terragrunt apply --terragrunt-working-dir dev/regions/asia-northeast3/memorystore/
๋ชจ๋ํฐ๋ง ๋ฐ ๋ก๊น โ
Region๋ณ ๋ชจ๋ํฐ๋งโ
# Europe region ์ํ ํ์ธ
gcloud monitoring dashboards list --project=dta-cloud-de-dev
# Asia region ์ํ ํ์ธ
gcloud monitoring dashboards list --project=dta-cloud-dev
ํตํฉ ๋ก๊ทธ ๋ถ์โ
# ๋ชจ๋ region์ ๋ก๊ทธ ํตํฉ ์ฟผ๋ฆฌ
gcloud logging read "
resource.type=cloud_run_revision AND
(resource.labels.project_id=dta-cloud-de-dev OR resource.labels.project_id=dta-cloud-dev)
" --limit=100
๐จ ์ฅ์ ๋์โ
Region๋ณ ์ฅ์ ์๋๋ฆฌ์คโ
Europe Region ์ฅ์ โ
# 1. Asia region์ผ๋ก ํธ๋ํฝ ์ฐํ
gcloud compute url-maps edit dta-wide-global-lb
# 2. ๋ฐ์ดํฐ ๋๊ธฐํ ํ์ธ
# 3. ์๋น์ค ๋ณต๊ตฌ ํ ํธ๋ํฝ ๋ณต์
Asia Region ์ฅ์ โ
# 1. Europe region์์ Asia ์ฌ์ฉ์ ์ฒ๋ฆฌ
# 2. ์บ์ ๋ฐ์ดํฐ ๋ณต๊ตฌ
# 3. ๋จ๊ณ์ ์๋น์ค ๋ณต์
Cross-Region ๋ฐ์ดํฐ ๋ณต๊ตฌโ
# Europe -> Asia ๋ฐ์ดํฐ ๋ณต์
gcloud sql export sql dta-wide-eu-instance gs://backup-bucket/eu-backup.sql \
--project=dta-cloud-de-dev
gcloud sql import sql dta-wide-asia-instance gs://backup-bucket/eu-backup.sql \
--project=dta-cloud-dev
๐ ์ ๋ฐ์ดํธ ๋ฐ ํจ์นโ
Rolling Update ์ ๋ตโ
์๋น์ค๋ณ ์ ๋ฐ์ดํธ ์์โ
- Global Services: APIs, IAM, Firebase
- Network Infrastructure: VPC, Subnets
- Data Services: Cloud SQL, Memorystore
- Compute Services: Cloud Run, Scheduler
- Monitoring: OTEL, Logging
๐ ๏ธ ์ ์ฉํ ์คํฌ๋ฆฝํธโ
์ผ๊ด ๋ฐฐํฌ ์คํฌ๋ฆฝํธโ
#!/bin/bash
# deploy-all-regions.sh
ENVIRONMENT=${1:-dev}
ACTION=${2:-plan}
echo "๐ Deploying $ENVIRONMENT environment..."
# Global services first
echo "๐ฆ Deploying global services..."
terragrunt run-all $ACTION --terragrunt-working-dir $ENVIRONMENT/global/
# Europe region
echo "๐ช๐บ Deploying Europe region..."
terragrunt run-all $ACTION --terragrunt-working-dir $ENVIRONMENT/regions/europe-west3/
# Asia region
echo "๐ฐ๐ท Deploying Asia region..."
terragrunt run-all $ACTION --terragrunt-working-dir $ENVIRONMENT/regions/asia-northeast3/
echo "โ
Deployment completed!"
์ค์ ๊ฒ์ฆ ์คํฌ๋ฆฝํธโ
#!/bin/bash
# validate-all.sh
for env in dev stage prod; do
echo "๐ Validating $env environment..."
# Global services
terragrunt validate --terragrunt-working-dir $env/global/
# Regional services
for region in europe-west3 asia-northeast3; do
echo " ๐ Validating $region..."
terragrunt validate --terragrunt-working-dir $env/regions/$region/
done
done
๋น์ฉ ๋ชจ๋ํฐ๋ง ์คํฌ๋ฆฝํธโ
#!/bin/bash
# cost-monitoring.sh
echo "๐ฐ Multi-Region Cost Analysis"
# Europe region ๋น์ฉ
echo "๐ช๐บ Europe Region Costs:"
gcloud billing budgets list --project=dta-cloud-de-dev
# Asia region ๋น์ฉ
echo "๐ฐ๐ท Asia Region Costs:"
gcloud billing budgets list --project=dta-cloud-dev
# ๋น์ฉ ์๋ฆผ ์ค์
gcloud alpha billing budgets create \
--billing-account=01A3DE-04193F-06C496 \
--display-name="DTA-Wide Multi-Region Budget" \
--budget-amount=500USD
๐ ์ฑ๋ฅ ํ๋โ
Region๋ณ ๋ฆฌ์์ค ์ต์ ํโ
์ฌ์ฉ๋ ๊ธฐ๋ฐ ์กฐ์ โ
# ์ค์ ์ฌ์ฉ๋์ ๋ฐ๋ฅธ ๋์ ์กฐ์
locals {
# ์ฌ์ฉ์ ๋ถํฌ์ ๋ฐ๋ฅธ ๋ฆฌ์์ค ํ ๋น
user_distribution = {
europe = 70 # 70% ์ฌ์ฉ์
asia = 30 # 30% ์ฌ์ฉ์
}
# ๋น๋ก์ ๋ฆฌ์์ค ํ ๋น
instance_configs = {
europe = {
min_instances = ceil(local.user_distribution.europe / 10) # 7๊ฐ
max_instances = local.user_distribution.europe / 5 # 14๊ฐ
}
asia = {
min_instances = ceil(local.user_distribution.asia / 10) # 3๊ฐ
max_instances = local.user_distribution.asia / 5 # 6๊ฐ
}
}
}
์คํ ์ค์ผ์ผ๋ง ์ค์ โ
# Cloud Run ์คํ ์ค์ผ์ผ๋ง ์
๋ฐ์ดํธ
gcloud run services update dta-wide-api \
--region=asia-northeast3 \
--project=dta-cloud-dev \
--min-instances=0 \
--max-instances=5
๐ ๋ณด์ ๊ด๋ฆฌโ
Service Account ๊ด๋ฆฌโ
Cross-Region Service Account ๊ถํโ
# Asia region Service Account๊ฐ EU BigQuery ์ ๊ทผ
gcloud projects add-iam-policy-binding dta-cloud-de-dev \
--member="serviceAccount:dta-wide-api@dta-cloud-dev.iam.gserviceaccount.com" \
--role="roles/bigquery.dataViewer"
๋คํธ์ํฌ ๋ณด์โ
# Region๋ณ ๋ฐฉํ๋ฒฝ ๊ท์น ๊ด๋ฆฌ
gcloud compute firewall-rules create allow-asia-to-eu-db \
--project=dta-cloud-de-dev \
--source-ranges=10.9.0.0/16 \
--allow=tcp:5432 \
--target-tags=cloudsql-asia-access
์ํฌ๋ฆฟ ๊ด๋ฆฌโ
Region๋ณ ์ํฌ๋ฆฟ ๋ณต์ โ
# EU์์ Asia๋ก ์ํฌ๋ฆฟ ๋ณต์
gcloud secrets versions access latest \
--secret=dta-wide-api-key \
--project=dta-cloud-de-dev | \
gcloud secrets create dta-wide-api-key \
--project=dta-cloud-dev \
--data-file=-
๐ ๋ชจ๋ํฐ๋ง ๋ฐ ์๋ฆผโ
Multi-Region ๋์๋ณด๋โ
ํตํฉ ๋ชจ๋ํฐ๋ง ์ค์ โ
# monitoring-config.yaml
dashboards:
- name: "Multi-Region Overview"
widgets:
- title: "EU Region Health"
project: "dta-cloud-de-dev"
metrics: ["cloud_run/request_count", "cloudsql/cpu_utilization"]
- title: "Asia Region Health"
project: "dta-cloud-dev"
metrics: ["cloud_run/request_count", "cloudsql/cpu_utilization"]
- title: "Cross-Region Comparison"
projects: ["dta-cloud-de-dev", "dta-cloud-dev"]
metrics: ["latency", "error_rate", "throughput"]
์๋ฆผ ์ ์ฑ โ
# Region๋ณ ์๋ฆผ ์ ์ฑ
์ค์
gcloud alpha monitoring policies create \
--policy-file=multi-region-alerts.yaml \
--project=dta-cloud-de-dev
# Cross-region ์ฅ์ ์๋ฆผ
gcloud alpha monitoring policies create \
--notification-channels=$SLACK_CHANNEL \
--display-name="Multi-Region Failover Alert"
๐ ๋ฐฑ์ ๋ฐ ๋ณต๊ตฌโ
์๋ ๋ฐฑ์ ์ค์ โ
Cross-Region ๋ฐฑ์ โ
# Cloud SQL ์๋ ๋ฐฑ์
backup_configuration = {
enabled = true
start_time = "02:00" # ๊ฐ region timezone ๊ธฐ์ค
location = "asia-northeast3" # ๋ฐฑ์
์ ์ฅ ์์น
point_in_time_recovery_enabled = true
# Cross-region ๋ฐฑ์
backup_retention_settings = {
retained_backups = 30
retention_unit = "COUNT"
}
}
๋ฐ์ดํฐ ๋๊ธฐํ ์ค์ผ์คโ
# ๋งค์๊ฐ ์ฆ๋ถ ๋๊ธฐํ
0 * * * * /scripts/sync-eu-to-asia.sh
# ๋งค์ผ ์ ์ฒด ๋ฐฑ์
0 2 * * * /scripts/full-backup-cross-region.sh
๐ฏ ์ด์ ์ฒดํฌ๋ฆฌ์คํธโ
์ผ์ผ ์ฒดํฌโ
- ๋ชจ๋ region ์๋น์ค ์ํ ํ์ธ
- ์ง์ฐ์๊ฐ ๋ชจ๋ํฐ๋ง ํ์ธ
- ์๋ฌ์จ ์๊ณ์น ํ์ธ
- ๋น์ฉ ์ฌ์ฉ๋ ํ์ธ
์ฃผ๊ฐ ์ฒดํฌโ
- ๊ฐ region๋ณ ์ฑ๋ฅ ๋ฆฌํฌํธ ๊ฒํ
- ๋ฐฑ์ ์ํ ๊ฒ์ฆ
- ๋ณด์ ์ ๋ฐ์ดํธ ์ ์ฉ
- ์ฉ๋ ๊ณํ ๊ฒํ
์๊ฐ ์ฒดํฌโ
- ๋น์ฉ ์ต์ ํ ๋ถ์
- ์๋ก์ด region ํ์์ฑ ๊ฒํ
- DR(์ฌํด๋ณต๊ตฌ) ํ ์คํธ ์ํ
- ์ํคํ ์ฒ ๊ฐ์ ์ฌํญ ๊ฒํ
๐จ ํธ๋ฌ๋ธ์ํ โ
์ผ๋ฐ์ ์ธ ๋ฌธ์ ๋คโ
์ค์ ๋ฌธ์ โ
# Terragrunt ์ค์ ๊ฒ์ฆ
terragrunt validate --terragrunt-working-dir dev/regions/asia-northeast3/
# ์ข
์์ฑ ๊ทธ๋ํ ํ์ธ
terragrunt graph-dependencies --terragrunt-working-dir dev/
๊ถํ ๋ฌธ์ โ
# Service Account ๊ถํ ํ์ธ
gcloud projects get-iam-policy dta-cloud-dev \
--flatten="bindings[].members" \
--filter="bindings.members:serviceAccount:*"
๋คํธ์ํฌ ์ฐ๊ฒฐ ๋ฌธ์ โ
# VPC Connector ์ํ ํ์ธ
gcloud compute networks vpc-access connectors list \
--region=asia-northeast3 \
--project=dta-cloud-dev
๐ ๊ด๋ จ ๋ฌธ์โ
- Multi-Region ์ํคํ ์ฒ: ์ ์ฒด ๊ตฌ์กฐ ์ดํด
- Multi-Region ๋ฐฐํฌ ๊ฐ์ด๋: ๋ฐฐํฌ ์ ์ฐจ
- Terraform ๊ฐ์ด๋: Terraform ๋ชจ๋ ์ฌ์ฉ๋ฒ
๐ง ๋ฌธ์: DevOps Team (bok@weltcorp.com)