はじめに
ProxmoxのVMでUbuntuをインストールを作るとき、毎回何回もポチポチしていてめんどくさくないですか...?
Google先生に聞いてみると、Terraformやansibleなどがあるようですが、そこまで使わなくてもCloud-initとシェルスクリプトだけでできそうだったので、Cloud-initとそれを使ってProxmoxにVMを作るシェルスクリプトを作成してみました。
お急ぎの方はこちらに全文のコードを貼ってあります
Cloud-initに自動でしてほしいこと
- OSのインストール&初期設定
- Ubuntuのインストール
- ユーザの設定
- SSHの設定
- 初回のapt update & apt upgrade
- よく使うソフトウェアのインストールと設定
- net-tools
- VScode
- Tailscale (必要に応じて)
- Zabbix agent (必要に応じて)
いろいろ入れておく
apt install cloud-init libguestfs-tools
ベースとなるCloud-init
#cloud-config
package_upgrade: true
packages: # aptでインストールしたいソフトウェア一覧
- qemu-guest-agent
- wget
- curl
- nano
- traceroute
- net-tools
- sl
#user setup
user: #USER_NAME
password: #PASSWORD
ssh_pwauth: False
ssh_authorized_keys:
- ssh-rsa #SSH_KEY
timezone: Asia/Tokyo
locale: ja_JP.utf8
keyboard:
layout: jp
runcmd:
#vscode install
- curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
- install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
- sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list'
- apt update
- apt install -y code
これで、Cloud-initを設定すると毎回使用するソフトウェアのインストールなどは最低限のことは自動でしてくれます。
(ネットワークの設定は後でします)
Cloud-initとそれを使ってProxmoxにVMを作るシェルスクリプト(基本)
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
まず、ubuntuのイメージをダウンロードしてきます。
qm create ${vmid} --core ${PVE_CORE} --memory ${PVE_MEMORY} --net0 virtio,bridge=vmbr0
qm importdisk ${vmid} ubuntu-22.04.img local-lvm
qm set ${vmid} --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-${vmid}-disk-0
qm resize ${vmid} scsi0 +${PVE_VOLUME}G
qm set ${vmid} --ide2 local-lvm:cloudinit
qm set ${vmid} --boot order=scsi0
qm set ${vmid} --serial0 socket --vga serial0
qm set ${vmid} --agent enabled=1
qm set ${vmid} --ipconfig0 ip=dhcp
qm template ${vmid}
基本的にはこれで十分できます。
しかし、毎回vmidを指定して...などなど、めんどくさいのでさらに簡単にしましょう。
Cloud-initとそれを使ってProxmoxにVMを作るシェルスクリプト(改良)
最後にコードをすべて貼ってあるのでお急ぎの方はそちらをご使用ください。
先ほどのコードに少しずつ機能を足して便利にしていきましょう。
ネットワークの設定
サクッと使うだけのVMならばDHCPで十分なので、基本は追加したネットデバイスに
qm set ${vmid} --ipconfig0 ip=dhcp
といった感じで設定しておけば問題ないです。
固定IPをしたい場合
-
qm set ${vmid}
のところで、--ipconfig0 "gw=○○.○○.○○.○○,ip=○○.○○.○○.○○/24" --nameserver ○○.○○.○○.○○
を追加する - GUIから設定(省略)
- Cloud-initで
/etc/netplan
にファイルを書く(省略)
など、いろいろあるのでお好きな方法でしてください
ネットデバイスを複数使いたい場合 (SDNなどの使用時)
qm create ${vmid} --core ${PVE_CORE} --memory ${PVE_MEMORY} --net0 virtio,bridge=vmbr0 --net1 virtio,bridge=vnet01
qm set ${vmid} --ipconfig1 ip=dhcp
といったように順番に足していけばいいです。(vnet01はSDNのVnet名)
まず、VMID考えるのめんどくさい問題から
vmid=100
for i in {100..900}; do
if ! [[ " ${vmids[@]} " =~ " $i " ]]; then
vmid=$i
break
fi
done
qm list
でVMのリストが得られるのでVMIDだけ取り出して使っていないVMIDを探します。
(この記事では、VMは100番以降、テンプレートは9000番以降のVMIDを取るように設定します)
複数ノードの場合は、普通に指定してください。
vmid=$1
if [ -z "${vmid}" ]; then
echo "VMID is required."
exit 1
fi
~~~
if [[ " ${vmids[@]} " =~ " $vmid " ]]; then
echo "エラー: 指定されたVMID ($vmid) は既に使用されています。"
exit 1
fi
Tailscaleをインストールしてみる
tailscale_key="tskey-auth-○○○" #TailscaleのAuth keyを指定してください。
echo -e ' - ['sh', '-c', "curl -fsSL https://tailscale.com/install.sh | sh"]' >> ${cloud_init_path}
echo -e ' - ['sh', '-c', "echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf && echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf && sudo sysctl -p /etc/sysctl.d/99-tailscale.conf" ]' >>${cloud_init_path}
echo -e ' - ['tailscale', 'set', '--ssh']' >> ${cloud_init_path}
echo -e ' - ['tailscale', 'set', '--auto-update']' >> ${cloud_init_path}
echo -e " - ['tailscale', 'up', '--authkey=${tailscale_key}']" >> ${cloud_init_path}
TailscaleをインストールするようにCloud-initにを加筆します。
Zabbix agentをインストールしてみる
zabbix_server_IP= #Zabbix_serverのIPを指定してください。
echo -e ' - wget https://repo.zabbix.com/zabbix/6.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_6.4-1+ubuntu22.04_all.deb ' >> ${cloud_init_path}
echo -e ' - dpkg -i zabbix-release_6.4-1+ubuntu22.04_all.deb' >> ${cloud_init_path}
echo -e ' - apt update' >> ${cloud_init_path}
echo -e ' - apt install zabbix-agent2 zabbix-agent2-plugin-*' >> ${cloud_init_path}
echo -e " - sed -i s/Server=127.0.0.1/Server=${zabbix_server_IP}/g /etc/zabbix/zabbix_agent2.conf" >> ${cloud_init_path}
echo -e " - sed -i s/ServerActive=127.0.0.1/ServerActive=${zabbix_server_IP}/g /etc/zabbix/zabbix_agent2.conf" >> ${cloud_init_path}
echo -e ' - systemctl restart zabbix-agent2' >> ${cloud_init_path}
echo -e ' - systemctl enable zabbix-agent2' >> ${cloud_init_path}
ZabbixをインストールするようにCloud-initにを加筆します。
そして、/etc/zabbix/zabbix_agent2.conf
に最低限の設定を記入します。
毎回環境変数設定するめんどくさい問題
if [ -z "${PVE_CORE}" ]; then
PVE_CORE=4 # デフォルト値を設定
fi
if [ -z "${PVE_MEMORY}" ]; then
PVE_MEMORY=4096 # デフォルト値を設定
fi
if [ -z "${PVE_VOLUME}" ]; then
PVE_VOLUME=20 # デフォルト値を設定
fi
環境変数の有無を確認して、なければデフォルト値を設定する。
引数とってみる
おそらく、毎回テンプレートを作成したいわけでもないですし、毎回Tailscaleをインストールするわけでもないとおもうので、そこら辺を各種指定できるような引数をシェルスクリプトがとるようにしてみましょう。
while [ -n "${1:-}" ]; do
case "$1" in
-h|--help) usage; exit 0;;
-e|--echo) echo "hello world"; exit 0;;
-t|--tailscale) echo "install tailscale"; tailscale=1;;
-z|--zabbix) echo "install zabbix"; zabbix=1;;
-temp) echo "convert to template"; temp=1;;
-*) echo -e 'エラー: 無効なオプションです。「-h」を使用してください。'; exit 1;;
"") break;;
*) test="$1";;
esac
shift
done
で、この引数の情報をもとに条件分岐などを追加したのが、以下のコード全文です。
コード全文
Cloud-init
#cloud-config
package_upgrade: true
packages: # aptでインストールしたいソフトウェア一覧
- qemu-guest-agent
- wget
- curl
- nano
- traceroute
- net-tools
- sl
#user setup
user: #USER_NAME
password: #PASSWORD
ssh_pwauth: False
ssh_authorized_keys:
- ssh-rsa #SSH_KEY
timezone: Asia/Tokyo
locale: ja_JP.utf8
keyboard:
layout: "jp"
runcmd:
#vscode install
- curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
- install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
- sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list'
- apt update
- apt install -y code
シェルスクリプト
#!/usr/bin/env bash
function usage() {
cat <<EOF
Usage: command [<options>...]
(Options must be specified one at a time.)
-------------
Options:
-h|--help show help
-t|--tailscale install tailscale
-z|--zabbix install zabbix
-temp convert to template
EOF
}
while [ -n "${1:-}" ]; do
case "$1" in
-h|--help) usage; exit 0;;
-e|--echo) echo "hello world"; exit 0;;
-t|--tailscale) echo "install tailscale"; tailscale=1;;
-z|--zabbix) echo "install zabbix"; zabbix=1;;
-temp) echo "convert to template"; temp=1;;
-*) echo -e 'エラー: 無効なオプションです。「-h」を使用してください。'; exit 1;;
"") break;;
*) test="$1";;
esac
shift
done
# 既存のVMIDのリストから空いているVMIDを取得
output=$(qm list)
vmids=($(echo "$output" | tail -n +2 | awk '{print $1}'))
if [ "$temp" = 1 ]; then
vmid=9000
for i in {9000..10000}; do
if ! [[ " ${vmids[@]} " =~ " $i " ]]; then
vmid=$i
break
fi
done
else
vmid=100
for i in {100..900}; do
if ! [[ " ${vmids[@]} " =~ " $i " ]]; then
vmid=$i
break
fi
done
fi
echo "VMID: $vmid"
# Cloud-init の設定ファイルを編集
cloud_init_base_path="11_template_base.cfg"
cloud_init_path="11_template.cfg"
cp -av ${cloud_init_base_path} ${cloud_init_path}
echo -e ' ' >> ${cloud_init_path}
# Tailscale のインストール
if [ "$tailscale" = 1 ]; then
tailscale_key="tskey-auth-○○○" #TailscaleのAuth keyを指定してください。
echo -e ' - ['sh', '-c', "curl -fsSL https://tailscale.com/install.sh | sh"]' >> ${cloud_init_path}
echo -e ' - ['sh', '-c', "echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf && echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf && sudo sysctl -p /etc/sysctl.d/99-tailscale.conf" ]' >>${cloud_init_path}
echo -e ' - ['tailscale', 'set', '--ssh']' >> ${cloud_init_path}
echo -e ' - ['tailscale', 'set', '--auto-update']' >> ${cloud_init_path}
echo -e " - ['tailscale', 'up', '--authkey=${tailscale_key}']" >> ${cloud_init_path}
fi
# Zabbix のインストール
if [ "$zabbix" = 1 ]; then
zabbix_server_IP= #Zabbix_serverのIPを指定してください。
echo -e ' - wget https://repo.zabbix.com/zabbix/6.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_6.4-1+ubuntu22.04_all.deb ' >> ${cloud_init_path}
echo -e ' - dpkg -i zabbix-release_6.4-1+ubuntu22.04_all.deb' >> ${cloud_init_path}
echo -e ' - apt update' >> ${cloud_init_path}
echo -e ' - apt install zabbix-agent2 zabbix-agent2-plugin-*' >> ${cloud_init_path}
echo -e " - sed -i s/Server=127.0.0.1/Server=${zabbix_server_IP}/g /etc/zabbix/zabbix_agent2.conf" >> ${cloud_init_path}
echo -e " - sed -i s/ServerActive=127.0.0.1/ServerActive=${zabbix_server_IP}/g /etc/zabbix/zabbix_agent2.conf" >> ${cloud_init_path}
echo -e ' - systemctl restart zabbix-agent2' >> ${cloud_init_path}
echo -e ' - systemctl enable zabbix-agent2' >> ${cloud_init_path}
echo -e ' - systemctl stop zabbix-agent2' >> ${cloud_init_path}
fi
# イメージファイルのコピー
cp -av jammy-server-cloudimg-amd64.img ubuntu-22.04.img
virt-copy-in -a ubuntu-22.04.img 11_template.cfg /etc/cloud/cloud.cfg.d
# virt-ls -a ubuntu-22.04.img 11_template.cfg /etc/cloud/cloud.cfg.d/
# VM の作成
if [ -z "${PVE_CORE}" ]; then
PVE_CORE=4 # デフォルト値を設定
fi
if [ -z "${PVE_MEMORY}" ]; then
PVE_MEMORY=4096 # デフォルト値を設定
fi
if [ -z "${PVE_VOLUME}" ]; then
PVE_VOLUME=20 # デフォルト値を設定
fi
qm create ${vmid} --core ${PVE_CORE} --memory ${PVE_MEMORY} --net0 virtio,bridge=vmbr0
qm importdisk ${vmid} ubuntu-22.04.img local-lvm
qm set ${vmid} --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-${vmid}-disk-0
qm resize ${vmid} scsi0 +${PVE_VOLUME}G
qm set ${vmid} --ide2 local-lvm:cloudinit
qm set ${vmid} --boot order=scsi0
qm set ${vmid} --serial0 socket --vga serial0
qm set ${vmid} --agent enabled=1
qm set ${vmid} --ipconfig0 ip=dhcp # DHCP
# qm set ${vmid} --ipconfig0 "gw=○○.○○.○○.○○,ip=○○.○○.○○.○○/24" --nameserver ○○.○○.○○.○○ #固定IP
# テンプレートに変換
if [ "$temp" = 1 ]; then
qm template ${vmid}
fi
# お行儀よく後片付け
rm 11_template.cfg
rm ubuntu-22.04.img
まとめ
いかがだったでしょうか。
意外とTerraformやansibleなどを使わなくてもいろいろできたんじゃないかと思います。(Terraformやansibleを使っていないのでわかりませんが...)
数百台など作るのであれば話は違いますが、数台程度ならこれで十分じゃないかと思います。
ぜひ参考にしてみてください。
最後までご覧いただきありがとうございました。
(コードは使っていただいて結構ですが、転載などはしないでください。)