IaC

[IaC] Terraform으로 Kubernetes 다루기 - 번외 Helm Chart

cloudraw 2025. 8. 18. 10:11

안녕하세요, Cloudraw입니다!
이번 글은 Terraform으로 Kubernetes 다루기 시리즈의 번외편으로, Kubernetes 환경에서 자주 사용되는 패키지 매니저인 Helm Chart를 Terraform과 함께 어떻게 활용할 수 있는지를 설명합니다.

앞서 작성한 시리즈에서는 아래와 같은 구성 요소들을 다뤘습니다.

  1. Kubernetes Provider 사용 방법, 기본 오브젝트 생성하기(Namespace, Pod, Service, Secret)
  2. 볼륨 리소스 다루기(CSP별 Blob 및 configmap mount)
  3. 네트워크 리소스 다루기(Ingress, Nginx-Ingress(Helm Chart))
  4. DNS 연동 및 인증서 발급(Let's Encrypt 및 Cert Manager(Helm))
  5. CloudStudio로 위 1~4 구성하기

이번 번외편에서는 Helm이 무엇인지, 그리고 Terraform으로 Helm Chart를 어떻게 선언하고 관리할 수 있는지를 실습 예제와 함께 소개합니다.

 


Helm Chart란?

Helm은 Kubernetes의 패키지 매니저입니다.
YAML로 작성된 복잡한 리소스를 Chart라는 패키지 단위로 묶어, 쉽고 일관성 있게 설치하고 업데이트할 수 있게 해줍니다.

Chart는 다음 구성 요소로 이루어집니다:

 

Helm Chart 구성 요소

구성  파일설명
Chart.yaml Chart에 대한 메타 정보
values.yaml 기본 설정값들을 정의한 파일
templates/ 실제 Kubernetes 리소스 템플릿(YAML)들이 위치하는 디렉토리
✅ 즉, Helm Chart는 kubectl apply로 일일이 배포하지 않아도 되는 재사용 가능한 패키지화된 Kubernetes 앱이라고 볼 수 있습니다.

 

 

💡Terraform에서 Helm Chart 사용하는 이유

Terraform은 helm_release 리소스를 통해 Helm Chart를 선언적으로 배포할 수 있습니다.
즉, Terraform 코드로 Kubernetes 인프라 구성과 동시에 Helm Chart를 활용한 앱 배포도 자동화할 수 있습니다.

 

장점

  • 코드 기반으로 Helm Chart 구성 및 배포
  • 환경 재현 및 GitOps에 유리
  • 다른 Terraform 리소스와 통합 관리 가능

 

마치 apt나 brew처럼, Helm은 복잡한 배포를 쉽게 만들어주는 역할을 하며, 특히 재사용 가능하고, 선언적인 배포가 필요한 환경에서 큰 강점을 가집니다.

 

Terraform의 helm_release 공식 문서는 아래에서 확인할 수 있습니다.
👉 https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release


 

실습: Terraform으로 Grafana Chart 설치하기

이번 실습에서는 모니터링 도구인 Grafana를 Helm Chart를 통해 설치해보겠습니다.

1️⃣ Helm Provider 설정

terraform {
  required_providers {
    helm = {
      source  = "hashicorp/helm"
      version = "~> 2.11.0"
    }
  }
}

provider "helm" {
  kubernetes {
    config_path = "~/.kube/config"
    config_context = "<context 이름>" # kubectl config get-contexts
  }
}
✅ ~/.kube/config는 로컬 클러스터의 kubeconfig 경로로 정의된 기본 컨텍스트의 클러스터에 Helm Chart가 배포됩니다.

 

💡로컬 환경에 저장되어 있는 config를 불러와서 설정하는 방법이 아닌 CSP별 구성되어 있는 Cluster를 불러오는 방법으로 설정하려면 첫 번째 게시글인 Terraform으로 Kubernetes 다루기 - 1/5 를 참고하여 진행하시면 됩니다.

 

2️⃣ Helm Chart 배포: Grafana 설치

Helm Chart의 버전이나 repository 주소는 공식 Grafana Helm repository 기준으로 설정하면 됩니다.

resource "helm_release" "grafana" {
  name       = "grafana"
  repository = "https://grafana.github.io/helm-charts"
  chart      = "grafana"
  version    = "6.60.1"

  namespace           = "monitoring"
  create_namespace    = true

  values = [
    file("${path.module}/grafana-values.yaml")
  ]
}

 

이제 중요한 설정 파일인 grafana-values.yaml을 작성해 보겠습니다.

 

 

 

3️⃣ Grafana 설정 예시 (grafana-values.yaml)

A. 도메인을 사용하는 환경 (Ingress + DNS)

adminUser: admin
adminPassword: admin1234

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  ingressClassName: cloudraw
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
  hosts:
    - host: grafana.cloudraw.kr
      paths:
        - path: /
          pathType: Prefix

✅ 위 설정은 grafana.cloudraw.kr 도메인으로 접근 가능한 Ingress를 구성합니다. 실제로 도메인을 연결하려면 DNS A 레코드 설정도 함께 필요합니다.

 

 

 

B. 로컬 테스트 환경 (NodePort 사용)

테스트나 로컬 환경에서는 도메인이 필요하지 않을 수 있습니다. 이럴 땐 Ingress 없이 NodePort 서비스로 구성해 Node의 IP와 포트를 통해 접근할 수 있습니다.

 

NodePort 방식 설정 예시

adminUser: admin
adminPassword: admin1234

service:
  type: NodePort
  port: 80
  nodePort: 30030  # 원하는 포트 지정

ingress:
  enabled: false

 

브라우저 접속 테스트 할 경우 (EXTERNAL-IP 없이)

  • kubectl port-forward 사용
  • Minikube 전용 명령어 사용
 
kubectl port-forward svc/grafana 30030:80 -n monitoring

 

또는

 
minikube service grafana -n monitoring

이런 방식으로 외부 노출 없이도 브라우저로 접근이 가능합니다.

 

 

 

⚠️ 복잡한 키 설정 시 주의할 점

예시 1. annotation 키에 점(.)이 포함된 경우

grafana:
  ingress:
    annotations:
      alb.ingress.kubernetes.io/group.name: shared-ingress

 

Terraform에서는 다음처럼 작성해야 합니다.

set = [
  {
    name  = "grafana.ingress.annotations.alb\\.ingress\\.kubernetes\\.io/group\\.name"
    value = "shared-ingress"
  }
]
 
 

 

예시 2. 값이 JSON 객체인 경우

controller:
  pod:
    annotations:
      status.kubernetes.io/restart-on-failure: {"timeout": "30s"}
 

Terraform에서는 다음처럼 표현합니다.

set = [
  {
    name  = "controller.pod.annotations.status\\.kubernetes\\.io/restart-on-failure"
    value = "{\"timeout\": \"30s\"}"
  }
]
점(.)은 \\.로 escape 처리 값은 문자열 내 JSON → \" 형태로 이중 escape 필요
💡이처럼 복잡한 설정은 .tf 파일에서 직접 다루는 것보다 values.yaml에 따로 정의하고 불러오는 방식이 유지보수에 더 유리합니다.

 

 

 

💡Terraform에서 Helm values 설정 방법

Terraform에서는 Helm Chart의 설정값(values.yaml)을 아래 3가지 방식으로 정의할 수 있습니다.

 

방법 1. values 블록으로 파일 참조

values = [
  file("grafana-values.yaml")
]
전체 설정이 많거나 복잡할 경우 values.yaml로 분리하는 방식이 유지보수에 유리합니다.

 

 

방법 2. set 블록으로 key/value 직접 설정

set {
  name  = "adminUser"
  value = "admin"
}

set {
  name  = "ingress.enabled"
  value = "true"
}
간단한 설정이나 파라미터 변경 시 유용합니다.

 

 

방법 3. set_sensitive로 비밀번호 등 민감한 값 처리

set_sensitive {
  name  = "adminPassword"
  value = var.grafana_admin_password
}
이 방식은 비밀번호를 Terraform 변수로 관리하며, terraform.tfvars 또는 Secret Manager와 연동해 민감 정보 보호에 효과적입니다.

 

 

Terraform에서 Helm values 설정 방식 정리

방법 설명 예시
 values 블록 파일로 전체 설정을 분리 file("grafana-values.yaml")
 set 블록 단일 Key/Value 설정 시 set { name = "...", value = "..." }
 set_list 블록 값이 리스트일 경우 value = ["a", "b"]

 


 

배포 및 확인

terraform init
terraform plan
terraform apply

 

terraform init

 

terraform plan

 

terraform apply

 
kubectl get pods -n monitoring  # grafana pod 생성 확인
kubectl get svc -n monitoring   # grafana service 생성 확인
 

생성된 pod 확인
생성된 service 확인

 

 

 

 

 접속 URL:

  • 도메인 환경: https://{설정한 도메인 주소}   예시) https://grafana.cloudraw.kr
  • 로컬 환경: http://localhost:{포트포워딩 포트}   예시) http://localhost:30030

 

 

 

이번 글에서는 Terraform으로 Helm Chart를 선언하고, Grafana를 설치하는 예제를 다뤘습니다.

  • Helm은 Kubernetes 리소스를 패키지로 관리하는 도구입니다.
  • Terraform은 Helm Chart를 helm_release로 코드 기반으로 설치할 수 있게 해줍니다.
  • 단순한 값은 set, 복잡한 설정은 values.yaml로 분리하는 것이 좋습니다.

Helm은 Kubernetes 앱을 쉽게 배포할 수 있는 도구이며, Terraform과 결합하면 IaC 형태로 완벽한 재현 가능성과 관리성을 제공합니다.

 

 

 


 

    

 

Cloudraw는 쉽게 클라우드 인프라를 그리고 사용할 수 있는 서비스를 제공하기 위해 노력하고 있습니다.

 

클라우드가 있는 곳 어디든 Cloudraw가 함께합니다.

 

📨 help@cloudraw.kr