From b0c9fbae476eb56be93c3309c2c9dcfa1c5586fb Mon Sep 17 00:00:00 2001 From: eedo_y Date: Mon, 6 Apr 2026 11:28:47 +0900 Subject: [PATCH 1/5] =?UTF-8?q?style:=20gitignore=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B0=9C=ED=96=89=20=EC=B6=94=EA=B0=80=20(#12)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- k8s-kustomize/.gitignore | 1 + terraform/environments/prod/terraform.tfvars.example | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/k8s-kustomize/.gitignore b/k8s-kustomize/.gitignore index c53f714..9f01f03 100644 --- a/k8s-kustomize/.gitignore +++ b/k8s-kustomize/.gitignore @@ -3,3 +3,4 @@ # ======================================== platform/**/secrets/*.yaml !platform/**/secrets/*.yaml.example +README.md \ No newline at end of file diff --git a/terraform/environments/prod/terraform.tfvars.example b/terraform/environments/prod/terraform.tfvars.example index 17425e3..bec276a 100644 --- a/terraform/environments/prod/terraform.tfvars.example +++ b/terraform/environments/prod/terraform.tfvars.example @@ -95,4 +95,4 @@ secret_manager_secret_iam_members = { role = "roles/secretmanager.secretAccessor" member = "serviceAccount:example-secrets@example-pinhouse.iam.gserviceaccount.com" } -} \ No newline at end of file +} From 246560fffc40cebdafe1c09bc7ad828bc15823b2 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Mon, 6 Apr 2026 12:00:08 +0900 Subject: [PATCH 2/5] =?UTF-8?q?chore:=20NLB=20=EC=84=A4=EC=A0=95=20NodePor?= =?UTF-8?q?t=20=EB=B0=98=EC=98=81=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(#12)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- terraform/environments/prod/compute.tf | 12 +- terraform/environments/prod/firewall.tf | 53 +++-- terraform/environments/prod/load-balancer.tf | 195 ++++++++++++++---- terraform/environments/prod/outputs.tf | 2 +- .../prod/terraform.tfvars.example | 3 + terraform/environments/prod/variables.tf | 18 ++ 6 files changed, 219 insertions(+), 64 deletions(-) diff --git a/terraform/environments/prod/compute.tf b/terraform/environments/prod/compute.tf index cdff2f0..b257c7a 100644 --- a/terraform/environments/prod/compute.tf +++ b/terraform/environments/prod/compute.tf @@ -75,7 +75,17 @@ module "k8s_worker_nodes" { boot_disk_type = "pd-balanced" enable_external_ip = false startup_script = file("${path.module}/scripts/k8s-worker-init.sh") - tags = ["k8s-worker", var.environment] + named_ports = [ + { + name = "ngf-http" + port = var.nginx_gateway_http_node_port + }, + { + name = "ngf-https" + port = var.nginx_gateway_https_node_port + } + ] + tags = ["k8s-worker", var.environment] # 태그 common_tags = merge(var.common_tags, { diff --git a/terraform/environments/prod/firewall.tf b/terraform/environments/prod/firewall.tf index 886fd3e..3dfd8c5 100644 --- a/terraform/environments/prod/firewall.tf +++ b/terraform/environments/prod/firewall.tf @@ -2,36 +2,34 @@ # 프로덕션 방화벽 값 # ======================================== locals { - prod_firewall_rules = merge( - { - # 워커 노드가 외부 HTTP 트래픽을 받을 수 있도록 허용합니다. - allow_http = { - name = "${var.vpc_name}-allow-http" - allow = [ - { - protocol = "tcp" - ports = ["80"] - } - ] - source_ranges = ["0.0.0.0/0"] - target_tags = ["k8s-worker"] - priority = 1000 - } + gcp_load_balancer_health_check_source_ranges = [ + "35.191.0.0/16", + "130.211.0.0/22", + ] - # 워커 노드가 외부 HTTPS 트래픽을 받을 수 있도록 허용합니다. - allow_https = { - name = "${var.vpc_name}-allow-https" + prod_firewall_rules = merge( + var.create_load_balancer ? { + # 외부 프록시 NLB와 헬스 체크가 워커 NodePort로 접근할 수 있도록 허용합니다. + allow_nginx_gateway_nodeports = { + name = "${var.vpc_name}-allow-nginx-gateway-nodeports" allow = [ { protocol = "tcp" - ports = ["443"] + ports = [ + tostring(var.nginx_gateway_http_node_port), + tostring(var.nginx_gateway_https_node_port), + ] } ] - source_ranges = ["0.0.0.0/0"] - target_tags = ["k8s-worker"] - priority = 1000 + source_ranges = concat( + local.gcp_load_balancer_health_check_source_ranges, + [var.load_balancer_proxy_only_subnet_cidr] + ) + target_tags = ["k8s-worker"] + priority = 1000 } - + } : {}, + { # 마스터와 워커 노드가 Kubernetes API 서버에 접근할 수 있도록 허용합니다. allow_k8s_api_from_nodes = { name = "${var.vpc_name}-allow-k8s-api-from-nodes" @@ -102,12 +100,13 @@ locals { priority = 1000 } - # Calico IP-in-IP 터널링 트래픽을 허용합니다. - allow_calico_ipip = { - name = "${var.vpc_name}-allow-calico-ipip" + # Calico VXLAN 터널링 트래픽을 허용합니다. + allow_calico_vxlan = { + name = "${var.vpc_name}-allow-calico-vxlan" allow = [ { - protocol = "ipip" + protocol = "udp" + ports = ["4789"] } ] source_tags = ["k8s-master", "k8s-worker"] diff --git a/terraform/environments/prod/load-balancer.tf b/terraform/environments/prod/load-balancer.tf index 23fdfd5..99518c5 100644 --- a/terraform/environments/prod/load-balancer.tf +++ b/terraform/environments/prod/load-balancer.tf @@ -1,37 +1,162 @@ # ======================================== -# 로드 밸런서 모듈 -# ======================================== -module "load_balancer" { - source = "../../modules/load-balancer" - - count = var.create_load_balancer ? 1 : 0 - - name_prefix = "${var.project}-${var.environment}-nlb" - region = var.region - - # 헬스 체크 설정 - create_health_check = true - health_check_protocol = "TCP" - health_check_port = 80 - health_check_request_path = "/health" - health_check_interval = 5 - health_check_timeout = 5 - health_check_healthy_threshold = 2 - health_check_unhealthy_threshold = 3 - - # 백엔드 서비스 설정 - backend_protocol = "TCP" - backend_timeout_sec = 30 - session_affinity = "CLIENT_IP" - backend_groups = [ - { - group = module.k8s_worker_nodes.instance_group_instance_group - balancing_mode = "CONNECTION" - } - ] - - # 포워딩 규칙 설정 - forwarding_rule_ip_protocol = "TCP" - forwarding_rule_port_range = "80" - network_tier = "PREMIUM" +# 외부 프록시 NLB 기본 로컬 값 +# ======================================== +locals { + load_balancer_name_prefix = "${var.project}-${var.environment}-nlb" +} + +# ======================================== +# 외부 프록시 NLB용 proxy-only 서브넷 +# ======================================== +resource "google_compute_subnetwork" "load_balancer_proxy_only" { + count = var.create_load_balancer ? 1 : 0 + + name = "${local.load_balancer_name_prefix}-proxy-only-subnet" + ip_cidr_range = var.load_balancer_proxy_only_subnet_cidr + region = var.region + network = module.vpc.vpc_self_link + description = "프로덕션 외부 프록시 NLB용 proxy-only subnet" + purpose = "REGIONAL_MANAGED_PROXY" + role = "ACTIVE" +} + +# ======================================== +# 외부 프록시 NLB 공인 IP +# ======================================== +resource "google_compute_address" "load_balancer_ip" { + count = var.create_load_balancer ? 1 : 0 + + name = "${local.load_balancer_name_prefix}-ip" + region = var.region + network_tier = "PREMIUM" +} + +# ======================================== +# HTTP NodePort 헬스 체크 +# ======================================== +resource "google_compute_region_health_check" "nginx_gateway_http" { + count = var.create_load_balancer ? 1 : 0 + + name = "${local.load_balancer_name_prefix}-http-health-check" + region = var.region + check_interval_sec = 5 + timeout_sec = 5 + healthy_threshold = 2 + unhealthy_threshold = 3 + + tcp_health_check { + port = var.nginx_gateway_http_node_port + } +} + +# ======================================== +# HTTPS NodePort 헬스 체크 +# ======================================== +resource "google_compute_region_health_check" "nginx_gateway_https" { + count = var.create_load_balancer ? 1 : 0 + + name = "${local.load_balancer_name_prefix}-https-health-check" + region = var.region + check_interval_sec = 5 + timeout_sec = 5 + healthy_threshold = 2 + unhealthy_threshold = 3 + + tcp_health_check { + port = var.nginx_gateway_https_node_port + } +} + +# ======================================== +# HTTP 백엔드 서비스 +# ======================================== +resource "google_compute_region_backend_service" "nginx_gateway_http" { + count = var.create_load_balancer ? 1 : 0 + + name = "${local.load_balancer_name_prefix}-http-backend-service" + region = var.region + protocol = "TCP" + load_balancing_scheme = "EXTERNAL_MANAGED" + port_name = "ngf-http" + timeout_sec = 30 + session_affinity = "CLIENT_IP" + health_checks = [google_compute_region_health_check.nginx_gateway_http[0].id] + + backend { + group = module.k8s_worker_nodes.instance_group_instance_group + } +} + +# ======================================== +# HTTPS 백엔드 서비스 +# ======================================== +resource "google_compute_region_backend_service" "nginx_gateway_https" { + count = var.create_load_balancer ? 1 : 0 + + name = "${local.load_balancer_name_prefix}-https-backend-service" + region = var.region + protocol = "TCP" + load_balancing_scheme = "EXTERNAL_MANAGED" + port_name = "ngf-https" + timeout_sec = 30 + session_affinity = "CLIENT_IP" + health_checks = [google_compute_region_health_check.nginx_gateway_https[0].id] + + backend { + group = module.k8s_worker_nodes.instance_group_instance_group + } +} + +# ======================================== +# HTTP 타깃 TCP 프록시 +# ======================================== +resource "google_compute_region_target_tcp_proxy" "nginx_gateway_http" { + count = var.create_load_balancer ? 1 : 0 + + name = "${local.load_balancer_name_prefix}-http-proxy" + region = var.region + backend_service = google_compute_region_backend_service.nginx_gateway_http[0].id +} + +# ======================================== +# HTTPS 타깃 TCP 프록시 +# ======================================== +resource "google_compute_region_target_tcp_proxy" "nginx_gateway_https" { + count = var.create_load_balancer ? 1 : 0 + + name = "${local.load_balancer_name_prefix}-https-proxy" + region = var.region + backend_service = google_compute_region_backend_service.nginx_gateway_https[0].id +} + +# ======================================== +# HTTP 포워딩 규칙 +# ======================================== +resource "google_compute_forwarding_rule" "nginx_gateway_http" { + count = var.create_load_balancer ? 1 : 0 + + name = "${local.load_balancer_name_prefix}-http-forwarding-rule" + region = var.region + ip_protocol = "TCP" + load_balancing_scheme = "EXTERNAL_MANAGED" + port_range = "80" + target = google_compute_region_target_tcp_proxy.nginx_gateway_http[0].id + network_tier = "PREMIUM" + ip_address = google_compute_address.load_balancer_ip[0].address +} + +# ======================================== +# HTTPS 포워딩 규칙 +# ======================================== +resource "google_compute_forwarding_rule" "nginx_gateway_https" { + count = var.create_load_balancer ? 1 : 0 + + name = "${local.load_balancer_name_prefix}-https-forwarding-rule" + region = var.region + ip_protocol = "TCP" + load_balancing_scheme = "EXTERNAL_MANAGED" + port_range = "443" + target = google_compute_region_target_tcp_proxy.nginx_gateway_https[0].id + network_tier = "PREMIUM" + ip_address = google_compute_address.load_balancer_ip[0].address } diff --git a/terraform/environments/prod/outputs.tf b/terraform/environments/prod/outputs.tf index 2dfccf8..367db5f 100644 --- a/terraform/environments/prod/outputs.tf +++ b/terraform/environments/prod/outputs.tf @@ -88,7 +88,7 @@ output "secret_manager_secret_ids" { # ======================================== output "load_balancer_ip" { description = "로드 밸런서 IP 주소입니다." - value = var.create_load_balancer ? module.load_balancer[0].forwarding_rule_ip_address : null + value = var.create_load_balancer ? google_compute_address.load_balancer_ip[0].address : null } # ======================================== diff --git a/terraform/environments/prod/terraform.tfvars.example b/terraform/environments/prod/terraform.tfvars.example index bec276a..ae64caa 100644 --- a/terraform/environments/prod/terraform.tfvars.example +++ b/terraform/environments/prod/terraform.tfvars.example @@ -80,6 +80,9 @@ allowed_cors_origins = [ # 로드 밸런서 관련 값 # ======================================== create_load_balancer = true +load_balancer_proxy_only_subnet_cidr = "10.2.10.0/23" +nginx_gateway_http_node_port = 30080 +nginx_gateway_https_node_port = 30443 # ======================================== # Secret Manager 관련 값 diff --git a/terraform/environments/prod/variables.tf b/terraform/environments/prod/variables.tf index 4a85902..ef89f3e 100644 --- a/terraform/environments/prod/variables.tf +++ b/terraform/environments/prod/variables.tf @@ -282,6 +282,24 @@ variable "create_load_balancer" { default = true } +variable "load_balancer_proxy_only_subnet_cidr" { + description = "외부 프록시 네트워크 로드 밸런서가 사용할 proxy-only subnet CIDR입니다." + type = string + default = "10.2.10.0/23" +} + +variable "nginx_gateway_http_node_port" { + description = "NGINX Gateway Fabric HTTP NodePort 포트입니다." + type = number + default = 30080 +} + +variable "nginx_gateway_https_node_port" { + description = "NGINX Gateway Fabric HTTPS NodePort 포트입니다." + type = number + default = 30443 +} + # ======================================== # 공통 태그 변수 # ======================================== From 4c98d56b132c5ba443db057711f775d061e78956 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Mon, 6 Apr 2026 12:01:01 +0900 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20NLB=20=EC=84=A4=EC=A0=95=20capacity?= =?UTF-8?q?=5Fscaler=20=EC=B6=94=EA=B0=80=20(#12)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- terraform/environments/prod/load-balancer.tf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/terraform/environments/prod/load-balancer.tf b/terraform/environments/prod/load-balancer.tf index 99518c5..b94af10 100644 --- a/terraform/environments/prod/load-balancer.tf +++ b/terraform/environments/prod/load-balancer.tf @@ -83,7 +83,8 @@ resource "google_compute_region_backend_service" "nginx_gateway_http" { health_checks = [google_compute_region_health_check.nginx_gateway_http[0].id] backend { - group = module.k8s_worker_nodes.instance_group_instance_group + group = module.k8s_worker_nodes.instance_group_instance_group + capacity_scaler = 1.0 } } @@ -103,7 +104,8 @@ resource "google_compute_region_backend_service" "nginx_gateway_https" { health_checks = [google_compute_region_health_check.nginx_gateway_https[0].id] backend { - group = module.k8s_worker_nodes.instance_group_instance_group + group = module.k8s_worker_nodes.instance_group_instance_group + capacity_scaler = 1.0 } } From aba81f85dadd3b524e3015b6ae5179c2ef38aedc Mon Sep 17 00:00:00 2001 From: eedo_y Date: Mon, 6 Apr 2026 12:22:08 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20NLB=20=EC=84=A4=EC=A0=95=20balancing?= =?UTF-8?q?=5Fmode=20=EC=B6=94=EA=B0=80=20(#12)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- terraform/environments/prod/load-balancer.tf | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/terraform/environments/prod/load-balancer.tf b/terraform/environments/prod/load-balancer.tf index b94af10..974882c 100644 --- a/terraform/environments/prod/load-balancer.tf +++ b/terraform/environments/prod/load-balancer.tf @@ -84,6 +84,8 @@ resource "google_compute_region_backend_service" "nginx_gateway_http" { backend { group = module.k8s_worker_nodes.instance_group_instance_group + balancing_mode = "UTILIZATION" + max_utilization = 0.6 capacity_scaler = 1.0 } } @@ -105,6 +107,8 @@ resource "google_compute_region_backend_service" "nginx_gateway_https" { backend { group = module.k8s_worker_nodes.instance_group_instance_group + balancing_mode = "UTILIZATION" + max_utilization = 0.8 capacity_scaler = 1.0 } } @@ -141,10 +145,13 @@ resource "google_compute_forwarding_rule" "nginx_gateway_http" { region = var.region ip_protocol = "TCP" load_balancing_scheme = "EXTERNAL_MANAGED" + network = module.vpc.vpc_self_link port_range = "80" target = google_compute_region_target_tcp_proxy.nginx_gateway_http[0].id network_tier = "PREMIUM" ip_address = google_compute_address.load_balancer_ip[0].address + + depends_on = [google_compute_subnetwork.load_balancer_proxy_only] } # ======================================== @@ -157,8 +164,11 @@ resource "google_compute_forwarding_rule" "nginx_gateway_https" { region = var.region ip_protocol = "TCP" load_balancing_scheme = "EXTERNAL_MANAGED" + network = module.vpc.vpc_self_link port_range = "443" target = google_compute_region_target_tcp_proxy.nginx_gateway_https[0].id network_tier = "PREMIUM" ip_address = google_compute_address.load_balancer_ip[0].address + + depends_on = [google_compute_subnetwork.load_balancer_proxy_only] } From 07d6a5ed7801d74f6608d94487a3d954b22429d5 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Mon, 6 Apr 2026 13:02:53 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20gitOps=20=EB=A0=88=ED=8F=AC=EC=A7=80?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20=EC=B0=B8=EC=A1=B0=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(#12)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- k8s-argocd/applications/prod/frontend.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s-argocd/applications/prod/frontend.yaml b/k8s-argocd/applications/prod/frontend.yaml index 05650b8..cba8ec0 100644 --- a/k8s-argocd/applications/prod/frontend.yaml +++ b/k8s-argocd/applications/prod/frontend.yaml @@ -41,7 +41,7 @@ spec: # Kustomize 소스 설정 source: # GitOps URL - repoURL: https://github.com/100-hours-a-week/9-team-Devths-CLOUD + repoURL: https://github.com/PinHouse/PinHouse_CLOUD # Main 브랜치 참조 (환경은 overlay로 구분) targetRevision: main # Kustomize 오버레이 경로