

 **このページの改善にご協力ください** 

このユーザーガイドに貢献するには、すべてのページの右側のペインにある「**GitHub でこのページを編集する**」リンクを選択してください。

# Amazon EKS 用のカスタム Bottlerocket AMI バリアントを構築する
<a name="bottlerocket-custom-variant"></a>

Amazon Elastic Kubernetes Service (Amazon EKS) で GPU ワークロードを実行する場合は、Bottlerocket バリアントを選択します。バリアントは、Kubernetes バージョンとアクセラレータータイプと一致する必要があります。Bottlerocket は、一般的な設定用に検証済みバリアントを提供します。ただし、次のいずれかの理由により、組織で別のバリアントが必要になる可能性があります:
+ 新しい NVIDIA ドライバーブランチ
+ 規制コンプライアンスのためのピン留めされたドライバーバージョン
+ モニタリング用の追加パッケージ
+ セキュリティチームが必要とする強化されたベースライン

GitHub ウェブサイトの [Bottlerocket](https://github.com/bottlerocket-os/bottlerocket) は完全なオープンソースであるため、これらのニーズを満たすカスタムバリアントを作成できます。このトピックでは、既存のバリアントのクローンを作成し、NVIDIA ドライバーを R580 ブランチから R595 (バージョン 595.71.05) にスワップする方法について説明します。次に、イメージを構築し、それをプライベート AMI として登録します。

**重要**  
G7 EC2 インスタンスタイプには NVIDIA ドライバーバージョン 595 以降が必要です。EKS Bottlerocket NVIDIA AMI には現在、G7 インスタンスをサポートしていない NVIDIA ドライバーバージョン 580 が含まれています。  
NVIDIA ドライバーバージョン 595 でバリアントを構築する手順については、GitHub ウェブサイトの「[Bottlerocket リポジトリ](https://github.com/bottlerocket-os/bottlerocket)」を参照してください。このトピックでは、[ステップ 1](#bottlerocket-custom-variant-step1) から始まる完全なプロセスについて説明します。

## ビルドシステムの仕組み
<a name="bottlerocket-custom-variant-build-system"></a>

`cargo make -e BUILDSYS_VARIANT=aws-k8s-1.36-nvidia` を実行すると、次の 3 つのことが発生します:
+  **依存関係を取得する。**Twoliter (Bottlerocket ビルドオーケストレーター) は `Twoliter.toml` を読み取り、`public.ecr.aws/bottlerocket` から 3 つの Open Container Initiative (OCI) アーティファクトをプルします:
  +  **bottlerocket-sdk** – 完全なクロスコンパイルツールチェーン (GCC、Rust、Go、RPM マクロ) を持つコンテナイメージ。
  +  **bottlerocket-kernel-kit** – カーネル、カーネルモジュール (NVIDIA kmod パッケージを含む)、およびファームウェア用の構築済み RPM。
  +  **bottlerocket-core-kit** – ユーザースペース用の構築済み RPM: kubelet、containerd、NVIDIA デバイスプラグインとコンテナツールキット、設定プラグイン、システムサービス。

     `Twoliter.toml` はバージョンをピン留めし、`Twoliter.lock` はダイジェストをロックします。いずれかを変更するには、`./tools/twoliter/twoliter update` を実行して再解決します。
+  **バリアントを構築する。**Twoliter は SDK コンテナ内で Docker ビルドを起動します。バリアントの設定デフォルトクレートをコンパイルし、キットから RPM 依存関係ツリーを解決し、すべてをディスクイメージにアセンブルします。
+  **出力する。**Twoliter は最終 `.img.lz4` ファイルを `build/images/` に書き込みます。ビルドは決定論的な出力を生成します: ホストに関係なく、同じ `Twoliter.toml` ピンとバリアント `Cargo.toml` は常に同じイメージを生成します。

## リポジトリレイアウト
<a name="bottlerocket-custom-variant-repo-layout"></a>

次のディレクトリはバリアント作業に関連しています:

```
bottlerocket/
├── Cargo.toml                       # workspace: lists every variant
├── Twoliter.toml                    # pins SDK + kit versions
├── Twoliter.lock                    # locked digests for the above
├── Licenses.toml                    # you create this (NVIDIA license acknowledgement)
├── Infra.toml                       # you create this (AMI publish regions)
│
├── variants/
│   ├── aws-k8s-1.36-nvidia/         # example variant you'll copy
│   │   ├── Cargo.toml               #   package list + kernel params
│   │   └── amispec.toml             #   symlink → ../shared/amispec-split.toml
│   └── shared/                      # shared AMI spec templates
│
├── sources/
│   ├── Cargo.toml                   # workspace: lists every settings-defaults crate
│   ├── shared-defaults/             # the actual defaults (symlink targets)
│   └── settings-defaults/
│       └── aws-k8s-1.36-nvidia/
│           ├── Cargo.toml
│           └── defaults.d/          # 30+ symlinks into shared-defaults/
│
└── packages/
    ├── settings-defaults/
    │   └── settings-defaults.spec   # RPM: declares which variants exist
    └── settings-plugins/
        └── settings-plugins.spec    # RPM: maps variants to settings plugins
```

リポジトリ構造に関する次の注意事項をレビューします:
+ バリアントは主にメタデータです。外部キットは、カーネル、ドライバー、ユーザースペースを提供します。
+ Settings-defaults ファイルは、コピーではなくシンボリックリンクです。`cp -R` (macOS の `cp -r` ではなく) を使用してそれらを保持します。
+ バリアントを追加するには、次の 5 つの場所で編集する必要があります: 2 つのワークスペース `Cargo.toml` ファイル、2 つの `.spec` ファイル、および `README.md`。

## 前提条件
<a name="bottlerocket-custom-variant-prereqs"></a>

このチュートリアルを完了するには、以下が必要になります:
+ EC2 インスタンスを起動して AMI を登録するアクセス許可を持つ AWS アカウント
+ 少なくとも 8 コア、16 GiB メモリ、および 150 GB ディスクを持つ EC2 インスタンス (または同等の Linux x86\_64 ホスト)
+ Ubuntu 24.04 LTS (または Fedora。macOS はビルドホストとしてサポートされていません)
+ Docker 20.10 以降
+ Rust (安定ツールチェーン、rustup 経由でインストールされている)
+ cargo-make (最新バージョン)
+ Git、Rust の Cargo、RPM パッケージングの概念に精通していること

**注記**  
このチュートリアルを完了したら、EC2 インスタンスを終了し、継続的な料金が発生しないよう不要になった AMI を登録解除します。クリーンアップ手順については、[クリーンアップ](#bottlerocket-custom-variant-cleanup) を参照してください。

## ステップ 1: ビルドホストを準備する
<a name="bottlerocket-custom-variant-step1"></a>

EC2 インスタンスを起動します – 例えば、`c7i.8xlarge` (32 vCPU、64 GiB メモリ)。150 GB の gp3 ルートボリュームを使用し、SSM アクセス用の `AmazonSSMManagedInstanceCore` マネージドポリシーをアタッチします。

AWS Systems Manager (SSM) Session Manager を使用してインスタンスに接続します:

```
aws ssm start-session --target <instance-id>
cd ~
```

必要なオペレーティングシステムパッケージをインストールします:

```
apt-get update
apt-get install -y build-essential openssl libssl-dev pkg-config lz4 \
                   git ca-certificates curl gnupg
```

**注記**  
公式の `BUILDING.md` は `liblz4-tool` を参照します。最近の Ubuntu バージョンでは、パッケージは `lz4` という名前です。

次のコマンドを使用して Docker をインストールします:

```
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/ubuntu noble stable" \
  > /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin
systemctl enable --now docker
```

次のコマンドを使用して Rust と cargo-make をインストールします:

```
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
. "$HOME/.cargo/env"
cargo install cargo-make
```

## ステップ 2: リポジトリのクローンを作成する
<a name="bottlerocket-custom-variant-step2"></a>

GitHub ウェブサイトの [Bottlerocket リポジトリ](https://github.com/bottlerocket-os/bottlerocket)のクローンを作成し、ディレクトリに移動します:

```
cd ~/bottlerocket
```

再現可能なビルドを作成するには、タグ付けされたリリース (`git checkout v1.62.1` など) をチェックアウトします。最新のパッケージを使用するには、`develop` ブランチに留まります。

## ステップ 3: キットのバージョンを確認する
<a name="bottlerocket-custom-variant-step3"></a>

`Twoliter.toml` を開き、キットのバージョンを確認します。R595 をサポートするには、`bottlerocket-kernel-kit` バージョン 6.2.2 以降が必要です。

```
[[kit]]
name = "bottlerocket-kernel-kit"
version = "6.2.2"
vendor = "bottlerocket"
```

バージョンが古い場合は、更新してロックを再生成します:

```
./tools/twoliter/twoliter update
```

## ステップ 4: cargo-make パスの問題を回避する
<a name="bottlerocket-custom-variant-step4"></a>

Twoliter は `CARGO_HOME` を `~/bottlerocket/.cargo` に設定します。これにより、内部の Cargo プロセスが、グローバルにインストールされた cargo-make を検索できなくなります。シンボリックリンクを作成します。

```
mkdir -p ~/bottlerocket/.cargo/bin
ln -sf /root/.cargo/bin/cargo-make ~/bottlerocket/.cargo/bin/cargo-make
```

このステップを行わないと、ビルドは `error: no such command: make` で失敗します。

## ステップ 5: 使用可能なドライバーブランチを検索する
<a name="bottlerocket-custom-variant-step5"></a>

NVIDIA kmod パッケージは `bottlerocket-kernel-kit` 内に含まれています。使用可能なドライバーパッケージの詳細については、GitHub ウェブサイトの「[kernel-kit パッケージディレクトリ](https://github.com/bottlerocket-os/bottlerocket-kernel-kit)」、または GitHub ウェブサイトの「[リリースノート](https://github.com/bottlerocket-os/bottlerocket-kernel-kit/releases)」を参照してください。

カーネル 6.18 (`aws-k8s-1.36` バリアントで使用) の場合:

```
kmod-6.18-nvidia-r580   ← driver 580.159.03 (current default)
kmod-6.18-nvidia-r595   ← driver 595.71.05
```

カーネル 6.12 (`aws-k8s-1.33`、`1.34`、`1.35` で使用) の場合:

```
kmod-6.12-nvidia-r580
kmod-6.12-nvidia-r595
```

**注記**  
各 kmod パッケージにはサブパッケージ (`-tesla`、`-open-gpu`、`-grid`、`-fabricmanager`、`-imex`) が含まれています。公式 Bottlerocket NVIDIA バリアントは `-tesla` を参照します。これは、RPM 依存関係を介して必要なすべてのサブパッケージをプルします。起動時に、Bottlerocket はインスタンスタイプに基づいて適切なドライバーフレーバーを自動的に選択します。

## ステップ 6: 新しいバリアントを作成する
<a name="bottlerocket-custom-variant-step6"></a>

既存のバリアントをコピーします。シンボリックリンクを保持するには、`cp -R` を使用します:

```
cp -R variants/aws-k8s-1.36-nvidia variants/aws-k8s-1.36-nvidia-595
cp -R sources/settings-defaults/aws-k8s-1.36-nvidia \
      sources/settings-defaults/aws-k8s-1.36-nvidia-595
```

`variants/aws-k8s-1.36-nvidia-595/Cargo.toml` を編集します:

```
- name = "aws-k8s-1_36-nvidia"
+ name = "aws-k8s-1_36-nvidia-595"

- "kmod-6.18-nvidia-r580-tesla",
+ "kmod-6.18-nvidia-r595-tesla",
```

`sources/settings-defaults/aws-k8s-1.36-nvidia-595/Cargo.toml` を編集します:

```
- name = "settings-defaults-aws-k8s-1_36-nvidia"
+ name = "settings-defaults-aws-k8s-1_36-nvidia-595"
```

## ステップ 7: バリアントを登録する
<a name="bottlerocket-custom-variant-step7"></a>

新しいバリアントを 5 つのファイルに登録します:

 **1. `Cargo.toml` ** – ワークスペースメンバーを追加します:

```
 "variants/aws-k8s-1.36-nvidia",
+    "variants/aws-k8s-1.36-nvidia-595",
 "variants/aws-k8s-1.36-nvidia-fips",
```

 **2. `sources/Cargo.toml` ** – settings-defaults メンバーを追加します:

```
 "settings-defaults/aws-k8s-1.36-nvidia",
+    "settings-defaults/aws-k8s-1.36-nvidia-595",
```

 **3. `packages/settings-defaults/settings-defaults.spec` ** – `%package` ブロック、両方のビルドループのエントリ、および `%files` セクションを追加します:

```
%package aws-k8s-1.36-nvidia-595
Summary: Settings defaults for the aws-k8s 1.36 nvidia-595 variant
Requires: %{_cross_os}variant(aws-k8s-1.36-nvidia-595)
Provides: %{_cross_os}settings-defaults(any)
Provides: %{_cross_os}settings-defaults(aws-k8s-1.36-nvidia-595)
Conflicts: %{_cross_os}settings-defaults(any)

%description aws-k8s-1.36-nvidia-595
%{summary}.
```

両方の `for defaults in` ループに追加します:

```
    aws-k8s-1.36-nvidia \
+   aws-k8s-1.36-nvidia-595 \
    metal-dev \
```

`%files` セクションを追加します:

```
%files aws-k8s-1.36-nvidia-595
%{_cross_defaultsdir}/aws-k8s-1.36-nvidia-595.toml
%{_cross_tmpfilesdir}/storewolf-defaults-aws-k8s-1.36-nvidia-595.conf
```

 **4. `packages/settings-plugins/settings-plugins.spec` ** – `%package aws-k8s-nvidia` の下に `Provides:` 行を追加します:

```
 Provides: %{_cross_os}settings-plugin(aws-k8s-1.36-nvidia)
+Provides: %{_cross_os}settings-plugin(aws-k8s-1.36-nvidia-595)
 Conflicts: %{_cross_os}settings-plugin(any)
```

## ステップ 8: ロックファイルを更新する
<a name="bottlerocket-custom-variant-step8"></a>

ワークスペースメンバーを追加すると、`sources/Cargo.lock` が無効になります。それを更新します:

```
cd ~/bottlerocket/sources
cargo update --workspace
```

**重要**  
`cargo generate-lockfile` を使用しないでください。これにより、ロックファイル全体が書き換えられ、推移的な依存関係がバンプされ、`cargo-deny` バージョンが重複するエラーが発生します。

## ステップ 9: NVIDIA ライセンスファイルを作成する
<a name="bottlerocket-custom-variant-step9"></a>

NVIDIA はドライバーソースの再配布を制限します。以下を構築する前に、明示的なライセンス確認を追加する必要があります:

```
cat > ~/bottlerocket/Licenses.toml <<'EOF'
[nvidia]
spdx-id = "LicensesRef-NVIDIA-Customer-Use"
licenses = [
  { path = "LICENSE", license-url = "https://www.nvidia.com/en-us/drivers/nvidia-license/" }
]
EOF
```

## ステップ 10: AMI を構築して発行する
<a name="bottlerocket-custom-variant-step10"></a>

ターゲットリージョンで `Infra.toml` を作成します:

```
cat > ~/bottlerocket/Infra.toml <<'EOF'
[aws]
regions = ["us-west-2", "us-east-1", "us-east-2"]
EOF
```

イメージを構築する:

```
cd ~/bottlerocket
cargo make \
  -e BUILDSYS_VARIANT=aws-k8s-1.36-nvidia-595 \
  -e BUILDSYS_UPSTREAM_SOURCE_FALLBACK=true \
  -e BUILDSYS_UPSTREAM_LICENSE_FETCH=true \
  -e BUILDSYS_JOBS=32
```

最初のビルドでは、SDK イメージとキットイメージ (合計約 2 GB) をプルします。それ以降のビルドは、32 コアホストで 3～5 分かかります。

AMI を発行します:

```
cargo make \
  -e BUILDSYS_VARIANT=aws-k8s-1.36-nvidia-595 \
  -e PUBLISH_REGIONS=us-west-2,us-east-1,us-east-2 \
  ami
```

ビルドは AMI ID を `build/images/x86_64-aws-k8s-1.36-nvidia-595/latest/*-amis.json` に書き込みます。EKS マネージドノードグループ、Karpenter `EC2NodeClass`、または起動テンプレートでこれらを使用します。

## 構築できるその他の組み合わせ
<a name="bottlerocket-custom-variant-other-combinations"></a>

このチュートリアルでは NVIDIA ドライバーブランチをスワップしますが、アップストリームキットで利用可能なパッケージでも同じアプローチを使用できます。次の例は、キットをフォークせずにアセンブルできる内容を示しています:


| 必要なもの | バリアント `Cargo.toml` の変更点  | 
| --- | --- | 
| 異なる NVIDIA ドライバーブランチ |  `kmod-6.18-nvidia-r580-tesla` → `kmod-6.18-nvidia-r595-tesla`  | 
| 異なるカーネルバージョン |  `kernel-6.18` → `kernel-6.12` (それに応じて kmod を調整する) | 
| NVIDIA を完全に削除する | `included-packages` から 3 つの `nvidia-*` 行を削除する  | 
| EFA サポートを追加する | `included-packages` に `kmod-6.18-efa` を追加する  | 
| コンテナランタイムバージョンを切り替える |  `containerd-2.2` → `containerd-2.1`  | 

利用可能なパッケージの詳細については、GitHub ウェブサイトの「[kernel-kit](https://github.com/bottlerocket-os/bottlerocket-kernel-kit)」と GitHub ウェブサイトの「[core-kit](https://github.com/bottlerocket-os/bottlerocket-core-kit)」を参照してください。

**重要**  
Bottlerocket ルートファイルシステムはイミュータブルです。ランタイム時にパッケージをインストールすることはできません。キット内のすべてのパッケージは、Bottlerocket 専用にクロスコンパイルされています。標準のアップストリーム RPM は機能しません。キットにまだ含まれていないソフトウェアが必要な場合は、ランタイムの代替手段として、GitHub ウェブサイトの「[ブートストラップコンテナ](https://github.com/bottlerocket-os/bottlerocket#bootstrap-containers-settings)」または GitHub ウェブサイトの「[ホストコンテナ](https://github.com/bottlerocket-os/bottlerocket#host-containers)」を検討してください。

## クリーンアップ
<a name="bottlerocket-custom-variant-cleanup"></a>

ビルドホストが不要になった場合は、継続的な料金が発生しないように EC2 インスタンスを終了してください。AMI はアカウント内で個別に保持されます。不要になった場合は EC2 コンソールまたは CLI で登録解除します。

## 概要
<a name="bottlerocket-custom-variant-summary"></a>

このトピックでは、別の NVIDIA ドライバーブランチを使用してカスタム Bottlerocket バリアントを作成する方法を示しました。このプロセスには、既存のバリアントのコピー、1 つのパッケージ参照の変更、ワークスペースと RPM 仕様への新しいバリアントの登録、およびビルドの実行が含まれます。カーネルバージョンの切り替え、パッケージの追加、新しい Kubernetes リリース向けのバリアントの作成など、あらゆるカスタマイズに同じアプローチが適用されます。