[Kubernetes] Terraform을 통한 k8s 클러스터 배포

배창민·2025년 12월 5일
post-thumbnail

Terraform으로 Kubernetes 리소스 관리하기 정리

Terraform 설치 과정은 공식 문서를 따라가면 충분하다고 보고, 여기서는 Kubernetes 환경에서 Terraform을 어떻게 구성하고 쓰는지에 집중해서 정리한다.


1. Terraform 구성 파일 구조와 핵심 개념

1-1. Terraform 기본 디렉터리 구조

보통 프로젝트 구조는 이렇게 나눈다.

project/
 ├ main.tf           # 실제 리소스 정의
 ├ variables.tf      # 변수 정의 (하드코딩 방지)
 ├ outputs.tf        # 생성된 값 출력
 └ terraform.tfstate # 인프라 상태 파일 (자동 생성)

이 구조로 나누면:

  • 역할이 분리돼서 읽기 쉽고
  • 실제 기업에서 쓰는 IaC 구조와도 비슷해진다.

1-2. Terraform State(tfstate)

Terraform은 인프라의 현재 상태terraform.tfstate 파일로 저장한다.
이 파일을 기준으로 Terraform은 이런 걸 계산한다.

  • 새로 만들 리소스
  • 수정해야 할 리소스
  • 삭제해야 할 리소스

즉, tfstate는 Terraform 입장에서 싱글 소스 오브 트루스(Single Source of Truth) 역할을 한다.

특징 요약:

  • 손상되면 plan/apply가 꼬일 수 있다.
  • 절대 Git에 올리면 안 된다.
  • 팀 작업에서는 S3, GCS, Consul 같은 remote state로 관리하는 패턴을 많이 쓴다.

1-3. Terraform의 멱등성(Idempotency)

Terraform의 중요한 성질:

같은 코드를 가지고 terraform apply를 여러 번 실행해도
결과 인프라 상태는 항상 동일해야 한다.

  • 코드(main.tf) ↔ 실제 상태(tfstate 기반)를 비교해서
  • “차이 나는 부분만” 생성/수정/삭제한다.
  • 이미 코드와 상태가 같으면 No changes만 출력하고 아무것도 안 한다.

그래서 인프라를 항상 원하는 상태로 유지할 수 있고,
단순 YAML + kubectl 조합보다 더 안정적인 운영이 가능하다.


1-4. Kubernetes Provider 사용할 때 주의점

Kubernetes를 Terraform으로 다룰 때 가장 중요한 포인트:

  • kubectl apply서버 쪽에서 YAML을 머지(merge) 하는 방식
  • Terraform은 자기가 관리하는 필드만 상태와 비교해 조작하는 방식

그래서:

  • Terraform이 만든 리소스를 나중에 kubectl edit으로 바꿔 버리면
  • 다시 terraform apply 할 때 충돌·되돌림이 발생할 수 있다.
  • 원칙적으로 Terraform으로 만든 리소스는 Terraform으로만 관리하는 게 맞다.

실습 전에 깨끗하게 맞추고 시작하려면:

kubectl delete deployment --all
kubectl delete service --all
kubectl delete ingress --all

같은 식으로 기존 리소스를 지우고 Terraform으로 올리는 흐름이 안전하다.


2. variables.tf – 하드코딩 방지

variables.tf에는 자주 바뀌는 값들을 변수로 빼서 관리한다.

예시:

variable "image_vue" {
  default = "limu810/k8s-vue-ing:latest"
}

variable "image_boot" {
  default = "limu810/k8s-boot-ing:latest"
}

variable "replicas_vue" {
  default = 1
}

variable "replicas_boot" {
  default = 1
}

장점:

  • 이미지 태그, replica 수 같은 값을 여러 파일에서 반복해서 고치지 않아도 된다.
  • 나중에 환경별(dev, stage, prod)로 값만 바꿔서 재사용하기 좋다.

3. outputs.tf – 생성된 값 꺼내 쓰기

Terraform이 만든 리소스의 특정 값을 output으로 노출하면,
나중에 자동화 스크립트나 다른 도구에서 쉽게 가져다 쓸 수 있다.

예시:

output "vue_service_ip" {
  value = kubernetes_service.vue002ser.spec[0].cluster_ip
}

이렇게 정의해두면:

terraform output
terraform output vue_service_ip

로 Service의 ClusterIP를 바로 확인할 수 있다.

운영·모니터링 자동화에서 굉장히 자주 쓰이는 패턴이다.


4. main.tf – Kubernetes 리소스를 코드로 선언

main.tf에는 실제 리소스를 정의한다.

4-1. Kubernetes Provider 설정

provider "kubernetes" {
  config_path = "~/.kube/config"
}
  • 어떤 kubeconfig를 사용할지 지정
  • 로컬에서 kubectl이 잘 동작하는 환경이라면 같은 설정을 그대로 쓰면 된다.

4-2. 대표적인 리소스들

예시 구조:

  • kubernetes_deployment → Vue/Spring Boot Deployment 정의
  • kubernetes_service → 각 Deployment에 대응하는 Service 정의
  • kubernetes_ingress_v1 → nginx Ingress로 경로 기반 라우팅

Terraform 리소스 구조는 Kubernetes YAML과 거의 1:1 대응된다.

  • metadata.name
  • spec.replicas
  • spec.template.metadata.labels
  • spec.template.spec.containers[...]

등 대부분이 그대로 HCL로 옮겨진 형태라
“YAML을 Terraform 문법으로 다시 쓴 것”이라고 생각하면 이해가 빠르다.

예를 들어 Vue Deployment 부분만 간단히 보면:

resource "kubernetes_deployment" "vue002dep" {
  metadata {
    name = "vue002dep"
  }

  spec {
    replicas = var.replicas_vue

    selector {
      match_labels = {
        app = "vue002kube"
      }
    }

    template {
      metadata {
        labels = {
          app = "vue002kube"
        }
      }

      spec {
        container {
          name  = "vue-container"
          image = var.image_vue

          port {
            container_port = 80
          }
        }
      }
    }
  }
}

YAML에 적을 내용을 HCL로 표현했다고 보면 된다.


5. Terraform 기본 워크플로우

Terraform 작업 순서는 항상 같다.

init → plan → apply

5-1. init – 초기화

terraform init
  • 필요한 provider 플러그인 다운로드
  • .terraform/ 디렉터리 생성
  • .terraform.lock.hcl로 provider 버전 고정

5-2. plan – 변경 사항 미리보기

terraform plan
  • 현재 state ↔ 코드 차이를 계산해서
  • 무엇이 생성/변경/삭제될지 미리 보여준다.

실행 결과 예:

  • + : 새로 생성
  • ~ : 수정
  • - : 삭제

코드가 의도한 대로 동작하는지 확인하는 단계다.

5-3. apply – 실제 적용

terraform apply
  • plan에서 계산된 내용을 실제 Kubernetes에 반영
  • 끝나면 terraform.tfstate가 최신 상태로 업데이트된다.

적용이 끝나면:

kubectl get all
terraform output

로 K8s 리소스와 output 값까지 함께 확인할 수 있다.


5-4. init/apply 후 생성되는 파일들

  • .terraform/

    • provider 바이너리 저장 폴더
  • .terraform.lock.hcl

    • provider 버전 잠금 파일
  • terraform.tfstate

    • 인프라 상태 파일 (절대 Git에 올리지 말 것)

6. 인프라 수정 예제 – replicas 변경

Terraform의 강점은 “코드를 수정하면 인프라가 거기에 맞게 따라온다”는 점이다.

6-1. replicas 값 수정

variables.tf에서 Vue replicas 값을 1 → 3으로 변경한다고 가정한다.

variable "replicas_vue" {
  default = 3
}

이 한 줄로 “Vue 파드를 3개 유지하라”는 인프라 스펙이 바뀐다.

6-2. 변경 내용 확인 – plan

terraform plan

예상되는 출력:

~ resource "kubernetes_deployment" "vue002dep" {
      spec.0.replicas: "1" => "3"
}
  • ~는 기존 리소스를 수정한다는 의미
  • Deployment의 replicas 값이 1 → 3으로 변경될 예정이라는 것만 딱 보여준다.

6-3. 적용 – apply

terraform apply

그 후에 K8s에서 확인:

kubectl get deploy
kubectl get pods -l app=vue002kube

확인할 것:

  • vue002dep의 replicas/desire/current/ready가 모두 3
  • app=vue002kube 라벨의 Pod가 3개 생성

6-4. 멱등성 확인

같은 코드 상태에서 한 번 더 실행해 본다.

terraform apply

출력 예:

No changes. Your infrastructure matches the configuration.
  • 이미 코드와 실제 상태가 일치하므로
  • Terraform은 아무것도 바꾸지 않는다.

이게 바로 Terraform의 멱등성이다.


7. 리소스 삭제와 정리

7-1. Terraform으로 만든 리소스 삭제

terraform destroy
  • Terraform이 관리하던 리소스만 깔끔하게 삭제
  • 삭제 계획을 먼저 보여준 후, 정말 진행할지 물어본다.

7-2. 로컬 파일까지 깨끗하게 지우기

테스트만 해보고 프로젝트 자체를 초기화하고 싶다면:

rm -rf .terraform*
rm terraform.tfstate*

이렇게 하면:

  • provider 캐시
  • lock 파일
  • state 파일

까지 깨끗하게 제거된다.


마무리

이 정리의 포인트를 한 줄로 요약하면:

Kubernetes 리소스를 YAML이 아니라 Terraform 코드로 선언하고,
init → plan → apply + tfstate 기반으로 멱등하게 관리하는 패턴을 익히는 것

여기에 variables, outputs, provider, state 개념까지 이해하면
실제 프로젝트에서 Terraform으로 K8s 인프라를 안정적으로 운영할 수 있는 기본기는 갖추게 된다.

profile
개발자 희망자

0개의 댓글