libvirt な KVM のホストに、ベースとなるイメージからゲストをダバーっと作りたかったんですけど、IP アドレスやホスト名の設定を個別にやるのは流石にしんどいと思ったので cloud-init を使ってみたメモ。
最初は libvirt のネットワークの DHCP でどうにかしようと思いましたが、ゲストのネットワークをブリッジにしたかったので諦めました。
ベースイメージの cloud-init
ベースイメージのゲストに cloud-init をインストールします。
yum -y install cloud-init cloud-utils-growpart
次のように設定ファイルを作成します。
cp -a /etc/cloud/cloud.cfg{,.orig}
cat <<EOS | sudo tee /etc/cloud/cloud.cfg
datasource_list:
- NoCloud
cloud_init_modules:
- write-files
- bootcmd
- growpart
- resizefs
- set_hostname
- update_hostname
cloud_config_modules:
- timezone
- runcmd
cloud_final_modules:
- scripts-per-once
- scripts-per-boot
- scripts-per-instance
- scripts-user
- final-message
system_info:
distro: rhel
EOS
cloud-init のモジュールは使いそうなやつだけ有効にしています。また、データソースには NoCloud を指定します。
終わったらゲストはシャットダウンしておきます。
shutdown -h now
ゲストを作成(ひとつ)
ゲストを 1 つだけ作成してみます。
ベースイメージからスナップショットで新たしいイメージを作成します。
lvcreate -s /dev/vg1/base -n ore-no-server -L 5G
メタデータファイルを作成します。とりあえず instance-id
だけあればなんとかなりました。
cat <<EOS> meta-data
instance-id: $(uuidgen)
EOS
ユーザーデータファイルを作成します。cloud-init で I/F を設定するうまい方法がわからなかったので ifcfg-eth0 を作成して ifdown/ifup しています。
cat <<EOS> user-data
#cloud-config
hostname: ore-no-server
timezone: "Asia/Tokyo"
write_files:
- path: /etc/sysconfig/network-scripts/ifcfg-eth0
owner: root:root
permissions: '0644'
content: |
TYPE=Ethernet
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=none
IPADDR=192.168.8.10
PREFIX=24
GATEWAY=192.168.8.1
DNS1=192.168.8.1
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=no
bootcmd:
- ifdown eth0
- ifup eth0
EOS
これら 2 つのファイルを含む ISO を作成します。
genisoimage -output ore-no-server.iso -volid cidata -joliet -rock user-data meta-data
ゲストを作成します。このとき↑で作成した ISO もアタッチします。
virt-install \
--name ore-no-server \
--disk path=/dev/vg1/ore-no-server \
--disk path="$PWD/ore-no-server.iso,bus=ide,device=cdrom" \
--network bridge=br1 \
--hvm --virt-type kvm \
--vcpus 1 --ram 1024 --arch x86_64 \
--os-type linux --os-variant rhel7 \
--boot hd --graphics none --serial pty --console pty \
--import --noreboot
ゲストを開始します。
virsh start ore-no-server
IP アドレスやホスト名の設定ができているか確認します。
ssh root@192.168.8.10 uname -n
意図した通りに表示されれば成功です。
ゲストの作成(たくさん)
ゲストをたくさんダバーっと作成してみます。
作成するゲストのホスト名と IP アドレスの一覧を配列に入れます。
guests=(
sv01:192.168.8.11
sv02:192.168.8.12
sv03:192.168.8.13
sv04:192.168.8.14
sv05:192.168.8.15
sv06:192.168.8.16
sv07:192.168.8.17
sv08:192.168.8.18
)
イメージを作成します。
for guest in "${guests[@]}"; do
name=${guest%:*}
lvcreate -s /dev/vg1/base -n "$name" -L 5G
done
メタデータとユーザーデータの ISO を作成します。
for guest in "${guests[@]}"; do
addr=${guest#*:}
name=${guest%:*}
cat <<EOS> meta-data
instance-id: $(uuidgen)
EOS
cat <<EOS> user-data
#cloud-config
hostname: $name
timezone: "Asia/Tokyo"
write_files:
- path: /etc/sysconfig/network-scripts/ifcfg-eth0
owner: root:root
permissions: '0644'
content: |
TYPE=Ethernet
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=none
IPADDR=$addr
PREFIX=24
GATEWAY=192.168.8.10
DNS1=192.168.8.1
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=no
bootcmd:
- ifdown eth0
- ifup eth0
EOS
genisoimage -output "$name.iso" -volid cidata -joliet -rock user-data meta-data
done
ゲストを作成します。
(
set -eux
for guest in "${guests[@]}"; do
name=${guest%:*}
virt-install \
--name "$name" \
--disk path="/dev/vg1/$name" \
--disk path="$PWD/$name.iso,bus=ide,device=cdrom" \
--network bridge=br1 \
--hvm --virt-type kvm \
--vcpus 1 --ram 1024 --arch x86_64 \
--os-type linux --os-variant rhel7 \
--boot hd --graphics none --serial pty --console pty \
--import --noreboot
virsh start "$name"
done
)