ansible の libvirt モジュールがあったので使おうとしてみた。
動機
Production 環境でもダイジョーブな、 Linux での仮想環境をさくっと作りたい、でもなんちゃら Stack を入れるのはちょっと重すぎ!ていうわけで、手軽に KVM で動かせればなーという動機です。探したら別の手段ありそうですが。そこ Docker でいいじゃんとは言わない。
で、色々調べていた所、ansible のモジュール virt
を発見:virt - Manages virtual machines supported by libvirt — Ansible Documentation
怪しい匂いがする、というところで、KVM を勉強するついでに触ろうとしました。
動作環境
DigitalOcean は日本に進出しないみたいですかねー。DigitalOcean は vagrant 用のプラグインを公開しているので、それを使うと楽です。
KVM の操作
必要なものの準備
最低限のパッケージと OS イメージは準備しておく。
- name: Ensure kvm packages are installed yum: name: "{{ item }}" state: present with_items: - libvirt - qemu-kvm - bridge-utils - libvirt-python - name: Ensure Centos 7 ISO file is downloaded get_url: url: http://ftp.jaist.ac.jp/pub/Linux/CentOS/7/isos/x86_64/CentOS-7-x86_64-Minimal-1511.iso dest: /download/path/to/CentOS-7-x86_64-Minimal-1511.iso sha256sum: f90e4d28fa377669b2db16cbcb451fcb9a89d2460e3645993e30e137ac37d284
get_url
で何回もダウンロードさせないよう、dest
はファイル名まで指定するという基本テク?ですね。
virt モジュールを使う
libvirt でいうところの define コマンドを使う
では virt モジュールで指定しましょう。
にあるように、XML は実は文字列を指定するものです。ファイル名であれば {{lookup('template', 'your_define.xml.j2')}}
のようにしようね、とのことです。ちなみに lookup('template', path)
も、roles/some_role/template
ではなくroles/some_role/file
を探しに行くようです。こんなエラーがでました。
fatal: [machine1] => Failed to template {{ lookup('template', 'centos7_def.j2') }}: unable to read /path/to/roles/some_role/files/centos7_def.j2
壮大なるフェイントじゃないか。だからといって、template ファイルを flle
ディレクトリに置くのは気持ち悪い。というわけでこんな感じ
- name: Define VM using the XML file virt: command: define name: centos_via_ansible xml: "{{ lookup('template', '../templates/centos7_def.xml.j2') }}"
なんだかなー感あるのは気にしない。これを実行すると、
[vagrant@digital_ocean_host ~]$ sudo virsh list --all Id 名前 状態 ---------------------------------------------------- - centos7_temp シャットオフ
とでます。ちなみに、XML で name
を指定しないと怒られます。
<domain type='kvm'> <name>centos7_temp</name> (後略:最後に貼り付け)
と指定してます。VM の定義はできましたが、なんかやな予感……
define した VM を走らせる。
さて、定義した VM を走らせてみましょう。タスクは次のようにします
- name: Define VM using the XML file virt: command: define name: centos_via_ansible xml: "{{ lookup('template', '../templates/centos7_def.xml.j2') }}" - name: Ensure VM is started virt: name: centos_via_ansible state: running uri: qemu:///system
実行結果
TASK: [some_role | Define VM using the XML file] ********************************* failed: [digital_ocean_host] => {"failed": true} msg: operation failed: domain 'centos7_temp' already exists with uuid 6106bbb7-a310-43e8-b94e-576d00e98b3e FATAL: all hosts have already failed -- aborting PLAY RECAP ******************************************************************** to retry, use: --limit @/Users/******/site.retry digital_ocean_host : ok=1 changed=0 unreachable=0 failed=1
冪等性がないようです。ちなみに、公式 virt モジュールのドキュメントにも
in addition to state management, various non-idempotent commands are available. See examples
と、冪等性なんてないよ!といってます。
では Ensure VM s Started
だけで実行してみます。
TASK: [some_role | Ensure VM is started] ***************************************** failed: [digital_ocean_host] => {"failed": true} msg: virtual machine centos_via_ansible not found FATAL: all hosts have already failed -- aborting
やな予感的中。ちなみに、先ほど2つのタスクを同時に実行しても同じ結果です。そのため結局 XML の方に合わせました。
- name: Define VM using the XML file virt: command: define name: centos_via_ansible xml: "{{ lookup('template', '../templates/centos7_def.xml.j2') }}" - name: Ensure VM is started virt: name: centos_temp state: running uri: qemu:///system
この後しばらく libviet の VM 定義ファイル(XML)と格闘する
結局格闘し続けてます。
おわりに
virt-install
というツールが優秀すぎて、ansible の virt
モジュールを使う気がなくなりました。まずは KVM をがっつり勉強しなさいっていうことですね、はい。
そのため、libvirt での VM 定義ファイルをふつーに勉強すれば、おそらく virt-install
ではなく ansible の virt
モジュールと template エンジンでうまいこと様々なことが出来そうですね。
また、virt-install
でも virt
モジュールでも、どちらでも KickStart が必要ですね。kickstart と、ansible または virt-install のどちらか一つを組み合わせると無人で VM デプロイが可能ですね。この辺が見えてきてよかったかなーと。もうちょっと virt
モジュールは頑張っても良かったのでは