NetBSD/amd64-currentをAmazon Web Service EC2 c5インスタンスで動かしてみる

この記事は、 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ボリュームに書き込むのを繰り返してデバッグするしかなさそうです。

10 comments:

  1. Thank you very much for seeing 밤알바 information.
    Thank you very much for seeing 밤알바 information.
    Thank you very much for seeing 밤알바 information.
    Thank you very much for seeing 밤알바 information.
    Thank you very much for seeing 밤알바 information.

    ReplyDelete

Firefox for WindowsでWindows Certificate Storeの電子証明書を利用する

Firefox for Windowsは、あくまでNSSを使っていて、Windows Certificate Storeに 登録されている電子証明書を利用することはできない。 security. enterprise_roots=true という設定も、 私の求めているWind...