LinuxインスタンスにEBSをアタッチする

CloudFormationでLinuxインスタンスにEBSをアタッチする

LinuxインスタンスにEBSをアタッチする構成

LinuxインスタンスにEBS(Elastic Block Store)をアタッチする構成を確認します。

EBSはAWSが提供するブロックストレージです。

Amazon EBS を使用すると、ストレージボリュームを作成して Amazon EC2 インスタンスにアタッチできます。いったんアタッチすると、これらのボリュームの上にファイルシステムを構築したり、データベースを実行したり、ブロックストレージを使用するその他の方法でボリュームを使用したりできます。

Amazon EBS の特徴

本ページでは、LinuxインスタンスにEBSをアタッチし、ストレージとして使用できるようにするまでの手順を確認します。
アタッチ以降の手順は、AWS公式サイト「Linux で Amazon EBS ボリュームを使用できるようにする」で紹介されている内容に沿って進めます。

具体的には、以下の3パターンを確認します。

  1. Nitro Systemで構築されたインスタンではない場合
  2. Nitro Systemで構築されたインスタンスの場合
  3. SSMドキュメントを使用して、シェルスクリプトを実行する方法

またWindowsインスタンスにEBSをアタッチする手順については、以下のページをご確認ください。

あわせて読みたい
WindowsインスタンスにEBSをアタッチする4つの方法 【WindowsインスタンスにEBSをアタッチする】 WindowsインスタンスにEBS(Elastic Block Store)をアタッチする構成を確認します。 本ページでは、WindowsインスタンスにE...

構築する環境

Diagram of Attaching EBS to Linux instance.

VPC内の1つのサブネットを作成します。このサブネットはインターネットにアクセス不可なプライベートサブネットとします。
同サブネットに2つのEC2インスタンスを配置します。いずれも最新のAmazon Linux 2ベースのインスタンスとします。ただし指定するインスタンスタイプに変化をつけます。一方(①)をT2.nanoとし、もう一方(②)をT4g.nanoとします。
同サブネットにEBSを2つ作成します。先述の2インスタンスに1つずつEBSをアタッチします。
SSM用のVPCエンドポイントを配置します。同サービスのSession Manager機能で、プライベートサブネット内のインスタンスにアクセスするために使用します。

環境構築用のCloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置してます。

https://github.com/awstut-an-r/awstut-fa/tree/main/008

テンプレートファイルのポイント解説

今回の環境を構成するための、各テンプレートファイルのポイントを取り上げます。

(参考)SSM Parameter Storeを参照して、最新のAMIからインスタンスを作成する

EBSをアタッチするEC2を確認します。
ポイントは作成するインスタンスのアーキテクチャに応じたAMIを設定する必要があるという点です。

Parameters:
  ImageId1:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>

  ImageId2:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>

  InstanceType1:
    Type: String

  InstanceType2:
    Type: String


Resources:
  Instance1:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref InstanceProfile
      ImageId: !Ref ImageId1
      InstanceType: !Ref InstanceType1
      NetworkInterfaces:
        - DeviceIndex: 0
          SubnetId: !Ref PrivateSubnet
          GroupSet:
            - !Ref InstanceSecurityGroup

  Instance2:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref InstanceProfile
      ImageId: !Ref ImageId2
      InstanceType: !Ref InstanceType2
      NetworkInterfaces:
        - DeviceIndex: 0
          SubnetId: !Ref PrivateSubnet
          GroupSet:
            - !Ref InstanceSecurityGroup
Code language: YAML (yaml)

今回の構成でポイントとなる設定はInstanceTypeおよびImageIdプロパティです。
先述の通り、今回は2インスタンスに対して、以下の通りインスタンスタイプを指定します。

  • インスタンス①:T2.nano
  • インスタンス②:T4g.nano

組み込み関数Fn::Refを使用して、Parametersセクションの値を参照し、2インスタンスのInstanceTypeプロパティを設定します。

2インスタンスのOSは共通してAmazon Linux 2を動作させますが、注意が必要です。
それは上記のインスタンスタイプはアーキテクチャが異なるため、同じAMIを指定することはできないという点です。

T2はx86_64ベースのインスタンスです。

特徴:
高クロックのインテル Xeon プロセッサ

Amazon EC2 インスタンスタイプ

一方、T4gはArmベースのインスタンスです。

特徴:
64 ビットの Arm Neoverse コアを搭載したカスタムビルドの AWS Graviton2 プロセッサ
専用ハードウェアと軽量ハイパーバイザーを組み合わせた AWS Nitro System で駆動

Amazon EC2 インスタンスタイプ

SSM Parameter Storeを使用することによって、アーキテクチャに合わせた最新のAMI IDを取得することが可能です。

AWS Systems Manager Parameter Store はすでに最新の Windows AMI を取得できます。今回、最新の Linux AMI も取得できるよう機能が拡張されました。各 Amazon Linux AMI は、固有の 公開パラメータストア名前空間 を持ちます。AMIの名前空間をクエリすることで、指定したリージョンのイメージIDを得ることができます。

AWS Systems Manager Parameter Store を使用して最新の Amazon Linux AMI IDを取得する

またCloudFormationにおいて、ParametersセクションのTypeプロパティに「AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>」を指定することによって、SSM Parameter Storeに格納された値を取得することができるようになります。

You can use the existing Parameters section of your CloudFormation template to define Systems Manager parameters, along with other parameters. Systems Manager parameters are a unique type that is different from existing parameters because they refer to actual values in the Parameter Store. The value for this type of parameter would be the Systems Manager (SSM) parameter key instead of a string or other value. CloudFormation will fetch values stored against these keys in Systems Manager in your account and use them for the current stack operation.

Integrating AWS CloudFormation with AWS Systems Manager Parameter Store

今回は以下の条件でSSM Parameter Storeから値を参照することで、各アーキテクチャの最新AMI IDを取得します。

  • インスタンス①:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
  • インスタンス②:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2

なお2021年10月現在、上記の条件でSSM Parameter Storeにアクセスした場合に取得できるAMI IDは以下の通りです。

  • インスタンス①
    • AMI ID:ami-0701e21c502689c31
    • 仮想化タイプ:hvm
  • インスタンス②
    • AMI ID:ami-0427ff21031d224a8
    • 仮想化タイプ:hvm

仮想化タイプは後述のルートデバイス名に関係がある情報です。

EBSをインスタンスにアタッチする

EC2インスタンスにEBSをアタッチする方法を確認します。

Resources:
  EBS1:
    Type: AWS::EC2::Volume
    Properties:
      AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone}"
      Size: !Ref VolumeSize
      VolumeType: !Ref VolumeType

  EBSAttachment1:
    Type: AWS::EC2::VolumeAttachment
    Properties:
      Device: !Sub "/dev/sd${DeviceNameSuffix}"
      InstanceId: !Ref Instance1
      VolumeId: !Ref EBS1
Code language: YAML (yaml)

まずEBSリソースを定義します。
AvailabilityZoneプロパティでEBSを配置するAZを指定します。EBSはアタッチ先のEC2インスタンスと同じAZに配置する必要があります。

同じアベイラビリティーゾーンに 1 つ以上のインスタンスに、利用可能な EBS ボリュームをボリュームとしてアタッチできます。

インスタンスへの Amazon EBS ボリュームのアタッチ

上記に従い、組み込み関数Fn::Subを使用して、インスタンスと同じAZに配置されるように指定します。

VolumeTypeプロパティでEBSのボリュームタイプを指定します。指定可能なボリュームタイプは以下の5種類です。

  • 汎用SSD
  • Provisioned IOPS SSD
  • スループット最適化 HDD
  • Cold HDD
  • マグネティック(旧世代)

今回は汎用SSDを選択します。
汎用SSDは2タイプあります。1つ目はgp2です。
性能(IOPS)に関して、2つの指標(ベースライン、バースト)があり、確保した容量に応じて、ベースラインが高まる仕組みが特徴です。

ベースライン IOPS パフォーマンスは、最小 100 から最大 16,000 の間で、ボリュームサイズの GiB あたり 3 IOPS のレートで直線的にスケールします。

汎用 SSD ボリューム

2つ目はgp3です。
ボリュームの容量に関係なく、一定の性能が提供されます。

gp3 ボリュームは、ストレージの料金に含まれている 3,000 IOPS の一貫したベースライン IOPS パフォーマンスを提供します。

gp3 ボリュームは、ストレージの料金に含まれている 125 MiB/秒の一貫したベースラインスループットパフォーマンスを提供します。

汎用 SSD ボリューム

Sizeプロパティで確保する容量を指定します。
汎用SSDの場合、1 GiB~16 TiBで指定可能です。
今回は最小の1GiB確保します。

続いてEC2インスタンスにEBSをアタッチするためのリソースを定義します。

Resources:
  EBSAttachment1:
    Type: AWS::EC2::VolumeAttachment
    Properties:
      Device: !Sub "/dev/sd${DeviceNameSuffix}"
      InstanceId: !Ref Instance1
      VolumeId: !Ref EBS1
Code language: YAML (yaml)

InstanceIdおよびVolumeIdプロパティでインスタンスとアタッチするEBSを指定します。

DeviceプロパティでEBSに割り当てるデバイス名を指定します。
Linux AMIにおけるデバイス名は、仮想化タイプによって取り得る値が定まります。
先述の通り、今回の2インスタンスのAMIはどちらもhvmタイプです。
hvmのルート用、あるいは推奨されるデバイス名は以下の通りです。

ルート用に予約済み:/dev/sda1 or /dev/xvda
EBS ボリュームとして推奨:/dev/sd[f-p]

Linux インスタンス上のデバイス名

よって今回は2つのEBSに対して、デバイス名に「/dev/sdf」を指定します。

SSM Session Managerを使用してアクセスすればキーペアの設定は不要

Linuxインスタンスにアクセスする方法は、キーペアを使用したSSHが一般的ですが、今回はSSM Session Managerを使用します。
今回の構成では、インスタンスはプライベートサブネットに設置されているため、SSM用VPCエンドポイントを通じて、SSMにアクセスする形となります。詳細は以下のページをご確認ください。

あわせて読みたい
LinuxインスタンスにSSM Session Manager経由でアクセスする 【LinuxインスタンスにSSM Session Manager経由でアクセスする】 EC2インスタンスにSSM Session Manager経由でアクセスする構成を確認します。 Session Manager は完全...

SSMドキュメントを使ってEBSを使用可能にする

後ほどEBSを使用可能にするコマンドをご紹介しますが、コマンドを手動で実行するだけでなく、SSMドキュメントを通して実行することもできます。

Resources:
  RunShellScriptAssociation:
    Type: AWS::SSM::Association
    Properties:
      AssociationName: !Sub "${Prefix}-run-shellscript-association"
      Name: AWS-RunShellScript
      Parameters:
        commands:
          - !Sub |
            for d in $(lsblk -n -r -p | grep disk | awk '{ print $1 }' )
            do
              if  [ "$(sudo file -s -b $d)" == data ]; then
                sudo mkfs -t xfs $d
                sudo mkdir ${MountPoint}
                sudo mount $d ${MountPoint}
              fi
            done
      Targets:
        - Key: InstanceIds
          Values:
            - !Ref Instance
      WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds
Code language: YAML (yaml)

SSMドキュメントAWS-RunShellScriptを使用することで、Linuxインスタンス(Amazon Linux 2)に対して、指定したコマンドを実行することができます。
詳細は後ほど確認します。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

EBSのアタッチ状況を確認する1

AWS Management Consoleから各インスタンスの状況を確認します。
代表して、インスタンス1と2を取り上げます。

EBS is attached to the Block Device Mapping of the instance 1.
EBS is attached to the Block Device Mapping of the instance 2.

両インスタンスのBlock devicesの項目を見ると、2つずつEBSがアタッチされていることが確認できます。
「dev/xvda」の方はルートデバイスです。先述の通り、このデバイス名はルート用として予約されています。
もう一方の「/dev/sdf」が今回作成したEBSです。

EBSのアタッチ状況を確認する2:Nitro System上ではないインスタンスの場合

次に実際にインスタンスにアクセスして、EBSのアタッチ状況を確認します。
まずInstance1(i-00f95cd8419e73461)にアクセスします。
インスタンスへのアクセスはSSM Session Managerを使用します。

$ aws ssm start-session \
--target i-00f95cd8419e73461
...
sh-4.2$
Code language: Bash (bash)

lsblkコマンドでブロックデバイスの状況を確認することができます。

sh-4.2$ lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0   8G  0 disk
└─xvda1 202:1    0   8G  0 part /
xvdf    202:80   0   1G  0 disk 
Code language: Bash (bash)

「xvda」と「xvdf」という2つのブロックデバイスが認識されていることがわかります。
先ほど確認した通り、前者はルートデバイスです。
後者は今回アタッチしたEBSです。デバイス名がCloudFormationテンプレートで指定したもの(/dev/sdf)から変更されています。これはEBSの仕様によるものです。

カーネルのブロックデバイスドライバによっては、指定した名前とは異なる名前でデバイスがアタッチされる可能性があります。たとえば、デバイス名 (/dev/sdh) を指定した場合、デバイスの名前が /dev/xvdh や /dev/hdh に変更される場合があります。ほとんどの場合、末尾の文字は変更されません。

デバイス名に関する考慮事項

以上より、EBSアタッチ時に指定したデバイス名と、インスタンス側で認識しているデバイス名が異なる場合があることがわかりました。

EBSのアタッチ状況を確認する3:Nitro System上のインスタンスの場合

次にInstance2(i-03f376aac4fcc98ab)にアクセスしてEBSのアタッチ状況を確認します。

$ aws ssm start-session \
--target i-03f376aac4fcc98ab
...
sh-4.2$
Code language: Bash (bash)
sh-4.2$ lsblk
NAME          MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0   8G  0 disk
├─nvme0n1p1   259:1    0   8G  0 part /
└─nvme0n1p128 259:2    0  10M  0 part /boot/efi
nvme1n1       259:3    0   1G  0 disk
Code language: Bash (bash)

「nvme0n1」と「nvme1n1」という2つのブロックデバイスが認識されていることがわかります。これはNitro System上のインスタンスにおける仕様によるものです。

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

Amazon EBS および Linux インスタンス上の NVMe

Instance2に指定したインスタンスタイプはT4gですが、これはNitro System上で動作するタイプです。

以下のインスタンスが Nitro System に基づいています。
仮想化: A1, C5, C5a, C5ad, C5d, C5n, C6g, C6gd, C6gn, D3, D3en, G4, I3en, Inf1, M5, M5a, M5ad, M5d, M5dn, M5n, M5zn, M6g, M6gd, M6i, p3dn.24xlarge, P4, R5, R5a, R5ad, R5b, R5d, R5dn, R5n, R6g, R6gd, T3, T3a, T4g, ハイメモリ (u-*), X2gd, および z1d

インスタンスタイプ

以上より、「nvme0n1」がルートデバイス、「nvme1n1」がアタッチしたEBSです。

アタッチしたEBSを使用可能な状態にするまでの手順

引き続きInstance2で以降の手順の確認を進めます。

アタッチ以降の手順は、AWS公式サイト「Linux で Amazon EBS ボリュームを使用できるようにする」で取り上げられていますが、まとめると以下の流れになります。

  1. ファイルシステムを作成する
  2. マウントポイントを作成し、ボリュームをマウントする

実際に行います。
まずmkfsコマンでファイルシステムを作成します。

sh-4.2$ sudo mkfs -t xfs /dev/nvme1n1
meta-data=/dev/nvme1n1           isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=0
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
Code language: Bash (bash)

作成するファイルシステムはXFSを指定しました。

次にmkdirコマンドでマウントポイントを作成後、mountコマンドでボリュームをマウントします。

sh-4.2$ sudo mkdir /data
sh-4.2$ sudo mount /dev/nvme1n1 /data
Code language: Bash (bash)

改めてlsblkコマンドで状況を確認します。

sh-4.2$ lsblk -f
NAME          FSTYPE LABEL UUID                                 MOUNTPOINT
nvme0n1
├─nvme0n1p1   xfs    /     9e2f3182-7352-4382-adbd-c67f6be433ed /
└─nvme0n1p128 vfat         2EE0-5AE9                            /boot/efi
nvme1n1       xfs          5c851eca-35be-4d6a-a4e8-e10c1efed050 /data
Code language: Bash (bash)

ファイルシステムやマウントポイントを確認することができます。

試しにファイルを書き込みます。

sh-4.2$ cd /data
sh-4.2$ sudo touch test.txt
sh-4.2$ ls
test.txt
Code language: Bash (bash)

マウントポイントにアクセスし、ファイルを設置することができました。

このようにEBSをアタッチ後、ファイルシステムを作成し、マウントすることによって、通常のストレージと同様に使用可能であることがわかりました。

再起動時に自動的にEBSをマウントする方法

自動的にEBSボリュームをマウントする方法を確認します。
公式サイトでは、/etc/fstabを編集する方法が紹介されています。同ファイルをvim等のエディタで開き、以下の通り編集します。

sh-4.2$ sudo vim /etc/fstab
sh-4.2$ cat /etc/fstab
#
UUID=9e2f3182-7352-4382-adbd-c67f6be433ed     /           xfs    defaults,noatime  1   1
UUID=2EE0-5AE9        /boot/efi       vfat    defaults,noatime,uid=0,gid=0,umask=0077,shortname=winnt 0 0
UUID=5c851eca-35be-4d6a-a4e8-e10c1efed050     /data       xfs    defaults,nofail   0   2
Code language: Bash (bash)

3行目が該当箇所です。lsblkコマンドで確認したUUIDを指定して、マウントポイント(/data)に自動的にマウントするように記述します。

設定の正常性の確認ですが、以下の手順で確認することができます。

  1. EBSボリュームをアンマウントする
  2. /etc/fstabに従って全ボリュームをマウントする
  3. マウントポイントにアクセスする

エラーなく最後まで辿り着けば成功と言えます。

sh-4.2$ sudo umount /data
sh-4.2$ sudo mount -a
sh-4.2$ ls /data
test.txt
Code language: Bash (bash)

正常に最後まで進むことができました。
これで再起動後も自動的にEBSボリュームがマウントされるようになりました。

SSMドキュメントを使用してEBSをマウントする

最後にSSMドキュメントAWS-RunShellScriptを使用して、Linuxインスタンス(Amazon Linux 2)において、自動的にEBSを使用できる状態に設定する方法をご紹介します。
改めて以下に実行するシェルスクリプトを記載します。

- !Sub |
  for d in $(lsblk -n -r -p | grep disk | awk '{ print $1 }' )
  do
    if  [ "$(sudo file -s -b $d)" == data ]; then
      sudo mkfs -t ${FileSystem} $d
      sudo mkdir ${MountPoint}
      sudo mount $d ${MountPoint}

      uuid=$(sudo blkid $d -o export | grep ^UUID)
      echo -e "$uuid\t/data\t${FileSystem}\tdefaults,nofail\t0\t2" >> /etc/fstab
    fi
  done
Code language: YAML (yaml)

スクリプトの内容は先述の通りですが、一応簡単に解説します。

  1. lsblkコマンドを実行して、TYPEがdiskのデバイス名を取得する。
  2. fileコマンドで各デバイスの情報を確認し、「data」のものをEBSで、かつ未処理のデバイスと見做して処理を進める。
  3. ファイルシステム作成後、EBSをマウントする。
  4. 自動マウント設定のために、UUIDを取得して、/etc/fstabに追記する。

CloudFormationスタック作成時に、自動的に本スクリプトが実行されます。

SSM Document Result.

インスタンス3にアクセスし、スクリプトが正常に動作したかを確認します。

% aws ssm start-session \
--target i-0bbda6e4d4e4bcdc3
...
sh-4.2$

sh-4.2$ lsblk
NAME          MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0   8G  0 disk
├─nvme0n1p1   259:1    0   8G  0 part /
└─nvme0n1p128 259:2    0  10M  0 part /boot/efi
nvme1n1       259:3    0   1G  0 disk /data
Code language: Bash (bash)

EBSにファイルシステムが作成され、正常にマウントされていることがわかります。

自動マウントに関する設定を確認します。

sh-4.2$ cat /etc/fstab
#
UUID=b2d2af18-472e-4a07-a7f5-313592c907b9     /           xfs    defaults,noatime  1   1
UUID=7882-6D24        /boot/efi       vfat    defaults,noatime,uid=0,gid=0,umask=0077,shortname=winnt 0 0
UUID=a38658f8-ad51-417d-b7a7-4d865bd500b9	/data	xfs	defaults,nofail	0	2

sh-4.2$ sudo umount /data

sh-4.2$ lsblk
NAME          MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0   8G  0 disk
├─nvme0n1p1   259:1    0   8G  0 part /
└─nvme0n1p128 259:2    0  10M  0 part /boot/efi
nvme1n1       259:3    0   1G  0 disk

sh-4.2$ sudo mount -a

sh-4.2$ lsblk
NAME          MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0   8G  0 disk
├─nvme0n1p1   259:1    0   8G  0 part /
└─nvme0n1p128 259:2    0  10M  0 part /boot/efi
nvme1n1       259:3    0   1G  0 disk /data
Code language: Bash (bash)

/etc/fstabにEBS情報が書き込まれ、それに基づいてマウントされることが確認できました。

まとめ

CloudFormationでEC2インスタンスにEBSをアタッチする方法を確認しました。
アタッチしたEBSを使用可能な状態にするまでの手順と、自動的にマウントする手順を確認しました。
SSMドキュメントを使用し、自動的にEBSを使用可能な状態に設定する方法をご紹介しました。