NitroなEC2でEBSをマウントする(Ubuntu編)

こんにちは!
コンストラクションソリューション事業部 開発部の藤井です。初投稿となります。

弊社ではAWSを用いた案件が多く、私の所属部署でも、AWS用語が解説無しで普通に飛び交います。
私は昨年9月にエコモットへ入社するまでAWS経験歴は無く、最初のころは正直いって焦りました。ですが、社内勉強会などに誘ってもらい参加したり、業務で実際に使ったりしているうちに慣れ、いまは少し世界が広がったように思います。

この記事では、先日、Nitro なEC2でEBSをマウントする際に起きた小さな小さな問題解決までの流れをまとめます。AWSに振り回される業務風景として眺めていただけると幸いです。

◇きっかけ

先日 Linux のEC2インスタンスを新規構築中に、EBSをマウントしようとしてAWS公式ドキュメントを調べているとき、例示コマンドが2種類あることに気が付きました。

再起動後に接続ボリュームを自動的にマウントする

 

EBS デバイスの特定

今回の構築対象は、 T3a  ファミリのインスタンスで、 Ubuntu20.04LTS  です。

実際に端末で試してみると、前者の  lsblk  でも構築時に指定したデバイス名

ではなく、 /dev/nvme1n1 という見慣れないものが表示されました。なんだこれは……。

 

◇わかったこと

さらに公式ドキュメント『 Linux インスタンスの Amazon EBS および NVMe 』をたどると、2017年以降の比較的新しい  Nitro System  (公式動画によると発音はニトロじゃなくてナイトロ)なインスタンスの場合に、

になることが判明しました。この記事からリンクされている『Nitro System 上に構築されたインスタンス』にインスタンスタイプ一覧があり、T3aも含まれています。なるほど!

 

◇検討と解決

ここから、マウントテーブル /etc/fstab  に定義を書いて  mount -a  コマンドでマウントする、というよくあるゴールを目指します。いくつかの方法について仲間と社内チャットで検討しました。

方法1 シンプルなやり方

lsblk などOS側から見えるデバイス名(今回なら /dev/nvme1n1 ) を fstab  で直接指定する方法です。

上記AWS公式ドキュメントでは非推奨として書かれており、今回は見送りになりました。

方法2 UUIDを指定する

上述のきっかけの部分に書いた、公式ドキュメント推奨のコマンドで UUID を先に調べて、それを fstab に追記する方法です。

が、よく考えるとEBS1つならこれで良いのですが、複数あるときは引き当てが面倒です。それによく考えると、上記の

を使う場合にしても、事前にどれになるか不定なはずの引数( /dev/nvme[0-26]n1 )を指定しているので、ちょっと矛盾しているようにも思います。

/dev をループ処理で調べるしかないのでしょうか。上記の NVMe の解説には、

Amazon Linux はブロックデバイスマッピング (たとえば、/dev/sdf )内のデバイス名から NVMe デバイス名へのシンボリックリンクを作成します

との記載があるのですが、今回は Ubuntu なので自力でやるしかありません。

方法3 車輪を探す

nvme id-ctrl でループして目的のデバイス名を探すスクリプトを作る前に、絶対に誰か既にやってるだろうと検索すると、案の定公開してくださってる方がすでにおられました。
https://github.com/transferwise/ansible-ebs-automatic-nvme-mapping
この ebs-nvme-mapping.sh を流せば、(再起動するまで一時的ですが)Amazon Linux のように NVMe デバイス名へのシンボリックリンクが作られます。

そこからお目当てのデバイスだけ、UUID を wipefs コマンドを使ってデバイス名から一本釣りします。

その結果を /etc/fstab マウントテーブルへ UUID 指定で追記することで、無事ゴールできました。

再起動後でも UUID だけあれば大丈夫です。

おまけ1 EC2 のUser data

参考までに、構築時のUser dataから該当箇所だけ転記します。

※実際は CloudFormation のテンプレートファイルで指定していました。AWS マネジメントコンソールで構築する際は、ユーザーデーター欄に入れてください。この直前で s3 に配置したセットアップスクリプト群をコピーしており、ebs-nvme-mapping.sh もそこに入れて事前に配置していたので下記なのですが、もし S3 など使ってファイルを配置するのが面倒なら、直接 sh の for 以下を埋め込んでください。

※構築後に流す場合はそれぞれコマンドごとに sudo してください。

 

おまけ2

この件で人生で初めて wipefs を使いました。
上記のスクリプトで欲しいのは UUID だけなので、ヘッダ行省略の noheadings のようなオプションがあるだろうと man wipefs しました。

※ http://manpages.ubuntu.com/manpages/focal/man8/wipefs.8.html (focal は Ubuntu20.04 の開発コードです)の通り、Ubuntu公式サイトでも確認できます。

noheadings で検索して見えたオプションをつけて

としたのですが、まったくヘッダ行が省略されないため、さらに5分ほど悩みました。だって noheadings の n で違和感ないですし……。

おかしいな、とコマンドラインヘルプ出して気が付きました。まさかの man TYPO です。

いま振り返ってこの記事を書いていて思い出したのでバグレポートに報告しようと本家を見に行ったら、既に直っていました。
https://cdn.kernel.org/pub/linux/utils/util-linux/v2.35/v2.35.2-ChangeLog

Ubuntu にも、Ubuntu20.10 で取り込まれてました。ただ Ubuntu 側の ChangeLog にも記載は無く、マージ主は Diff 時に見てはいるでしょうがスルーされており、おそらく誰にも気にもされずひっそりと直っていたようです。

学生時代に読んだ、ヤックシェービングの話[1] を思い出しました。

参考文献

[1] 高林哲さん(日本語の全文検索システムNamazuの原作者さん)のブログ記事