Raspberry Pi OS でクラウドイメージの利用
はじめに
OSインストールは通常だと、インストールメディアを挿入してインストールを進める形になります。
仮想環境でも同様にインストールCDメディアからインストールするというのが普通でしたが、最近ではOSインストール済みの仮想ディスクイメージが配布されています。
こういった仮想ディスクイメージは、クラウドイメージと呼ばれています。こちらを利用するとインストールの手間を省いて手っ取り早く仮想環境を用意することができます。
クラウドイメージは(必要な設定がされており)、cloud-init という仕組みで初期設定することができるようになっています。
ここでは、クラウドイメージで cloud-init を動かしてみます。
参考
環境
https://zenn.dev/mnod/articles/ed212df5a8786f の環境を利用します。
インストール
クラウドイメージで cloud-init を利用する場合、初期設定したい内容を含んだ所定の形式の iso イメージを cdrom としてマウントします。
この iso イメージを簡単に作るために、必要なパッケージをインストールします。
$ sudo apt install --no-install-recommends cloud-utils
クラウドイメージの入手
例としてDebian。
Debianの公式 https://cloud.debian.org/images/cloud/ からCloudイメージを取得します。
$ sudo curl -L https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-arm64.qcow2 -o debian-12-genericcloud-arm64.qcow2
$ ls -l /media/work/libvirt/images/debian-12-genericcloud-arm64.qcow2
-rw-r--r-- 1 root root 333499392 Nov 4 19:50 /media/work/libvirt/images/debian-12-genericcloud-arm64.qcow2
$ qemu-img info /media/work/libvirt/images/debian-12-genericcloud-arm64.qcow2
image: /media/work/libvirt/images/debian-12-genericcloud-arm64.qcow2
file format: qcow2
virtual size: 2 GiB (2147483648 bytes)
disk size: 318 MiB
cluster_size: 65536
Format specific information:
compat: 1.1
compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false
簡単に初期状態へ戻せるようにしておきます。
$ mv debian-12-genericcloud-arm64.qcow2 debian-12-genericcloud-arm64.qcow2.base
$ qemu-img create -f qcow2 -b debian-12-genericcloud-arm64.qcow2.base -F qcow2 debian-12-genericcloud-arm64.qcow2 2G
Formatting 'debian-12-genericcloud-arm64.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2147483648 backing_file=debian-12-genericcloud-arm64.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
cloudinit.iso の作成
- パスワード認証を使用
- クラウドイメージのデフォルトユーザ(debian)と、rootユーザのパスワードを設定する
- ログイン時にパス変更を求められないようにする
$ cloud-localds cloudinit.iso <(cat <<EOF
#cloud-config
ssh_pwauth: True
chpasswd:
expire: false
users:
- name: root
password: password
type: text
- name: debian
password: password
type: text
EOF
);
作成したファイルを確認
$ ls -l cloudinit.iso
-rw-r--r-- 1 pi pi 374784 Nov 6 07:41 cloudinit.iso
$ file cloudinit.iso
cloudinit.iso: ISO 9660 CD-ROM filesystem data 'cidata'
$ sudo mount cloudinit.iso /media/tmp/
mount: /media/tmp: WARNING: source write-protected, mounted read-only.
$ cat /media/tmp/meta-data
{
"instance-id": "iid-local01"
}
$ cat /media/tmp/user-data
#cloud-config
ssh_pwauth: True
chpasswd:
expire: false
users:
- name: root
password: password
type: text
- name: debian
password: password
type: text
KVMで起動する場合
クラウドイメージ内からコピーしたカーネルと初期化RAMディスクを指定。また 作成した cloudinit.iso を cdrom として利用。
$ sudo qemu-system-aarch64 \
-machine virt \
-cpu host \
-m 1024 \
-enable-kvm \
-kernel debian-12-genericcloud-arm64.vmlinuz \
-initrd debian-12-genericcloud-arm64.initrd.img \
-append root=/dev/vdb1 \
-cdrom cloudinit.iso \
-drive file=debian-12-genericcloud-arm64.qcow2 \
-net nic,macaddr=52:54:00:12:34:0 -net tap,ifname=tap1 \
-vnc 0.0.0.0:0 \
-daemonize
virt-install で作成する場合
$ sudo virt-install --virt-type kvm \
--features acpi=off \
--connect qemu:///system \
--name debian-12-genericcloud-arm64 \
--os-variant debian11 \
--memory 1024 \
--cdrom /media/work/libvirt/images/cloudinit.iso \
--boot kernel=/media/work/libvirt/images/debian-12-genericcloud-arm64.vmlinuz,initrd=/media/work/libvirt/images/debian-12-genericcloud-arm64.initrd.img,kernel_args='root=/dev/vda1' \
--disk /media/work/libvirt/images/debian-12-genericcloud-arm64.qcow2 \
--network network=host-bridge \
--graphics none --serial pty --console pty \
--import
仮想マシンのコンソールが標準出力に接続されるが Ctrl + ]
でデタッチする
Domain is still running. Installation may be in progress.
You can reconnect to the console to complete the installation process.
デタッチしたコンソールは virsh console
で接続できる
$ sudo virsh list --all
Id Name State
-----------------------------------------------
1 debian-12-genericcloud-arm64 running
- debian-12.7.0-arm64 shut off
$ sudo virsh console debian-12-genericcloud-arm64
Connected to domain 'debian-12-genericcloud-arm64'
Escape character is ^] (Ctrl + ])
cloud-init の内容の作成(1)
duckduckgo https://duckduckgo.com/ の chat 機能を利用して gpt-4o mini にお伺いする
お伺い内容
cloud-localds を利用してcloudinit.iso を作成したい。
以下の内容のユーザデータ、メタデータ、ネットワークコンフィグを生成したい。
YAMLの内容とcloud-localds のコマンドラインを教えて。
- タイムゾーンJST
- ホスト名は myhost01
- IPアドレス 192.168.11.101/24 デフォルトGW 192.168.11.254、DNS 192.168.11.254, 192.168.11.253
- 10.0.0.1/16 へのネクストホップは192.168.11.1
下されたご宣託
cloud-localds
を使用して cloudinit.iso
を作成するためには、ユーザーデータ、メタデータ、ネットワーク設定を含むYAMLファイルを作成する必要があります。以下に、必要なYAMLの内容と cloud-localds
コマンドラインを示します。
1. YAMLファイルの作成
以下の内容で user-data
と meta-data
、network-config
の3つのファイルを作成します。
user-data
#cloud-config
timezone: Asia/Tokyo
hostname: myhost01
meta-data
instance-id: iid-local01
local-hostname: myhost01
network-config
version: 2
ethernets:
eth0:
dhcp4: no
addresses:
- 192.168.11.101/24
gateway4: 192.168.11.254
nameservers:
addresses:
- 192.168.11.254
- 192.168.11.253
routes:
- to: 10.0.0.0/16
via: 192.168.11.1
2. cloud-localds コマンドライン
次に、上記のファイルを使用して cloudinit.iso
を作成するための cloud-localds
コマンドを実行します。以下のコマンドを使用します。
cloud-localds -v cloudinit.iso user-data meta-data network-config
3. ファイルの配置
上記のコマンドを実行する前に、user-data
、meta-data
、network-config
の各ファイルを同じディレクトリに保存してください。
これで、指定された内容の cloudinit.iso
が作成されます。
試してみる
変更したこと
- ユーザデータには前述のパスワード設定を追記
- 利用するインタフェース名は enp1s0 とする
$ cloud-localds -v cloudinit.iso user-data meta-data network-config
Usage: cloud-localds [ options ] output user-data [meta-data]
confused by additional args
エラーとなった。現時点でははまだ AI を100%信頼できるわけではない。
慌てず騒がず、以下で再実行
$ cloud-localds -v cloudinit.iso user-data meta-data -N network-config
wrote cloudinit.iso with filesystem=iso9660 and diskformat=raw
作成された内容を確認
$ file cloudinit.iso
cloudinit.iso: ISO 9660 CD-ROM filesystem data 'cidata'
$ sudo mount cloudinit.iso /media/tmp
mount: /media/tmp: WARNING: source write-protected, mounted read-only.
$ cat /media/tmp/meta-data
instance-id: iid-local01
local-hostname: myhost01
$ cat /media/tmp/user-data
#cloud-config
timezone: Asia/Tokyo
hostname: myhost01
ssh_pwauth: True
chpasswd:
expire: false
users:
- name: root
password: password
type: text
- name: debian
password: password
type: text
$ cat /media/tmp/network-config
version: 2
ethernets:
enp1s0:
dhcp4: no
addresses:
- 192.168.11.101/24
gateway4: 192.168.11.254
nameservers:
addresses:
- 192.168.11.254
- 192.168.11.253
routes:
- to: 10.0.0.0/16
via: 192.168.11.1
$ sudo umount /media/tmp
前述のオプションで virt-install を実行して、結果を確認する。
- 所定のパスワードで debian ユーザでログインできる
- ホスト名が所定のものに変わっている
- タイムゾーンがJSTになっている
- ip アドレスが所定のものになっている
- 指定したとおりルーティングが設定されている
- 指定したとおり名前解決が設定されている
- 所定のパスワードで root ユーザでログインできる
$ id
uid=1000(debian) gid=1000(debian) groups=1000(debian),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev)
$ hostname
myhost01
$ date
Sun Nov 10 07:58:12 JST 2024
$ ip a show enp1s0
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:44:23:67 brd ff:ff:ff:ff:ff:ff
inet 192.168.11.101/24 brd 192.168.11.255 scope global enp1s0
valid_lft forever preferred_lft forever
inet6 2405:6580:d400:2900:5054:ff:fe44:2367/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 86388sec preferred_lft 14388sec
inet6 fe80::5054:ff:fe44:2367/64 scope link
valid_lft forever preferred_lft forever
$ ip route
default via 192.168.11.254 dev enp1s0 proto static
10.0.0.0/16 via 192.168.11.1 dev enp1s0 proto static
192.168.11.0/24 dev enp1s0 proto kernel scope link src 192.168.11.101
$ cat /etc/resolv.conf
:
:
nameserver 192.168.11.254
nameserver 192.168.11.253
search .
$ host www.yahoo.co.jp
www.yahoo.co.jp is an alias for edge12.g.yimg.jp.
edge12.g.yimg.jp has address 183.79.249.252
$ su -
Password:
# id
uid=0(root) gid=0(root) groups=0(root)
なお、ネットワーク設定は netplan が利用されている。
$ ls -l /etc/netplan/50-cloud-init.yaml
-rw-r--r-- 1 root root 688 Nov 10 07:57 /etc/netplan/50-cloud-init.yaml
$ cat /etc/netplan/50-cloud-init.yaml
# This file is generated from information provided by the datasource. Changes
# to it will not persist across an instance reboot. To disable cloud-init's
# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
ethernets:
enp1s0:
addresses:
- 192.168.11.101/24
dhcp4: false
gateway4: 192.168.11.254
nameservers:
addresses:
- 192.168.11.254
- 192.168.11.253
routes:
- to: 10.0.0.0/16
via: 192.168.11.1
version: 2
cloud-init 関連のログは下記。
$ ls -l /var/log/cloud-init*
-rw-r----- 1 root adm 5452 Nov 10 07:57 /var/log/cloud-init-output.log
-rw-r--r-- 1 root adm 90888 Nov 10 07:57 /var/log/cloud-init.log
cloud-init の内容の作成(2)
CA証明書を利用したsshd設定
仮想マシン作成
以下の内容で cloudinit.iso を作成して、virt-install で仮想マシン作成
instance-id: iid-local01
local-hostname: myhost01
#cloud-config
timezone: Asia/Tokyo
hostname: ${local-hostname}
write_files:
- path: /etc/ssh/ca_key
content: |
-----BEGIN OPENSSH PRIVATE KEY-----
(省略)
-----END OPENSSH PRIVATE KEY-----
owner: root:root
permissions: '0600'
- path: /etc/ssh/ca_cert.pub
content: |
(省略)
owner: root:root
permissions: '0644'
runcmd:
- |
CA_KEY="/etc/ssh/ca_key"
ssh-keygen -s ${CA_KEY} -I $(hostname) -h /etc/ssh/ssh_host_ed25519_key.pub
echo "TrustedUserCAKeys /etc/ssh/ca_cert.pub" >> /etc/ssh/sshd_config
echo "HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub" >> /etc/ssh/sshd_config
sed -i -e '/#PasswordAuthentication/ s/.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd
version: 2
ethernets:
enp1s0:
dhcp4: no
addresses:
- 192.168.11.101/24
gateway4: 192.168.11.254
nameservers:
addresses:
- 192.168.11.254
- 192.168.11.253
routes:
- to: 10.0.0.0/16
via: 192.168.11.1
ssh クライアント側の設定
以下でCA秘密鍵でsshキーに署名。署名したユーザ証明書とsshキーをssh クライアントのカレントディレクトリに配置
$ ssh-keygen -s ca.key -I certificate-test -n debian -z $(date +%Y%m%d%H%M) -V +365d id_ed25519
CA公開鍵の情報で カレントディレクトリに known_hosts ファイルを作成
$ echo "@cert-authority 192.168.11.* $(cat ca.key.pub)" >> known_hosts
ssh config を作成
Host myalias
HostName 192.168.11.101
User debian
IdentityFile ./id_ed25519
UserKnownHostsFile ./known_hosts
接続テスト
$ ssh -v -F config myalias
:
debug1: Server host certificate: ssh-ed25519-cert-v01@openssh.com SHA256:Yx/G3La3/ckdOIprHoUyQIBoRM2rwGrWJMqfq+Kxwmw, serial 0 ID "myhost01" CA ssh-ed25519 SHA256:p12hRLK8xDAv+ArfcrZS1loLBUXkTC3JRtlRyYZvpwQ valid forever
:
debug1: Host '192.168.11.101' is known and matches the ED25519-CERT host certificate.
debug1: Found CA key in ./known_hosts:1
:
debug1: Offering public key: ./id_ed25519 ED25519-CERT SHA256:tPR4rIIfnnh7gHp9sqNnrDGv2nukqx8QwlS2SxTC1Os explicit
debug1: Server accepts key: ./id_ed25519 ED25519-CERT SHA256:tPR4rIIfnnh7gHp9sqNnrDGv2nukqx8QwlS2SxTC1Os explicit
:
サーバ上でログ確認
$ journalctl -u ssh:
:
Nov 10 17:21:52 myhost01 sshd[588]: Accepted publickey for debian from 192.168.11.250 port 45000 ssh2: ED25519-CERT SHA256:tPR4rIIfnnh7gHp9sqNnrDGv2nukqx8QwlS2SxTC1Os ID certificate-test (serial 202411100738) CA ED25519 SHA256:p12hRLK8x>
:
Discussion