0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

UEFIブートのx86_64 Ubuntu AMIを作成する

Last updated at Posted at 2022-05-08

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になっている可能性があります。
(ap-northeast-1 Ubuntu 22.04 x86_64 Image
利用したい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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?