Terraform 은 HashiCorp 가 만든 IaC(코드형 인프라) 도구다. 클라우드 · 온프레미스 자원을 HCL 로 선언하고 plan 으로 변경을 미리 본 뒤 apply 로 반영한다. 자원 상태는 state 파일에 기록한다.
현행 버전은 1.16.3 이다.[1] 1.6 부터 라이선스가 MPL 2.0 에서 BUSL 1.1 로 바뀌었고, 그 시점에 갈라져 나온 오픈소스 포크가 Linux Foundation 산하 OpenTofu 다. 현행 1.12.6 이며[2] 구성 파일 · provider · state 형식이 호환된다. 명령은 terraform 대신 tofu 다. 라이선스가 걸리는 환경이면 OpenTofu 를 쓴다.
클라우드 공급자에 관계없이 provider 플러그인으로 확장한다. AWS · Azure · GCP 는 물론 Kubernetes · vSphere · GitLab 같은 API 도 provider 가 있다.
대부분의 코드형 인프라는 변경 가능한 인프라를 만든다. 미들웨어 업그레이드나 스토리지 추가 같은 변경이 쌓이면 실제 상태가 원래 구성에서 '드리프트' 해 문제를 진단하기 어려워진다. Terraform 은 변경이 생기면 현재 구성을 새 구성으로 대체하고 인프라를 다시 프로비저닝하는 쪽을 택한다. 이전 구성은 롤백 가능한 버전으로 남는다.
terraform init 이 provider 를 registry.terraform.io 에서 내려받는다. 폐쇄망이면 provider 미러가 필요하다.현행 버전[1:1]. 공식 절차 그대로다.
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum install -y terraform
terraform version
공식 RPM 저장소를 등록한다.[3]
cat <<EOF | sudo tee /etc/yum.repos.d/opentofu.repo
[opentofu]
name=opentofu
baseurl=https://packages.opentofu.org/opentofu/tofu/rpm_any/rpm_any/\$basearch
repo_gpgcheck=0
gpgcheck=1
enabled=1
gpgkey=https://get.opentofu.org/opentofu.gpg https://packages.opentofu.org/opentofu/tofu/gpgkeys
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300
EOF
sudo yum install -y tofu
tofu version
Kubernetes provider 로 네임스페이스 · Deployment · NodePort 서비스를 만든다. 2022년 테스트 됨. 아래 명령의 terraform 은 OpenTofu 에서는 tofu 로 바꿔 쓴다.
접근할 클러스터의 kubeconfig 를 가져온다.
mkdir ~/.kube
scp manager@192.168.103.101:/home/manager/.kube/config ~/.kube/
mkdir nginx_k8s
cd nginx_k8s
vi main.tf
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = ">= 2.0.0"
}
}
}
provider "kubernetes" {
config_path = "~/.kube/config"
}
resource "kubernetes_namespace" "igkim" {
metadata {
name = "nginx"
}
}
resource "kubernetes_deployment" "igkim" {
metadata {
name = "nginx"
namespace = kubernetes_namespace.igkim.metadata.0.name
}
spec {
replicas = 2
selector {
match_labels = {
app = "igkim_nginx"
}
}
template {
metadata {
labels = {
app = "igkim_nginx"
}
}
spec {
container {
image = "nginx"
name = "nginx-container"
port {
container_port = 80
}
}
}
}
}
}
resource "kubernetes_service" "igkim" {
metadata {
name = "nginx"
namespace = kubernetes_namespace.igkim.metadata.0.name
}
spec {
selector = {
app = kubernetes_deployment.igkim.spec.0.template.0.metadata.0.labels.app
}
type = "NodePort"
port {
node_port = 30201
port = 80
target_port = 80
}
}
}
terraform init 은 구성 파일이 있는 작업 디렉터리를 초기화하고 provider 를 내려받는다. 새 구성을 만들거나 저장소에서 복제한 뒤 가장 먼저 실행하며, 여러 번 실행해도 안전하다.
terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/kubernetes versions matching ">= 2.0.0"...
- Installing hashicorp/kubernetes v2.9.0...
- Installed hashicorp/kubernetes v2.9.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
terraform plan 은 실행 계획을 만들어 인프라에 적용할 변경을 미리 보여 준다.
terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
+ create
Terraform will perform the following actions:
# kubernetes_deployment.igkim will be created
+ resource "kubernetes_deployment" "igkim" {
+ id = (known after apply)
+ wait_for_rollout = true
+ metadata {
+ generation = (known after apply)
+ name = "nginx"
+ namespace = "nginx"
...
+ spec {
+ cluster_ip = (known after apply)
+ type = "NodePort"
+ port {
+ node_port = 30201
+ port = 80
+ protocol = "TCP"
+ target_port = "80"
}
}
}
Plan: 3 to add, 0 to change, 0 to destroy.
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run
"terraform apply" now.
terraform apply 는 plan 이 제안한 작업을 실행한다.
terraform apply
Plan: 3 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
kubernetes_namespace.igkim: Creating...
kubernetes_namespace.igkim: Creation complete after 0s [id=nginx]
kubernetes_deployment.igkim: Creating...
kubernetes_deployment.igkim: Still creating... [10s elapsed]
kubernetes_deployment.igkim: Creation complete after 16s [id=nginx/nginx]
kubernetes_service.igkim: Creating...
kubernetes_service.igkim: Creation complete after 0s [id=nginx/nginx]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
kubectl get all -n nginx
NAME READY STATUS RESTARTS AGE
pod/nginx-66d9f6b7f-f64bl 1/1 Running 0 94m
pod/nginx-66d9f6b7f-vrnnl 1/1 Running 0 94m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx NodePort 10.107.141.230 <none> 80:30201/TCP 94m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 2/2 2 2 94m
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-66d9f6b7f 2 2 2 94m
정리는 terraform destroy 다.
최신 버전 1.16.3 — 2026-09-20 확인. https://developer.hashicorp.com/terraform/install ↩︎ ↩︎
OpenTofu 최신 버전 v1.12.6 — 2026-09-20 확인. https://github.com/opentofu/opentofu/releases ↩︎
Installing OpenTofu — RPM. 2026-09-20 확인. https://opentofu.org/docs/intro/install/rpm/ ↩︎