

 **Ayude a mejorar esta página** 

Para contribuir a esta guía del usuario, elija el enlace **Edit this page on GitHub** que se encuentra en el panel derecho de cada página.

# Creación de una variante de AMI de Bottlerocket personalizada para Amazon EKS
<a name="bottlerocket-custom-variant"></a>

Al ejecutar cargas de trabajo de GPU en Amazon Elastic Kubernetes Service (Amazon EKS), elija una variante de Bottlerocket. La variante debe coincidir con la versión de Kubernetes y el tipo de acelerador. Bottlerocket envía variantes validadas para las configuraciones comunes. Sin embargo, es posible que su organización necesite una variante distinta por cualquiera de los siguientes motivos:
+ Una ramificación de controladores de NVIDIA más reciente
+ Una versión de controlador fija para cumplir con la normativa
+ Paquetes adicionales para la supervisión
+ Una línea de base sólida que su equipo de seguridad necesita

Como [Bottlerocket](https://github.com/bottlerocket-os/bottlerocket) en el sitio web de GitHub es completamente de código abierto, puede crear una variante personalizada que satisfaga estas necesidades. En este tema, se muestra cómo clonar una variante existente y cambiar el controlador de NVIDIA de la ramificación R580 a la R595 (versión 595.71.05). A continuación, se crea la imagen y se registra como una AMI privada.

**importante**  
El tipo de instancia de EC2 G7 requiere la versión 595 o posterior del controlador de NVIDIA. Las AMI de NVIDIA de Bottlerocket de EKS incluyen actualmente la versión 580 del controlador de NVIDIA, que no es compatible con las instancias G7.  
Consulte el [repositorio de Bottlerocket](https://github.com/bottlerocket-os/bottlerocket) en el sitio web de GitHub para obtener instrucciones sobre cómo crear una variante con la versión 595 del controlador de NVIDIA. En este tema, se explica todo el proceso a partir del [paso 1](#bottlerocket-custom-variant-step1).

## Cómo funciona el sistema de creación
<a name="bottlerocket-custom-variant-build-system"></a>

Al ejecutar `cargo make -e BUILDSYS_VARIANT=aws-k8s-1.36-nvidia`, suceden tres cosas:
+  **Extracción de dependencias.** Twoliter (el orquestador de creación de Bottlerocket) lee `Twoliter.toml` y extrae tres artefactos de Open Container Initiative (OCI) de `public.ecr.aws/bottlerocket`:
  +  **bottlerocket-sdk:** una imagen de contenedor con toda la cadena de herramientas de compilación cruzada (macros de RMP, Go, Rust y GCC).
  +  **bottlerocket-kernel-kit:** RPM prediseñados para kernels, módulos de kernel (incluidos los paquetes kmod de NVIDIA) y firmware.
  +  **bottlerocket-core-kit:** RPM prediseñados para el espacio de usuario: kubelet, containerd, el complemento para dispositivos y el kit de herramientas para contenedores de NVIDIA, complementos de configuración y servicios del sistema.

     `Twoliter.toml` fija las versiones y `Twoliter.lock` bloquea sus resúmenes. Para cambiarlos, ejecute `./tools/twoliter/twoliter update` para volver a resolverlos.
+  **Creación de la variante.** Twoliter lanza una compilación de Docker dentro del contenedor del SDK. Compila la caja de configuración predeterminada de la variante, resuelve el árbol de dependencias de RPM de los kits y lo ensambla todo en una imagen de disco.
+  **Salida.** Twoliter escribe el archivo `.img.lz4` final en `build/images/`. La compilación produce una salida determinista: los mismos pines de `Twoliter.toml` y la misma variante de `Cargo.toml` siempre generan la misma imagen, independientemente del host.

## Diseño del repositorio
<a name="bottlerocket-custom-variant-repo-layout"></a>

Los siguientes directorios son pertinentes para el trabajo con variantes:

```
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
```

Revise las siguientes notas sobre la estructura del repositorio:
+ Una variante consiste principalmente en metadatos. Los kits externos proporcionan el kernel, los controladores y el espacio de usuario.
+ Los archivos de valores predeterminados de configuración son symlinks, no copias. Utilice `cp -R` (no `cp -r` en macOS) para conservarlos.
+ Para agregar una variante, es necesario llevar a cabo ediciones en cinco lugares: dos archivos `Cargo.toml` del espacio de trabajo, dos archivos `.spec` y `README.md`.

## Requisitos previos
<a name="bottlerocket-custom-variant-prereqs"></a>

Para completar este tutorial, necesitará lo siguiente:
+ Una cuenta de AWS con permisos para lanzar instancias de EC2 y registrar AMI
+ Una instancia de EC2 (o un host de Linux x86\_64 equivalente) con al menos 8 núcleos, 16 GiB de memoria y 150 GB de disco
+ Ubuntu 24.04 LTS (o Fedora; macOS no es compatible como host de compilación)
+ Docker 20.10 o posterior
+ Rust (cadena de herramientas estable, instalada mediante rustup)
+ cargo-make (versión más reciente)
+ Familiaridad con los conceptos de empaquetado de Git, Cargo de Rust y RPM

**nota**  
Cuando complete este tutorial, termine la instancia de EC2 y anule el registro de cualquier AMI que ya no necesite para evitar cargos continuos. Para obtener instrucciones sobre la limpieza, consulte [Limpieza](#bottlerocket-custom-variant-cleanup).

## Paso 1: preparación del host de compilación
<a name="bottlerocket-custom-variant-step1"></a>

Lance una instancia de EC2, por ejemplo, `c7i.8xlarge` (32 vCPU, 64 GiB de memoria). Utilice un volumen raíz gp3 de 150 GB y adjunte la política administrada `AmazonSSMManagedInstanceCore` para el acceso a SSM.

Conéctese a la instancia mediante el Administrador de sesiones de AWS Systems Manager (SSM):

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

Instale los paquetes del sistema operativo obligatorios:

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

**nota**  
El archivo `BUILDING.md` oficial hace referencia a `liblz4-tool`. En las versiones recientes de Ubuntu, el paquete se llama `lz4`.

Instale Docker con los siguientes comandos:

```
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
```

Instale Rust y cargo-make con los siguientes comandos:

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

## Paso 2: Clonar el repositorio
<a name="bottlerocket-custom-variant-step2"></a>

Clone el [repositorio de Bottlerocket](https://github.com/bottlerocket-os/bottlerocket) del sitio web de GitHub y vaya al directorio:

```
cd ~/bottlerocket
```

Para crear una compilación reproducible, consulte una versión etiquetada (por ejemplo, `git checkout v1.62.1`). Para usar los paquetes más recientes, permanezca en la ramificación `develop`.

## Paso 3: verificación de las versiones del kit
<a name="bottlerocket-custom-variant-step3"></a>

Abra `Twoliter.toml` y confirme las versiones del kit. Para que sea compatible con R595, necesita la versión 6.2.2 o posterior de `bottlerocket-kernel-kit`:

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

Si la versión es anterior, actualízala y vuelva a generar el bloqueo:

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

## Paso 4: solución del problema de ruta de cargo-make
<a name="bottlerocket-custom-variant-step4"></a>

Twoliter establece `CARGO_HOME` en `~/bottlerocket/.cargo`, lo que evita que el proceso interno de Cargo encuentre el cargo-make instalado globalmente. Cree un enlace simbólico

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

Sin este paso, la compilación falla con el `error: no such command: make`.

## Paso 5: búsqueda de las ramificaciones de controladores disponibles
<a name="bottlerocket-custom-variant-step5"></a>

Los paquetes kmod de NVIDIA se incluyen dentro de `bottlerocket-kernel-kit`. Para obtener información sobre los paquetes de controladores disponibles, consulte el [directorio de paquetes de kernel-kit](https://github.com/bottlerocket-os/bottlerocket-kernel-kit) en el sitio web de GitHub o las [notas de la versión](https://github.com/bottlerocket-os/bottlerocket-kernel-kit/releases) en el sitio web de GitHub.

Para el kernel 6.18 (usado por las variantes `aws-k8s-1.36`):

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

Para el kernel 6.12 (usado por `aws-k8s-1.33`, `1.34`, `1.35`):

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

**nota**  
Cada paquete kmod envía subpaquetes (`-tesla`, `-open-gpu`, `-grid`, `-fabricmanager`, `-imex`). Las variantes de NVIDIA de Bottlerocket oficiales hacen referencia a `-tesla`, que incluye todos los subpaquetes necesarios mediante dependencias de RPM. Al arrancar, Bottlerocket selecciona automáticamente el tipo de controlador adecuado en función del tipo de instancia.

## Paso 6: creación de la nueva variante
<a name="bottlerocket-custom-variant-step6"></a>

Copie la variante existente. Utilice `cp -R` para conservar los symlinks:

```
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
```

Editar `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",
```

Editar `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"
```

## Paso 7: registro de la variante
<a name="bottlerocket-custom-variant-step7"></a>

Registre la nueva variante en cinco archivos:

 **1. `Cargo.toml`**, agregue el miembro del espacio de trabajo:

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

 **2. `sources/Cargo.toml`**, agregue el miembro de settings-defaults:

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

 **3. `packages/settings-defaults/settings-defaults.spec`**, agregue un bloque `%package`, entradas en ambos bucles de compilación y una sección `%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}.
```

Agregue lo siguiente a ambos bucles `for defaults in`:

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

Agregue la sección `%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`**, agregue una línea `Provides:` debajo de `%package aws-k8s-nvidia`:

```
 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)
```

## Paso 8: actualización del archivo de bloqueo
<a name="bottlerocket-custom-variant-step8"></a>

Al agregar un miembro del espacio de trabajo, se invalida `sources/Cargo.lock`. Actualícelo:

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

**importante**  
No utilice `cargo generate-lockfile`. Reescribe todo el archivo de bloqueo y aumenta las dependencias transitivas, lo que provoca errores de versiones duplicadas de `cargo-deny`.

## Paso 9: creación del archivo de licencia de NVIDIA
<a name="bottlerocket-custom-variant-step9"></a>

NVIDIA restringe la redistribución de los orígenes de los controladores. Debe agregar una confirmación de licencia explícita antes de compilar:

```
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
```

## Paso 10: creación y publicación de la AMI
<a name="bottlerocket-custom-variant-step10"></a>

Cree `Infra.toml` con las regiones de destino:

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

Compile la imagen:

```
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
```

La primera compilación extrae las imágenes del SDK y del kit (aproximadamente 2 GB en total). Las compilaciones posteriores tardan entre 3 y 5 minutos en un host de 32 núcleos.

Publique la 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
```

La compilación escribe los ID de AMI en `build/images/x86_64-aws-k8s-1.36-nvidia-595/latest/*-amis.json`. Úselos en los grupos de nodos administrados de EKS, en `EC2NodeClass` de Karpenter o en las plantillas de lanzamiento.

## Otras combinaciones que puede compilar
<a name="bottlerocket-custom-variant-other-combinations"></a>

Este tutorial cambia la ramificación de controladores de NVIDIA, pero puede usar el mismo enfoque para cualquier paquete disponible en los kits originales. En los siguientes ejemplos, se muestra lo que se puede ensamblar sin necesidad de bifurcar un kit:


| Qué desea | Qué cambiar en `Cargo.toml` de la variante  | 
| --- | --- | 
| Diferente ramificación de controladores de NVIDIA |  `kmod-6.18-nvidia-r580-tesla` → `kmod-6.18-nvidia-r595-tesla`  | 
| Versión del kernel diferente |  `kernel-6.18` → `kernel-6.12` (ajuste kmod en consecuencia) | 
| Eliminación de NVIDIA por completo | Eliminación de las tres líneas `nvidia-*` de `included-packages`  | 
| Agregación de compatibilidad con EFA | Agregación de `kmod-6.18-efa` a `included-packages`.  | 
| Cambio de la versión en tiempo de ejecución del contenedor |  `containerd-2.2` → `containerd-2.1`  | 

Para obtener información sobre los paquetes de controladores disponibles, consulte [kernel-kit](https://github.com/bottlerocket-os/bottlerocket-kernel-kit) en el sitio web de GitHub o [core-kit](https://github.com/bottlerocket-os/bottlerocket-core-kit) en el sitio web de GitHub.

**importante**  
El sistema de archivos raíz de Bottlerocket es inmutable. No puede instalar paquetes en tiempo de ejecución. Todos los paquetes de los kits se compilan de forma cruzada específicamente para Bottlerocket; los RPM ascendentes estándar no funcionan. Si necesita un software que aún no se ha incluido en un kit, considere la posibilidad de utilizar usar [contenedores de arranque](https://github.com/bottlerocket-os/bottlerocket#bootstrap-containers-settings) del sitio web de GitHub o [contenedores de host](https://github.com/bottlerocket-os/bottlerocket#host-containers) del sitio web de GitHub como alternativa de tiempo de ejecución.

## Limpieza
<a name="bottlerocket-custom-variant-cleanup"></a>

Si ya no necesita el host de compilación, termine la instancia de EC2 para evitar cargos continuos. Las AMI persisten de forma independiente en su cuenta: anule su registro con la consola de EC2 o la CLI si ya no las necesita.

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

En este tema, se muestra cómo crear una variante de Bottlerocket personalizada con una ramificación de controladores de NVIDIA diferente. El proceso implica copiar una variante existente, cambiar la referencia de un paquete, registrar la nueva variante en el espacio de trabajo y en las especificaciones de RPM y ejecutar la compilación. El mismo enfoque se aplica a cualquier personalización: cambio de versiones del kernel, adición de paquetes o creación de variantes para nuevas versiones de Kubernetes.