proxmox cloud-init 으로 우분투 템플릿 이미지 만들기

yangs.dev·
시작하며
개인 장비에서 Proxmox 클러스터를 운영 하고 있다.
처음에는 VM 만들어지는것에 감사 했는데, 사람이 참 간사하다.

점점 우분투 설치 하는게 귀찮아지는 것이다.
그래서 마치 AWS Console에서 딸깍 하고 만들수있도록 처음에는 셋팅된 VM을 클론 해서 썼다.
근데, id 충돌, DHCP 실패등 또 사람 귀찮게 하는 일들이 늘어난다.
이래저래 찾아보던 중 진짜 AWS에서 cloud-init 이라는 방식으로 딸깍 하고 설치 한다고 하길래 그 내용을 오늘 정리 해보려고 한다.
1️⃣ Ubuntu Cloud Image 다운로드 및 디스크 크기 조정
먼저 최신 Jammy(22.04) 이미지 파일을 다운로드하고, 디스크 크기를 확장합니다.
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
qemu-img resize jammy-server-cloudimg-amd64.img 50G
- Ubuntu 공식 Cloud Image는 cloud-init이 이미 내장되어 있어, 초기설정을 자동화하기에 적합합니다.\
- 기본 크기가 작으므로 qemu-img resize 명령으로 50GB로 확장합니다.
2️⃣ Proxmox VM 생성
qm create 99001 --name=ubuntu-22-04 --memory=2048 --net0 virtio,bridge=vmbr1
- VM ID: 99001
- 이름: ubuntu-22-04
- 메모리: 2GB
- 네트워크: VirtIO + 브릿지(vmbr1)
네트워크 브리지는 환경에 맞게 vmbr0 또는 vmbr1로 변경 가능합니다.
3️⃣ Cloud Image를 VM 디스크로 등록
qm set 99001 --virtio0 iSCSI-2T:0,import-from=/mnt/pve/NFS-AN/template/iso/jammy-server-cloudimg-amd64.img
- virtio0 디스크로 연결\
- import-from 옵션을 이용해 기존 Cloud Image를 지정스토리지(iSCSI-2T)로 직접 가져옵니다.\
- import 과정에서 자동으로 QCOW2 → RAW 변환이 이뤄집니다.
4️⃣ Cloud-Init 드라이브 추가
qm set 99001 --ide2 iSCSI-2T:cloudinit
- Cloud-Init 설정 드라이브를 추가하여, 초기 부팅 시 사용자 메타데이터를 주입할 수 있습니다.\
- 주로 SSH 키, 호스트명, 네트워크 설정 등을 자동화할 때 사용됩니다.
5️⃣ 부팅 및 콘솔 설정
qm set 99001 --boot order=virtio0
qm set 99001 --serial0 socket --vga serial0
- 부팅 순서를 virtio0로 설정\
- serial0 콘솔을 통해 텍스트 기반 터미널 접속이 가능하도록설정합니다.→ qm terminal 99001로 콘솔 접근 가능
6️⃣ Cloud-Init 사용자 스크립트 지정
qm set 99001 --cicustom "user=NFS-GS:snippets/ubuntu-init.yaml"
- 사용자 정의 Cloud-Init YAML을 지정합니다.\
- snippets/ubuntu-init.yaml 파일에는 사용자, 패키지, SSH 설정 등을포함할 수 있습니다.
예시 (ubuntu-init.yaml):
#cloud-config
package_update: true
package_upgrade: true
timezone: Asia/Seoul
packages:
- qemu-guest-agent
- curl
- ca-certificates
- sudo
users:
- default
- name: yangs
gecos: Yangs Admin
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
groups: [sudo, docker]
lock_passwd: false
ssh_authorized_keys:
- "ssh-rsa ..."
runcmd:
- |
echo "=== 타임존 설정 (Asia/Seoul) ==="
timedatectl set-timezone Asia/Seoul
echo "현재 타임존: $(timedatectl show --property=Timezone --value)"
- |
echo "=== Docker 설치 중 ==="
curl -fsSL https://get.docker.com -o /tmp/get-docker.sh
chmod +x /tmp/get-docker.sh
sh /tmp/get-docker.sh
- |
echo "=== Docker Compose 설치 중 ==="
curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
- |
echo "=== Docker 서비스 설정: 자동 시작 및 재시작 정책 ==="
systemctl enable docker
mkdir -p /etc/docker
echo '{' > /etc/docker/daemon.json
echo ' "log-driver": "json-file",' >> /etc/docker/daemon.json
echo ' "log-opts": {' >> /etc/docker/daemon.json
echo ' "max-size": "50m",' >> /etc/docker/daemon.json
echo ' "max-file": "3"' >> /etc/docker/daemon.json
echo ' }' >> /etc/docker/daemon.json
echo '}' >> /etc/docker/daemon.json
systemctl daemon-reload
systemctl restart docker
sudo usermod -aG docker yangs || true
echo "=== Docker 설정 완료 ==="
- |
echo "=== QEMU Guest Agent 활성화 ==="
systemctl enable qemu-guest-agent
systemctl start qemu-guest-agent
- |
echo "=== Prometheus Node Exporter 컨테이너 생성 ==="
sudo docker run --name=node-exporter \
--restart=always \
-d \
--net="host" \
--pid="host" \
-v "/:/host:ro,rslave" \
quay.io/prometheus/node-exporter:latest \
--path.rootfs=/host || true
echo "=== Node Exporter 실행 확인 ==="
sudo docker ps | grep node-exporter || echo "Node Exporter 컨테이너 생성 완료"
- |
echo "=== Ubuntu Clone 초기화 시작 ==="
set -e
echo "[1/6] machine-id 초기화 중..."
rm -f /etc/machine-id
dbus-uuidgen --ensure=/etc/machine-id
systemd-machine-id-setup
echo "[2/6] SSH 호스트 키 초기화 중..."
rm -f /etc/ssh/ssh_host_*
dpkg-reconfigure -f noninteractive openssh-server
echo "[4/6] netplan / udev 네트워크 캐시 초기화 중..."
rm -f /etc/udev/rules.d/70-persistent-net.rules
rm -f /etc/netplan/*.bak
echo "[5/6] 호스트네임 초기화 중..."
new_hostname="ubuntu-$(openssl rand -hex 3)"
hostnamectl set-hostname "$new_hostname"
echo "새 호스트명: $new_hostname"
echo "[6/6] 로그 및 캐시 정리 중..."
rm -rf /var/log/*
rm -rf /tmp/*
rm -rf /var/tmp/*
echo "=== 초기화 완료 ==="
echo "이제 'sudo reboot'으로 재부팅 해주세요."
power_state:
mode: reboot
timeout: 30
message: "Ubuntu 초기화 완료 후 자동 재부팅합니다."
7️⃣ 템플릿으로 변환
qm template 99001
- 설정 완료된 VM을 템플릿으로 변환합니다.\
- 이후 qm clone 명령을 통해 여러 인스턴스를 빠르게 생성할 수 있습니다.