Proxmox 설치부터 Terraform으로 VM 찍어내기까지 (홈랩 k8s 구축기 1편)

munilive
munilive
Proxmox 설치부터 Terraform으로 VM 찍어내기까지 (홈랩 k8s 구축기 1편)

집에 Kubernetes 클러스터를 구축해 봤습니다에서 전체 구성과 삽질의 개요를 간략하게 정리했다. 이번 편부터는 각 단계를 좀 더 구체적으로 풀어볼 생각이다. 1편의 주제는 Proxmox 설치와 Terraform을 이용한 VM 프로비저닝이다.

Proxmox 설치

ASRock DeskMini X600은 워낙 작은 폼팩터다 보니 설치 자체는 간단했다. USB 부팅 디스크를 만들고, BIOS에서 몇 가지를 확인한 뒤 설치 화면을 따라가면 된다.

그런데 BIOS에서 놓치면 안 되는 항목이 두 가지 있었다. 하나는 SVM Enable(AMD 가상화), 다른 하나는 Secure Boot Disabled다. 둘 다 기본값 그대로 두면 문제가 생기는데, Secure Boot이 켜져 있으면 Proxmox USB 자체가 부팅이 안 된다. 처음에 이걸 확인 안 하고 진행했다가 괜히 USB를 다시 굽고 설치 이미지를 의심하는 시간을 보냈다. (당연히 USB 문제가 아니었다.)

설치 시 스토리지 설정에서 파일시스템으로 ZFS를 선택했다. NVMe SSD 한 개짜리 환경에서 zfs (RAID0)는 이름은 RAID0이지만 실제로는 단일 디스크 ZFS 모드로 동작한다. Proxmox에서 ZFS를 쓰면 스냅샷, thin-provisioning 등 여러 기능이 따라오고, 이후 Terraform에서 VM 디스크로 local-zfs 스토리지를 쓰게 되니 일관성 면에서도 좋았다.

설치 직후에는 바로 보안 설정을 진행했다. root 계정으로만 운영하는 것은 찜찜하니 별도 관리자 계정(munilive)을 만들고, 1Password에서 SSH 키를 새로 생성해 Proxmox에 등록했다. SSH 키 인증이 정상 동작하는 것을 확인한 뒤에 비밀번호 로그인을 막았다. 순서를 틀리면 접속이 안 되는 상황이 생기니 이 순서는 반드시 지켜야 한다.

Terraform으로 VM 프로비저닝

Proxmox를 코드로 관리하는 방법을 찾다 보면 telmate/proxmoxbpg/proxmox 두 provider가 자주 나온다. 전자가 오래됐고, 후자가 더 활발하게 유지보수되고 있어서 bpg/proxmox를 선택했다.

VM 설정은 locals.tf에 맵 형태로 관리했다.

locals {
  vms = {
    "k8s-control-plane" = {
      vm_id  = 110
      cores  = 4
      memory = 8192
      disk   = 50
      ip     = "192.168.50.110"
    }
    "k8s-worker-1" = {
      vm_id  = 111
      cores  = 4
      memory = 10240
      disk   = 300
      ip     = "192.168.50.111"
    }
    "k8s-worker-2" = {
      vm_id  = 112
      cores  = 4
      memory = 10240
      disk   = 300
      ip     = "192.168.50.112"
    }
  }
}

이렇게 해두면 나중에 노드를 추가하거나 스펙을 변경할 때 이 파일 하나만 수정하면 된다. vms.tf에서는 for_each로 이 맵을 순회하며 VM을 생성한다.

OS 이미지는 Ubuntu 24.04 LTS 클라우드 이미지를 사용했다. bpg/proxmox provider가 이 이미지를 Proxmox에 자동으로 업로드해주는데, 이때 내부적으로 SSH를 통해 qm importdisk 명령을 실행한다. Cloud-init을 이용해 SSH 공개키, 고정 IP, 호스트명 등을 VM 생성 시점에 한 번에 주입할 수 있어서 편리했다.

SSH 인증 문제

여기서 첫 번째 삽질이 시작됐다. 나는 SSH 키를 1Password SSH 에이전트로 관리하고 있어서, 터미널에서 ssh root@192.168.50.100은 비밀번호 없이 잘 된다. 당연히 Terraform도 에이전트를 통해 인증할 수 있을 거라 생각했다.

그런데 terraform apply를 실행하면 계속 SSH 인증 오류가 났다.

unable to authenticate user "" over SSH to "192.168.50.100:22"
attempted methods [none], no supported methods remain

SSH_AUTH_SOCK 환경변수도 확인해봤고, agent_socket 경로를 직접 지정해보기도 했지만 전부 실패였다. bpg/proxmox provider 내부의 Go SSH 라이브러리가 1Password 에이전트 소켓을 제대로 읽지 못하는 것이 원인이었다. 터미널에서 직접 SSH는 되는데 provider만 안 된다는 게 꽤 어처구니없었다.

결국 1Password에서 개인키를 파일로 내보내어 직접 참조하는 방식으로 해결했다.

ssh {
  agent       = false
  username    = "root"
  private_key = file(pathexpand("~/.ssh/proxmox_deskmini"))
}

이 파일은 ~/.ssh/ 아래에 두어서 레포에는 포함되지 않는다. 거슬리지 않는 방법은 아니었지만, 이게 현재로서는 가장 확실한 해결책이었다.

CPU 타입과 AVX

VM CPU 타입을 처음에는 x86-64-v2-AES로 설정했다. 이 타입은 특정 CPU 기능 수준을 보장하면서 VM 마이그레이션 호환성을 높여주는데, 문제는 AVX 명령어가 포함되지 않는다는 점이었다.

MongoDB 5.0부터 AVX가 필수가 됐다. 그래서 나중에 MongoDB를 설치하면 Pod이 계속 Illegal instruction (core dumped)으로 죽었다. 한참을 들여다보다가 CPU 타입 문제라는 걸 알고 나서 host로 변경했다. host 타입은 Proxmox 호스트의 CPU 기능을 VM에 그대로 노출하는 방식이라 Ryzen 7 8700G가 지원하는 AVX도 당연히 VM에서 쓸 수 있게 된다.

단점은 VM을 다른 CPU의 호스트로 마이그레이션할 수 없다는 것이다. 홈랩 단일 머신 환경에서는 마이그레이션할 곳이 없으니 상관없었지만, 나중에 노드를 추가하면서 VM을 옮겨야 하는 상황이 생기면 다시 고민이 필요할 수 있다.

실행

준비가 끝나면 아래 순서로 진행한다.

cd infrastructure/proxmox
source .env
terraform init
terraform plan
terraform apply

apply가 완료되면 Proxmox 웹 UI에서 VM 3개(vm-110, vm-111, vm-112)가 생성된 것을 확인할 수 있다. Cloud-init 덕분에 VM이 부팅되면 바로 SSH로 접속이 가능하다.

ssh ubuntu@192.168.50.110
ssh ubuntu@192.168.50.111
ssh ubuntu@192.168.50.112

Proxmox 설치와 VM 프로비저닝, 이 두 단계만 하면 Kubernetes 클러스터를 올릴 기반이 준비된다. 다음 편에서는 이 VM 3개 위에 Ansible로 Kubernetes 클러스터를 구성하는 과정을 이야기 하겠다.

munilive

munilive

Backend Application Developer

Share

Comments

Related Posts

집에 Kubernetes 클러스터를 구축해 봤습니다

집에 Kubernetes 클러스터를 구축해 봤습니다

퇴근하고 집에 돌아와 미니 PC 한 대를 책상 위에 올려두고는 여기다가 Kubernetes 클러스터를 직접 구축해 보겠다고 마음먹은 게 몇 달 전이었다. 그리고 지금, 그 미니 P…

munilive munilive ·
Ansible로 Kubernetes 클러스터를 코드 한 줄로 (홈랩 k8s 구축기 2편)

Ansible로 Kubernetes 클러스터를 코드 한 줄로 (홈랩 k8s 구축기 2편)

지난 편에서 Terraform으로 VM 3개를 만들었다. 이번에는 그 VM들 위에 Kubernetes 클러스터를 올리는 과정이다. kubeadm으로 클러스터를 직접 구성하고, 그…

munilive munilive ·
MetalLB, ingress-nginx, Longhorn으로 네트워크와 스토리지 구성하기 (홈랩 k8s 구축기 3편)

MetalLB, ingress-nginx, Longhorn으로 네트워크와 스토리지 구성하기 (홈랩 k8s 구축기 3편)

지난 편에서 Ansible로 Kubernetes 클러스터를 구성했다. 클러스터는 올라왔지만, 이 상태로는 아무것도 할 수 없다. 외부에서 트래픽을 받는 방법도 없고, 데이터를 저장…

munilive munilive ·