Skip to content

Commit

Permalink
init terraform gcp
Browse files Browse the repository at this point in the history
  • Loading branch information
area363 committed Jan 22, 2025
1 parent 348d2e0 commit 74a4d62
Show file tree
Hide file tree
Showing 16 changed files with 1,141 additions and 0 deletions.
171 changes: 171 additions & 0 deletions terraform-gcp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# Terraform for EKS cluster

9c-infra에서 terraform을 통해 EKS cluster를 구축하는 방법을 다룹니다.

운영계정은 일반 사용자의 경우 권한문제로 막힐수 있으니 개발 계정에서 진행하는 것을 전제로 합니다.

9c-infra의 terraform은 다음과 같이 구성되어 있습니다.

```yaml
terraform
├── environments
│ ├── 9c-internal
│ │ ├── main.tf
│ │ └── provider.tf
│ └── 9c-sample
│ ├── main.tf
│ └── provider.tf
└── modules
└── root
├── addons.tf
├── aws_loadbalancer_controller.tf
├── cluster_autoscaler.tf
├── eks.tf
├── external_dns.tf
├── external_secrets.tf
├── fluent_bit.tf
├── iam.tf
├── irsa.tf
├── loki.tf
├── main.tf
├── node_group.tf
├── subnet_tags.tf
├── variables.tf
└── vpc.tf
```

environments에서 module을 사용해서 cluster를 생성하도록 되어있습니다.

```yaml
terraform/environments/9c-sample/provider.tf
provider "aws" {
region = "us-east-2"
profile = "dev"
}
```

```yaml
terraform/environments/9c-sample/main.tf
terraform {
required_providers {
aws = {
version = ">= 3"
}
}
required_version = ">= 0.13.0"

backend "s3" {
bucket = "terraform-eks-backend"
key = "eks/9c-sample"
region = "us-east-2"
}
}

module "common" {
source = "../../modules/root"

name = "9c-sample"

create_vpc = false

# node group
node_groups = {
"9c-sample-c5_l_2c" = {
instance_types = ["c5.large"]
availability_zone = "us-east-2c"
desired_size = 5
min_size = 0
max_size = 5
capacity_type = "SPOT"
}
"9c-sample-r6g_xl_2c" = {
instance_types = ["r6g.xlarge"]
availability_zone = "us-east-2c"
desired_size = 5
min_size = 0
max_size = 10
capacity_type = "SPOT"
ami_type = "AL2_ARM_64"
}
}

addon_versions = {
"coredns" = "v1.10.1-eksbuild.1"
"kube-proxy" = "v1.27.1-eksbuild.1"
"vpc_cni" = "v1.12.6-eksbuild.2"
"aws_ebs_csi_driver" = "v1.17.0-eksbuild.1"
}
}
```

새롭게 cluster를 생성하고자 할 경우 다음의 순서로 진행합니다.

1. `terraform/environments` 에서 9c-sample을 원하는 이름으로 복사합니다.

```yaml
$ cp terraform/environments/9c-sample terraform/environments/9c-test
```

2. `[main.tf](http://main.tf)` 를 다음과 같이 수정합니다.

```yaml
terraform/environments/9c-test/main.tf
terraform {
required_providers {
aws = {
version = ">= 3"
}
}
required_version = ">= 0.13.0"
backend "s3" {
bucket = "terraform-eks-backend"
key = "eks/9c-test" -> state가 저장될 s3 경로
region = "us-east-2"
}
}
module "common" {
source = "../../modules/root"
name = "9c-test" -> cluster의 이름과 다른 리소스의 prefix
create_vpc = false
# node group
node_groups = {
"9c-test-c5_l_2c" = { -> nodegroup의 이름: cluster 이름이 포함되는 것을 권장
instance_types = ["c5.large"] -> node group의 instance type
availability_zone = "us-east-2c"
desired_size = 5
min_size = 0
max_size = 5
capacity_type = "SPOT" -> 비용 과다지출을 방지하기 위해 권장합니다.
}
"9c-test-r6g_xl_2c" = {
instance_types = ["r6g.xlarge"]
availability_zone = "us-east-2c"
desired_size = 5
min_size = 0
max_size = 1
capacity_type = "SPOT"
ami_type = "AL2_ARM_64" -> graviton instance를 사용하는 경우
}
}
addon_versions = {
"coredns" = "v1.10.1-eksbuild.1"
"kube-proxy" = "v1.27.1-eksbuild.1"
"vpc_cni" = "v1.12.6-eksbuild.2"
"aws_ebs_csi_driver" = "v1.17.0-eksbuild.1"
}
}
```

node group 의 instance type이나 size설정은 필요에 따라 자율적으로 설정합니다.

3. `terraform plan` command를 통해 다른 리소스를 수정 혹은 삭제하는 것이 없는지 먼저 확인합니다.(devops 팀에 확인을 요청해주셔도 됩니다.)
4. 문제가 없을 경우 9c-infra에 PR을 올립니다.
5. 승인되면 `terraform apply` 로 적용하고 merge합니다.

(주의) apply 도중 addon 설치에 실패하는 경우가 간혹 있습니다. 생성한 eks버전에 호환되는 addon 버전이 아니기 때문에 발생하는 이슈로, console에서 직접 설치하는 페이지에서 호환되는 버전을 찾아서 넣어주시면 됩니다.
174 changes: 174 additions & 0 deletions terraform-gcp/environments/internal-gcp/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
##############################################################################
# 1. Terraform 및 Provider 설정
##############################################################################

terraform {
required_version = ">= 1.3.6"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.0"
}
}

# AWS S3 대신 GCS(Google Cloud Storage)를 backend로 사용
backend "gcs" {
bucket = "9c-tfstates" # 기존 예시처럼 동일 버킷 이름 가정
prefix = "gke/9c-internal-v2" # 예: eks/9c-internal-v2 -> gke/9c-internal-v2
}
}

provider "google" {
project = var.project_id
region = var.region
# credentials = file("path/to/credentials.json")
# 또는 애플리케이션 기본 자격증명(Application Default Credentials) 사용
}

##############################################################################
# 2. VPC (네트워크) 및 서브넷 설정
##############################################################################

# 기존 "create_vpc = true" 및 "vpc_name = 9c-internal", "vpc_cidr_block = 10.0.0.0/16"
# AWS에서는 AZ별 퍼블릭/프라이빗 서브넷이 있었지만, GCP에서는 리전 단위 Subnetwork만 생성 예시
##############################################################################

resource "google_compute_network" "vpc" {
name = "9c-internal"
auto_create_subnetworks = false
}

# 하나의 큰 서브넷 혹은 여러 개로 나눌 수도 있음
# 여기서는 AWS에서 사용한 CIDR 중 하나(10.0.0.0/16)를 그대로 사용
resource "google_compute_subnetwork" "main_subnet" {
name = "9c-internal-subnet"
ip_cidr_range = "10.0.0.0/16"
region = var.region
network = google_compute_network.vpc.self_link
private_ip_google_access = true
}

##############################################################################
# 3. GKE 클러스터 설정
##############################################################################

# AWS EKS -> GKE 로 매핑
# - EKS의 addon_versions(VPC CNI, CoreDNS 등)는 GKE에서 자동 제공 혹은 내장
# - EKS의 퍼블릭/프라이빗 엔드포인트 설정은 GKE private_cluster_config로 대응 가능

resource "google_container_cluster" "gke_cluster" {
name = "9c-internal-cluster"
region = var.region
project = var.project_id

network = google_compute_network.vpc.self_link
subnetwork = google_compute_subnetwork.main_subnet.self_link

# GKE의 VPC Native 모드(= Alias IP) 사용 권장
ip_allocation_policy {
use_ip_aliases = true
}

# 예) Private Cluster 로 쓰고 싶다면 (선택사항)
# private_cluster_config {
# enable_private_endpoint = false
# enable_private_nodes = true
# master_ipv4_cidr_block = "172.16.0.0/28"
# }

# 원하는 GKE 버전 채널 (예: STABLE, REGULAR, RAPID)
release_channel {
channel = "STABLE"
}

# 일부 Add-on 설정 (예: GCE PD CSI Driver)
addons_config {
gce_persistent_disk_csi_driver_config {
enabled = true
}
}
}

##############################################################################
# 4. Node Pool 설정 (EKS의 node_groups -> GKE node pools)
##############################################################################
# - AWS SPOT → GCP Preemptible
# - AWS ARM Instance Types(r7g, m6g 등) → GCP Machine Types(e2, n2d, t2d 등)로 매핑
##############################################################################

# 예시: 작은 스펙(r7g.large 등)에 해당 -> t2d-standard-2(2vCPU, 4GB 메모리 등)
resource "google_container_node_pool" "heimdall_spot_2c" {
name = "heimdall-spot-2c"
project = var.project_id
location = var.region
cluster = google_container_cluster.gke_cluster.name

node_config {
preemptible = true # AWS SPOT 대응
machine_type = "t2d-standard-2" # AWS r7g.large 대체 예시
# image_type = "COS_CONTAINERD" # OS 이미지 선택 가능
# service_account = "..." # 노드에 할당할 GCP SA
# labels, taints 등 추가 가능
}

autoscaling {
min_node_count = 0
max_node_count = 15
}

initial_node_count = 1
}


resource "google_container_node_pool" "odin_spot_2c" {
name = "odin-spot-2c"
project = var.project_id
location = var.region
cluster = google_container_cluster.gke_cluster.name

node_config {
preemptible = true
machine_type = "t2d-standard-2"
}

autoscaling {
min_node_count = 0
max_node_count = 15
}

initial_node_count = 1
}


resource "google_container_node_pool" "thor_spot_2c" {
name = "thor-spot-2c"
project = var.project_id
location = var.region
cluster = google_container_cluster.gke_cluster.name

node_config {
preemptible = true
machine_type = "t2d-standard-2"
}

autoscaling {
min_node_count = 0
max_node_count = 15
}

initial_node_count = 1
}

##############################################################################
# 5. 변수 예시 (variables.tf)
##############################################################################
variable "project_id" {
type = string
description = "GCP Project ID"
}

variable "region" {
type = string
description = "GCP Region"
default = "us-east1" # 예시
}
5 changes: 5 additions & 0 deletions terraform-gcp/environments/internal-gcp/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
provider "google" {
project = var.project_id
region = var.region
credentials = file("/path/to/service-account.json")
}
32 changes: 32 additions & 0 deletions terraform-gcp/modules/root/cluster_autoscaler.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
##############################################################################
# 1) GCP Service Account for Cluster Autoscaler
##############################################################################
resource "google_service_account" "cluster_autoscaler" {
account_id = "cluster-autoscaler"
display_name = "Cluster Autoscaler Service Account"
project = var.project_id
}

##############################################################################
# 2) IAM Role Binding
# - CA가 GKE Node Pool을 조작하려면, container.admin 혹은 container.clusterAdmin 등이 필요
##############################################################################
resource "google_project_iam_member" "cluster_autoscaler_container_admin" {
project = var.project_id
role = "roles/container.admin"
member = "serviceAccount:${google_service_account.cluster_autoscaler.email}"
}

# 추가로, GKE 노드 제어에 compute.instanceAdmin 등이 필요한 경우가 있으나,
# 대부분 container.admin 권한에 포함돼 있습니다.

##############################################################################
# 3) Workload Identity 바인딩
# - K8s SA (kube-system/aws-cluster-autoscaler) -> GCP SA
##############################################################################
resource "google_service_account_iam_member" "cluster_autoscaler_wi" {
service_account_id = google_service_account.cluster_autoscaler.name
role = "roles/iam.workloadIdentityUser"

member = "serviceAccount:${var.project_id}.svc.id.goog[kube-system/aws-cluster-autoscaler]"
}
Loading

0 comments on commit 74a4d62

Please sign in to comment.