[본투비엔지니어] 나에게 베어본만 주어진다면?? (6)

2026. 1. 29. 08:15·project/본투비엔지니어

지난 글에서 Proxmox 서버 내부에 Rocky Linux 10 클라우드 이미지를 다운로드하고, 이를 템플릿(Template)으로 변환하는 작업을 완료했습니다. 이로써 서버 측면에서의 물리적, 논리적 준비는 모두 끝났습니다.

 

우리의 목표는 매번 Proxmox 웹 콘솔에 접속해 마우스를 클릭하는 것이 아니라, 로컬 컴퓨터에서 코드를 작성하고 실행하는 것만으로 서버를 생성하는 것입니다. 이를 위해 인프라 자동화 도구인 테라폼(Terraform)을 로컬 환경에 설치하고, Proxmox와 통신할 수 있도록 연동하는 과정을 진행하겠습니다.

 

1. Terraform 설치

# 1. HashiCorp 공식 탭(저장소) 추가
brew tap hashicorp/tap

# 2. Terraform 패키지 설치
brew install hashicorp/tap/terraform

# 3. 설치 확인 (버전 정보가 출력되면 성공)
terraform -version

 

2. Provider 설정

Terraform 자체는 인프라를 생성하는 '엔진'일 뿐, 실제로 어떤 플랫폼(AWS, Azure, Proxmox 등)을 제어할지는 Provider(플러그인)가 결정합니다.

 

provider.tf 파일을 생성하고, Proxmox 연동을 위한 설정을 작성합니다.

terraform {
  required_providers {
    proxmox = {
      source = "Telmate/proxmox"
      version = "3.0.1-rc3"
    }
  }
}

provider "proxmox" {
  # Proxmox API 주소 (https 필수, 포트 8006, /api2/json 경로 포함)
  pm_api_url = var.proxmox_api_url

  # API Token 인증 정보 (변수 처리)
  pm_api_token_id = var.proxmox_api_token_id
  pm_api_token_secret = var.proxmox_api_token_secret

  # 사설 인증서 검증 무시 (홈랩 환경에서는 필수)
  pm_tls_insecure = true
}

3. 자격 증명 분리

변수 선언 파일

variables.tf 사용할 변수의 이름과 타입을 정의합니다.

variable "proxmox_api_url" {
  type = string
}

variable "proxmox_api_token_id" {
  type = string
  sensitive = true
}

variable "proxmox_api_token_secret" {
  type = string
  sensitive = true
}

 

실제 값 입력 파일

terraform.tfvars 이곳에  Proxmox API Token 정보를 입력합니다. 이 파일은 .gitignore 등에 포함하여 외부에 노출되지 않도록 관리하는 것이 원칙입니다.

Proxmox API Token 생성하기

Proxmox 웹 대시보드에서 진행합니다.

  1. 위치 이동:
    • 왼쪽 상단 Datacenter 클릭.
    • 중앙 메뉴에서 Permissions -> API Tokens 클릭.
    • [Add] 버튼 클릭.
  2. 토큰 정보 입력:
    • User: root@pam (최고 관리자 권한을 줍니다.)
    • Token ID: terraform (이름은 맘대로 지어도 됩니다.)
    • Privilege Separation: [체크 해제]
      • (중요: 이걸 체크하면 권한을 따로 줘야 해서 복잡합니다. 학습용이니 체크를 풀어서 root의 전권을 위임합니다.)
    • [Add] 클릭.
  3. Secret 복사:
    • 화면에 Token ID와 Secret이 뜹니다.
    • Secret 값(UUID처럼 긴 문자열)은 한 번만 보여줍니다. 창 닫으면 다시는 못 봅니다.
      • 예: root@pam!terraform (ID)
      • 예: 8f3b2a1c-.... (Secret)

# 예: https://192.168.219.200:8006/api2/json
proxmox_api_url = "https://[Proxmox-IP]:8006/api2/json"

# 예: root@pam!terraform
proxmox_api_token_id = "[Proxmox에서-생성한-Token-ID]"

# 예: 8f3b2a1c-xxxx-xxxx...
proxmox_api_token_secret = "[복사해둔-Secret-Key]"

4. 연결 초기화

Terraform에게 "Proxmox 플러그인을 다운로드하고 준비하라"는 명령을 내립니다.

terraform init

5. 인프라 정의

Terraform의 핵심인 main.tf 파일을 생성합니다. 이곳에 우리가 원하는 서버의 사양(Spec)과 개수를 코드로 정의합니다.

# 1. Master Node
resource "proxmox_vm_qemu" "k8s_master" {
  vmid        = 120
  name        = "k8s-master"
  target_node = "pve-cluster"
  clone       = "rocky-10-template"
  full_clone  = true

  cores       = 4
  sockets     = 1
  cpu         = "host"
  memory      = 8192
  scsihw      = "virtio-scsi-pci"
  agent       = 1

  network {
    model  = "virtio"
    bridge = "vmbr0"
  }

  os_type    = "cloud-init"
  ipconfig0  = "ip=192.168.219.120/24,gw=192.168.219.1"
  ciuser     = "root"
  cipassword = "password1234"

  bootdisk = "scsi0"

  disks {
    scsi {
      scsi0 {
        disk {
          storage = "local-lvm"
          size    = "40G"
        }
      }
    }
    ide {
      ide2 {
        cloudinit {
          storage = "local-lvm"
        }
      }
    }
  }
}

# 2. Worker Nodes
resource "proxmox_vm_qemu" "k8s_worker" {
  count       = 4
  vmid        = 121 + count.index
  name        = "k8s-worker-${count.index + 1}"
  target_node = "pve-cluster"
  clone       = "rocky-10-template"
  full_clone  = true

  cores       = 4
  sockets     = 1
  cpu         = "host"
  memory      = 10240
  scsihw      = "virtio-scsi-pci"
  agent       = 1
   
  network {
    model  = "virtio"
    bridge = "vmbr0"
  }

  os_type    = "cloud-init"
  ipconfig0  = "ip=192.168.219.12${count.index + 1}/24,gw=192.168.219.1"
  ciuser     = "root"
  cipassword = "password1234"

  bootdisk = "scsi0"

  disks {
    scsi {
      scsi0 {
        disk {
          storage = "local-lvm"
          size    = "100G"
        }
      }
    }
    ide {
      ide2 {
        cloudinit {
          storage = "local-lvm"
        }
      }
    }
  }
}

6. 계획 확인

terraform plan

 

마지막에 이렇게 문구가 나오면 성공입니다.

7. 적용 및 생성

terraform apply

 

40분을 기다리고 있어도 작업이 끝나지 않았습니다. 그래서 강제 종료하고 원인을 찾아보니 main.tf 파일에서 'target_node' 가 잘못 설정 되어 있어서 계속 멤돌고 있었습니다. 수정하고 다시 실행해 보니

 

rm terraform.tfstate terraform.tfstate.backup

 

위의 명령어로 상태 파일을 삭제하고 'terraform init', 'terraform apply' 로 다시 실행해도 똑같은 오류가 생겼습니다. 여러가지 방법을 시도 했는데 결국엔 원인은

 

proxmox 8.4 버전과 테라폼 2.9.4 버전이 호환이 되지 않았습니다.

 

테라폼 버전을 3.0.1 로 업그레이드하고, main.tf 파일의 문법을 수정하니

 

1분 만에 5개의 VM 을 만드는 것에 성공했습니다.

8.접속 테스트

# Master 노드 접속
ssh root@192.168.219.120
# (비밀번호: password1234)

 

하지만 접속이 안됐습니다.

이유를 찾아보니 Cloud-Init 이 제대로 안붙어서 계정 정보가 생기지 않았습니다.

Telmate 방법에서 BPG 방법으로 전환

 

  • Telmate: Proxmox 7.x 버전을 기준으로 개발되었습니다. Proxmox 8.x 버전에서 변경된 API 응답(디스크 용량 데이터 타입 등)을 제대로 처리하지 못해 'Panic' 에러가 발생하거나 플러그인이 비정상 종료되는 문제가 잦습니다.
  • BPG: 최신 Proxmox 버전을 지원하기 위해 개발되었습니다. Proxmox 8.x의 API를 올바르게 해석하므로 버전 충돌로 인한 에러가 발생하지 않습니다.

 

provider.tf

terraform {
  required_providers {
    proxmox = {
      source  = "bpg/proxmox"
      version = ">= 0.78.0"
    }
  }
}

provider "proxmox" {
  endpoint = var.proxmox_api_url

  api_token = "${var.proxmox_api_token_id}=${var.proxmox_api_token_secret}"

  insecure = true

  ssh {
    agent = true
  }
}

terraform.tfvars

# 예: https://192.168.219.200:8006/api2/json
proxmox_api_url = "https://[Proxmox-IP]:8006/"

# 예: root@pam!terraform
proxmox_api_token_id = "[Proxmox에서-생성한-Token-ID]"

# 예: 8f3b2a1c-xxxx-xxxx...
proxmox_api_token_secret = "[복사해둔-Secret-Key]"

main.tf

# 1. Master Node
resource "proxmox_virtual_environment_vm" "k8s_master" {
  name      = "k8s-master"
  node_name = "pve-cluster"
  vm_id     = 120

  # 기존 템플릿(9010)을 복제
  clone {
    vm_id = 9010
    full  = true
  }

  cpu {
    cores = 4
    type  = "host"
  }

  memory {
    dedicated = 8192
  }

  agent {
    enabled = true
  }

  network_device {
    bridge = "vmbr0"
    model  = "virtio"
  }

  initialization {
    
    # IP 설정
    ip_config {
      ipv4 {
        address = "192.168.219.120/24"
        gateway = "192.168.219.1"
      }
    }

    # 사용자 계정 설정 (자동으로 적용됨)
    user_account {
      username = "root"
      password = "password1234"
      # 맥북의 공개키 파일 등록
      keys = [trimspace(file("~/.ssh/id_ed25519.pub"))]
    }
  }
}

# 2. Worker Nodes
resource "proxmox_virtual_environment_vm" "k8s_worker" {
  count     = 4
  name      = "k8s-worker-${count.index + 1}"
  node_name = "pve-cluster"
  vm_id     = 121 + count.index

  clone {
    vm_id = 9010
    full  = true
  }

  cpu {
    cores = 4
    type  = "host"
  }

  memory {
    dedicated = 10240
  }

  agent {
    enabled = true
  }

  network_device {
    bridge = "vmbr0"
    model  = "virtio"
  }

  initialization {
    ip_config {
      ipv4 {
        address = "192.168.219.12${count.index + 1}/24"
        gateway = "192.168.219.1"
      }
    }

    user_account {
      username = "root"
      password = "password1234"
      keys = [trimspace(file("~/.ssh/id_ed25519.pub"))]
    }
  }
}

생성

접속 테스트

 

 

드디어 VM 생성 후 접속까지 성공했습니다.

'project > 본투비엔지니어' 카테고리의 다른 글

[본투비엔지니어] 나에게 베어본만 주어진다면?? (8)  (0) 2026.01.29
[본투비엔지니어] 나에게 베어본만 주어진다면?? (7)  (0) 2026.01.29
[본투비엔지니어] 나에게 베어본만 주어진다면?? (5)  (0) 2026.01.28
[본투비엔지니어] 나에게 베어본만 주어진다면?? (4)  (0) 2026.01.27
[본투비엔지니어] 나에게 베어본만 주어진다면?? (3)  (0) 2026.01.27
'project/본투비엔지니어' 카테고리의 다른 글
  • [본투비엔지니어] 나에게 베어본만 주어진다면?? (8)
  • [본투비엔지니어] 나에게 베어본만 주어진다면?? (7)
  • [본투비엔지니어] 나에게 베어본만 주어진다면?? (5)
  • [본투비엔지니어] 나에게 베어본만 주어진다면?? (4)
heejunp
heejunp
희준개발
  • heejunp
    희준개발
    heejunp
  • 전체
    오늘
    어제
    • 분류 전체보기 (60)
      • 회고 (1)
      • project (13)
        • 본투비엔지니어 (12)
        • 페어쉐어 (1)
      • java (16)
      • spring (1)
      • go (1)
      • web (1)
      • cloud (1)
      • cloudflare (1)
      • database (1)
      • algorithm (16)
      • OS (1)
      • ai (1)
      • 기타 (2)
      • 오류 (1)
      • 생각정리 (2)
      • 자격증 (1)
        • RHCSA (1)
      • linux (0)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    heejunp
    [본투비엔지니어] 나에게 베어본만 주어진다면?? (6)
    상단으로

    티스토리툴바