x86_64のEC2インスタンスは通常BIOSを利用しますが、UEFIも利用できます。ところがAWSはx86_64向けにUEFIベースのAMIを提供しておらず、ディストリビューションが提供する公式AMIもBIOSベースです。Ubuntu, Debian, CentOSなどいずれもUEFIイメージを提供しておらず、おそらく公式にUEFIベースで提供しているディストリビューションは存在しない模様です。
UEFIイメージを使うメリットはAWS外にあるUEFI VMからの移行が楽な点、SecureBootが利用できる点、TPMが利用できる点です。
現状SecureBoot対応のAMIが公開されていないため、SecureBootに対応させるには手間がかかります。現時点ではUEFIを使っていたサーバからの移行支援機能と扱われているようです。
先述の通りUEFIモードのAMIは非常にレアなので、x86_64でUEFIを使うには自分でAMIを作成する必要があります。
普通AMIを作成するときはAWS CLIのcreate-imageコマンドを利用しますが、create-imageコマンドは作成元イメージの起動モードを引き継ぎます。つまりBIOSモードのイメージからcreate-imageを実行すると、引き続きBIOSモードのイメージになります。
UEFIモードのイメージを作るには、register-imageでEBSスナップショットからAMIに変換します。この方法によるイメージ作成はPackerのEBS Surrogateビルダーなどを使いますが、OSイメージを一から作るのは手間がかかるので、Ubuntu公式AMIのEBSスナップショットを流用する方法を紹介します。
Ubuntu 22.04公式AMIはUEFI用の設定がすでに入っているため、モードを切り替えるだけで動作しますが、必ずしもすべてのAMIでできるわけではないので注意してください。例えばUbuntu20.04の公式イメージはモードを切り替えると起動しなくなります。
Ubuntu AMIのEBSスナップショットIDを調べる
Amazon EC2 AMI LocatorからベースにしたいUbuntu AMIのAMI-IDを探します。ここでは東京リージョンのUbuntu 22.04イメージ(ami-081ce1b631be2b337)を利用します。なお、AMIは随時更新されるので、現在は異なるami-idになっている可能性があります。
(
利用したいAMIにdescribe-imagesを実行し、パラメータを確認します。
$ aws ec2 describe-images --image-ids ami-081ce1b631be2b337
{
"Images": [
{
"Architecture": "x86_64",
"CreationDate": "2022-04-21T14:55:23.000Z",
"ImageId": "ami-081ce1b631be2b337",
"ImageLocation": "099720109477/ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-20220420",
"ImageType": "machine",
"Public": true,
"OwnerId": "099720109477",
"PlatformDetails": "Linux/UNIX",
"UsageOperation": "RunInstances",
"State": "available",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/sda1",
"Ebs": {
"DeleteOnTermination": true,
"SnapshotId": "snap-056cc90ae7df4ae18",
"VolumeSize": 8,
"VolumeType": "gp2",
"Encrypted": false
}
},
{
"DeviceName": "/dev/sdc",
"VirtualName": "ephemeral1"
},
{
"DeviceName": "/dev/sdb",
"VirtualName": "ephemeral0"
}
],
"Description": "Canonical, Ubuntu, 22.04 LTS, amd64 jammy image build on 2022-04-20",
"EnaSupport": true,
"Hypervisor": "xen",
"Name": "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-20220420",
"RootDeviceName": "/dev/sda1",
"RootDeviceType": "ebs",
"SriovNetSupport": "simple",
"VirtualizationType": "hvm",
"DeprecationTime": "2024-04-21T14:55:23.000Z"
}
]
}
実行すると、このようにBlockDeviceMappingsから/dev/sda1がEBSスナップショット(snap-056cc90ae7df4ae18)から生成されることがわかります。
/dev/sdb, /dev/sdcはインスタンスストアの設定です。
スナップショットのコピー
このスナップショットをベースにregister-imageすれば、UEFI AMIが作成できます。ただし、他アカウントが保有するスナップショットからAMIを作ることはできないので、まずcopy-snapshotで自分のアカウントにコピーします。
$ aws ec2 copy-snapshot --source-snapshot-id snap-056cc90ae7df4ae18 --source-region ap-northeast-1 --destination-region ap-northeast-1
{
"SnapshotId": "snap-xxx"
}
AMIの作成
スナップショットをコピーしたら、register-imageでこのスナップショットからAMIを作成します。architectureでx86_64を指定するのを忘れないようにしましょう。architecureのデフォルト値はi386のため、起動できないイメージになってしまいます。
追記:NitroTPMがリリースされました。AMIビルド時のパラメータに--tpm-support v2.0を追加するとTPMが有効化されたAMIが作成されます。
$ aws ec2 register-image --name jammy-uefi-image --root-device-name /dev/sda1 --block-device-mappings DeviceName=/dev/sda1,Ebs={SnapshotId=snap-xxx} DeviceName=/dev/sdb,VirtualName=ephemeral0 DeviceName=/dev/sdc,VirtualName=ephemeral1 --ena-support --sriov-net-support simple --virtualization-type hvm --boot-mode uefi --architecture x86_64
{
"ImageId": "ami-xxx"
}
作成したイメージにdescribe-imagesを実行してみると、確かにuefiモードになっていることが確認できます。
$ aws ec2 describe-images --image-ids ami-xxx
{
"Images": [
{
"Architecture": "x86_64",
"CreationDate": "2022-05-08T04:08:51.000Z",
"ImageId": "ami-xxx",
"ImageLocation": "xxx/jammy-uefi-image",
"ImageType": "machine",
"Public": false,
"OwnerId": "xxx",
"PlatformDetails": "Linux/UNIX",
"UsageOperation": "RunInstances",
"State": "available",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/sda1",
"Ebs": {
"DeleteOnTermination": true,
"SnapshotId": "snap-xxx",
"VolumeSize": 8,
"VolumeType": "gp2",
"Encrypted": false
}
},
{
"DeviceName": "/dev/sdb",
"VirtualName": "ephemeral0"
},
{
"DeviceName": "/dev/sdc",
"VirtualName": "ephemeral1"
}
],
"EnaSupport": true,
"Hypervisor": "xen",
"Name": "jammy-uefi-image",
"RootDeviceName": "/dev/sda1",
"RootDeviceType": "ebs",
"SriovNetSupport": "simple",
"VirtualizationType": "hvm",
"BootMode": "uefi"
}
]
}
実際にこのイメージでEC2を起動してみますと、UEFI関連のパラメータが取得できます。
$ sudo /usr/bin/efibootmgr
BootCurrent: 0001
Timeout: 0 seconds
BootOrder: 0002,0000,0001
Boot0000* UiApp
Boot0001* UEFI Amazon Elastic Block Store volxxx 1
Boot0002* ubuntu
$ efivar -l
605dab50-e046-4300-abb6-3dd810dd8b23-SbatLevelRT
605dab50-e046-4300-abb6-3dd810dd8b23-MokListXRT
605dab50-e046-4300-abb6-3dd810dd8b23-MokListRT
8be4df61-93ca-11d2-aa0d-00e098032b8c-BootOrder
8be4df61-93ca-11d2-aa0d-00e098032b8c-Boot0002
8be4df61-93ca-11d2-aa0d-00e098032b8c-BootCurrent
8be4df61-93ca-11d2-aa0d-00e098032b8c-Boot0001
8be4df61-93ca-11d2-aa0d-00e098032b8c-ErrOutDev
8be4df61-93ca-11d2-aa0d-00e098032b8c-ConInDev
8be4df61-93ca-11d2-aa0d-00e098032b8c-Key0001
8be4df61-93ca-11d2-aa0d-00e098032b8c-Key0000
8be4df61-93ca-11d2-aa0d-00e098032b8c-ConOutDev
8be4df61-93ca-11d2-aa0d-00e098032b8c-ErrOut
8be4df61-93ca-11d2-aa0d-00e098032b8c-ConOut
8be4df61-93ca-11d2-aa0d-00e098032b8c-ConIn
7c436110-ab2a-4bbb-a880-fe41995c9f82-csr-active-config
7c436110-ab2a-4bbb-a880-fe41995c9f82-boot-args
4d1ede05-38c7-4a6a-9cc6-4bcca8b38c14-FirmwareFeaturesMask
4d1ede05-38c7-4a6a-9cc6-4bcca8b38c14-FirmwareFeatures
4d1ede05-38c7-4a6a-9cc6-4bcca8b38c14-BackgroundClear
8be4df61-93ca-11d2-aa0d-00e098032b8c-PlatformRecovery0000
8be4df61-93ca-11d2-aa0d-00e098032b8c-PlatformLang
8be4df61-93ca-11d2-aa0d-00e098032b8c-Lang
8be4df61-93ca-11d2-aa0d-00e098032b8c-PlatformLangCodes
8be4df61-93ca-11d2-aa0d-00e098032b8c-LangCodes
8be4df61-93ca-11d2-aa0d-00e098032b8c-BootOptionSupport
8be4df61-93ca-11d2-aa0d-00e098032b8c-Timeout
8be4df61-93ca-11d2-aa0d-00e098032b8c-OsIndicationsSupported
8be4df61-93ca-11d2-aa0d-00e098032b8c-Boot0000
eb704011-1402-11d3-8e77-00a0c969723b-MTC
8be4df61-93ca-11d2-aa0d-00e098032b8c-X-Nitro-SecurebootStatus
e20939be-32d4-41be-a150-897f85d49829-MemoryOverwriteRequestControl
c076ec0c-7028-4399-a072-71ee5c448b9f-CustomMode
8be4df61-93ca-11d2-aa0d-00e098032b8c-DeployedMode
f0a30bc7-af08-4556-99c4-001009c93a44-SecureBootEnable
8be4df61-93ca-11d2-aa0d-00e098032b8c-SetupMode
8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot
8be4df61-93ca-11d2-aa0d-00e098032b8c-X-Nitro-BootServicesExited
X-Nitro-SecurebootStatusという変数もありますが、今のところ中身は0です。NitroTPMがリリースされたタイミングで、SecureBootも利用可能になるものと思われます。
Deep dive into NitroTPM and UEFI Secure Boot support in Amazon EC2
$ efivar --print -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-X-Nitro-SecurebootStatus
GUID: 8be4df61-93ca-11d2-aa0d-00e098032b8c
Name: "X-Nitro-SecurebootStatus"
Attributes:
Boot Service Access
Runtime Service Access
Value:
00000000 00 00 00 00 00 00 00 00 |........ |
UEFI未対応のインスタンスタイプ
x86系インスタンスの対応状況は以下の通りです。Nitro世代の仮想インスタンスは基本的に概ね対応します。armインスタンスの記載はありませんが、armインスタンスは必ずUEFIを使います。
表記上わかりにくいのですが、ベアメタルインスタンスはUEFIモードに対応していません。(インスタンスファミリー一覧の頭にVirtualizedとあるのはそのため)
そんなに使わないとは思いますが、ベアメタルインスタンスを利用する可能性があるなら、現時点ではUEFIモードのAMIを避けておくほうがよいでしょう。
Boot modes
Intel and AMD instance types that support UEFI, in addition to Legacy BIOS:
Virtualized: C5, C5a, C5ad, C5d, C5n, D3, D3en, G4, I3en, M5, M5a, M5ad, M5d, M5dn, M5n, M5zn, M6i, R5, R5a, R5ad, R5b, R5d, R5dn, R5n, T3, T3a, and z1d
NitroTPM未対応のインスタンスタイプ
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm-instance.html#launch-instance-with-nitrotpm
記載がありますが、現時点ではUEFI対応していてもNitroTPMに対応しないタイプが複数あります。特にt3シリーズには未対応なので注意してください。
また今のところarmインスタンスでは利用できません。個人的にはエントロピーの少ないGravitonではTPMを乱数生成器にしたかったので残念でした。そのうち実装されると思うので楽しみに待っています。
SecureBootの注意点
NitroTPMを有効化してもただちにSecureBootが有効になるわけではありません。SecureBoot対応AMIを使うならよいのですが、今のところ対応AMIは提供されていないので、自分でSecureBoot用の鍵を生成しAMIに同梱する必要があります。ドキュメントはありますが、かなり面倒で手間がかかります。いずれSecureBoot対応AMIが増えてくると思うので、急いでいなければ待った方がいいかもしれません。
おまけ
UEFI対応AMIに変換するスクリプトを書きました。
https://github.com/bateleurX/generate_uefi_ami