-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
1,141 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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에서 직접 설치하는 페이지에서 호환되는 버전을 찾아서 넣어주시면 됩니다. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" # 예시 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]" | ||
} |
Oops, something went wrong.