homelab89 Docs Logs Legacy Files ☰ TOC 🌓
guidek8s 2026-06-29kubernetesvirshkvmcloud-init

virsh + cloud-init VM 생성 가이드

작성일: 2026-03-05 환경: Ubuntu 24.04 호스트, libvirt/KVM, cloud-init

사전 조건

  • 호스트에 br-host 브릿지가 구성되어 있어야 함 (203.0.113.0/24 대역)
  • 원본 클라우드 이미지: /var/lib/libvirt/images/noble-server-cloudimg-amd64.img
  • cloud-init 설정 디렉토리: /var/lib/libvirt/cloud-init/

디렉토리 구조

/var/lib/libvirt/
├── images/
│   ├── noble-server-cloudimg-amd64.img   ← 원본 (수정 금지)
│   ├── k8s-cp1.qcow2                     ← VM별 디스크
│   └── ...
└── cloud-init/
    ├── k8s-cp1-user-data.yaml
    ├── k8s-cp1-network-config.yaml
    ├── k8s-cp1-cidata.iso
    └── ...

생성 절차

1. 변수 설정

NAME=k8s-worker1         # VM 이름
IP=203.0.113.71          # 할당할 IP
MEM=2048                 # 메모리 (MB)
VCPU=2                   # vCPU 수
DISK_SIZE=20G            # 디스크 크기
BASE_IMG=/var/lib/libvirt/images/noble-server-cloudimg-amd64.img
IMG=/var/lib/libvirt/images/${NAME}.qcow2
CLOUD_INIT_DIR=/var/lib/libvirt/cloud-init

2. user-data.yaml 작성

sudo tee ${CLOUD_INIT_DIR}/${NAME}-user-data.yaml > /dev/null <<'EOF'
#cloud-config
hostname: k8s-worker1
manage_etc_hosts: true
users:
  - name: kube
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    ssh_authorized_keys:
      - ssh-ed25519 AAAA...REPLACE-WITH-YOUR-PUBLIC-KEY... user@host
package_update: true
packages:
  - curl
  - wget
  - vim
  - net-tools
  - jq
  - tree
  - tcpdump
  - socat
  - conntrack
  - ipset
EOF

주의: 첫 줄의 #cloud-config은 반드시 포함해야 한다. 없으면 cloud-init이 동작하지 않는다.

3. network-config.yaml 작성

sudo tee ${CLOUD_INIT_DIR}/${NAME}-network-config.yaml > /dev/null <<EOF
version: 2
ethernets:
  enp1s0:
    dhcp4: false
    addresses:
      - ${IP}/24
    gateway4: 203.0.113.1
    nameservers:
      addresses:
        - 1.1.1.1
        - 8.8.8.8
EOF

주의: IP 대역은 연결할 브릿지 대역(br-host = 203.0.113.0/24)과 일치해야 한다.

4. cloud-init ISO 생성

sudo cloud-localds "${CLOUD_INIT_DIR}/${NAME}-cidata.iso" \
  "${CLOUD_INIT_DIR}/${NAME}-user-data.yaml" \
  --network-config "${CLOUD_INIT_DIR}/${NAME}-network-config.yaml"

5. 디스크 이미지 준비

sudo cp "$BASE_IMG" "$IMG"
sudo qemu-img resize "$IMG" "$DISK_SIZE"

주의: 반드시 원본 클라우드 이미지(noble-server-cloudimg-amd64.img)에서 복사해야 한다. 이미 cloud-init이 실행된 이미지를 복사하면 새 설정이 적용되지 않는다.

6. VM 생성

sudo virt-install \
  --name "$NAME" \
  --memory "$MEM" \
  --vcpus "$VCPU" \
  --disk path="$IMG",format=qcow2 \
  --disk path="${CLOUD_INIT_DIR}/${NAME}-cidata.iso",device=cdrom \
  --os-variant ubuntu24.04 \
  --network bridge=br-host,model=virtio \
  --graphics none \
  --console pty,target_type=serial \
  --noautoconsole \
  --import

7. 접속 확인

# 30초 정도 대기 후
ping -c 3 ${IP}
ssh kube@${IP}

전체 스크립트 (복사-붙여넣기용)

#!/bin/bash
set -e

NAME=k8s-worker1
IP=203.0.113.71
MEM=2048
VCPU=2
DISK_SIZE=20G
BASE_IMG=/var/lib/libvirt/images/noble-server-cloudimg-amd64.img
IMG=/var/lib/libvirt/images/${NAME}.qcow2
CLOUD_INIT_DIR=/var/lib/libvirt/cloud-init

# user-data
sudo tee ${CLOUD_INIT_DIR}/${NAME}-user-data.yaml > /dev/null <<EOF
#cloud-config
hostname: ${NAME}
manage_etc_hosts: true
users:
  - name: kube
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    ssh_authorized_keys:
      - ssh-ed25519 AAAA...REPLACE-WITH-YOUR-PUBLIC-KEY... user@host
package_update: true
packages:
  - curl
  - wget
  - vim
  - net-tools
  - jq
  - tree
  - tcpdump
  - socat
  - conntrack
  - ipset
EOF

# network-config
sudo tee ${CLOUD_INIT_DIR}/${NAME}-network-config.yaml > /dev/null <<EOF
version: 2
ethernets:
  enp1s0:
    dhcp4: false
    addresses:
      - ${IP}/24
    gateway4: 203.0.113.1
    nameservers:
      addresses:
        - 1.1.1.1
        - 8.8.8.8
EOF

# cloud-init ISO
sudo cloud-localds "${CLOUD_INIT_DIR}/${NAME}-cidata.iso" \
  "${CLOUD_INIT_DIR}/${NAME}-user-data.yaml" \
  --network-config "${CLOUD_INIT_DIR}/${NAME}-network-config.yaml"

# 디스크
sudo cp "$BASE_IMG" "$IMG"
sudo qemu-img resize "$IMG" "$DISK_SIZE"

# VM 생성
sudo virt-install \
  --name "$NAME" \
  --memory "$MEM" \
  --vcpus "$VCPU" \
  --disk path="$IMG",format=qcow2 \
  --disk path="${CLOUD_INIT_DIR}/${NAME}-cidata.iso",device=cdrom \
  --os-variant ubuntu24.04 \
  --network bridge=br-host,model=virtio \
  --graphics none \
  --console pty,target_type=serial \
  --noautoconsole \
  --import

echo "VM '${NAME}' 생성 완료. 30초 후 ssh kube@${IP} 로 접속 가능."

VM 삭제

sudo virsh destroy $NAME        # 강제 종료
sudo virsh undefine $NAME       # 정의 제거
sudo rm /var/lib/libvirt/images/${NAME}.qcow2
sudo rm /var/lib/libvirt/cloud-init/${NAME}-*

현재 IP 할당 현황

VM 이름 IP 용도
호스트 (br-host) 203.0.113.2 KVM 호스트
k8s-cp1 203.0.113.70 K8s Control Plane

주의사항 체크리스트

  • user-data.yaml 첫 줄이 #cloud-config인가?
  • network-config의 IP가 br-host 대역(203.0.113.0/24)인가?
  • 디스크를 원본 클라우드 이미지에서 복사했는가?
  • --network bridge=br-host을 사용했는가? (virbr0 아님)
  • IP가 다른 VM과 충돌하지 않는가?

Files