Migration

AWS에서 GCP로 마이그레이션하는 방법 및 고려사항

Somaz 2024. 5. 5. 14:54
728x90
반응형

Overview

작년에 진행했었던 AWS에서 GCP로 마이그레이션 여정에 대해서 정리해보려고 한다.

 

 


 

1. AWS ↔ GCP 리소스 정리

2023.05.05 - [GCP] - GCP vs AWS 리소스 비교

 

GCP vs AWS 리소스 비교

Overview 오늘은 GCP와 AWS의 리소스별 비교를 해보려고 한다. GCP ↔ AWS 리소스 비교 Network Compute Containers Serverless Storage Database Security & Identity 1. Network 멀티리전 - 리전 - 존으로 구분한다. 멀티리전 구

somaz.tistory.com

 

 

기존 AWS 리소스와 GCP 리소스를 간단하게 정리하였다. 

 

Network

  • Virtual Private Cloud = AWS VPC
  • Cloud Firewall = AWS SG, NetworkACL
  • Google Cloud Armor = AWS WAF
  • Cloud NAT = AWS NAT Gateway
  • Cloud Load Balancing = AWS CLB, ELB, ALB
  • Cloud CDN = AWS CloudFront
  • Static External IP = AWS Elastic IP

Compute

  • Compute Engine = AWS EC2

Containers

  • Google Kubernetes Engin(GKE) = AWS EKS
    • GCP GKE Autopilot mode = AWS EKS Fargate (?)
  • Container Registry & Artifact Registry = AWS ECR

Storage

  • Cloud Storage = AWS S3
  • Filestore Instance = AWS EFS

Database

  • Memorystore = AWS ElasticCache
  • Cloud SQL = AWS RDS & Amazon Aurora
  • Cloud Spanner = Amazon Aurora

Security & Identity

  • Secret Manager = AWS Secrets Manager
  • IAM = AWS IAM
  • Certificate Authority Service = AWS Certificate Manager(ACM)

 

2. GCP 공부(IAM, 구조, SDK..)

GCP에서 대해서 공부를 시작하였다. GCP의 IAM을 공부하며 조직-폴더-프로젝트에 구조 그리고 gcloud SDK 설정도 하였다.

 

Shared VPC와 Workload Identity Federation이라는 중요한 개념에 대해서도 알게되었다. 해당 개념을 바탕으로 Host Project와 Service Project를 구분하여 Shared VPC를 구성하였다. 그리고 CICD를 Github Action과 ArgoCD를 사용중인데, Github Action에서 서비스 어카운트를 사용하지 않고 Workload Identity Federation을 통해 임시 토큰을 생성해서 CICD를 구성할 수 있게되었다.

 

2023.04.06 - [GCP] - GCP란? - 서비스 계정 & Project 생성 / SDK(gcloud) 설치

 

GCP란? - 서비스 계정 & Project 생성 / SDK(gcloud) 설치

Overview 오늘은 GCP에 대해서 공부해보려고 한다. 오늘 실습할 내용은 아래와 같다. 무료 체험판 아이디 생성 Project 생성 서비스 계정 생성 서비스 계정 키 생성 SDK(gcloud) GCP란? GCP는 Google에서 제공

somaz.tistory.com

2023.04.12 - [GCP] - GCP - SDK(gcloud) 계정 2개 등록하기

 

GCP - SDK(gcloud) 계정 2개 등록하기

Overview 오늘은 gcloud 명령어를 사용해 gmail 계정 2개를 등록해보려고 한다. 아직 계정이 없거나 gcloud init을 한번도 하지 않았다면 아래의 게시물을 참조하기 바란다. 2023.04.06 - [GCP] - GCP란? - 서비스

somaz.tistory.com

2023.04.06 - [GCP] - GCP IAM이란?

 

GCP IAM이란?

Overview 오늘은 GCP IAM에 대해서 공부해보려고 한다. GCP IAM이란? Google Identity and Access Management는 클라우드 관리자에게 특정 리소스에 대해 특정 작업을 수행할 수 있는 사람을 결정할 수 있는 권한

somaz.tistory.com

 

 

Terraform으로 간단하게 Workload Identity Federation 생성하는 방법이다.

## Service Account ##
module "service_accounts" {
  source       = "../../modules/service_accounts"
  project_id   = var.project
  names        = ["github-action"]
  display_name = "github-action"
  description  = "github-action admin"
}

## Workload Identity Federation ##

data "google_service_account" "github-action" {
  account_id = "github-action"

  depends_on = [module.service_accounts]
}

module "workload_identity_federation" {
  source      = "../../modules/workload_identity_federation"
  project_id  = var.project
  pool_id     = "pool-github-action"
  provider_id = "provider-github-action"

  attribute_mapping = {
    "google.subject"       = "assertion.sub"
    "attribute.actor"      = "assertion.actor"
    "attribute.aud"        = "assertion.aud"
    "attribute.repository" = "assertion.repository"
  }
  issuer_uri = "https://token.actions.githubusercontent.com"

  service_accounts = [
    {
      name           = data.google_service_account.github-action.name
      attribute      = "attribute.repository/somaz94/*"
      all_identities = true
    },
    {
      name           = data.google_service_account.github-action.name
      attribute      = "attribute.repository/somaz94-ai/*"
      all_identities = true
    }
  ]
}

 

 

3. AWS ↔ GCP DNS Migration 준비

AWS Route53에서 사용하고 있는 DNS를 전부 정리하였고, GCP에 동일하게 생성하였다. 그리고 AWS에서 서브도메인을 생성해 GCP에 생성한 서브도메인 Zone의 NS를 바라보게 설정해서 위임하였다.

Hosting.kr → AWS Route53 → GCP Cloud DNS(서브 도메인)

서브도메인을 생성한 이유는 모든 DNS를 Migration하려면 결국 Production을 옮길때 전부다 옮겨줄 수 있기 때문이다.

최종적으로는 AWS Route53을 바라보고 있는 도메인을 GCP Cloud DNS를 바라보게 설정해줘야 한다.

Hosting.kr → AWS Route53 / Hosting.kr → GCP Cloud DNS

 

 

4. Terraform 공부 및 리소스 생성

GCP에선 Terraform을 사용해서 모든 리소스를 관리하려고 하였다. 따라서 Terraform 공부가 필요했고 여러개의 기술 블로그와 Terraform Docs, Terraform Github Module을 보며 공부하였다.

 

그리고 파일구조에 대해서 고민하였다. 처음에는 리소스별로 파일구조를 구성하였지만, 너무 복잡해지고 디렉토리가 너무 많아졌다. 따라서, 고민한 결과 아래의 구조가 완성되었다.

.
├── LICENSE
├── README.md
├── key
├── modules
│   ├── cloud_armor
│   ├── gcs_buckets
│   ├── gke_autopilot
│   ├── memorystore
│   ├── mysql
│   ├── network
│   │   ├── README.md
│   │   ├── main.tf
│   │   ├── metadata.yaml
│   │   ├── modules
│   │   │   ├── fabric-net-svpc-access
│   │   │   ├── firewall-rules
│   │   │   ├── network-firewall-policy
│   │   │   ├── private-service-connect
│   │   │   ├── routes
│   │   │   ├── routes-beta
│   │   │   ├── subnets
│   │   │   ├── subnets-beta
│   │   │   ├── vpc
│   │   │   └── vpc-serverless-connector-beta
│   │   ├── outputs.tf
│   │   ├── variables.tf
│   │   └── versions.tf
│   ├── network_peering
│   ├── postgresql
│   ├── private_service_access
│   ├── secret_manager
│   ├── service_accounts
│   └── workload_identity_federation
└── project
    ├── somaz-ai-project
    ├── somaz-bigquery-project
    ├── somaz-host-project
    └── somaz-service-project
        ├── dev
        ├── prod
        └── qa

https://github.com/somaz94/terraform-infra-gcp

 

GitHub - somaz94/terraform-infra-gcp: This is an example of a Terraform GCP Infrastructure as Code

This is an example of a Terraform GCP Infrastructure as Code - somaz94/terraform-infra-gcp

github.com

 

리소스를 구성하면서 특이사항이 있었는데 AWS EFS와 유사한 기능을 가지고 있는 Firestore Instance를 구성하였지만, SSD 최소 크기가 2.5TB라서 비용문제가 있기 때문에 사용하지 못하게 되었다.
https://cloud.google.com/filestore/docs/creating-instances?hl=ko#allocate_capacity

 

따라서 Compute Engine을 만들어 NFS Server를 아래와 같이 구성하였다.

## Compute Engine ##
resource "google_compute_address" "nfs_server_ip" {
  name = var.nfs_server_ip
}

resource "google_compute_disk" "additional_pd_balanced" {
  name = "nfs-disk"
  type = "pd-balanced"
  zone = "${var.region}-a"
  size = 1000
}

resource "google_compute_instance" "nfs_server" {
  name                      = var.nfs_server
  machine_type              = "e2-standard-2"
  labels                    = local.default_labels
  zone                      = "${var.region}-a"
  allow_stopping_for_update = true

  tags = [var.nfs_server]

  boot_disk {
    initialize_params {
      image = "ubuntu-os-cloud/ubuntu-2004-lts"
    }
  }

  attached_disk {
    source      = google_compute_disk.additional_pd_balanced.self_link
    device_name = google_compute_disk.additional_pd_balanced.name
  }

  metadata = {
    ssh-keys = "somaz:${file("../../key/somaz-nfs-server.pub")}" # Change somaz (your compute engine user)
  }

  metadata_startup_script = <<-EOF
      #!/bin/bash
      sudo apt-get update
      sudo apt-get install -y nfs-kernel-server
      sudo mkdir /nfs
      sudo mkfs.xfs /dev/sdb
      echo -e '/dev/sdb /nfs xfs defaults,nofail 0 0' | sudo tee -a /etc/fstab
      sudo mount -a
      EOF

  network_interface {
    network    = var.shared_vpc
    subnetwork = "${var.subnet_share}-mgmt-a"

    access_config {
      ## Include this section to give the VM an external ip ##
      nat_ip = google_compute_address.nfs_server_ip.address

    }
  }

  depends_on = [module.vpc, google_compute_address.nfs_server_ip, google_compute_disk.additional_pd_balanced]
}

 

 

 

5. CICD 구성(Github Action + ArgoCD)

Github Action과 ArgoCD를 사용해서 CICD를 구성하였다. Github Action은 모듈이 잘되어 있어서 크게 어렵지 않았다.

ArgoCD Docs를 읽으면서 구성하였다.

https://github.com/somaz94/cicd-monitoring/tree/main/github-cicd

 

cicd-monitoring/github-cicd at main · somaz94/cicd-monitoring

This is CICD and Monitoring. Contribute to somaz94/cicd-monitoring development by creating an account on GitHub.

github.com

2023.08.09 - [IaC/CI CD Tool] - ArgoCD 설치 AWS & GCP

 

ArgoCD 설치 AWS & GCP

Overview 오늘은 ArgoCD AWS GCP 설치 방법에 대해서 알아보려고 한다. 2023.05.17 - [IaC/CI CD Tool] - ArgoCD란? ArgoCD란? Overview 오늘은 ArgoCD에 대해 공부해보려고 한다. ArgoCD란? Argo CD 는 Kubernetes를 위한 선언적

somaz.tistory.com

https://github.com/somaz94/helm-chart-template/tree/main/gcp

 

helm-chart-template/gcp at main · somaz94/helm-chart-template

This is helm chart template with ArgoCD. Contribute to somaz94/helm-chart-template development by creating an account on GitHub.

github.com

 

 

6. Monitoring 구성

현재 모니터링은 PLG 스택을 사용중이다. PLG 스택은 Prometheus, Loki, Grafana이다. 그리고 Pod마다 Promtail을 SideCar로 붙여서 Loki로 수집하고 Grafana로 시각화 해주고 있다.

2023.02.12 - [교육, 커뮤니티 후기/PKOS 쿠버네티스 스터디] - PKOS 쿠버네티스 스터디 5주차 - 프로메테우스 그라파나

 

PKOS 쿠버네티스 스터디 5주차 - 프로메테우스 그라파나

Overview 가시다님이 진행하시는 쿠버네티스 스터디 5주차가 되었다. 오늘은 프로메테우스와 그라파나에 대하여 공부하는 시간이 되었다. 그림 실습 시라니오는 '24단계 실습으로 정복하는 쿠버네

somaz.tistory.com

https://github.com/somaz94/cicd-monitoring/tree/main/gcp

 

cicd-monitoring/gcp at main · somaz94/cicd-monitoring

This is CICD and Monitoring. Contribute to somaz94/cicd-monitoring development by creating an account on GitHub.

github.com

 

 

7. 마이그레이션 중 어려웠거나 특이사항

  1. GCP 전체구조를 이해하는게 생각보다 오래걸렸다. 조직, 폴더, 프로젝트별로 전부 권한을 줄수가 있었고 심지어 프로젝트가 다르면 A 프로젝트의 API의 권한을 B 프로젝트의 서비스 어카운트 또는 API 어카운트에게 부여해야 했다. 따라서 실행할때마다 권한문제가 자주 발생하였고, 하나씩 확인해가면서 진행하였다.
  2. Terraform을 처음 사용해보았기 때문에 Reference를 많이 찾아보았지만 생각보다 Terraform 구조에 대한 설명이 나와있는 Reference가 많지 않았다. 따라서 최대한 참고하여 나만의 구조를 만들었고, tf 파일은 Resource 별로 분류하였다. 그리고 Terraform Registry DocsTerraform Module이 도움이 많이 되었다. Module과 Resource를 적절하게 섞어서 구성하였다.
    README.md             cloud-nat.tf       firewall.tf           locals.tf                   organization-custom-iam.tf  provider.tf           vpc.tf
    artifact-registry.tf  cloud-storage.tf   gitlab.tf             mgmt.tfvars                 outputs.tf                  terraform-backend.tf  workload-identity-federation.tf
    cloud-dns-lb-ip.tf    compute-engine.tf  kubernetes-engine.tf  mongo-log-blockchain-lb.tf  private-service-access.tf   variables.tf​
  3. GKE를 사용해서 Ingress를 구성할때, backendconfig와 frontendconfig, managedcertificate와 같이 GKE에서만 사용하는 리소스들이 있었다. 그리고 AWS와 다르게 GKE LoadBalancer BackendConfig에 정의된 healthCheck 경로의 requestPath에서 응답을 받지 못하면 Server Error(503)이 발생하였다. health check가 성공해야 외부에서 확인이 가능하다. 그리고 DNS 생성시 static lb ip(ex. somaz-gke-lb-ip)를 생성해주는 것이 좋다.
    apiVersion: networking.gke.io/v1
    kind: ManagedCertificate
    metadata:
      name: argocd-certificate
    spec:
      domains:
        - argocd.somaz.link # Modified your Domain
    ---
    apiVersion: cloud.google.com/v1
    kind: BackendConfig
    metadata:
      name: argocd-backend-config
      namespace: argocd
    spec:
      healthCheck:
        checkIntervalSec: 30
        timeoutSec: 5
        healthyThreshold: 1
        unhealthyThreshold: 2
        type: HTTP
        requestPath: /healthz
        port: 8080
    ---
    apiVersion: networking.gke.io/v1beta1
    kind: FrontendConfig
    metadata:
      name: argocd-frontend-config
      namespace: argocd
    spec:
      redirectToHttps:
        enabled: true
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: argocd-server-ingress
      namespace: argocd
      annotations:
        kubernetes.io/ingress.global-static-ip-name: "somaz-gke-argocd-lb-ip" # Modified global-static-ip-name
        networking.gke.io/managed-certificates: "argocd-certificate"
        kubernetes.io/ingress.class: "gce"
        networking.gke.io/v1beta1.FrontendConfig: argocd-frontend-config
    spec:
      rules:
      - host: argocd.somaz.link # Modified Domain
        http:
          paths:
          - pathType: Prefix
            path: "/"
            backend:
              service:
                name: argocd-server
                port:
                  number: 80​
  4. 다행히 게임을 서비스하고 있어서 점검을 걸고 실시간 마이그레이션을 진행하지 않아도 되었다. 그리고 DNS까지 전체 마이그레이션을 진행해야 했기 때문에 기존 DNS를 사용하려면 실시간 마이그레이션은 불가능하였다. 모든 리소스와 CICD Monitoring 구성을 완료한뒤에, DNS만 변경해주면서 마이그레이션을 진행하였다.
  5. 마이그레이션 완료후에 CDN에 http → https redirect 설정을 해주지 않아서  게임 클라이언트 파일 다운로드 에러가 발생하였다. 다행히 금방 원인을 찾을 수 있었고 아래와 같이 수정하여 해결하였다.
    ## CDN(somaz_link) ##
    resource "google_compute_managed_ssl_certificate" "cdn_lb_certificate" {
      name = "somaz-link-ssl-cert"
      managed {
        domains = [var.somaz_link]
      }
    }
    
    resource "google_compute_backend_bucket" "somaz_link_bucket_backend" {
      name                 = "somaz-link-backend"
      bucket_name          = var.somaz_link
      enable_cdn           = true
      edge_security_policy = module.cloud_armor_region_block.policy_self_link
      compression_mode     = "AUTOMATIC"
      custom_response_headers = [
        "Access-Control-Allow-Origin: *",
        "Access-Control-Allow-Methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE",
        "Access-Control-Allow-Headers: *",
        "Strict-Transport-Security: max-age=31536000",
        "X-Content-Type-Options: nosniff",
        "X-XSS-Protection: 1; mode=block",
        "Referrer-Policy: strict-origin-when-cross-origin"
      ]
      depends_on = [google_storage_bucket.somaz_link, module.cloud_armor_ip_allow]
    }
    
    resource "google_compute_url_map" "somaz_link_http_url_map" {
      name = "somaz-link-http-url-map"
      default_url_redirect {
        https_redirect = true
        strip_query    = false
      }
      depends_on = [google_storage_bucket.somaz_link, google_compute_backend_bucket.somaz_link_bucket_backend]
    }
    
    resource "google_compute_url_map" "somaz_link_https_url_map" {
      name            = "somaz-link-https-url-map"
      default_service = google_compute_backend_bucket.somaz_link_bucket_backend.id
      depends_on      = [google_storage_bucket.somaz_link, google_compute_backend_bucket.somaz_link_bucket_backend]
    }
    
    resource "google_compute_target_http_proxy" "somaz_link_http_proxy" {
      name    = "somaz-link-http-proxy"
      url_map = google_compute_url_map.somaz_link_http_url_map.self_link
    }
    
    resource "google_compute_global_forwarding_rule" "somaz_link_http_forwarding_rule" {
      name       = "somaz-link-http-forwarding-rule"
      target     = google_compute_target_http_proxy.somaz_link_http_proxy.self_link
      port_range = "80"
      ip_address = google_compute_global_address.somaz_link_lb_ip.address
    }
    
    resource "google_compute_target_https_proxy" "somaz_link_https_proxy" {
      name             = "somaz-link-https-proxy"
      url_map          = google_compute_url_map.somaz_link_https_url_map.self_link
      ssl_certificates = [google_compute_managed_ssl_certificate.cdn_lb_certificate.self_link]
    }
    
    resource "google_compute_global_forwarding_rule" "somaz_link_https_forwarding_rule" {
      name       = "somaz-link-https-forwarding-rule"
      target     = google_compute_target_https_proxy.somaz_link_https_proxy.self_link
      port_range = "443"
      ip_address = google_compute_global_address.somaz_link_lb_ip.address
    }​
  6. Helm chart template을 Customize하여 새롭게 작성하는 방법도 필요하였다. 생각보다 오랜시간이 걸렸고, yaml과 helm에 대한 이해도를 높일 수 있었다.
  7. 마지막으로 AWS 전체 인프라를 GCP로 마이그레이션 하면서 인프라와 다양한 Tool에 대한 이해도가 높아졌다. 상당히 좋은 경험이 되었고 한걸음? 성장하는 계기가 되었던 것 같다.

 

 


Reference

728x90
반응형