Skip to content
Published on

Multi-Cloud 전략 & 마이그레이션 완전 가이드 2025: AWS/GCP/Azure 비교, 하이브리드 클라우드

Authors

목차

1. 왜 Multi-Cloud인가?

클라우드 시장이 성숙해지면서 단일 클라우드 제공자에 모든 워크로드를 집중하는 전략이 점점 더 위험해지고 있습니다. 2025년 기준 Fortune 500 기업의 약 89%가 멀티클라우드 전략을 채택하고 있으며, 평균적으로 2.6개의 퍼블릭 클라우드를 사용합니다.

1.1 벤더 락인(Vendor Lock-in) 리스크

단일 클라우드에 의존할 때 발생하는 핵심 리스크:

  • 가격 협상력 상실: 대안이 없으면 클라우드 제공자의 가격 인상에 종속
  • 서비스 중단 리스크: 2024년 주요 클라우드 제공자별 평균 대형 장애 4.2건 발생
  • 기술 종속: 독점 서비스(AWS Lambda, Azure Functions 등) 사용 시 이전 비용 기하급수적 증가
  • 규제 변화: 데이터 주권법, 규제 변화 시 유연한 대응 불가

1.2 Multi-Cloud를 선택하는 4가지 이유

Best-of-Breed 전략: 각 클라우드의 강점을 활용합니다.

  • AWS: 가장 넓은 서비스 포트폴리오, 엔터프라이즈 생태계
  • GCP: 데이터 분석(BigQuery), AI/ML(Vertex AI), Kubernetes(GKE)
  • Azure: 엔터프라이즈 통합(Active Directory, Office 365), 하이브리드(Azure Arc)

규제 준수(Compliance): 산업/지역별 데이터 요구사항 충족

  • 금융: 특정 데이터는 국내 리전에 저장 의무
  • 의료: HIPAA 준수 가능한 서비스 선택
  • 공공: 정부 전용 클라우드 리전 활용

재해 복구(DR): 클라우드 제공자 수준의 장애 대비

  • 단일 클라우드 DR: 리전 간 복제 (같은 제공자 내)
  • 멀티클라우드 DR: 제공자 간 복제 (AWS 장애 시 GCP로 페일오버)

비용 최적화: 워크로드별 최적 가격 선택

  • 스팟/프리엠티블 인스턴스 가격 차이 활용
  • 커밋 사용 할인(Reserved/Committed Use) 전략적 분배
  • 데이터 이그레스 비용 비교 후 최적 배치

1.3 Multi-Cloud의 현실적 과제

멀티클라우드가 만능은 아닙니다. 반드시 고려해야 할 과제:

과제설명완화 전략
복잡성 증가2-3배의 운영 오버헤드IaC, 통합 관리 플랫폼
인력 부족각 클라우드 전문가 필요추상화 레이어, 교육 투자
네트워크 비용클라우드 간 데이터 전송 비용데이터 지역성 설계
보안 통합서로 다른 IAM/보안 모델Zero Trust, 통합 IdP
일관성 유지서비스별 동작 차이표준화된 추상화 레이어

2. AWS vs GCP vs Azure: 서비스 매핑

2.1 컴퓨팅 서비스 비교

카테고리AWSGCPAzure
가상 머신EC2Compute EngineVirtual Machines
컨테이너 오케스트레이션EKSGKEAKS
서버리스 컨테이너FargateCloud RunContainer Apps
서버리스 함수LambdaCloud FunctionsAzure Functions
배치 처리AWS BatchCloud BatchAzure Batch
앱 플랫폼Elastic BeanstalkApp EngineApp Service
VMware 통합VMware Cloud on AWSGoogle Cloud VMware EngineAzure VMware Solution

2.2 스토리지 서비스 비교

카테고리AWSGCPAzure
오브젝트 스토리지S3Cloud StorageBlob Storage
블록 스토리지EBSPersistent DiskManaged Disks
파일 스토리지EFSFilestoreAzure Files
아카이브S3 GlacierArchive StorageArchive Storage
하이브리드 스토리지Storage GatewayTransfer ApplianceStorSimple

2.3 데이터베이스 서비스 비교

카테고리AWSGCPAzure
관계형 DBRDS, AuroraCloud SQL, AlloyDBAzure SQL, MySQL/PostgreSQL
NoSQL 문서DynamoDBFirestoreCosmos DB
인메모리ElastiCacheMemorystoreAzure Cache for Redis
그래프 DBNeptune-Cosmos DB (Gremlin)
시계열 DBTimestream-Azure Data Explorer
글로벌 분산 DBAurora Global, DynamoDB Global TablesSpannerCosmos DB

2.4 네트워킹 서비스 비교

카테고리AWSGCPAzure
가상 네트워크VPCVPCVNet
로드 밸런서ALB/NLB/GLBCloud Load BalancingAzure Load Balancer/App Gateway
CDNCloudFrontCloud CDNAzure CDN/Front Door
DNSRoute 53Cloud DNSAzure DNS
전용 연결Direct ConnectCloud InterconnectExpressRoute
VPNSite-to-Site VPNCloud VPNVPN Gateway
서비스 메시App MeshTraffic Director-

2.5 AI/ML 서비스 비교

카테고리AWSGCPAzure
ML 플랫폼SageMakerVertex AIAzure ML
LLM 서비스BedrockGemini API, Model GardenAzure OpenAI Service
자연어 처리ComprehendNatural Language AICognitive Services
이미지 분석RekognitionVision AIComputer Vision
음성 처리Transcribe/PollySpeech-to-Text/Text-to-SpeechSpeech Services
추천 시스템PersonalizeRecommendations AIPersonalizer

2.6 데이터 분석 비교

카테고리AWSGCPAzure
데이터 웨어하우스RedshiftBigQuerySynapse Analytics
스트림 처리KinesisDataflowStream Analytics
ETL/ELTGlueDataflow, DataprocData Factory
데이터 카탈로그Glue Data CatalogData CatalogPurview
BI 도구QuickSightLookerPower BI

3. 멀티클라우드 아키텍처 패턴

3.1 Active-Active 패턴

두 개 이상의 클라우드에서 동시에 트래픽을 처리합니다.

                    ┌─────────────────────┐
Global DNS / LB                      (Route 53 / CF)                    └──────────┬──────────┘
                         ┌─────┴─────┐
                         │           │
                    ┌────▼────┐ ┌────▼────┐
AWS    │ │  GCPRegion  │ │ Region                    │         │ │         │
                    │ ┌─────┐ │ │ ┌─────┐ │
                    │ │ K8s │ │ │ │ GKE │ │
                    │ │ EKS │ │ │ │     │ │
                    │ └──┬──┘ │ │ └──┬──┘ │
                    │    │    │ │    │    │
                    │ ┌──▼──┐ │ │ ┌──▼──┐ │
                    │ │ DB  │◄┼─┼─► DB  │ │
                    │ │ RDS │ │ │ │ SQL │ │
                    │ └─────┘ │ │ └─────┘ │
                    └─────────┘ └─────────┘

장점: 최대 가용성, 제로 다운타임 페일오버 단점: 데이터 동기화 복잡성, 높은 비용 적합한 경우: 미션 크리티컬 서비스, 글로벌 서비스

3.2 Active-Passive 패턴

주 클라우드에서 트래픽을 처리하고, 보조 클라우드는 DR 용도로 대기합니다.

                    ┌────────────────────┐
Global DNS                    └────────┬───────────┘
                    ┌────────▼────────┐          ┌────────────────┐
AWS (Active)  │  복제 ──►│  Azure (Passive)                    │                 │          │                │
                    │  ┌───────────┐  │          │  ┌───────────┐ │
                    │  │ Workloads │  │          │  │ Standby   │ │
                    │  └───────────┘  │          │  └───────────┘ │
                    │  ┌───────────┐  │          │  ┌───────────┐ │
                    │  │ Database  │──┼──────────┼─►│ Replica   │ │
                    │  └───────────┘  │          │  └───────────┘ │
                    └─────────────────┘          └────────────────┘

장점: 합리적인 비용, 클라우드 레벨 DR 단점: 페일오버 시 약간의 다운타임, 패시브 리소스 비용 적합한 경우: 높은 가용성 요구하지만 비용에 민감한 경우

3.3 Cloud Bursting 패턴

평소에는 온프레미스/주 클라우드에서 처리하고, 피크 시 보조 클라우드로 확장합니다.

# Kubernetes Federation - Cloud Bursting 예시
apiVersion: types.kubefed.io/v1beta1
kind: FederatedDeployment
metadata:
  name: web-app
  namespace: production
spec:
  template:
    spec:
      replicas: 10
      containers:
        - name: web
          image: registry.example.com/web-app:v2.1
  placement:
    clusters:
      - name: on-prem-cluster
        weight: 70
      - name: aws-eks-cluster
        weight: 20
      - name: gcp-gke-cluster
        weight: 10
  overrides:
    - clusterName: aws-eks-cluster
      clusterOverrides:
        - path: "/spec/replicas"
          value: 5

3.4 Arbitrage(중재) 패턴

워크로드 특성에 따라 가장 비용 효율적인 클라우드에 배치합니다.

# 클라우드 비용 비교 및 자동 배치 예시
class CloudArbitrage:
    def __init__(self):
        self.providers = {
            "aws": AWSProvider(),
            "gcp": GCPProvider(),
            "azure": AzureProvider()
        }

    def find_optimal_placement(self, workload):
        costs = {}
        for name, provider in self.providers.items():
            cost = provider.estimate_cost(
                cpu=workload.cpu_cores,
                memory_gb=workload.memory_gb,
                storage_gb=workload.storage_gb,
                gpu=workload.gpu_type,
                duration_hours=workload.expected_duration,
                region=workload.preferred_region
            )
            costs[name] = cost

        # 비용 대비 성능 점수 계산
        scores = {}
        for name, cost in costs.items():
            perf = self.providers[name].benchmark_score(workload.type)
            scores[name] = perf / cost  # 가성비

        best = max(scores, key=scores.get)
        return best, costs[best], scores[best]

    def auto_schedule(self, workloads):
        placements = []
        for wl in workloads:
            provider, cost, score = self.find_optimal_placement(wl)
            placements.append({
                "workload": wl.name,
                "provider": provider,
                "estimated_cost": cost,
                "efficiency_score": score
            })
        return placements

4. 하이브리드 클라우드 솔루션

4.1 Google Anthos

Anthos는 GKE를 기반으로 온프레미스, AWS, Azure에서도 동일한 Kubernetes 환경을 제공합니다.

# Anthos Config Management - 멀티 클러스터 설정
apiVersion: configmanagement.gke.io/v1
kind: ConfigManagement
metadata:
  name: config-management
spec:
  clusterName: production-cluster
  git:
    syncRepo: https://github.com/org/anthos-config
    syncBranch: main
    secretType: ssh
    policyDir: "policies"
  policyController:
    enabled: true
    templateLibraryInstalled: true
    referentialRulesEnabled: true
  hierarchyController:
    enabled: true
    enablePodTreeLabels: true
    enableHierarchicalResourceQuotas: true

Anthos 핵심 구성 요소:

  • Anthos on GKE: GCP 내 관리형 Kubernetes
  • Anthos on VMware: 온프레미스 vSphere 위에 GKE 실행
  • Anthos on AWS: AWS에서 Anthos 관리형 클러스터
  • Anthos on Azure: Azure에서 Anthos 관리형 클러스터
  • Anthos Config Management: GitOps 기반 멀티 클러스터 정책 관리
  • Anthos Service Mesh: Istio 기반 서비스 메시 통합 관리

4.2 Azure Arc

Azure Arc는 Azure 관리 플레인을 온프레미스, AWS, GCP 등 어디든 확장합니다.

# Azure Arc에 Kubernetes 클러스터 등록
az connectedk8s connect \
  --name production-eks \
  --resource-group multi-cloud-rg \
  --location eastus \
  --tags "environment=production" "cloud=aws"

# Arc 지원 데이터 서비스 배포
az arcdata dc create \
  --name arc-dc \
  --k8s-namespace arc \
  --connectivity-mode indirect \
  --resource-group multi-cloud-rg \
  --location eastus \
  --storage-class managed-premium \
  --profile-name azure-arc-kubeadm

# Arc 지원 SQL Managed Instance
az sql mi-arc create \
  --name sql-prod \
  --resource-group multi-cloud-rg \
  --location eastus \
  --storage-class-data managed-premium \
  --storage-class-logs managed-premium \
  --cores-limit 8 \
  --memory-limit 32Gi \
  --k8s-namespace arc

4.3 AWS EKS Anywhere

EKS Anywhere는 온프레미스에서 AWS EKS와 동일한 Kubernetes를 실행합니다.

# EKS Anywhere 클러스터 설정
apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: Cluster
metadata:
  name: prod-cluster
spec:
  clusterNetwork:
    cniConfig:
      cilium: {}
    pods:
      cidrBlocks:
        - "192.168.0.0/16"
    services:
      cidrBlocks:
        - "10.96.0.0/12"
  controlPlaneConfiguration:
    count: 3
    endpoint:
      host: "10.0.0.100"
    machineGroupRef:
      kind: VSphereMachineConfig
      name: cp-machines
  workerNodeGroupConfigurations:
    - count: 5
      machineGroupRef:
        kind: VSphereMachineConfig
        name: worker-machines
      name: md-0
  kubernetesVersion: "1.29"
  managementCluster:
    name: prod-cluster

4.4 Red Hat OpenShift (하이브리드)

OpenShift는 모든 주요 클라우드와 온프레미스에서 일관된 Kubernetes 플랫폼을 제공합니다.

# OpenShift 멀티클러스터 허브 설정
apiVersion: operator.open-cluster-management.io/v1
kind: MultiClusterHub
metadata:
  name: multiclusterhub
  namespace: open-cluster-management
spec:
  availabilityConfig: High
  enableClusterBackup: true
  overrides:
    components:
      - name: cluster-lifecycle
        enabled: true
      - name: cluster-backup
        enabled: true
      - name: multicluster-engine
        enabled: true
      - name: grc
        enabled: true
      - name: app-lifecycle
        enabled: true

5. 클라우드 마이그레이션 6R 전략

5.1 6R 개요와 의사결정 트리

마이그레이션 대상 워크로드를 분석할 때 6가지 전략(6R) 중 하나를 선택합니다.

워크로드 분석 시작
  비즈니스 가치 있는가? ─── No ──► Retire (폐기)
Yes
  변경 필요한가? ─── No ──► Retain (유지)
Yes
  SaaS로 대체 가능? ─── Yes ──► Repurchase (재구매)
No
  아키텍처 변경 필요? ─── No ──► Rehost (리호스트)
Yes                      또는 Replatform
  완전 재설계 필요? ─── No ──► Replatform (리플랫폼)
Yes
  Refactor (리팩터)

5.2 각 전략 상세

Rehost (Lift and Shift):

  • 기존 애플리케이션을 그대로 클라우드 VM으로 이전
  • 가장 빠르고 리스크가 낮음
  • 클라우드 네이티브 이점은 제한적
  • AWS Application Migration Service, Azure Migrate, Google Migrate for Compute Engine 활용

Replatform (Lift and Reshape):

  • 핵심 아키텍처는 유지하면서 클라우드 서비스 활용
  • 예: 자체 MySQL을 RDS/Cloud SQL로 이전
  • 중간 수준의 노력, 운영 이점 즉시 확보

Refactor (Re-architect):

  • 클라우드 네이티브로 완전 재설계
  • 마이크로서비스, 서버리스, 컨테이너화
  • 가장 높은 노력, 가장 높은 클라우드 이점
  • 장기적 비용 절감과 확장성

Repurchase (Replace):

  • SaaS 제품으로 교체
  • 예: 자체 이메일 서버를 Office 365/Google Workspace로
  • 운영 부담 완전 제거

Retire (폐기):

  • 더 이상 필요 없는 워크로드 제거
  • 평균적으로 전체의 10-20%가 폐기 대상

Retain (유지):

  • 아직 마이그레이션할 준비가 안 된 워크로드
  • 레거시 의존성, 규제 요구사항 등

5.3 마이그레이션 평가 스코어카드

# 마이그레이션 전략 결정 자동화 예시
class MigrationAssessor:
    def assess_workload(self, workload):
        score = {
            "business_value": self._rate_business_value(workload),
            "technical_complexity": self._rate_complexity(workload),
            "cloud_readiness": self._rate_cloud_readiness(workload),
            "data_sensitivity": self._rate_data_sensitivity(workload),
            "dependency_count": len(workload.dependencies),
            "team_skill_level": self._rate_team_skills(workload.team)
        }

        # 전략 추천 로직
        if score["business_value"] < 3:
            return "Retire"
        if score["cloud_readiness"] < 2:
            return "Retain"
        if workload.has_saas_alternative and score["technical_complexity"] > 7:
            return "Repurchase"
        if score["technical_complexity"] < 4 and score["cloud_readiness"] > 6:
            return "Rehost"
        if score["technical_complexity"] < 7:
            return "Replatform"
        return "Refactor"

    def generate_report(self, workloads):
        results = {}
        for wl in workloads:
            strategy = self.assess_workload(wl)
            if strategy not in results:
                results[strategy] = []
            results[strategy].append({
                "name": wl.name,
                "estimated_effort_weeks": self._estimate_effort(wl, strategy),
                "estimated_cost": self._estimate_cost(wl, strategy),
                "risk_level": self._assess_risk(wl, strategy)
            })
        return results

6. 마이그레이션 계획 수립

6.1 디스커버리와 의존성 매핑

마이그레이션 전 현재 환경을 정확히 파악하는 것이 핵심입니다.

# AWS Application Discovery Service 사용
aws discovery start-continuous-export

# 에이전트 기반 수집
aws discovery start-data-collection-by-agent-ids \
  --agent-ids agent-001 agent-002 agent-003

# 서버 의존성 맵 조회
aws discovery describe-agents \
  --filters name=hostName,values=web-server-*,condition=CONTAINS

# 수집된 데이터로 마이그레이션 계획 생성
aws migrationhub-strategy create-assessment \
  --s3bucket migration-data \
  --s3key discovery-export.csv

6.2 TCO (Total Cost of Ownership) 분석

# TCO 비교 분석 프레임워크
class TCOAnalysis:
    def calculate_on_prem_tco(self, infra):
        annual_costs = {
            "hardware": infra.server_count * 8000 / 3,  # 3년 감가상각
            "software_licenses": infra.license_costs,
            "datacenter": infra.rack_units * 1200,  # 전력, 냉각, 공간
            "network": infra.bandwidth_gbps * 500,
            "personnel": infra.fte_count * 120000,
            "maintenance": infra.server_count * 2400,
            "disaster_recovery": infra.dr_cost_annual,
            "security": infra.security_cost_annual,
            "compliance": infra.compliance_cost_annual
        }
        return sum(annual_costs.values()), annual_costs

    def calculate_cloud_tco(self, workloads, provider="aws"):
        annual_costs = {
            "compute": self._estimate_compute(workloads, provider),
            "storage": self._estimate_storage(workloads, provider),
            "network": self._estimate_network(workloads, provider),
            "managed_services": self._estimate_managed(workloads, provider),
            "personnel": workloads.cloud_fte * 130000,  # 클라우드 인력
            "migration_amortized": workloads.migration_cost / 3,
            "training": workloads.team_size * 5000,
            "tools": workloads.tool_licenses
        }
        return sum(annual_costs.values()), annual_costs

    def compare(self, infra, workloads):
        on_prem_total, on_prem_detail = self.calculate_on_prem_tco(infra)
        cloud_totals = {}
        for provider in ["aws", "gcp", "azure"]:
            total, detail = self.calculate_cloud_tco(workloads, provider)
            cloud_totals[provider] = {
                "total": total,
                "detail": detail,
                "savings_pct": (on_prem_total - total) / on_prem_total * 100
            }
        return {
            "on_prem": {"total": on_prem_total, "detail": on_prem_detail},
            "cloud": cloud_totals
        }

6.3 마이그레이션 웨이브 계획

대규모 마이그레이션은 웨이브(단계)로 나눠 실행합니다.

웨이브대상전략기간리스크
Wave 0파일럿 (비핵심 앱 2-3개)Rehost4주낮음
Wave 1웹 프론트엔드, 정적 사이트Rehost/Replatform6주낮음
Wave 2API 서버, 마이크로서비스Replatform/Refactor8주중간
Wave 3데이터베이스, 스토리지Replatform6주높음
Wave 4레거시 모놀리스Refactor12주높음
Wave 5최종 전환, 정리-4주중간

7. 데이터 마이그레이션 전략

7.1 온라인 vs 오프라인 마이그레이션

온라인 마이그레이션 (네트워크 전송):

  • 100TB 이하 데이터에 적합
  • 전용 연결(Direct Connect/ExpressRoute) 권장
  • 증분 동기화 가능

오프라인 마이그레이션 (물리적 전송):

  • AWS Snowball / Snowball Edge: 최대 80TB/디바이스
  • AWS Snowmobile: 페타바이트 규모
  • Azure Data Box: 최대 100TB
  • Google Transfer Appliance: 최대 300TB

7.2 데이터베이스 마이그레이션

# AWS DMS (Database Migration Service) 태스크 설정 예시
# 소스: 온프레미스 Oracle, 타겟: Amazon Aurora PostgreSQL
Resources:
  DMSReplicationTask:
    Type: AWS::DMS::ReplicationTask
    Properties:
      MigrationType: full-load-and-cdc
      SourceEndpointArn: !Ref OracleSourceEndpoint
      TargetEndpointArn: !Ref AuroraTargetEndpoint
      ReplicationInstanceArn: !Ref DMSReplicationInstance
      TableMappings: |
        {
          "rules": [
            {
              "rule-type": "selection",
              "rule-id": "1",
              "rule-name": "select-all-tables",
              "object-locator": {
                "schema-name": "PROD_SCHEMA",
                "table-name": "%"
              },
              "rule-action": "include"
            },
            {
              "rule-type": "transformation",
              "rule-id": "2",
              "rule-name": "lowercase-schema",
              "rule-action": "convert-lowercase",
              "rule-target": "schema",
              "object-locator": {
                "schema-name": "PROD_SCHEMA"
              }
            }
          ]
        }
      ReplicationTaskSettings: |
        {
          "TargetMetadata": {
            "SupportLobs": true,
            "FullLobMode": false,
            "LobChunkSize": 64
          },
          "FullLoadSettings": {
            "TargetTablePrepMode": "DROP_AND_CREATE",
            "MaxFullLoadSubTasks": 8
          },
          "Logging": {
            "EnableLogging": true,
            "LogComponents": [
              { "Id": "SOURCE_UNLOAD", "Severity": "LOGGER_SEVERITY_DEFAULT" },
              { "Id": "TARGET_LOAD", "Severity": "LOGGER_SEVERITY_DEFAULT" }
            ]
          }
        }

7.3 스토리지 전송

# AWS에서 GCP로 스토리지 전송
gcloud transfer jobs create \
  --source-agent-pool=transfer-pool \
  --source-s3-bucket=my-aws-bucket \
  --source-s3-region=us-east-1 \
  --destination-gcs-bucket=my-gcp-bucket \
  --schedule-starts=2025-01-15T00:00:00Z \
  --schedule-repeats-every=24h \
  --include-prefixes="data/,backups/" \
  --exclude-prefixes="temp/,logs/"

8. 애플리케이션 마이그레이션 패턴

8.1 Strangler Fig 패턴

기존 모놀리스를 점진적으로 마이크로서비스로 교체합니다.

Phase 1: 프록시 레이어 추가
┌────────────────┐
API Gateway /Load Balancer└───────┬────────┘
┌────────────────┐
Monolith     │  ← 모든 트래픽
  (온프레미스)└────────────────┘

Phase 2: 일부 기능 마이그레이션
┌────────────────┐
API Gateway└───┬────────┬───┘
    │        │
    ▼        ▼
┌──────┐ ┌──────────┐
New  │ │ Monolith │  ← 나머지 트래픽
Auth │ │          │
(Cloud)(온프레미스)└──────┘ └──────────┘

Phase 3: 대부분 마이그레이션 완료
┌────────────────┐
API Gateway└┬──┬──┬──┬──┬───┘
 │  │  │  │  │
 ▼  ▼  ▼  ▼  ▼
┌─┐┌─┐┌─┐┌─┐┌────────┐
A││B││C││D││Monolith│ ← 최소 트래픽
└─┘└─┘└─┘└─┘└────────┘
 (Cloud services)

8.2 Blue-Green 전환

# Kubernetes 기반 Blue-Green 전환 설정
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: web-app-migration
spec:
  replicas: 10
  strategy:
    blueGreen:
      activeService: web-app-active
      previewService: web-app-preview
      autoPromotionEnabled: false
      prePromotionAnalysis:
        templates:
          - templateName: migration-validation
        args:
          - name: service-name
            value: web-app-preview
      postPromotionAnalysis:
        templates:
          - templateName: post-migration-check
      scaleDownDelaySeconds: 3600
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
        version: cloud-native
    spec:
      containers:
        - name: web-app
          image: registry.example.com/web-app:v3.0-cloud
          resources:
            requests:
              cpu: "500m"
              memory: "512Mi"
            limits:
              cpu: "1000m"
              memory: "1Gi"

9. 멀티클라우드 네트워킹

9.1 클라우드 간 연결 옵션

┌─────────────────────────────────────────────────────┐
│                 연결 옵션 비교                        │
├────────────────┬──────────┬──────────┬──────────────┤
│                │  대역폭   │ 지연시간  │  비용         │
├────────────────┼──────────┼──────────┼──────────────┤
Public Internet│ 가변적    │ 높음     │ 이그레스 비용  │
VPN (IPsec)1-3 Gbps │ 중간     │ 낮음          │
Dedicated Link10-100Gb │ 낮음     │ 높음 (월정액)Megaport/Equinix│ 유연     │ 낮음     │ 중간          │
└────────────────┴──────────┴──────────┴──────────────┘

9.2 Transit 아키텍처

# Terraform - AWS Transit Gateway와 VPN 설정
resource "aws_ec2_transit_gateway" "main" {
  description                     = "Multi-cloud transit gateway"
  default_route_table_association = "disable"
  default_route_table_propagation = "disable"
  auto_accept_shared_attachments  = "enable"

  tags = {
    Name = "multi-cloud-tgw"
  }
}

resource "aws_vpn_connection" "to_gcp" {
  customer_gateway_id = aws_customer_gateway.gcp.id
  transit_gateway_id  = aws_ec2_transit_gateway.main.id
  type                = "ipsec.1"
  static_routes_only  = false

  tunnel1_inside_cidr   = "169.254.10.0/30"
  tunnel2_inside_cidr   = "169.254.10.4/30"

  tags = {
    Name = "aws-to-gcp-vpn"
  }
}

resource "aws_customer_gateway" "gcp" {
  bgp_asn    = 65000
  ip_address = var.gcp_vpn_gateway_ip
  type       = "ipsec.1"

  tags = {
    Name = "gcp-customer-gateway"
  }
}

9.3 서비스 메시 (멀티클라우드)

# Istio 멀티클러스터 설정 (Primary-Remote)
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: istio-primary
spec:
  values:
    global:
      meshID: multi-cloud-mesh
      multiCluster:
        clusterName: aws-cluster
      network: aws-network
    pilot:
      env:
        EXTERNAL_ISTIOD: "true"
  meshConfig:
    defaultConfig:
      proxyMetadata:
        ISTIO_META_DNS_CAPTURE: "true"
        ISTIO_META_DNS_AUTO_ALLOCATE: "true"
  components:
    ingressGateways:
      - name: istio-eastwestgateway
        label:
          istio: eastwestgateway
          topology.istio.io/network: aws-network
        enabled: true
        k8s:
          env:
            - name: ISTIO_META_REQUESTED_NETWORK_VIEW
              value: aws-network

10. 아이덴티티 페더레이션

10.1 멀티클라우드 IAM 전략

┌─────────────────────────────────────┐
│      중앙 Identity Provider    (Okta / Azure AD / Google)└──────────┬──────────────────────────┘
SAML / OIDC
     ┌─────┼──────┬───────┐
     ▼     ▼      ▼       ▼
  ┌─────┐┌─────┐┌──────┐┌─────────┐
AWS ││ GCP ││Azure ││On-PremIAM ││ IAM ││ AD   ││  LDAP  └─────┘└─────┘└──────┘└─────────┘

10.2 OIDC 기반 클라우드 간 인증

# AWS에서 GCP 리소스 접근 (Workload Identity Federation)
import google.auth
from google.auth import impersonated_credentials
import boto3

class CrossCloudAuth:
    def get_gcp_credentials_from_aws(self):
        # AWS STS에서 현재 자격증명 확인
        sts = boto3.client("sts")
        aws_identity = sts.get_caller_identity()

        # GCP Workload Identity Federation 사용
        # AWS 자격증명으로 GCP 토큰 교환
        credentials, project = google.auth.default(
            scopes=["https://www.googleapis.com/auth/cloud-platform"]
        )

        # 서비스 계정 임퍼소네이션
        target_credentials = impersonated_credentials.Credentials(
            source_credentials=credentials,
            target_principal="cross-cloud@project.iam.gserviceaccount.com",
            target_scopes=["https://www.googleapis.com/auth/cloud-platform"],
            lifetime=3600
        )

        return target_credentials

    def setup_workload_identity_pool(self):
        """GCP Workload Identity Pool 설정 (gcloud CLI)"""
        commands = [
            # 풀 생성
            "gcloud iam workload-identity-pools create aws-pool "
            "--location=global "
            "--description='AWS Workload Identity Pool'",

            # AWS 프로바이더 추가
            "gcloud iam workload-identity-pools providers create-aws aws-provider "
            "--location=global "
            "--workload-identity-pool=aws-pool "
            "--account-id=123456789012",

            # 서비스 계정 바인딩
            "gcloud iam service-accounts add-iam-policy-binding "
            "cross-cloud@project.iam.gserviceaccount.com "
            "--role=roles/iam.workloadIdentityUser "
            "--member='principalSet://iam.googleapis.com/"
            "projects/PROJECT_NUM/locations/global/"
            "workloadIdentityPools/aws-pool/attribute.aws_role/"
            "arn:aws:sts::123456789012:assumed-role/my-role'"
        ]
        return commands

11. 클라우드 네이티브 이식성

11.1 Kubernetes 기반 추상화

# 멀티클라우드 Kubernetes 배포 (Helm values)
# values-aws.yaml
cloud:
  provider: aws
  region: us-east-1
  storageClass: gp3
  ingressClass: alb
  serviceAnnotations:
    service.beta.kubernetes.io/aws-load-balancer-type: nlb
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing

# values-gcp.yaml
cloud:
  provider: gcp
  region: us-central1
  storageClass: pd-ssd
  ingressClass: gce
  serviceAnnotations:
    cloud.google.com/neg: '{"ingress": true}'
    cloud.google.com/backend-config: '{"default": "backend-config"}'

# values-azure.yaml
cloud:
  provider: azure
  region: eastus
  storageClass: managed-premium
  ingressClass: azure-application-gateway
  serviceAnnotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: "false"

11.2 Terraform 멀티클라우드 모듈

# modules/compute/main.tf - 클라우드 추상화 레이어
variable "cloud_provider" {
  type = string
  validation {
    condition     = contains(["aws", "gcp", "azure"], var.cloud_provider)
    error_message = "Supported providers: aws, gcp, azure"
  }
}

variable "instance_config" {
  type = object({
    name          = string
    cpu           = number
    memory_gb     = number
    disk_gb       = number
    os            = string
  })
}

# AWS 구현
module "aws_compute" {
  source = "./aws"
  count  = var.cloud_provider == "aws" ? 1 : 0

  instance_type = local.aws_instance_map[
    "${var.instance_config.cpu}-${var.instance_config.memory_gb}"
  ]
  ami_id      = local.aws_ami_map[var.instance_config.os]
  volume_size = var.instance_config.disk_gb
  name        = var.instance_config.name
}

# GCP 구현
module "gcp_compute" {
  source = "./gcp"
  count  = var.cloud_provider == "gcp" ? 1 : 0

  machine_type = local.gcp_machine_map[
    "${var.instance_config.cpu}-${var.instance_config.memory_gb}"
  ]
  image      = local.gcp_image_map[var.instance_config.os]
  disk_size  = var.instance_config.disk_gb
  name       = var.instance_config.name
}

# Azure 구현
module "azure_compute" {
  source = "./azure"
  count  = var.cloud_provider == "azure" ? 1 : 0

  vm_size     = local.azure_vm_map[
    "${var.instance_config.cpu}-${var.instance_config.memory_gb}"
  ]
  image_ref   = local.azure_image_map[var.instance_config.os]
  disk_size   = var.instance_config.disk_gb
  name        = var.instance_config.name
}

output "instance_id" {
  value = coalesce(
    try(module.aws_compute[0].instance_id, ""),
    try(module.gcp_compute[0].instance_id, ""),
    try(module.azure_compute[0].instance_id, "")
  )
}

11.3 OCI 컨테이너 이미지 전략

# 멀티 스테이지 빌드 - 클라우드 독립적 이미지
FROM golang:1.22-alpine AS builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/server ./cmd/server

# 최종 이미지 - distroless (클라우드 무관)
FROM gcr.io/distroless/static-debian12:nonroot

COPY --from=builder /app/server /server
COPY --from=builder /app/config /config

EXPOSE 8080
USER nonroot:nonroot
ENTRYPOINT ["/server"]

12. 멀티클라우드 재해 복구(DR)

12.1 DR 전략 비교

DR 전략RTORPO비용복잡성
Backup and Restore시간 단위시간 단위낮음낮음
Pilot Light10-30분분 단위중간중간
Warm Standby분 단위초 단위높음높음
Active-Active초 단위거의 0매우 높음매우 높음

12.2 멀티클라우드 DR 구현

# 멀티클라우드 DR 오케스트레이터
class MultiCloudDR:
    def __init__(self):
        self.primary = AWSProvider(region="us-east-1")
        self.secondary = AzureProvider(region="eastus")
        self.health_checker = HealthChecker()

    def execute_failover(self):
        """Primary(AWS) 장애 시 Secondary(Azure)로 전환"""
        steps = [
            self._verify_secondary_health,
            self._promote_database_replica,
            self._update_dns_records,
            self._scale_up_secondary,
            self._verify_application_health,
            self._notify_stakeholders
        ]

        for step in steps:
            result = step()
            if not result.success:
                self._rollback_failover(result.step_index)
                raise FailoverError(f"Failed at step: {step.__name__}")

    def _promote_database_replica(self):
        """Azure SQL 읽기 복제본을 프라이머리로 승격"""
        self.secondary.promote_replica(
            server="dr-sql-server",
            database="production-db",
            failover_group="prod-failover-group"
        )

    def _update_dns_records(self):
        """Route 53 / Azure DNS 레코드 업데이트"""
        self.primary.update_dns(
            zone="example.com",
            record="api.example.com",
            target=self.secondary.get_endpoint(),
            ttl=60
        )

    def continuous_replication(self):
        """지속적 데이터 동기화"""
        replication_config = {
            "database": {
                "type": "async",
                "lag_threshold_seconds": 30,
                "source": "aws-rds-primary",
                "target": "azure-sql-replica"
            },
            "storage": {
                "type": "incremental",
                "interval_minutes": 15,
                "source": "s3://prod-bucket",
                "target": "azure://prod-container"
            },
            "secrets": {
                "type": "sync",
                "source": "aws-secrets-manager",
                "target": "azure-key-vault"
            }
        }
        return replication_config

13. 멀티클라우드 비용 관리

13.1 통합 비용 모니터링

# 멀티클라우드 비용 대시보드 수집기
class MultiCloudCostCollector:
    def collect_all_costs(self, period="monthly"):
        aws_costs = self._get_aws_costs(period)
        gcp_costs = self._get_gcp_costs(period)
        azure_costs = self._get_azure_costs(period)

        return {
            "total": aws_costs["total"] + gcp_costs["total"] + azure_costs["total"],
            "by_provider": {
                "aws": aws_costs,
                "gcp": gcp_costs,
                "azure": azure_costs
            },
            "by_service": self._aggregate_by_service(
                aws_costs, gcp_costs, azure_costs
            ),
            "by_team": self._aggregate_by_tag(
                "team", aws_costs, gcp_costs, azure_costs
            ),
            "anomalies": self._detect_anomalies(
                aws_costs, gcp_costs, azure_costs
            ),
            "recommendations": self._generate_optimization_recommendations(
                aws_costs, gcp_costs, azure_costs
            )
        }

    def _detect_anomalies(self, *provider_costs):
        """비용 이상 감지"""
        anomalies = []
        for costs in provider_costs:
            for service, cost in costs["by_service"].items():
                avg = cost.get("rolling_avg_30d", 0)
                current = cost.get("current", 0)
                if avg > 0 and current > avg * 1.5:
                    anomalies.append({
                        "service": service,
                        "provider": costs["provider"],
                        "current": current,
                        "average": avg,
                        "increase_pct": (current - avg) / avg * 100
                    })
        return anomalies

13.2 비용 최적화 전략

전략절감률적용 대상
Reserved/Committed Use30-60%안정적 워크로드
스팟/프리엠티블 인스턴스60-90%배치, 테스트
자동 스케일링20-40%변동 트래픽
적정 크기(Right-sizing)15-35%모든 워크로드
스토리지 티어링40-70%아카이브 데이터
네트워크 최적화10-30%크로스 클라우드 통신

14. 거버넌스와 컴플라이언스

14.1 멀티클라우드 거버넌스 프레임워크

# Open Policy Agent (OPA) - 멀티클라우드 정책
package multicloud.governance

# 모든 리소스에 필수 태그 요구
required_tags := ["environment", "team", "cost-center", "data-classification"]

deny[msg] {
  resource := input.resource
  tag := required_tags[_]
  not resource.tags[tag]
  msg := sprintf(
    "Resource %v is missing required tag: %v",
    [resource.name, tag]
  )
}

# 데이터 주권 - 특정 데이터는 특정 리전에만 저장
deny[msg] {
  resource := input.resource
  resource.tags["data-classification"] == "pii-kr"
  not startswith(resource.region, "ap-northeast-2")  # 서울
  not startswith(resource.region, "korea")
  msg := sprintf(
    "Korean PII data must be stored in Korea region. Resource %v in %v",
    [resource.name, resource.region]
  )
}

# 비용 한도 초과 방지
deny[msg] {
  resource := input.resource
  resource.type == "compute_instance"
  resource.monthly_cost > 5000
  not resource.tags["approved-high-cost"] == "true"
  msg := sprintf(
    "Instance %v exceeds $5000/month limit. Get approval first.",
    [resource.name]
  )
}

# 암호화 필수
deny[msg] {
  resource := input.resource
  resource.type == "storage_bucket"
  not resource.encryption.enabled
  msg := sprintf(
    "Storage %v must have encryption enabled",
    [resource.name]
  )
}

15. 실전 퀴즈

Q1. 멀티클라우드 아키텍처에서 Active-Active 패턴과 Active-Passive 패턴의 핵심 차이점은 무엇이며, 각각 어떤 상황에 적합한가요?

Active-Active: 두 클라우드가 동시에 트래픽을 처리합니다. 최대 가용성을 제공하지만, 데이터 동기화 복잡성과 비용이 높습니다. 미션 크리티컬 서비스, 글로벌 서비스에 적합합니다.

Active-Passive: 주 클라우드만 트래픽을 처리하고 보조 클라우드는 DR 용도로 대기합니다. 비용이 합리적이지만 페일오버 시 약간의 다운타임이 발생합니다. 높은 가용성은 필요하지만 비용에 민감한 경우 적합합니다.

핵심 차이는 동시 처리 여부와 **페일오버 시간(RTO)**입니다. Active-Active는 RTO가 거의 0이고, Active-Passive는 수분의 RTO를 가집니다.

Q2. 6R 마이그레이션 전략 중 Replatform과 Refactor의 차이를 설명하고, 각각의 적합한 사용 사례를 제시하세요.

Replatform: 핵심 아키텍처는 유지하면서 일부를 클라우드 관리형 서비스로 교체합니다. 예를 들어 자체 MySQL을 Amazon RDS로 이전하거나, 자체 Redis를 ElastiCache로 교체합니다. 중간 수준의 노력으로 운영 이점을 빠르게 얻을 수 있습니다.

Refactor: 클라우드 네이티브로 완전히 재설계합니다. 모놀리스를 마이크로서비스로 분해하거나, 서버리스 아키텍처로 전환합니다. 가장 높은 노력이 필요하지만 장기적으로 최대의 클라우드 이점을 얻습니다.

Replatform은 빠른 성과가 필요할 때, Refactor는 장기적 혁신이 목표일 때 적합합니다.

Q3. Workload Identity Federation이란 무엇이며, 왜 서비스 계정 키보다 안전한가요?

Workload Identity Federation은 외부 IdP(AWS IAM, Azure AD 등)의 자격증명을 GCP의 임시 토큰으로 교환하는 메커니즘입니다.

서비스 계정 키보다 안전한 이유:

  1. 키 관리 불필요: JSON 키 파일을 생성/배포/로테이션할 필요가 없음
  2. 임시 토큰: 교환된 토큰은 1시간 후 자동 만료
  3. 최소 권한: 특정 속성(역할, 태그 등) 기반으로 세밀한 접근 제어
  4. 감사 용이: 모든 토큰 교환이 Cloud Audit Logs에 기록
  5. 유출 리스크 감소: 장기 자격증명이 존재하지 않으므로 유출될 것이 없음
Q4. Strangler Fig 패턴으로 모놀리스를 마이크로서비스로 마이그레이션할 때의 핵심 단계와 주의사항을 설명하세요.

핵심 단계:

  1. 프록시/API Gateway 추가: 모든 트래픽이 게이트웨이를 거치도록 설정
  2. 기능 식별: 분리할 수 있는 바운디드 컨텍스트 식별
  3. 점진적 추출: 하나씩 마이크로서비스로 추출, 게이트웨이에서 라우팅 변경
  4. 데이터 분리: 공유 DB에서 서비스별 DB로 분리
  5. 모놀리스 축소: 모든 기능 추출 후 모놀리스 폐기

주의사항:

  • 데이터베이스 분리가 가장 어려운 부분 - 트랜잭션 일관성 주의
  • 한 번에 너무 많은 서비스를 추출하지 말 것
  • 서비스 간 통신 패턴(동기/비동기) 신중히 결정
  • 모니터링/관찰성을 먼저 구축한 후 마이그레이션 시작
  • 롤백 계획 필수
Q5. 멀티클라우드 환경에서 데이터 이그레스(egress) 비용을 최적화하는 전략을 3가지 이상 제시하세요.
  1. 데이터 지역성(Data Locality) 설계: 처리 엔진을 데이터가 있는 클라우드에 배치. 데이터를 옮기지 말고 컴퓨팅을 옮김
  2. CDN 활용: 클라우드 내부에서 외부로 나가는 트래픽을 CDN으로 캐싱하여 오리진 이그레스 감소
  3. 압축과 프로토콜 최적화: gRPC, Protobuf 등 효율적인 직렬화로 전송 데이터 크기 감소
  4. 전용 연결(Dedicated Interconnect): Direct Connect, ExpressRoute 등을 사용하면 이그레스 비용이 인터넷 대비 낮음
  5. 비동기 배치 전송: 실시간 전송 대신 데이터를 모아서 비피크 시간에 배치 전송
  6. Private Peering: Megaport, Equinix Fabric 등 중립적 교환 포인트를 통해 클라우드 간 직접 피어링

참고 자료

  1. AWS Well-Architected Framework - Multi-Cloud
  2. Google Cloud - Hybrid and Multi-Cloud Patterns
  3. Azure Architecture Center - Multi-Cloud
  4. HashiCorp - Multi-Cloud with Terraform
  5. CNCF Multi-Cloud Reference Architecture
  6. Gartner - Cloud Migration Strategies
  7. AWS Migration Hub Documentation
  8. Google Anthos Documentation
  9. Azure Arc Documentation
  10. Istio Multi-Cluster Documentation
  11. Open Policy Agent Documentation
  12. Kubernetes Federation v2
  13. FinOps Foundation - Multi-Cloud Cost Management