この記事は、 NetBSD Advent Calendar 2018の23日目の記事です。
はじめに
もう1年以上前の話だと思うのですが、Amazon Web Service (AWS) EC2にc5という Linux KVMをAmazonが独自拡張したと言うインスタンスのタイプが追加されました。 その後、同じような仕組みのm5インスタンスと言うもの追加されているようです。 c5インスタンスでは、Elastic Network Adapter (ENA)と言うEthernetアダプター を利用できることが必須になっているようです。 NetBSD/aarch64では、a1インスタンスでena(4)がFreeBSDから移植されていて 無事に動いていますが、 c5インスタンスでのNetBSD/amd64の動作確認結果は聞いたことはありませんでした。
そもそもc5インスタンスで起動できるAMIの作り方も良く分かりませんでした。 今回は、カーネルパニックでena(4)は動かせるまで至りませんでしたが、 c5インスタンス用のAMIの作成をまとめておくことは意味があるかもしれません。
AMIファイルの作り方を調べてみる
AWS EC2のAMIは、直接ダウンロードしてみることはできないようです。 裏にはスナップショットと言うものがあるようですが、Amazonが公開している Amazon LinuxのAMI用のスナップショットを見ることはできないようです。
今回は、FreeBSD/amd64 12のAMIからc5インスタンスを作成し、そのディスクの 構造を見てみました。それを見ると、NetBSDで言うと、GPTパーティションからの BIOSブート(UEFIブートではない)であることが分かりました。 かつて、UEFIブートができないことにGPTを使っていたやり方を思い出せば良さそうです。
ここで、カーネルは、
ena* at pci? dev ? function ? # Amazon Elastic Network Adapterの行をGENERIC設定ファイルに追加した追加したGENERIC_ENA設定ファイルでビルドします。
; 3GBのディスクイメージファイルを作成します $ dd if=/dev/zero of=./netbsd-c5-gpt-bios-boot.img bs=1g count=3 ; vnd(4)を使ってブロックデバイスとして扱えるようにします。 # vndconfig vnd0 netbsd-c5-gpt-bios-boot.img ; GPTパーティションを作る準備をします # gpt create vnd0 ; 2GBのルートパーティションを作成します。私の場合には/dev/dk5として扱えるようになります。 # gpt add -s 2g -t ffs -l AWSROOT vnd0 ; 1GBのスワップパーティションを作成します。私の場合には/dev/dk6として扱えるようになります。 # gpt add -t swap -l AWSSWAP vnd0 ; ルートパーティションからBIOSブートするように設定します。 # gpt biosboot -A -i 1 vnd0 ; ルートパーティションをFFSv2でフォーマットします。 # newfs -O2 /dev/rdk5 ; FFSv2で起動できるようにブートローダーを配置します。 # installboot -v /dev/rdk5 /usr/mdec/bootxx_ffsv2 ; ユーザーランドをインストールするために/mntにマウントします。 # mount /dev/dk5 /mnt # cd /usr/src ; 以下でユーザーランドをビルドします。 # ./build.sh -U -O /usr/world/8.99/amd64/obj -T /usr/world/8.99/amd64/tools -D /usr/world/8.99/amd64/destdir -R /usr/world/8.99/amd64/release -u -j 8 -m amd64 tools # ./build.sh -U -O /usr/world/8.99/amd64/obj -T /usr/world/8.99/amd64/tools -D /usr/world/8.99/amd64/destdir -R /usr/world/8.99/amd64/release -u -j 8 -m amd64 kernel=GENERIC_ENA # ./build.sh -U -O /usr/world/8.99/amd64/obj -T /usr/world/8.99/amd64/tools -D /usr/world/8.99/amd64/destdir -R /usr/world/8.99/amd64/release -u -j 8 -m amd64 distribution ; ユーザーランドを/mntをルートにしてインストールします。 # ./build.sh -U -O /usr/world/8.99/amd64/obj -T /usr/world/8.99/amd64/tools -D /usr/world/8.99/amd64/destdir -R /usr/world/8.99/amd64/release -u -j 8 -m amd64 -V INSTALLSETS="base comp etc games man misc modules tests text" install=/mnt ; ブートローダーをインストールします。 # cp /usr/mdec/boot /mnt ; カーネルをインストールします (ena(4)が有効になっているカーネルをインストールします) # cp /usr/world/8.99/amd64/obj/sys/arch/amd64/compile/GENERIC_ENA/netbsd /mnt ; AWS EC2の公開鍵の配置のためのスクリプトを追加します。 # vi /mnt/etc/rc.d/ec2_init
/etc/rc.d/ec2_initは、NetBSD Wikiの
Build-up your own NetBSD AMIのウェブページにある以下のような内容です。
#!/bin/sh
#
# PROVIDE: ec2_init
# REQUIRE: NETWORKING
# BEFORE: LOGIN
$_rc_subr_loaded . /etc/rc.subr
name="ec2_init"
rcvar=${name}
start_cmd="ec2_init"
stop_cmd=":"
METADATA_URL="http://169.254.169.254/latest/meta-data/"
SSH_KEY_URL="public-keys/0/openssh-key"
HOSTNAME_URL="hostname"
SSH_KEY_FILE="/root/.ssh/authorized_keys"
ec2_init()
{
(
umask 022
# fetch the key pair from Amazon Web Services
EC2_SSH_KEY=$(ftp -o - "${METADATA_URL}${SSH_KEY_URL}")
if [ -n "$EC2_SSH_KEY" ]; then
# A key pair is associated with this instance, add it
# to root 'authorized_keys' file
mkdir -p $(dirname "$SSH_KEY_FILE")
touch "$SSH_KEY_FILE"
cd $(dirname "$SSH_KEY_FILE")
grep -q "$EC2_SSH_KEY" "$SSH_KEY_FILE"
if [ $? -ne 0 ]; then
echo "Setting EC2 SSH key pair: ${EC2_SSH_KEY##* }"
echo "$EC2_SSH_KEY" >> "$SSH_KEY_FILE"
fi
fi
# set hostname
HOSTNAME=$(ftp -o - "${METADATA_URL}${HOSTNAME_URL}")
echo "Setting EC2 hostname: ${HOSTNAME}"
echo "$HOSTNAME" > /etc/myname
hostname "$HOSTNAME"
)
}
load_rc_config $name
run_rc_command "$1"
; 実行可能に設定します。 # chmod 555 /mnt/etc/rc.d/ec2_init ; 起動時の設定をします。 # vi /mnt/etc/rc.conf rc_configured=YES ec2_init=YES sshd=YES # for remote shell access to instance ; rootユーザーでログインできるようにします。 # vi /mnt/etc/ssh/sshd_config PermitRootLogin without-password ; 以下でファイルシステムの設定をします。 # mkdir /mnt/proc /mnt/kern # vi /mnt/etc/ifconfig.ena0 dhcp # vi /mnt/etc/fstab NAME=AWSROOT / ffs rw,log 1 1 NAME=AWSSWAP none swap sw,dp 0 0 kernfs /kern kernfs rw ptyfs /dev/pts ptyfs rw procfs /proc procfs rw tmpfs /var/shm tmpfs rw,-m1777,-sram%25 ; /dev以下のノードを作成します。 # cd /mnt/dev # ./MAKEDEV all ; vnd0を開放します。 # cd ~ # umount /mnt # vndconfig -u vnd0これで、ディスクイメージファイルは完成です。 以下で、AMIファイルを作成して行きます。
AMIファイルの作成は、Elastic Block Store (EBS)でディスクを割り当てし、
そのディスクにローカルで作成したディスクイメージを書き込み、
そのスナップショットをとってAMIを作成します。
操作は、Pythonで書かれたawsコマンドを使います。
; pkgsrcからawsコマンドをインストールします。
# cd /usr/pkgsrc/net/py-awscli
# make install
; AWSの認証のための情報と、使用するリージョンの情報、実行結果の表示方法を設定します、
$ aws configure
AWS Access Key ID [None]: XXX
AWS Secret Access Key [None]: XXX
Default region name [None]: us-east-1
Default output format [None]: text
; 既にあるsshの鍵ペアを使って、Amazon Linux 2のHVMのAMIを使ってc5.largeインスタンスを起動させます、
$ aws ec2 run-instances --image-id ami-009d6802948d06e52 --instance-type c5.large --key-name c5-20181220
619017845909 r-0dab8fafc6dbc2a6c
INSTANCES 0 x86_64 False xen ami-009d6802948d06e52 i-01dfee86f4d0d109d c5.large c5-20181220 2018-12-21T13:41:14.000Z
ip-172-31-38-245.ec2.internal 172.31.38.245 /dev/xvda ebs True subnet-73de462f hvm vpc-d459f1ae
CPUOPTIONS 1 2
MONITORING disabled
NETWORKINTERFACES 0e:de:7c:89:d3:a2 eni-0a38d352461629255 619017845909 ip-172-31-38-245.ec2.internal 172.31.38.245 True in-use subnet-73de462f vpc-d459f1ae
ATTACHMENT 2018-12-21T13:41:14.000Z eni-attach-09acc70fb71f4bd95 True 0 attaching
GROUPS sg-1d45925e default
PRIVATEIPADDRESSES True ip-172-31-38-245.ec2.internal 172.31.38.245
PLACEMENT us-east-1d default
SECURITYGROUPS sg-1d45925e default
STATE 0 pending
STATEREASON pending pending
; これで、i-01dfee86f4d0d109dというインスタンスIDのc5.largeインスタンスが起動されました、
; 起動完了してrunningステータスになっているか確認します。
$ aws ec2 describe-instances --instance-ids i-01dfee86f4d0d109d
ESERVATIONS 619017845909 r-0dab8fafc6dbc2a6c
INSTANCES 0 x86_64 False True xen ami-009d6802948d06e52 i-01dfee86f4d0d109d c5.large c5-20181220 2018-12-21T13:41:14.000Z ip-172-31-38-245.ec2.internal 172.31.38.245 ec2-34-229-210-170.compute-1.amazonaws.com 34.229.210.170 /dev/xvda ebs True subnet-73de462f hvm vpc-d459f1ae
BLOCKDEVICEMAPPINGS /dev/xvda
EBS 2018-12-21T13:41:15.000Z True attached vol-029d14d5198ee2174
CPUOPTIONS 1 2
HIBERNATIONOPTIONS False
MONITORING disabled
NETWORKINTERFACES 0e:de:7c:89:d3:a2 eni-0a38d352461629255 619017845909 ip-172-31-38-245.ec2.internal 172.31.38.245 True in-use subnet-73de462f vpc-d459f1ae
ASSOCIATION amazon ec2-34-229-210-170.compute-1.amazonaws.com 34.229.210.170
ATTACHMENT 2018-12-21T13:41:14.000Z eni-attach-09acc70fb71f4bd95 True 0 attached
GROUPS sg-1d45925e default
PRIVATEIPADDRESSES True ip-172-31-38-245.ec2.internal 172.31.38.245
ASSOCIATION amazon ec2-34-229-210-170.compute-1.amazonaws.com 34.229.210.170
PLACEMENT us-east-1d default
SECURITYGROUPS sg-1d45925e default
STATE 16 running
; runningステータスになっていることを確認して次に進みます。
; 3GBのstandardタイプ(磁気ハードディスクドライブ)のEBSボリュームを作成します、
$ aws ec2 create-volume --availability-zone us-east-1d --volume-type standard --size 3
; 作成したEBSボリュームの内容を確認します、
$ aws ec2 describe-volumes --volume-ids vol-076f8c399f56e6753
VOLUMES us-east-1d 2018-12-21T13:44:05.665Z False 3 available vol-076f8c399f56e6753 standard
; Amazon Linux 2のインスタンスに作成したEBSボリュームを接続します。
$ aws ec2 attach-volume --instance-id i-01dfee86f4d0d109d --volume-id vol-076f8c399f56e6753 --device "/dev/sdf"
2018-12-21T13:46:15.709Z /dev/sdf i-01dfee86f4d0d109d attaching vol-076f8c399f56e6753
; 接続できたことを確認します。
$ aws ec2 describe-volumes --volume-ids vol-076f8c399f56e6753
VOLUMES us-east-1d 2018-12-21T13:44:05.665Z False 3 in-use vol-076f8c399f56e6753 standard
ATTACHMENTS 2018-12-21T13:46:15.000Z False /dev/sdf i-01dfee86f4d0d109d attached vol-076f8c399f56e6753
; もし、送信側セキュリティー設定(ポートごとの通過できる通信の設定)を実施します。
$ aws ec2 authorize-security-group-egress --group-id sg-1d45925e --port 22 --protocol all
; 受信側のセキュリティー設定を実施します。
$ aws ec2 authorize-security-group-ingress --group-id sg-1d45925e --port 22 --protocol all --cidr 0.0.0.0/0
; Amazon Linux 2のディスク領域にディスクイメージファイルを転送します。
$ scp -i c5-20181220.pem netbsd-c5-gpt-bios-boot.img ec2-user@ec2-34-229-210-170.compute-1.amazonaws.com:~/
; sshでAmazon Linux 2にログインします。
$ ssh -i c5-20181220.pem ec2-user@ec2-34-229-210-170.compute-1.amazonaws.com
; 接続したEBSボリュームにディスクイメージファイルを書き込みます。これがスナップショットになり、AMIになります。
[ec2-user@ip-172-31-38-245 ~]$ sudo dd if=netbsd-c5-gpt-bios-boot.img of=/dev/sdf bs=64k
; /dev/sdfに接続したEBSボリュームを取り外します。
$ aws ec2 detach-volume --volume-id vol-076f8c399f56e6753
2018-12-21T13:46:15.000Z /dev/sdf i-01dfee86f4d0d109d detaching vol-076f8c399f56e6753
; 取り外したEBSボリュームのスナップショットを取得します。これにはしばらく時間がかかります。
$ aws ec2 create-snapshot --volume-id vol-076f8c399f56e6753
False 619017845909 snap-04eb837b14f764a00 2018-12-21T14:06:20.000Z pending vol-076f8c399f56e6753 3
; Amazon Linux 2のインスタンスを消します。
$ aws ec2 terminate-instances --instance-ids i-01dfee86f4d0d109d
TERMINATINGINSTANCES i-01dfee86f4d0d109d
CURRENTSTATE 32 shutting-down
PREVIOUSSTATE 16 running
; スナップショットを使ってAMIを作成します。
$ aws ec2 register-image --architecture x86_64 --name "NetBSD/amd64 8.99.28 with ena" --ena-support --virtualization-type hvm --block-device-mappings 'DeviceName=/dev/sda1,Ebs={SnapshotId=snap-04eb837b14f764a00}' --root-device-name "/dev/sda1"
ami-088a6d6fc2dccd87b
; これで、ami-088a6d6fc2dccd87bというIDのAMIが作成されました。ENAが有効で、c5.largeインスタンスに使えるように仮想化タイプもhvmにしました。
このAMIを使ってc5.largeインスタンスを起動させてみます。
NetBSD/amd64-currentの起動
ami-088a6d6fc2dccd87bを使って、c5.largeインスタンスを作成することで、
NetBSD/amd64-currentを起動させることができます。
起動したら、AWS ConsoleからInstanceを選び、起動させたインスタンスのInstance Settings
よりGet Instance Screenshotを選びます。
残念ながらMSI-X割り込みの関係でエラーになってカーネルパニックしてしまっています。
AWS EC2は、sshでログインできないと何もできませんので、
ディスクイメージファイルのカーネルファイル/netbsdを差し替えて
アップロードしてEBSボリュームに書き込むのを繰り返してデバッグするしかなさそうです。
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。