TORIPIYO DIARY

recent events, IoT, programming, security topics

Amazon Linux2のVagrant Boxを作成する

仕事でちょっとした設定をAmazon Linux 2で試したい時、AWSでEC2インスタンスを立ち上げると、お金がかかったり、消し忘れたり、うっかり作業ミスしたりする可能性があるので、簡単な設定を試すのであれば、ローカルマシン上で済ませたくなります。そこで、個人でAmazon Linux2のVagrant Boxイメージを作ってみることにしました。Amazon Linux 2のVirtualBoxのVDIファイルはAWSから公式で配布されているので、このVDIファイルを利用してVagrantイメージを作成出来ます。


AWSのドキュメントでも、Amazon Linux 2を仮想化プラットフォーム上で起動する方法を説明しています。Running Amazon Linux 2 as a Virtual Machine On-Premises - Amazon Elastic Compute Cloud


今回、Vagrant Boxを作成するにあたって、Vagrantのドキュメントを読んでいたら知らなかったことがいくつかあったので記載しておきます。Boxes - Vagrant by HashiCorp


ということで、bento/amazonlinux-2でもAmazon Linux2をVagrantで動かすことが出来そうですが、今回は手作りでAmazon Linux2のVagrant Boxを作成してみようと思います。

seed.isoの起動イメージ作成

まず、isoファイルを作成します。isoファイルは、CD/DVD/DBなどのデータ形式を完全に再現したファイルです。ISOファイルは、ディスクのコンテンツを丸々、一つのファイルで表現することが出来ます。今回は、seed.isoというファイル名の起動イメージを作ります。seed.iso起動イメージには、meta-data, user-dataの2個のファイルデータを焼き付けてあげます。Amazon Linux2のディスクイメージには、cloud-initパッケージがインストールされていて、起動時にmeta-data, user-dataのデータを参照してOS内に設定を追加することが出来るためです。What is 'cloud-init' and when would you use it? - Quora

meta-dataでは、ホスト名やネットワーク設定を記述します。user-dataでは、ユーザアカウントやパスワードの設定、認証鍵の配置、ロケール・時刻の設定などを記述します。user-dataの書き方については、このドキュメントが参考になります。
cloudinit.readthedocs.io

mkdir seedconfig
cd seedconfig

cat > meta-data << EOF
local-hostname: machine
EOF

cat > user-data <<- EOF
#cloud-config
#vim:syntax=yaml

users:
  - default
  - name: vagrant
    groups: wheel
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    plain_text_passwd: vagrant
    ssh-authorized-keys:
      - ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key
    lock_passwd: false

locale: ja_JP.UTF-8

timezone: Asia/Tokyo

write_files:
  - path: /etc/environment
    permissions: '0644'
    owner: root:root
    content: |
      LANG="ja_JP.UTF-8"
      LC_CTYPE="ja_JP.UTF-8"
# https://cloudinit.readthedocs.io/en/latest/topics/network-config.html
  - path: /etc/cloud/cloud.cfg.d/80_disable_network_after_firstboot.cfg
    content: |
      # Disable network configuration after first boot
      network:
        config: disabled
EOF

user-dataファイルとmeta-dataファイルを作ったので、seed.isoの起動イメージファイルを作成します。hdiutilはディスクイメージを操作するコマンドです。makehybridで、複数のファイルシステムが共存した状態の読み込み専用のディスクイメージを作ります。

# create seed.iso boot image
hdiutil makehybrid -o seed.iso -hfs -joliet -iso -default-volume-name cidata ./
  • hfsオプションは、HFS+ファイルシステムを作成するために指定します。
  • isoオプションは、ISO9660ファイルシステムを作成するために指定します。
  • jolietオプションは、ISO9660ファイルシステムを拡張したJolietファイルシステムで作成するために指定します。
  • oオプションで起動イメージファイルのファイル名を指定しています。
  • -hfs, -iso, -jolietというように複数のファイルシステムをオプションで指定しているとハイブリッドイメージとして起動イメージファイルが作成されます。
  • default-volume-nameでファイルシステムのデフォルトのボリューム名を指定しています。amazon linux 2のイメージが起動するとき、user-dataはnocloudという方法で読み込まれます。nocloudでuser-dataファイルをディスクから読み込むときは、cidataというボリュームラベルが付与されていなくてはいけません。NoCloud — Cloud-Init 18.5 documentation
  • ./と指定することで、./以下のファイルとディレクトリがディスクイメージのコンテンツとして焼き付けられます。

仮想マシンの起動

AWSのサイトからVDIファイルを取得してきます。
cdn.amazonlinux.com

amazon linux 2のvirtualbox用の仮想ディスク(amzn2-virtualbox-2.0.20190313-x86_64.xfs.gpt.vdi)と、起動イメージ(seed.iso)が用意出来たので、これらを使ってamazon linux 2の仮想マシンvirtualbox上に作成します。

# create vm
VM=vagrant-amznlinux2
VDI=amzn2-virtualbox-2.0.20190313-x86_64.xfs.gpt.vdi
VBoxManage createvm --name "$VM" --ostype "RedHat_64" --register

VBoxManage storagectl "$VM" --name "SATA Controller" --add "sata" --controller "IntelAHCI"
VBoxManage storagectl "$VM" --name "IDE Controller" --add "ide"
VBoxManage storageattach "$VM" --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium $VDI
VBoxManage storageattach "$VM" --storagectl "IDE Controller" --port 0 --device 0 --type dvddrive --medium seed.iso
VBoxManage modifyvm "$VM" --natpf1 "ssh,tcp,127.0.0.1,2222,,22" --memory 1024 --vram 8 --audio none --usb off
  • 仮想マシンvagrant-amznlinux2)のためにSATA controllerとIDE controllerを作成
  • SATAには仮想ディスク(amzn2-virtualbox-2.0.20190313-x86_64.xfs.gpt.vdi)
  • IDEには起動イメージファイル(seed.iso)をセット
  • ホストマシンの2222ポートのアクセスを仮想マシンの22ポートに転送するように設定
  • RAMを1024MB
  • グラフィックカードのRAMを8MB
  • audioサポートをオフ
  • USB仮想コントローラ機能をオフ

仮想マシンvagrant-amznlinux2)を起動します。--type headlessを指定することで、仮想マシンをコマンドから起動する際、VirtualBoxGUIツールが一緒に立ち上がらないようになります。Headless Mode for Virtual Machines of VirtualBox - Thomas-Krenn-Wiki

# boot amazon linux2
VBoxManage startvm "$VM" --type headless

仮想マシンが立ち上がったら、以下の手順で公開鍵を取得して、SSH経由でvagrantユーザとしてログインすることが出来ます。

# login amazon linux2
curl -sL https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant -o vagrant.pem
chmod 600 vagrant.pem

ssh -p 2222 vagrant@localhost -i vagrant.pem

これで、amazon linux2をVirtualBox上で利用できるようになりました。

vagrant box化

VirtualBox上で動いている仮想マシンをbox化します。ボックス化した時のサイズを小さくするために不要な物を削除します。ddコマンドを使って、0で埋めてしまうのは、仮想マシンイメージの圧縮時に効果的だからのようです。Making smaller base boxes · Issue #343 · hashicorp/vagrant · GitHub 0で埋める処理は、bentoでもboxを作成する際にやっているみたいです。bento/minimize.sh at master · chef/bento · GitHub

sudo rm -rf /var/cache/yum
sudo dd if=/dev/zero of=/0 bs=4k
sudo rm -f /0
history -c

仮想マシンをシャットダウンします。

sudo shutdown -h now

baseオプションで、box化したいVirtualBoxで動いている仮想マシンを指定しています。このコマンドを実行すると、デフォルトではpackage.boxという名前のファイルが作成されます。

vagrant package --base "$VM"

package.boxのboxファイルを、amzn2-2.0.20190313-x86_64という名前でvagrantに登録します。

vagrant box add --name "amzn2-2.0.20190313-x86_64" package.box

vagrantに登録されたので、vagrantから仮想マシンを起動してSSHログインしてみます。

mkdir amzn2 && cd amzn2
vagrant init amzn2-2.0.20190313-x86_64
vagrant up
vagrant ssh

これで、amazon linux 2のvagrant環境を手作りすることが出来ました。