LoginSignup
2
4

More than 5 years have passed since last update.

QCOW2 フォーマットのイメージを chroot で編集する

Last updated at Posted at 2017-04-28

AWS や OpenStack などで起動する仮想マシンのイメージを作る場合は Packer がよく使われますが、Packer は仮想マシンを起動し、そこにログインしてファイルなどを変更後、その仮想マシン全体を保存することでイメージを作成します。

一方 AWS を活用している Netflix は、aminator を使用してベースとなるイメージをビルド用のインスタンスにマウントし、chroot を使用してマウントしたイメージの中のファイルなどを編集後に、アンマウントするという手法をとっているようです。chroot を使った手法を採用することで、インスタンスの起動や停止の時間を省略でき、より高速に仮想マシンのイメージの作成ができるそうです。

chroot を使った手法は AWS AMI に限らず使えるのでは、と思ったため、今回は KVM や QEMU で使用される QCOW2 フォーマットのイメージを chroot でビルドする方法をまとめてみます。

事前準備

今回は Ubuntu 16.04 をインストールしたマシン上で QCOW2 フォーマットの仮想マシンイメージを変更します。QCOW2 をマウントするには Linux の Network Block Device (NBD) カーネルモジュールと qemu-nbd コマンドを使用する必要があるため、以下のコマンドでカーネルモジュールの読み込みと、qemu-nbd コマンドをインストールします。

$ sudo apt update
$ sudo apt install -y qemu-utils
$ sudo modprobe nbd

Ubuntu 16.04 イメージファイルの編集

ここからは Ubuntu Cloud Images で配布されている Ubuntu 16.04 のイメージファイルを編集する方法をまとめます。最初にイメージファイルをダウンロードします。以下は Ubuntu 16.04 のイメージファイルをダウンロードするコマンドです。

$ curl -L -O https://cloud-images.ubuntu.com/releases/xenial/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img

次に、ダウンロードしたイメージファイルを NBD デバイスに接続して、マウント可能な状態にします。NBD デバイスの接続には qemu-nbd コマンドを使用します。以下の例では /dev/nbd0 にイメージファイルを接続しています。

$ sudo qemu-nbd -c /dev/nbd0 ubuntu-16.04-server-cloudimg-amd64-disk1.img

QCOW2 フォーマットのイメージファイルには複数のパーティションを含めることができます。そのため、マウント時にパーティション情報も含める必要があるようです。パーティション情報はイメージファイルを接続した NBD デバイスに対して fdisk コマンドを使用して確認できます。以下の例では、パーティション数は1つで、/dev/nbd0p1 に接続されていることが分かります。

$ sudo fdisk -l /dev/nbd0
Disk /dev/nbd0: 2.2 GiB, 2361393152 bytes, 4612096 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x56add33d

Device      Boot Start     End Sectors  Size Id Type
/dev/nbd0p1 *     2048 4610047 4608000  2.2G 83 Linux

イメージファイルを NBD デバイスに接続でき、パーティション情報も確認できたら、マウント先のディレクトリを作成し、そこにイメージファイルを接続した NBD デバイスをマウントします。以下のコマンドでは mount コマンドのデバイスに先ほど確認した1番目のパーティションが接続されている /dev/nbd0p1 を指定しています。

$ sudo mkdir /mnt/ubuntu-image
$ sudo mount /dev/nbd0p1 /mnt/ubuntu-image

イメージのマウントができたら、chroot コマンドでイメージ内のファイルを直接編集できます。

$ sudo chroot /mnt/ubuntu-image

イメージ内のファイルの編集が完了したら、忘れずにアンマウントを実行します。

$ sudo umount /mnt/ubuntu-image

アンマウント後は、NBD デバイスに接続していたイメージファイルを以下のように切断することも忘れないようにします。

$ sudo qemu-nbd -d /dev/nbd0 

これで Ubuntu 16.04 のイメージファイルの編集は完了です。

Container Linux イメージファイルの編集

Container Linux のイメージファイルも Ubuntu 16.04 と同様の手順で chroot を使用して編集できます。しかしながら、Container Linux のパーティション情報は Ubuntu 16.04 のイメージとは異なり少し複雑で、それを正しく理解しておく必要があったので、ここにまとめておきます。

最初に Container Linux のイメージファイルを以下のようにダウンロードします。

$ curl -L -O https://stable.release.core-os.net/amd64-usr/current/coreos_production_qemu_image.img.bz2
$ bunzip2 coreos_production_qemu_image.img.bz2

ダウンロードしたイメージを NBD デバイスに接続します。

$ sudo qemu-nbd -c /dev/nbd0 coreos_production_qemu_image.img

パーティション情報を確認すると、以下のようになっています。Container Linux のドキュメントに記載されている情報と一致しています。

$ sudo fdisk -l /dev/nbd0
Disk /dev/nbd0: 8.5 GiB, 9116319744 bytes, 17805312 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 00000000-0000-0000-0000-000000000001

Device        Start      End  Sectors  Size Type
/dev/nbd0p1    4096   266239   262144  128M EFI System
/dev/nbd0p2  266240   270335     4096    2M BIOS boot
/dev/nbd0p3  270336  2367487  2097152    1G unknown
/dev/nbd0p4 2367488  4464639  2097152    1G unknown
/dev/nbd0p6 4464640  4726783   262144  128M Linux filesystem
/dev/nbd0p7 4726784  4857855   131072   64M unknown
/dev/nbd0p9 4857856 17801215 12943360  6.2G unknown

マウント先のディレクトリを作成し、そこにイメージファイルを接続した NBD デバイスをマウントします。Container Linux のルートファイルシステムが含まれているのは9番目のパーティションのようなので、デバイスは /dev/nbd0p9 を指定します。

$ sudo mkdir /mnt/container-linux-image
$ sudo mount /dev/nbd0p9 /mnt/container-linux-image

Container Linux のイメージファイルは、この状態ではまだ chroot できません。シェルなどのコマンドを含む /usr がルートファイルシステムに含まれていないためです。コマンドなどが含まれるのは3番目のパーティションなので、追加でこれをマウントします。

$ sudo mount -t ext4 -o ro /dev/nbd0p3 /mnt/container-linux-image/usr

/usr のマウントができれば、chroot コマンドでイメージ内のファイルを直接編集できます。

$ sudo chroot /mnt/container-linux-image

イメージ内のファイルの編集が完了したら、忘れずにアンマウントを実行します。

$ sudo umount /mnt/container-linux-image/usr
$ sudo umount /mnt/container-linux-image

アンマウント後は、NBD デバイスに接続していたイメージファイルを以下のように切断することも忘れないようにします。

$ sudo qemu-nbd -d /dev/nbd0 

これで Container Linux のイメージファイルの編集は完了です。

Docker コンテナ内でのイメージファイルの編集

Docker コンテナ内でも上記の手順のようにイメージファイルの編集ができます。--privileged オプション付きで ubuntu:16.04 コンテナを起動します。起動時にホストの /dev もマウントしてください。なおコンテナの起動前にホスト側で Network Block Device (NBD) カーネルモジュールは読み込んでおく必要があります。

$ docker run -it -v /dev:/dev --privileged ubuntu:16.04
2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4