Ansible: KVMの仮想マシンを削除する
はじめに
検証環境としてサクッとVMを作ったり壊したりするのに便利なKVM、よく使っています。今回はKVM上で動作する仮想マシンを削除するためのPlaybookを作ってみます。手動で操作する場合は virsh
を叩いたりしています。ただ、削除するにしても複数のサブコマンド実行が必要だったり、ホストマシンからの名前解決を/etc/hosts で簡易的に管理している場合はそちらのエントリも削除したりといった具合で手間がかかるため、そうした手間を省くのが今回のモチベーションです。
削除操作を自動化していますので試す場合はご注意ください&自己責任でお願いします。
準備
VMの操作には community.libvirt.virt
モジュールを使います。
Playbookと同じディレクトリで requirements.yml
を作成し、依存する collection を定義します。
requirements.yml
--- collections: - community.libvirt
collection をインストールします。
ansible-galaxy collection install -r requirements.yml -p collections
実装
今回作成したPlaybookがこちらです。
--- - name: Delete vms hosts: localhost gather_facts: false vars: vms: - hostname: 'centos8' tasks: - name: Get available vms community.libvirt.virt: command: list_vms register: existing_vms - name: Check if target vm name is existing ansible.builtin.assert: that: item.hostname in existing_vms['list_vms'] fail_msg: "target vm '{{ item.hostname }}' is not found on kvm" loop: "{{ vms }}" - name: Destroy vms community.libvirt.virt: command: destroy name: "{{ item.hostname }}" loop: "{{ vms }}" ignore_errors: true - name: Undefine vms community.libvirt.virt: command: undefine name: "{{ item.hostname }}" loop: "{{ vms }}" - name: Delete qcow2 image ansible.builtin.file: path: "/var/lib/libvirt/images/{{ item.hostname }}.qcow2" state: absent loop: "{{ vms }}" - name: Delete hosts entry ansible.builtin.lineinfile: path: /etc/hosts regex: ".*{{ item.hostname }}.*" state: absent loop: "{{ vms }}"
複数のVMをまとめて削除できるよう、ドメイン名のリストを変数として定義し、各タスクで loop させています。安直に1つのPlaybookにまとめましたが、この処理をまるっとタスクファイルに切り出して include_tasks
で呼び出すようにすれば、loopの定義が1箇所で済むのでもう少しスマートになりそうです。
削除の流れとしては、指定したドメインのVMが存在するかを確認した上で、問題なければ destory、undefineを実行してVMを削除します。仮想マシンが停止している状態だと destory する際にエラーを返すため、 ignore_errors: true
を対処しています。
また、前述の通り今回はホストマシンから仮想マシンに対する名前解決はホストマシン上の /etc/hosts で管理しているので、登録されたエントリも併せて削除しています。
実行結果
仮想マシンは以下のように停止した状態で削除してみます。
sudo virsh list --all Id Name State ----------------------------- - centos8 shut off
いざ実行。
PLAY [Delete vms] **************************************************************************************************************************************************************************** TASK [Get available vms] ********************************************************************************************************************************************************************* ok: [localhost] TASK [Check if target vm name is existing] *************************************************************************************************************************************************** ok: [localhost] => (item={'hostname': 'centos8'}) => { "ansible_loop_var": "item", "changed": false, "item": { "hostname": "centos8" }, "msg": "All assertions passed" } TASK [Destroy vms] *************************************************************************************************************************************************************************** An exception occurred during task execution. To see the full traceback, use -vvv. The error was: libvirt.libvirtError: Requested operation is not valid: domain is not running failed: [localhost] (item={'hostname': 'centos8'}) => {"ansible_loop_var": "item", "changed": false, "item": {"hostname": "centos8"}, "msg": "Requested operation is not valid: domain is not running"} ...ignoring TASK [Undefine vms] ************************************************************************************************************************************************************************** ok: [localhost] => (item={'hostname': 'centos8'}) TASK [Delete qcow2 image] ******************************************************************************************************************************************************************** changed: [localhost] => (item={'hostname': 'centos8'}) TASK [Delete hosts entry] ******************************************************************************************************************************************************************** changed: [localhost] => (item={'hostname': 'centos8'}) PLAY RECAP *********************************************************************************************************************************************************************************** localhost : ok=6 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
無事削除できました。