[Red Hat Enterprise Linux] EBSボリュームのデバイス名とOSが認識しているブロックデバイス名をマッピングさせてマウントしてみた

NVMeの情報に記載のEBSボリュームのデバイス名を活用しよう
2023.09.02

EBSボリュームがOSが認識しているどのブロックデバイスと対応しているのか分からない

こんにちは、のんピ(@non____97)です。

皆さんはEBSボリュームがOSが認識しているどのブロックデバイスと対応しているのか分からないなと思ったことはありますか? 私はあります。

EBSボリュームのデバイス名とOSが認識しているブロックデバイス名は異なる場合があります。

例えば、Amazon Linux 2023のt3.microのEC2インスタンスに各デバイス名が/dev/xvda/dev/sdb/dev/sdcのEBSボリュームをマウントします。

AL2023のEBSボリュームのデバイス名

OSから見ると、ブロックデバイス名はxvdaxvdbxvdcとなっています。

$ lsblk
NAME      MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
xvda      202:0    0   8G  0 disk
├─xvda1   202:1    0   8G  0 part /
├─xvda127 259:0    0   1M  0 part
└─xvda128 259:1    0  10M  0 part
xvdb      202:16   0   1G  0 disk
xvdc      202:32   0   2G  0 disk

こうなると、EBSボリュームをマウントポイントごとに作成している場合、OSが認識しているどのブロックデバイスをどのマウントポイントにマウントすれば良いのか判断が難しいです。ボリュームサイズが同じであれば特に困ります。

安心してください。Amazon Linux 2023の場合はブロックデバイス名がEBSボリュームで指定したデバイス名のシンボリックリンクになっています。

$ ls -l /dev/ | grep sd
lrwxrwxrwx. 1 root root           4 Sep  2 02:13 sda -> xvda
lrwxrwxrwx. 1 root root           5 Sep  2 02:13 sda1 -> xvda1
lrwxrwxrwx. 1 root root           7 Sep  2 02:13 sda127 -> xvda127
lrwxrwxrwx. 1 root root           7 Sep  2 02:13 sda128 -> xvda128
lrwxrwxrwx. 1 root root           4 Sep  2 02:13 sdb -> xvdb
lrwxrwxrwx. 1 root root           4 Sep  2 02:13 sdc -> xvdc

そのため、簡単にどのデバイスがどのEBSボリュームなのかを特定することが可能です。

re:Postにもlsblkとインスタンスメタデータを使用してマッピングすることが可能と紹介されています。

$ OSDEVICE=$(sudo lsblk -o NAME -n | grep -v '[[:digit:]]' | sed "s/^sd/xvd/g")
$ BDMURL="http://169.254.169.254/latest/meta-data/block-device-mapping/"
$ for bd in $(curl -s ${BDMURL}); do MAPDEVICE=$(curl -s ${BDMURL}/${bd}/ | sed "s/^sd/xvd/g"); if grep -wq ${MAPDEVICE} <<< "${OSDEVICE}"; then echo "${bd} is ${MAPDEVICE}"; fi; done | grep ephemeral
ephemeral0 is xvdb
ephemeral1 is xvdc
ephemeral2 is xvdd
ephemeral3 is xvde

ただし、Red Hat Enterprise Linux(以降RHEL)の場合はそういう訳にはいきません。

例えば、RHEL 9.2のt3.microのEC2インスタンスに各デバイス名が/dev/sda1/dev/sdb/dev/sdcのEBSボリュームをマウントします。

RHELのEBSボリュームのデバイス名

OSから見ると、ブロックデバイス名はxvdaxvdbxvdcとなっています。

$ lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
nvme0n1     259:0    0   10G  0 disk
├─nvme0n1p1 259:3    0    1M  0 part
├─nvme0n1p2 259:4    0  200M  0 part /boot/efi
├─nvme0n1p3 259:5    0  500M  0 part /boot
└─nvme0n1p4 259:6    0  9.3G  0 part /
nvme1n1     259:1    0    1G  0 disk
nvme2n1     259:2    0    2G  0 disk

nvme1n1xvdbとかのシンボリックリンクになっているんじゃないの?」と思われるかもしれませんが、RHELではそのようなシンボリックリンクは作成されていません。

$ ls -l /dev | grep sd

インスタンスメタデータからEBSボリュームのデバイス名を取得することは可能ですが、「OSが認識しているどのブロックデバイスなのか」という情報が欠けており、判断ができません。

# トークンの取得
$ token=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# EC2インスタンスにアタッチされている仮想デバイス一覧の取得
$ curl -H "X-aws-ec2-metadata-token: $token" http://169.254.169.254/latest/meta-data/block-device-mapping/
ami
ebs2
ebs3

# 各仮想デバイスの確認
$ curl -H "X-aws-ec2-metadata-token: $token" http://169.254.169.254/latest/meta-data/block-device-mapping/ami
sda1

$ curl -H "X-aws-ec2-metadata-token: $token" http://169.254.169.254/latest/meta-data/block-device-mapping/ami/sda1
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <title>404 - Not Found</title>
 </head>
 <body>
  <h1>404 - Not Found</h1>
 </body>
</html>

$ curl -H "X-aws-ec2-metadata-token: $token" http://169.254.169.254/latest/meta-data/block-device-mapping/ebs2
sdb

$ curl -H "X-aws-ec2-metadata-token: $token" http://169.254.169.254/latest/meta-data/block-device-mapping/ebs2/sdb
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <title>404 - Not Found</title>
 </head>
 <body>
  <h1>404 - Not Found</h1>
 </body>
</html>

$ curl -H "X-aws-ec2-metadata-token: $token" http://169.254.169.254/latest/meta-data/block-device-mapping/ebs3
sdc

$ curl -H "X-aws-ec2-metadata-token: $token" http://169.254.169.254/latest/meta-data/block-device-mapping/ebs3/sdc
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <title>404 - Not Found</title>
 </head>
 <body>
  <h1>404 - Not Found</h1>
 </body>
</html>

これは大変ですね。

そんな時はlsblk -o +SERIALを叩いてEBSボリュームのIDを取得することで、判断が可能です。

$ lsblk -o +SERIAL
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS SERIAL
nvme1n1     259:0    0    1G  0 disk             vol0c042e0f4f8ab87ed
nvme0n1     259:1    0   10G  0 disk             vol0ac4b53ee9d729ab8
├─nvme0n1p1 259:3    0    1M  0 part
├─nvme0n1p2 259:4    0  200M  0 part /efi
│                                    /boot/efi
├─nvme0n1p3 259:5    0  500M  0 part /boot
└─nvme0n1p4 259:6    0  9.3G  0 part /
nvme2n1     259:2    0    2G  0 disk             vol0f984dd35d3479403

では、AWS CDKなどボリュームIDが分からない状況において、一撃でマッピングするにはどのようにしたら良いでしょうか。

そんな時は対応としてnvme-cliを活用することで解決できます。

いきなりまとめ

  • RHELのEC2インスタンスでEBSボリュームのデバイス名とOSが認識しているブロックデバイス名をマッピングさせる場合は、nvme-cliを使用する必要がある
    • nvme1n1 = /dev/sdbnvme2n1 = /dev/sdcではない
  • nvme-cliでブロックデバイスからEBSボリュームのデバイス名を取得することが可能
    • バイナリ形式のnvme id-ctrlの出力結果の3072バイトから3088バイトの間に出現する
  • シェルスクリプトで頑張れば複数のEBSボリュームを意図したマウントポイントにマウントすることも可能

検証環境

RHEL 9.2(RHEL-9.2.0_HVM-20230726-x86_64-61-Hourly2-GP2)のEC2インスタンスにEBSボリュームをルートボリューム含めて10個アタッチします。

分かりやすいように/dev/sdbからボリュームサイズを1GiBづつ増やしています。

AWS CDKでデプロイしました。コードは以下の通りです。

./lib/constructs/ec2-instance.ts

    // Instance
    this.instance = new cdk.aws_ec2.Instance(this, "Default", {
      machineImage: cdk.aws_ec2.MachineImage.lookup({
        name: "RHEL-9.2.0_HVM-20230726-x86_64-61-Hourly2-GP2",
        owners: ["309956199498"],
      }),
      instanceType: new cdk.aws_ec2.InstanceType("t3.micro"),
      blockDevices: [
        {
          deviceName: "/dev/sda1",
          volume: cdk.aws_ec2.BlockDeviceVolume.ebs(10, {
            volumeType: cdk.aws_ec2.EbsDeviceVolumeType.GP3,
            encrypted: true,
          }),
        },
        {
          deviceName: "/dev/sdb",
          volume: cdk.aws_ec2.BlockDeviceVolume.ebs(1, {
            volumeType: cdk.aws_ec2.EbsDeviceVolumeType.GP3,
            encrypted: true,
          }),
        },
        {
          deviceName: "/dev/sdc",
          volume: cdk.aws_ec2.BlockDeviceVolume.ebs(2, {
            volumeType: cdk.aws_ec2.EbsDeviceVolumeType.GP3,
            encrypted: true,
          }),
        },
        {
          deviceName: "/dev/sdd",
          volume: cdk.aws_ec2.BlockDeviceVolume.ebs(3, {
            volumeType: cdk.aws_ec2.EbsDeviceVolumeType.GP3,
            encrypted: true,
          }),
        },
        {
          deviceName: "/dev/sde",
          volume: cdk.aws_ec2.BlockDeviceVolume.ebs(4, {
            volumeType: cdk.aws_ec2.EbsDeviceVolumeType.GP3,
            encrypted: true,
          }),
        },
        {
          deviceName: "/dev/sdf",
          volume: cdk.aws_ec2.BlockDeviceVolume.ebs(5, {
            volumeType: cdk.aws_ec2.EbsDeviceVolumeType.GP3,
            encrypted: true,
          }),
        },
        {
          deviceName: "/dev/sdg",
          volume: cdk.aws_ec2.BlockDeviceVolume.ebs(6, {
            volumeType: cdk.aws_ec2.EbsDeviceVolumeType.GP3,
            encrypted: true,
          }),
        },
        {
          deviceName: "/dev/sdh",
          volume: cdk.aws_ec2.BlockDeviceVolume.ebs(7, {
            volumeType: cdk.aws_ec2.EbsDeviceVolumeType.GP3,
            encrypted: true,
          }),
        },
        {
          deviceName: "/dev/sdi",
          volume: cdk.aws_ec2.BlockDeviceVolume.ebs(8, {
            volumeType: cdk.aws_ec2.EbsDeviceVolumeType.GP3,
            encrypted: true,
          }),
        },
        {
          deviceName: "/dev/sdi",
          volume: cdk.aws_ec2.BlockDeviceVolume.ebs(9, {
            volumeType: cdk.aws_ec2.EbsDeviceVolumeType.GP3,
            encrypted: true,
          }),
        },
      ],
      vpc: props.vpc,
      vpcSubnets: props.vpc.selectSubnets({
        subnetGroupName: "Public",
      }),
      ssmSessionPermissions: true,
      userData,
      requireImdsv2: true,
    });

AWS CDKのコードは以下リポジトリにも保存しています。

デプロイ後、EC2インスタンスに10個のEBSボリュームがアタッチされていることを確認します。

10個のEBSボリュームがアタッチされていることを確認

OSからもブロックデバイス一覧を確認します。

$ lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
nvme0n1     259:0    0   10G  0 disk
├─nvme0n1p1 259:1    0    1M  0 part
├─nvme0n1p2 259:2    0  200M  0 part /boot/efi
├─nvme0n1p3 259:3    0  500M  0 part /boot
└─nvme0n1p4 259:4    0  9.3G  0 part /
nvme1n1     259:5    0    9G  0 disk
nvme2n1     259:6    0    2G  0 disk
nvme3n1     259:7    0    3G  0 disk
nvme5n1     259:8    0    8G  0 disk
nvme4n1     259:9    0    1G  0 disk
nvme6n1     259:10   0    6G  0 disk
nvme7n1     259:11   0    5G  0 disk
nvme8n1     259:12   0    4G  0 disk
nvme9n1     259:13   0    7G  0 disk

$ ls -l /dev | grep sd

nvme1n1だから/dev/sdbで指定したボリュームサイズの2GiBである」ということはないですね。EC2のコンソールで表示されたEBSボリュームの順番ともリンクしていなさそうです。

やってみる

NVMeデバイスの一覧の表示

まず、nvme-cliをインストールします。

$ sudo dnf install nvme-cli -y
Updating Subscription Management repositories.
Unable to read consumer identity

This system is not registered with an entitlement server. You can use subscription-manager to register.

Last metadata expiration check: 0:07:58 ago on Sat 02 Sep 2023 03:25:38 AM UTC.
Dependencies resolved.
============================================================================================================
 Package             Architecture      Version                     Repository                          Size
============================================================================================================
Installing:
 nvme-cli            x86_64            2.2.1-4.el9_2               rhel-9-baseos-rhui-rpms            735 k
Installing dependencies:
 libnvme             x86_64            1.2-3.el9_2                 rhel-9-baseos-rhui-rpms             84 k

Transaction Summary
============================================================================================================
Install  2 Packages

Total download size: 819 k
Installed size: 4.7 M
Downloading Packages:
(1/2): libnvme-1.2-3.el9_2.x86_64.rpm                                       1.9 MB/s |  84 kB     00:00
(2/2): nvme-cli-2.2.1-4.el9_2.x86_64.rpm                                     11 MB/s | 735 kB     00:00
------------------------------------------------------------------------------------------------------------
Total                                                                       8.7 MB/s | 819 kB     00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                    1/1
  Installing       : libnvme-1.2-3.el9_2.x86_64                                                         1/2
  Installing       : nvme-cli-2.2.1-4.el9_2.x86_64                                                      2/2
  Running scriptlet: nvme-cli-2.2.1-4.el9_2.x86_64                                                      2/2
Created symlink /etc/systemd/system/default.target.wants/nvmefc-boot-connections.service → /usr/lib/systemd/system/nvmefc-boot-connections.service.

  Verifying        : nvme-cli-2.2.1-4.el9_2.x86_64                                                      1/2
  Verifying        : libnvme-1.2-3.el9_2.x86_64                                                         2/2
Installed products updated.

Installed:
  libnvme-1.2-3.el9_2.x86_64                          nvme-cli-2.2.1-4.el9_2.x86_64

Complete!

nvme-cliのマニュアルは以下をご覧ください。

それでは、NVMeのデバイス一覧を表示します。

$ sudo nvme list
Node                  Generic               SN                   Model                                    Namespace Usage                      Format           FW Rev
--------------------- --------------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme9n1          /dev/ng9n1            vol01e6f05cc38b00bca Amazon Elastic Block Store               1          7.52  GB /   7.52  GB    512   B +  0 B   1.0
/dev/nvme8n1          /dev/ng8n1            vol0f03216dd39d1ba88 Amazon Elastic Block Store               1          4.29  GB /   4.29  GB    512   B +  0 B   1.0
/dev/nvme7n1          /dev/ng7n1            vol07597c1950ee51fdb Amazon Elastic Block Store               1          5.37  GB /   5.37  GB    512   B +  0 B   1.0
/dev/nvme6n1          /dev/ng6n1            vol0fcf2d0dbfbb379a3 Amazon Elastic Block Store               1          6.44  GB /   6.44  GB    512   B +  0 B   1.0
/dev/nvme5n1          /dev/ng5n1            vol0f0c5b20e39976f7d Amazon Elastic Block Store               1          8.59  GB /   8.59  GB    512   B +  0 B   1.0
/dev/nvme4n1          /dev/ng4n1            vol090468b5a7a9c526b Amazon Elastic Block Store               1          1.07  GB /   1.07  GB    512   B +  0 B   1.0
/dev/nvme3n1          /dev/ng3n1            vol0219674504bdb3dca Amazon Elastic Block Store               1          3.22  GB /   3.22  GB    512   B +  0 B   1.0
/dev/nvme2n1          /dev/ng2n1            vol0bdf46387057b6985 Amazon Elastic Block Store               1          2.15  GB /   2.15  GB    512   B +  0 B   1.0
/dev/nvme1n1          /dev/ng1n1            vol079f22b6d68322c16 Amazon Elastic Block Store               1          9.66  GB /   9.66  GB    512   B +  0 B   1.0
/dev/nvme0n1          /dev/ng0n1            vol00098242ca87f8eb6 Amazon Elastic Block Store               1         10.74  GB /  10.74  GB    512   B +  0 B   1.0

# 詳細の表示
$ sudo nvme list -v
Subsystem        Subsystem-NQN      Controllers
---------------- ------------------------------------------------------------------------------------------------ ----------------
nvme-subsys9     nqn.2014.08.org.nvmexpress:1d0f1d0fvol01e6f05cc38b00bcaAmazon Elastic Block Store      nvme9
nvme-subsys8     nqn.2014.08.org.nvmexpress:1d0f1d0fvol0f03216dd39d1ba88Amazon Elastic Block Store      nvme8
nvme-subsys7     nqn.2014.08.org.nvmexpress:1d0f1d0fvol07597c1950ee51fdbAmazon Elastic Block Store      nvme7
nvme-subsys6     nqn.2014.08.org.nvmexpress:1d0f1d0fvol0fcf2d0dbfbb379a3Amazon Elastic Block Store      nvme6
nvme-subsys5     nqn.2014.08.org.nvmexpress:1d0f1d0fvol0f0c5b20e39976f7dAmazon Elastic Block Store      nvme5
nvme-subsys4     nqn.2014.08.org.nvmexpress:1d0f1d0fvol090468b5a7a9c526bAmazon Elastic Block Store      nvme4
nvme-subsys3     nqn.2014.08.org.nvmexpress:1d0f1d0fvol0219674504bdb3dcaAmazon Elastic Block Store      nvme3
nvme-subsys2     nqn.2014.08.org.nvmexpress:1d0f1d0fvol0bdf46387057b6985Amazon Elastic Block Store      nvme2
nvme-subsys1     nqn.2014.08.org.nvmexpress:1d0f1d0fvol079f22b6d68322c16Amazon Elastic Block Store      nvme1
nvme-subsys0     nqn.2014.08.org.nvmexpress:1d0f1d0fvol00098242ca87f8eb6Amazon Elastic Block Store      nvme0

Device   SN                   MN                                       FR       TxPort Address        Subsystem    Namespaces
-------- -------------------- ---------------------------------------- -------- ------ -------------- ------------ ----------------
nvme9    vol01e6f05cc38b00bca Amazon Elastic Block Store               1.0      pcie   0000:00:1f.0   nvme-subsys9 nvme9n1
nvme8    vol0f03216dd39d1ba88 Amazon Elastic Block Store               1.0      pcie   0000:00:1e.0   nvme-subsys8 nvme8n1
nvme7    vol07597c1950ee51fdb Amazon Elastic Block Store               1.0      pcie   0000:00:1d.0   nvme-subsys7 nvme7n1
nvme6    vol0fcf2d0dbfbb379a3 Amazon Elastic Block Store               1.0      pcie   0000:00:1c.0   nvme-subsys6 nvme6n1
nvme5    vol0f0c5b20e39976f7d Amazon Elastic Block Store               1.0      pcie   0000:00:1b.0   nvme-subsys5 nvme5n1
nvme4    vol090468b5a7a9c526b Amazon Elastic Block Store               1.0      pcie   0000:00:1a.0   nvme-subsys4 nvme4n1
nvme3    vol0219674504bdb3dca Amazon Elastic Block Store               1.0      pcie   0000:00:19.0   nvme-subsys3 nvme3n1
nvme2    vol0bdf46387057b6985 Amazon Elastic Block Store               1.0      pcie   0000:00:18.0   nvme-subsys2 nvme2n1
nvme1    vol079f22b6d68322c16 Amazon Elastic Block Store               1.0      pcie   0000:00:17.0   nvme-subsys1 nvme1n1
nvme0    vol00098242ca87f8eb6 Amazon Elastic Block Store               1.0      pcie   0000:00:04.0   nvme-subsys0 nvme0n1

Device       Generic      NSID     Usage                      Format           Controllers
------------ ------------ -------- -------------------------- ---------------- ----------------
/dev/nvme9n1 /dev/ng9n1   1          7.52  GB /   7.52  GB    512   B +  0 B   nvme9
/dev/nvme8n1 /dev/ng8n1   1          4.29  GB /   4.29  GB    512   B +  0 B   nvme8
/dev/nvme7n1 /dev/ng7n1   1          5.37  GB /   5.37  GB    512   B +  0 B   nvme7
/dev/nvme6n1 /dev/ng6n1   1          6.44  GB /   6.44  GB    512   B +  0 B   nvme6
/dev/nvme5n1 /dev/ng5n1   1          8.59  GB /   8.59  GB    512   B +  0 B   nvme5
/dev/nvme4n1 /dev/ng4n1   1          1.07  GB /   1.07  GB    512   B +  0 B   nvme4
/dev/nvme3n1 /dev/ng3n1   1          3.22  GB /   3.22  GB    512   B +  0 B   nvme3
/dev/nvme2n1 /dev/ng2n1   1          2.15  GB /   2.15  GB    512   B +  0 B   nvme2
/dev/nvme1n1 /dev/ng1n1   1          9.66  GB /   9.66  GB    512   B +  0 B   nvme1
/dev/nvme0n1 /dev/ng0n1   1         10.74  GB /  10.74  GB    512   B +  0 B   nvme0

EBSボリュームIDは確認できますが、/dev/sdbなどのEBSボリュームで指定したデバイス名は出力されていませんね。

EBSボリュームで指定したデバイス名の抽出

EBSボリュームで指定したデバイス名は言うなればAWSというベンダー固有の情報です。そのため、nvme id-ctrl デバイス名 -vというようにベンダー固有のフィールドを出力させてみます。

$ sudo nvme id-ctrl /dev/nvme1n1 -v
NVME Identify Controller:
vid       : 0x1d0f
ssvid     : 0x1d0f
sn        : vol079f22b6d68322c16
mn        : Amazon Elastic Block Store
fr        : 1.0
rab       : 32
ieee      : a002dc
cmic      : 0
mdts      : 6
cntlid    : 0
ver       : 0x10000
rtd3r     : 0
rtd3e     : 0
oaes      : 0x100
ctratt    : 0
rrls      : 0
cntrltype : 0
fguid     : 00000000-0000-0000-0000-000000000000
crdt1     : 0
crdt2     : 0
crdt3     : 0
nvmsr     : 0
vwci      : 0
mec       : 0
oacs      : 0
acl       : 4
aerl      : 0
frmw      : 0x3
lpa       : 0
elpe      : 63
npss      : 0
avscc     : 0x1
apsta     : 0
wctemp    : 343
cctemp    : 0
mtfa      : 0
hmpre     : 0
hmmin     : 0
tnvmcap   : 0
unvmcap   : 0
rpmbs     : 0
edstt     : 0
dsto      : 0
fwug      : 0
kas       : 0
hctma     : 0
mntmt     : 0
mxtmt     : 0
sanicap   : 0
hmminds   : 0
hmmaxd    : 0
nsetidmax : 0
endgidmax : 0
anatt     : 0
anacap    : 0
anagrpmax : 0
nanagrpid : 0
pels      : 0
domainid  : 0
megcap    : 0
sqes      : 0x66
cqes      : 0x44
maxcmd    : 0
nn        : 1
oncs      : 0
fuses     : 0
fna       : 0
vwc       : 0
awun      : 0
awupf     : 0
icsvscc   : 0
nwpc      : 0
acwu      : 0
ocfs      : 0
sgls      : 0
mnan      : 0
maxdna    : 0
maxcna    : 0
subnqn    :
ioccsz    : 0
iorcsz    : 0
icdoff    : 0
fcatt     : 0
msdbd     : 0
ofcs      : 0
ps      0 : mp:0.01W operational enlat:1000000 exlat:1000000 rrt:0 rrl:0
            rwt:0 rwl:0 idle_power:- active_power:-
            active_power_workload:-
vs[]:
       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
0000: 73 64 6a 20 20 20 20 20 20 20 20 20 20 20 20 20 "sdj............."
0010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 "................"
0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
00b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
00c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
00d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
00e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
00f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
01a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
01b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
01c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
01d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
01e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
01f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
02a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
02b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
02c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
02d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
02e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
02f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0310: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0340: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0350: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
0390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
03a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
03b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
03c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
03d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
03e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"
03f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "................"

sdjという文字列が隠れていました。

バイナリで表示してみましょう。

$ sudo nvme id-ctrl /dev/nvme1n1 -v -b
vol079f22b6d68322c16Amazon Elastic Block Store              1.0      ��?WfD@B@Bsdj   

$ sudo nvme id-ctrl /dev/nvme2n1 -v -b
vol0bdf46387057b6985Amazon Elastic Block Store              1.0      ��?WfD@B@Bsdc   

$ sudo nvme id-ctrl /dev/nvme3n1 -v -b
vol0219674504bdb3dcaAmazon Elastic Block Store              1.0      ��?WfD@B@Bsdd   

$ sudo nvme id-ctrl /dev/nvme4n1 -v -b
vol090468b5a7a9c526bAmazon Elastic Block Store              1.0      ��?WfD@B@Bsdb

末尾にデバイス名が出てきていますね。

色々試してみるとnvme id-ns デバイス名 -v -bでも確認できました。

$ sudo nvme id-ns /dev/nvme1n1 -v -b
   @    sdj                             vol079f22b6d68322c16

$ sudo nvme id-ns /dev/nvme2n1 -v -b
@@@�    sdc                             vol0bdf46387057b6985

$ sudo nvme id-ns /dev/nvme3n1 -v -b
```�    sdd                             vol0219674504bdb3dca

$ sudo nvme id-ns /dev/nvme4n1 -v -b
   @    sdb                             vol090468b5a7a9c526b[

こちらの方が前後にスペースがあるのでawkで調理しやすそうですね。

実際にやってみます。

$ sudo nvme id-ns /dev/nvme3n1 -v -b | awk '{print $2}'
sdd

EBSボリュームのデバイス名が表示できましたね。

全ブロックデバイスのEBSボリュームのデバイス名を表示してみましょう。

# OSが認識しているNVMeのブロックデバイスの数を取得
$ device_count=$(lsblk -d \
    | grep nvme \
    | wc -l)

# OSが認識しているNVMeのブロックデバイスから対応するEBSボリュームのデバイス名を取得
# grub は16進数で行われるようなので、ブロックデバイス数を16進数に変換
# "warning: command substitution: ignored null byte in input" が出力されたので null を削除
$ for os_device_name in /dev/nvme[0-$(printf '%x\n' $device_count)]n1; do

    ebs_device_name=$(sudo nvme id-ns "$os_device_name" -v -b | awk '{print $2}' | tr -d '\0')
    echo "=============================================="
    echo "OS Device Name : ${os_device_name}"
    echo "EBS Volume Device Name  : ${ebs_device_name}"
done
==============================================
OS Device Name : /dev/nvme0n1
EBS Volume Device Name  : sda1
==============================================
OS Device Name : /dev/nvme1n1
EBS Volume Device Name  :
==============================================
OS Device Name : /dev/nvme2n1
EBS Volume Device Name  : sdc
==============================================
OS Device Name : /dev/nvme3n1
EBS Volume Device Name  : sdd
==============================================
OS Device Name : /dev/nvme4n1
EBS Volume Device Name  :
==============================================
OS Device Name : /dev/nvme5n1
EBS Volume Device Name  : sdi
==============================================
OS Device Name : /dev/nvme6n1
EBS Volume Device Name  : sdg
==============================================
OS Device Name : /dev/nvme7n1
EBS Volume Device Name  : sdf
==============================================
OS Device Name : /dev/nvme8n1
EBS Volume Device Name  : sde
==============================================
OS Device Name : /dev/nvme9n1
EBS Volume Device Name  : sdh

一部のデバイスは取得できませんでした。

確認してみます。

$ sudo nvme id-ns /dev/nvme1n1 -v -b
   @    sdj                             vol079f22b6d68322c16

$ sudo nvme id-ns /dev/nvme4n1 -v -b
   @    sdb                             vol090468b5a7a9c526b

出力はされていますね。

しかし、awkだと5列目にあるような認識をされていました。バイナリだからでしょうか。

$ sudo nvme id-ns /dev/nvme4n1 -v -b | awk '{print $5}'
sdb

$ sudo nvme id-ns /dev/nvme1n1 -v -b | awk '{print $5}'
sdj

ということで、awkは難しそうです。

バイナリから直接判断しましょう。

まず、バリナリの何バイトから何バイトまででデバイス名が表示されているのか確認します。

$ sudo nvme id-ctrl /dev/nvme1n1 -v -b | hexdump -C
00000000  0f 1d 0f 1d 76 6f 6c 30  37 39 66 32 32 62 36 64  |....vol079f22b6d|
00000010  36 38 33 32 32 63 31 36  41 6d 61 7a 6f 6e 20 45  |68322c16Amazon E|
00000020  6c 61 73 74 69 63 20 42  6c 6f 63 6b 20 53 74 6f  |lastic Block Sto|
00000030  72 65 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |re              |
00000040  31 2e 30 20 20 20 20 20  20 dc 02 a0 00 06 00 00  |1.0      .......|
00000050  00 00 01 00 00 00 00 00  00 00 00 00 00 01 00 00  |................|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000100  00 00 04 00 03 00 3f 00  01 00 57 01 00 00 00 00  |......?...W.....|
00000110  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000200  66 44 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |fD..............|
00000210  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000800  01 00 00 00 40 42 0f 00  40 42 0f 00 00 00 00 00  |....@B..@B......|
00000810  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000c00  73 64 6a 20 20 20 20 20  20 20 20 20 20 20 20 20  |sdj             |
00000c10  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
00000c20  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000

sdjは16進数で00000c00から00000c10までの間に出力されているので、10進数で3072バイトから3088バイトまでですね。

cutコマンドで抽出してみます。

$ sudo nvme id-ctrl --raw-binary /dev/nvme1n1 | cut -c3072-3088
sdj

抽出できましたね。

全ボリュームで試してみましょう。

# OSが認識しているNVMeのブロックデバイスの数を取得
device_count=$(lsblk -d \
    | grep nvme \
    | wc -l)

# OSが認識しているNVMeのブロックデバイスから対応するEBSボリュームのデバイス名を取得
# grub は16進数で行われるようなので、ブロックデバイス数を16進数に変換
# "warning: command substitution: ignored null byte in input" が出力されたので null を削除
# 末尾にスペースが含まれるため除去
for os_device_name in /dev/nvme[0-$(printf '%x\n' $device_count)]n1; do
    ebs_device_name=$(sudo nvme id-ctrl "$os_device_name" -v -b | cut -c3072-3088 | tr -d '\0' | sed 's/ //g')
    echo "=============================================="
    echo "OS Device Name : ${os_device_name}"
    echo "EBS Volume Device Name  : ${ebs_device_name}"
done
==============================================
OS Device Name : /dev/nvme0n1
EBS Volume Device Name  : sda1
==============================================
OS Device Name : /dev/nvme1n1
EBS Volume Device Name  : sdj
==============================================
OS Device Name : /dev/nvme2n1
EBS Volume Device Name  : sdc
==============================================
OS Device Name : /dev/nvme3n1
EBS Volume Device Name  : sdd
==============================================
OS Device Name : /dev/nvme4n1
EBS Volume Device Name  : sdb
==============================================
OS Device Name : /dev/nvme5n1
EBS Volume Device Name  : sdi
==============================================
OS Device Name : /dev/nvme6n1
EBS Volume Device Name  : sdg
==============================================
OS Device Name : /dev/nvme7n1
EBS Volume Device Name  : sdf
==============================================
OS Device Name : /dev/nvme8n1
EBS Volume Device Name  : sde
==============================================
OS Device Name : /dev/nvme9n1
EBS Volume Device Name  : sdh

こちらは全ボリュームでマッピングできましたね。バイナリから切り出してデバイス名を抽出するのがよさそうです。

一撃で複数のEBSボリュームを意図したマウントポイントにマウントする

一撃で複数のEBSボリュームを意図したマウントポイントにマウントしてみます。

分かりやすいようにsdb/vol2sdc/vol3というようにマウントさせます。

# マウントポイントのリストアップ
declare -A mount_points=(
    ["sdb"]="/vol2"
    ["sdc"]="/vol3"
    ["sdd"]="/vol4"
    ["sde"]="/vol5"
    ["sdf"]="/vol6"
    ["sdg"]="/vol7"
    ["sdh"]="/vol8"
    ["sdi"]="/vol9"
    ["sdj"]="/vol10"
)

# OSが認識しているNVMeのブロックデバイスの数を取得
device_count=$(lsblk -d \
    | grep nvme \
    | wc -l)

# grub は16進数で行われるようなので、ブロックデバイス数を16進数に変換
for os_device_name in /dev/nvme[0-$(printf '%x\n' $device_count)]n1; do
    # OSが認識しているNVMeのブロックデバイスから対応するEBSボリュームのデバイス名を取得
    # "warning: command substitution: ignored null byte in input" が出力されたので null を削除
    # 末尾にスペースが含まれるため除去
    ebs_device_name=$(sudo nvme id-ctrl "$os_device_name" -v -b | cut -c3072-3088 | tr -d '\0' | sed 's/ //g')
    echo "=============================================="
    echo "OS Device Name : ${os_device_name}"
    echo "EBS Volume Device Name  : ${ebs_device_name}"

    # 配列に対応するマウントポイントがない場合はスキップ
    if [[ ! -v "mount_points[${ebs_device_name}]" ]]; then
        echo "No mount points found for ${ebs_device_name}. Skipping"
        continue
    fi
    mount_point=${mount_points["${ebs_device_name#/dev/}"]}
    echo "Mount Point  : ${mount_point}"

    # xfsでファイルシステムを作成
    sudo mkfs.xfs $os_device_name

    # マウント
    sudo mkdir -p $mount_point
    sudo mount $os_device_name $mount_point

    # /etc/fstab に追記
    uuid=$(sudo blkid | grep ${os_device_name} | sed 's/.*UUID="//; s/".*//')
    echo -e "UUID=${uuid}\t${mount_point}\txfs\tdefaults\t0\t0" | sudo tee -a /etc/fstab
    sudo systemctl daemon-reload
done
==============================================
OS Device Name : /dev/nvme0n1
EBS Volume Device Name  : sda1
No mount points found for sda1. Skipping
==============================================
OS Device Name : /dev/nvme1n1
EBS Volume Device Name  : sdj
Mount Point  : /vol10
meta-data=/dev/nvme1n1           isize=512    agcount=16, agsize=147456 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=2359296, imaxpct=25
         =                       sunit=1      swidth=1 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
UUID=07302d63-aeab-46f6-93d6-71efdc417eee       /vol10  xfs     defaults        0       0
==============================================
OS Device Name : /dev/nvme2n1
EBS Volume Device Name  : sdc
Mount Point  : /vol3
meta-data=/dev/nvme2n1           isize=512    agcount=8, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=524288, imaxpct=25
         =                       sunit=1      swidth=1 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
UUID=0097870f-f5ba-4a53-a1ee-1cf68ea9f746       /vol3   xfs     defaults        0       0
==============================================
OS Device Name : /dev/nvme3n1
EBS Volume Device Name  : sdd
Mount Point  : /vol4
meta-data=/dev/nvme3n1           isize=512    agcount=8, agsize=98304 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=786432, imaxpct=25
         =                       sunit=1      swidth=1 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
UUID=5c12d789-f201-4337-981b-4214752828c1       /vol4   xfs     defaults        0       0
==============================================
OS Device Name : /dev/nvme4n1
EBS Volume Device Name  : sdb
Mount Point  : /vol2
meta-data=/dev/nvme4n1           isize=512    agcount=8, agsize=32768 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=1      swidth=1 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
UUID=5d7a620e-56de-41e5-9ff0-fd389ed2d1c9       /vol2   xfs     defaults        0       0
==============================================
OS Device Name : /dev/nvme5n1
EBS Volume Device Name  : sdi
Mount Point  : /vol9
meta-data=/dev/nvme5n1           isize=512    agcount=8, agsize=262144 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=2097152, imaxpct=25
         =                       sunit=1      swidth=1 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
UUID=1bf0a0a0-5568-47fb-abf9-327036e5b353       /vol9   xfs     defaults        0       0
==============================================
OS Device Name : /dev/nvme6n1
EBS Volume Device Name  : sdg
Mount Point  : /vol7
meta-data=/dev/nvme6n1           isize=512    agcount=8, agsize=196608 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=1572864, imaxpct=25
         =                       sunit=1      swidth=1 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
UUID=8d9329db-755f-4573-bb22-6f388b93a753       /vol7   xfs     defaults        0       0
==============================================
OS Device Name : /dev/nvme7n1
EBS Volume Device Name  : sdf
Mount Point  : /vol6
meta-data=/dev/nvme7n1           isize=512    agcount=8, agsize=163840 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=1310720, imaxpct=25
         =                       sunit=1      swidth=1 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
UUID=9ad02547-47ce-482c-be6f-ed83fd8a1841       /vol6   xfs     defaults        0       0
==============================================
OS Device Name : /dev/nvme8n1
EBS Volume Device Name  : sde
Mount Point  : /vol5
meta-data=/dev/nvme8n1           isize=512    agcount=8, agsize=131072 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=1048576, imaxpct=25
         =                       sunit=1      swidth=1 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
UUID=20e3b918-133a-47af-b828-e3900f5faa45       /vol5   xfs     defaults        0       0
==============================================
OS Device Name : /dev/nvme9n1
EBS Volume Device Name  : sdh
Mount Point  : /vol8
meta-data=/dev/nvme9n1           isize=512    agcount=8, agsize=229376 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=1835008, imaxpct=25
         =                       sunit=1      swidth=1 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
UUID=1d70f256-7be4-4e8a-8da9-baf28d4321b8       /vol8   xfs     defaults        0       0

無事に実行完了しました。

マウントできているか確認しましょう。

$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
devtmpfs       devtmpfs  4.0M     0  4.0M   0% /dev
tmpfs          tmpfs     372M     0  372M   0% /dev/shm
tmpfs          tmpfs     149M   11M  139M   7% /run
/dev/nvme0n1p4 xfs       9.4G  1.9G  7.5G  20% /
/dev/nvme0n1p3 xfs       495M  164M  331M  34% /boot
/dev/nvme0n1p2 vfat      200M  8.0K  200M   1% /boot/efi
/dev/nvme1n1   xfs       9.0G   98M  8.9G   2% /vol10
/dev/nvme2n1   xfs       2.0G   47M  2.0G   3% /vol3
/dev/nvme3n1   xfs       3.0G   54M  3.0G   2% /vol4
/dev/nvme4n1   xfs      1014M   40M  975M   4% /vol2
/dev/nvme5n1   xfs       8.0G   90M  8.0G   2% /vol9
/dev/nvme6n1   xfs       6.0G   76M  6.0G   2% /vol7
/dev/nvme7n1   xfs       5.0G   69M  5.0G   2% /vol6
/dev/nvme8n1   xfs       4.0G   62M  4.0G   2% /vol5
/dev/nvme9n1   xfs       7.0G   83M  7.0G   2% /vol8

マウントできていますね。

ただ、こちらだと指定したブロックデバイス名に意図したマウントポイントをマウントしているのか分かりづらいので、ボリュームサイズの昇順でソートしてあげます。

$ lsblk -d | sort -n -k 4
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme4n1 259:9    0   1G  0 disk /vol2
nvme2n1 259:6    0   2G  0 disk /vol3
nvme3n1 259:7    0   3G  0 disk /vol4
nvme8n1 259:12   0   4G  0 disk /vol5
nvme7n1 259:11   0   5G  0 disk /vol6
nvme6n1 259:10   0   6G  0 disk /vol7
nvme9n1 259:13   0   7G  0 disk /vol8
nvme5n1 259:8    0   8G  0 disk /vol9
nvme1n1 259:5    0   9G  0 disk /vol10
nvme0n1 259:0    0  10G  0 disk

sdbの1GiBのボリュームは/vol2sdcの2GiBのボリュームは/vol3と意図した通りにマウントできていることが分かります。

/etc/fstabも確認します。

$ cat /etc/fstab
UUID=fac724b7-ede8-4b39-aff9-44db8e22c0f1       /       xfs     defaults        0       0
UUID=2e756c58-7b6e-4700-8a89-b9ab3e1058f1       /boot   xfs     defaults        0       0
UUID=7B77-95E7  /boot/efi       vfat    defaults,uid=0,gid=0,umask=077,shortname=winnt  0       2
UUID=07302d63-aeab-46f6-93d6-71efdc417eee       /vol10  xfs     defaults        0       0
UUID=0097870f-f5ba-4a53-a1ee-1cf68ea9f746       /vol3   xfs     defaults        0       0
UUID=5c12d789-f201-4337-981b-4214752828c1       /vol4   xfs     defaults        0       0
UUID=5d7a620e-56de-41e5-9ff0-fd389ed2d1c9       /vol2   xfs     defaults        0       0
UUID=1bf0a0a0-5568-47fb-abf9-327036e5b353       /vol9   xfs     defaults        0       0
UUID=8d9329db-755f-4573-bb22-6f388b93a753       /vol7   xfs     defaults        0       0
UUID=9ad02547-47ce-482c-be6f-ed83fd8a1841       /vol6   xfs     defaults        0       0
UUID=20e3b918-133a-47af-b828-e3900f5faa45       /vol5   xfs     defaults        0       0
UUID=1d70f256-7be4-4e8a-8da9-baf28d4321b8       /vol8   xfs     defaults        0       0

良い感じに記述されていそうですね。

一度アンマウントして、/etc/fstabの設定内容にしたがって再マウントさせてみます。

# アンマウント
$ sudo umount /vol*

# アンマウントされたことを確認
$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
devtmpfs       devtmpfs  4.0M     0  4.0M   0% /dev
tmpfs          tmpfs     372M     0  372M   0% /dev/shm
tmpfs          tmpfs     149M   11M  139M   7% /run
/dev/nvme0n1p4 xfs       9.4G  1.9G  7.5G  20% /
/dev/nvme0n1p3 xfs       495M  164M  331M  34% /boot
/dev/nvme0n1p2 vfat      200M  8.0K  200M   1% /boot/efi
tmpfs          tmpfs      75M     0   75M   0% /run/user/0

/etc/fstab`の設定内容にしたがって再マウント
[ec2-user@ip-10-10-10-30 ~]$ sudo mount -a

# 再マウントできたことを確認
$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
devtmpfs       devtmpfs  4.0M     0  4.0M   0% /dev
tmpfs          tmpfs     372M     0  372M   0% /dev/shm
tmpfs          tmpfs     149M   11M  139M   7% /run
/dev/nvme0n1p4 xfs       9.4G  1.9G  7.5G  20% /
/dev/nvme0n1p3 xfs       495M  164M  331M  34% /boot
/dev/nvme0n1p2 vfat      200M  8.0K  200M   1% /boot/efi
tmpfs          tmpfs      75M     0   75M   0% /run/user/0
/dev/nvme1n1   xfs       9.0G   98M  8.9G   2% /vol10
/dev/nvme2n1   xfs       2.0G   47M  2.0G   3% /vol3
/dev/nvme3n1   xfs       3.0G   54M  3.0G   2% /vol4
/dev/nvme4n1   xfs      1014M   40M  975M   4% /vol2
/dev/nvme5n1   xfs       8.0G   90M  8.0G   2% /vol9
/dev/nvme6n1   xfs       6.0G   76M  6.0G   2% /vol7
/dev/nvme7n1   xfs       5.0G   69M  5.0G   2% /vol6
/dev/nvme8n1   xfs       4.0G   62M  4.0G   2% /vol5
/dev/nvme9n1   xfs       7.0G   83M  7.0G   2% /vol8

問題なく再マウントできました。

NVMeの情報に記載のEBSボリュームのデバイス名を活用しよう

RHELのEC2インスタンスにおいて、EBSボリュームのデバイス名とOSが認識しているブロックデバイス名をマッピングさせてマウントしてみました。

NVMeの情報に記載のEBSボリュームのデバイス名を活用しましょう。

AWS CDKで一気にデプロイする時もユーザーデータに以下のようなスクリプトを仕組んでおけば、意図した通りにマウントポイントにEBSボリュームをマウントしてくれそうです。

# マウントポイントのリストアップ
declare -A mount_points=(
    ["EBSボリュームに指定したデバイス名"]="マウントポイント"
)

for os_device_name in /dev/nvme*n1; do
    # OSが認識しているNVMeのブロックデバイスから対応するEBSボリュームのデバイス名を取得
    # "warning: command substitution: ignored null byte in input" が出力されたので null を削除
    # 末尾にスペースが含まれるため除去
    ebs_device_name=$(sudo nvme id-ctrl "$os_device_name" -v -b | cut -c3072-3088 | tr -d '\0' | sed 's/ //g')
    echo "=============================================="
    echo "OS Device Name : ${os_device_name}"
    echo "EBS Volume Device Name  : ${ebs_device_name}"

    # 配列に対応するマウントポイントがない場合はスキップ
    if [[ ! -v "mount_points[${ebs_device_name}]" ]]; then
        echo "No mount points found for ${ebs_device_name}. Skipping"
        continue
    fi
    mount_point=${mount_points["${ebs_device_name}"]}
    echo "Mount Point  : ${mount_point}"

    # xfsでファイルシステムを作成
    sudo mkfs.xfs $os_device_name

    # マウント
    sudo mkdir -p $mount_point
    sudo mount $os_device_name $mount_point

    # /etc/fstab に追記
    uuid=$(sudo blkid | grep ${os_device_name} | sed 's/.*UUID="//; s/".*//')
    echo -e "UUID=${uuid}\t${mount_point}\txfs\tdefaults\t0\t0" | sudo tee -a /etc/fstab
    sudo systemctl daemon-reload
done

ちなみにこちらの手法はt2.microなどの非Nitroインスタンスでは使用出来ません。非Nitroインスタンスの場合はOSが認識するデバイス名はnvme[0-26]n1ではなくxvd[a-d][a-z]となります。

EBS ボリュームは、Nitro System上に構築されたインスタンスで NVMe ブロックデバイスとして公開されます。デバイス名は、/dev/nvme0n1、/dev/nvme1n1 などです。ブロックデバイスマッピングで指定したデバイス名は、NVMe デバイス名 (/dev/nvme[0-26]n1) を使用して名称変更されます。ブロックデバイスドライバーは、ブロックデバイスマッピングのボリュームに指定した順序とは異なる順序で NVMe デバイス名を割り当てることができます。

Linux インスタンスの Amazon EBS および NVMe - Amazon Elastic Compute Cloud

実際に、t2.microに変更して起動すると以下のようにxvdbなどとデバイス名が変わっていました。

$ lsblk
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
xvda    202:0    0   10G  0 disk
├─xvda1 202:1    0    1M  0 part
├─xvda2 202:2    0  200M  0 part /efi
│                                /boot/efi
├─xvda3 202:3    0  500M  0 part /boot
└─xvda4 202:4    0  9.3G  0 part /
xvdb    202:16   0    1G  0 disk /vol2
xvdc    202:32   0    2G  0 disk /vol3
xvdd    202:48   0    3G  0 disk /vol4
xvde    202:64   0    4G  0 disk /vol5
xvdf    202:80   0    5G  0 disk /vol6
xvdg    202:96   0    6G  0 disk /vol7
xvdh    202:112  0    7G  0 disk /vol8
xvdi    202:128  0    8G  0 disk /vol9
xvdj    202:144  0    9G  0 disk /vol10

$ ls -l /dev | grep sd

NVMe デバイスとして認識されていないので、nvme-cliで判別することは出来ません。

$ sudo nvme list
Failed to scan topology: No such file or directory

Linuxインスタンスのデバイス名は以下AWS公式ドキュメントをご覧ください。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!