以前まとめた以下の「テンプレートの作成」をAnsibleで自動化する、という話。
作業するのは年に数回なんでいつも心温まる手作業だったけど、コマンドの実行回数が6回くらいあってさすがに回を重ねるとダルくなってきたため、シェルスクリプトでも構わない内容ではあったけどせっかくなのでAnsible Playbookで実装。これならAWXとかと連携してwebのUIでテンプレート作成できるからね。
2026.02.15:ディスクサイズの指定が抜けてたので追記。VM作成時はできなさそうだったのでリサイズのタスクを追加
Playbook
作ったPlaybookは以下の通り。
--- - name: create VM template hosts: all gather_facts: false vars: install_iso_file: /mnt/pve/pecorino-dev/template/iso/rhel-10.0-x86_64-kvm.qcow2 vm_id: 9014 vm_name: rhel10.0-template3 pve_node: pve01 vm_cpu: x86-64-v3 vm_sockets: 1 vm_cores: 2 vm_memory: 8192 vm_disksize: 12G vm_ssh_key: ※ ssh公開鍵の文字列 vm_dns: - 192.168.0.4 - 8.8.8.8 vm_ip0: dhcp vm_ip1: 172.16.0.42/23 tasks: - name: create VM community.general.proxmox_kvm: name: "{{ vm_name }}" vmid: "{{ vm_id }}" node: "{{ pve_node }}" cpu: "{{ vm_cpu }}" sockets: "{{ vm_sockets }}" cores: "{{ vm_cores }}" memory: "{{ vm_memory }}" net: net0: 'virtio,bridge=vmbr0' net1: 'virtio,bridge=vmbr1,firewall=1' scsihw: virtio-scsi-pci scsi: scsi0: 'local-lvm:0,import-from={{ install_iso_file }}' ide: ide2: 'local-lvm:cloudinit' boot: order=scsi0 serial: serial0: socket vga: serial0 # options agent: enabled=1 # cloud-init ciuser: zaki sshkeys: "{{ vm_ssh_key }}" ipconfig: ipconfig0: "ip={{ vm_ip0 }}" ipconfig1: "ip={{ vm_ip1 }}" nameservers: "{{ vm_dns }}" - name: resize disk community.proxmox.proxmox_disk: vmid: "{{ vm_id }}" disk: scsi0 size: "{{ vm_disksize }}" state: resized - name: VM convert to template community.general.proxmox_kvm: vmid: "{{ vm_id }}" state: template
playの流れ
基本的に見ればわかる内容だと思うけど、以下の2段構成になっている。
community.general.proxmox_kvmモジュールの仕様で、「テンプレートとしてリソースを作成する」ことは一発では(たぶん)できないため、CLIで処理するときと同じく、まずVMを作成しそれをテンプレートに変換する、という流れになる。
VMの作成
community.general.proxmox_kvmモジュールを使って作成する。
詳しくは以下で一度まとめているが、今回はVM作成なのでcloneは使わない。
VMのスペック系のパラメタや、デフォルトとしてセットしたいcloud-initの内容をここで指定しておく。
(cloud-initのパラメタはVM作成時(クローン時)に都度調整できるんで、ここでは初期値をセットするイメージ)
前回まとめなかったパラメタとしてagent: enabled=1を追加しているが、これはオプションの「QEMU Guest Agent」を有効にする設定。
これはデフォルト無効だが、基本的には有効にしておいた方が便利。
ハード(仮想だけど)関連のパラメタは、CLIでVM作成時に指定するものをそのままAnsibleのproxmox_kvmモジュールのパラメタに落とし込んでいる。
備忘録を兼ねて内容のマッピングを以下にメモ。
| Ansible | CLI | comment |
|---|---|---|
scsihw: virtio-scsi-pci |
qm create ... --scsihw virtio-scsi-pci |
VM作成 |
scsi.scsi0: 'local-lvm:0,import-from=...' |
qm set ... --scsi0 local-lvm:0,import-from=... |
イメージのセット |
ide.ide2: 'local-lvm:cloudinit' |
qm set ... --ide2 local-lvm:cloudinit |
cloud-initの追加 |
boot: order=scsi0 |
qm set ... --boot order=scsi0 |
ブート順 |
serial.serial0: socket + vga: serial0 |
qm set ... --serial0 socket --vga serial0 |
シリアルコンソール設定 |
ディスクのリサイズ (2026.02.15追記)
クラウドイメージからVMを作ると5GB程度のサイズになっていろいろ不都合があるためリサイズ。
VM作成時のパラメタでディスクサイズの指定がどうしてもわからなかったので、VM作成後にディスクのリサイズを実施。
これも書いてある通りだけど、VM作成時にscsi0指定でストレージ設定しているので、それを対象にリサイズ実行。指定するサイズは増分でなく実行後のサイズ(この指定の場合+12GBでなく総量12GBになる)
CLIだと以下コマンドに相当(調べただけで未確認)
qm resize ${vmid} scsi0 12G
テンプレート変換
これ以上ないくらい書いてる通り。
テンプレート変換するには、stateにtemplateをセットしつつ、既存のVMのIDを指定する。
このときにVMが無い場合はエラーになる。(なので事前にVMを作成する必要がある)
fatal: [local]: FAILED! =>
changed: false
msg: VM with vmid NNN does not exist in cluster
なお、VM作成に時間がかかる場合はノータイムでテンプレート変換のタスクを実行するとエラーになる場合があるため、sleepを入れたりVMが存在するまでwaitする仕組みを入れるとより安全。
環境
- Python: 3.12.8
- ansible core 2.18.2 (Ansible 11.2.0)
- proxmoxer 2.2.0
- community.general: 10.3.0
これでISOファイルを指定ディレクトリに配置した後のVM作成&テンプレート変換を自動化できる。
今回はRHEL10のテンプレート作成だったのでストレージに手動で配置した後の作業になっている。
が、FeodraやUbuntuであればISOファイルのダウンロード自体がパブリックアクセス可能なので、それ含めて全自動できるはず。(つまりISOのURLを指定して実行するだけでテンプレート作成まで一気通貫で処理できる。今回はやってないけどそれ含めて自動化は可能なはず)