

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Déployez des modèles à partir d'un stockage NVMe local à l'aide de kubectl
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme"></a>

Cette rubrique explique comment déployer des points de terminaison d'inférence sur Amazon SageMaker HyperPod qui chargent les poids des modèles à partir du stockage NVMe local d'un nœud au lieu de les transférer via le réseau depuis Amazon S3 ou Amazon FSx. La lecture locale des poids élimine le saut réseau lors du démarrage du pod, ce qui réduit le temps de démarrage à froid du pod d'inférence et est utile pour les événements de dimensionnement automatique, les charges de travail à partir de zéro et les basculements sensibles à la latence. Pour les charges de travail pour lesquelles la latence de démarrage à froid n'est pas un problème, utilisez `modelSourceType: s3` ou `fsx` et ignorez cette rubrique.

Le NVMe local est local et éphémère : les données du NVMe sont perdues lorsqu'un nœud est remplacé, par exemple lors d'une interruption ponctuelle, d'une panne matérielle ou d'une actualisation de l'AMI. Les approches décrites dans cette rubrique traitent ce problème différemment : certaines nécessitent de pré-remplir chaque nœud, d'autres font automatiquement appel à Amazon S3 lorsque le modèle n'est pas mis en cache localement. Le stockage d'instance NVMe local se trouve généralement dans les familles d'instances P, G et Trn. Consultez les spécifications du magasin d'instances [ Amazon EC2 ](https://docs.aws.amazon.com/ec2/latest/instancetypes/ac.html#ac_instance-store) pour valider la disponibilité de votre type d'instance.

Vous pouvez choisir l'une des approches suivantes en fonction de vos besoins de stockage :


**Approches de déploiement NVMe**  

| \# | Approche | Description | 
| --- | --- | --- | 
| 1 | Volume Kubernetes (pas de solution de secours) | À utiliser lorsque des poids de modèle existent sur NVMe sur chaque nœud. Configuration la plus simple : aucun Amazon S3, Amazon FSx ou PV/PVC InitContainers n'est requis. | 
| 2 | Volume Kubernetes avec solution de secours | À utiliser lorsque le modèle n'existe peut-être pas sur NVMe sur tous les nœuds. Vous fournissez une option personnalisée initContainer qui vérifie d'abord NVMe et effectue les téléchargements depuis Amazon S3 à l'aide des informations d'identification IRSA si le modèle est absent. | 
| 3 | Amazon S3 avec fonction de prélecture et de repli | À utiliser lorsque vous souhaitez adapter le poids du modèle à la RAM pour le démarrage du pod. Vous fournissez une personnalisation initContainer qui vérifie d'abord NVMe et revient à la copie depuis le montage Amazon S3 provisionné par l'opérateur si le modèle n'est pas mis en cache localement. | 

## Conditions préalables
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-prereqs"></a>

Avant de commencer, vérifiez les points suivants :
+ Configurez des fonctionnalités d'inférence sur vos SageMaker HyperPod clusters Amazon. Pour de plus amples informations, veuillez consulter [Configuration de vos HyperPod clusters pour le déploiement de modèles](sagemaker-hyperpod-model-deployment-setup.md).
+ Vous avez installé l’utilitaire [kubectl](https://kubernetes.io/docs/reference/kubectl/) et configuré [jq](https://jqlang.org/) dans votre terminal.
+ Pre-populated modélisez les pondérations sur le stockage NVMe local de vos nœuds cibles (voir [Préchargez les poids du modèle dans NVMe](#sagemaker-hyperpod-model-deployment-deploy-nvme-preload) les instructions).

## Choisissez votre approche de déploiement
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-choose"></a>

Utilisez le flux de décision suivant pour déterminer l'approche la mieux adaptée à votre cas d'utilisation.

```
                  ┌────────────────────────────┐
                  │ Want to use a volume of    │
                  │ your choice, e.g. NVMe?    │
                  └─────┬──────────────┬───────┘
                   YES  │              │ NO
                        ▼              ▼
        ┌──────────────────────┐   Use S3/FSx/HF
        │ Are you sure EVERY   │   as-is (no volume
        │ node has the model   │   override needed)
        │ on NVMe?             │
        └─────┬──────────┬─────┘
         YES  │          │ NO
              ▼          ▼
  ┌─────────────────┐  ┌───────────────────────────────┐
  │ Approach 1      │  │ Do you need the operator to   │
  │                 │  │ create S3/FSx PVCs as a       │
  │ Use k8sVolume   │  │ fallback when the model is    │
  │ field in CRD to │  │ missing on a node?            │
  │ read from NVMe  │  └──────┬────────────────┬───────┘
  │ directly.       │    YES  │                │ NO
  └─────────────────┘         ▼                ▼
                  ┌──────────────────┐  ┌──────────────────────┐
                  │ Approach 3       │  │ Approach 2           │
                  │                  │  │                      │
                  │ Use S3 with      │  │ Use k8sVolume with a │
                  │ prefetch enabled.│  │ custom initContainer │
                  │ Custom           │  │ you create that      │
                  │ initContainer    │  │ checks NVMe first    │
                  │ checks NVMe      │  │ and downloads from   │
                  │ first, falls     │  │ S3 via IRSA if the   │
                  │ back to S3, and  │  │ model is missing.    │
                  │ copies to RAM.   │  └──────────────────────┘
                  └──────────────────┘
```

## Déploiement à l'aide d'un volume Kubernetes (pas de solution de secours)
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-volume"></a>

Utilisez cette approche lorsque vous avez des pondérations de modèle sur NVMe sur chaque nœud et que vous souhaitez la configuration la plus simple : pas de configuration Amazon S3 ou Amazon FSx PV/PVC, non et pas d'InitContainers.

Lorsque vous définissez`modelSourceType: kubernetesVolume`, l'opérateur ignore complètement PV/PVC la création. Aucun pilote CSI, aucun support de fusible Amazon S3 ou aucun support Amazon FSx n'est utilisé. Le `model-weights` volume fourni par le client est utilisé directement dans la spécification du pod, et le travailleur lit les données du modèle depuis NVMe à l'adresse. `/opt/ml/model`

**Important**  
Lors de l'utilisation`modelSourceType: kubernetesVolume`, l'opérateur dérive le nom de volume attendu à partir de la configuration `modelVolumeMount.name` de votre serveur de travail. `kubernetes.volumes`doit contenir un volume portant le même nom. L'opérateur valide cela et rejette le déploiement avec une `KubernetesVolumeValidationFailed` condition si aucun volume correspondant n'est trouvé. Dans les exemples suivants, les deux utilisent`model-weights`.

1. Créez le fichier `InferenceEndpointConfig` YAML. Remplacez les valeurs des espaces réservés par vos identifiants de ressources réels.

   ```
   cat <<EOF> deploy_nvme_k8s_volume.yaml
   apiVersion: inference.sagemaker.aws.amazon.com/v1
   kind: InferenceEndpointConfig
   metadata:
     name: nvme-k8s-volume
     namespace: default
   spec:
     endpointName: nvme-k8s-volume
     modelName: Qwen2.5-VL-7B-Instruct
     invocationEndpoint: v1/chat/completions
     replicas: 1
     modelSourceConfig:
       modelSourceType: kubernetesVolume
     kubernetes:
       volumes:
         - name: model-weights
           hostPath:
             path: /opt/dlami/nvme/<YOUR_MODEL>
             type: Directory
     loadBalancer:
       healthCheckPath: /health
     worker:
       image: lmcache/vllm-openai:latest
       args:
         - /opt/ml/model
         - --max-model-len
         - "15000"
         - --tensor-parallel-size
         - "1"
       modelInvocationPort:
         containerPort: 8000
         name: http
       modelVolumeMount:
         name: model-weights
         mountPath: /opt/ml/model
       resources:
         limits:
           nvidia.com/gpu: "1"
         requests:
           cpu: "6"
           memory: 30Gi
           nvidia.com/gpu: "1"
       environmentVariables:
         - name: PYTHONHASHSEED
           value: "123"
         - name: VLLM_REQUEST_TIMEOUT
           value: "600"
   EOF
   ```
**Note**  
Pour configurer la mise en cache KV et le routage intelligent afin d'améliorer les performances, consultez[Configuration de la mise en cache KV et du routage intelligent](sagemaker-hyperpod-model-deployment-caching-routing.md#sagemaker-hyperpod-model-deployment-deploy-ftm-cache-route).

1. Déployez le`InferenceEndpointConfig`.

   ```
   kubectl apply -f deploy_nvme_k8s_volume.yaml
   ```

1. Vérifiez l'état du déploiement.

   ```
   kubectl describe InferenceEndpointConfig nvme-k8s-volume -n default
   ```

## Déploiement à l'aide d'un volume Kubernetes avec solution de secours
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-fallback"></a>

Utilisez cette approche lorsque le modèle peut être sur NVMe ou non sur un nœud donné. Un `hostPath` volume ne fonctionne que sur les nœuds où les données existent : les pods planifiés sur d'autres nœuds créeraient un chemin vide ou inexistant, provoquant la défaillance du serveur modèle.

Dans cette approche, vous définissez `modelSourceType: kubernetesVolume` et fournissez une personnalisation `initContainer` qui vérifie d'abord NVMe et télécharge depuis Amazon S3 à l'aide des informations d'identification IRSA si le modèle est absent.

### Configurer IRSA
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-fallback-irsa"></a>

Avant le déploiement, configurez les rôles IAM pour les comptes de service (IRSA) pour fournir les informations d'identification de vos pods à télécharger depuis Amazon S3.

1. Obtenez l'ID du fournisseur OIDC pour votre cluster.

   ```
   aws eks describe-cluster --name <CLUSTER_NAME> --region <REGION> \
     --query "cluster.identity.oidc.issuer" --output text
   ```

1. Créez une politique de confiance IAM. Enregistrez ce qui suit sous`trust-policy.json`, en remplaçant les valeurs des espaces réservés.

   ```
   {
     "Version": "2012-10-17",		 	 	 
     "Statement": [{
       "Effect": "Allow",
       "Principal": {
         "Federated": "arn:aws:iam::<ACCOUNT_ID>:oidc-provider/oidc.eks.<REGION>.amazonaws.com/id/<OIDC_ID>"
       },
       "Action": "sts:AssumeRoleWithWebIdentity",
       "Condition": {
         "StringEquals": {
           "oidc.eks.<REGION>.amazonaws.com/id/<OIDC_ID>:sub": "system:serviceaccount:<NAMESPACE>:<SA_NAME>",
           "oidc.eks.<REGION>.amazonaws.com/id/<OIDC_ID>:aud": "sts.amazonaws.com"
         }
       }
     }]
   }
   ```
**Avertissement**  
Étendez toujours la politique de confiance à un espace de noms et à un ServiceAccount nom spécifiques. N'utilisez jamais de caractères génériques dans la condition d'objet (par exemple,`system:serviceaccount:*:*`), car cela permettrait à n'importe quel utilisateur de n'importe ServiceAccount quel espace de noms d'assumer le rôle.

1. Créez le rôle IAM et associez une politique de lecture Amazon S3 délimitée à votre compartiment de modèles.

   ```
   aws iam create-role --role-name <ROLE_NAME> \
     --assume-role-policy-document file://trust-policy.json
   
   aws iam put-role-policy --role-name <ROLE_NAME> \
     --policy-name S3ModelReadAccess \
     --policy-document '{
       "Version": "2012-10-17",		 	 	 
       "Statement": [{
         "Effect": "Allow",
         "Action": ["s3:GetObject", "s3:ListBucket"],
         "Resource": [
           "arn:aws:s3:::<YOUR_BUCKET>",
           "arn:aws:s3:::<YOUR_BUCKET>/<YOUR_MODEL_PREFIX>/*"
         ]
       }]
     }'
   ```

1. Créez le compte de service Kubernetes avec l'annotation IRSA.

   ```
   kubectl create sa <SA_NAME> -n <NAMESPACE>
   kubectl annotate sa <SA_NAME> -n <NAMESPACE> \
     eks.amazonaws.com/role-arn=arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME>
   ```

### Déploiement du modèle
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-fallback-deploy"></a>

1. Créez le fichier `InferenceEndpointConfig` YAML. Remplacez les valeurs des espaces réservés par vos identifiants de ressources réels.

   ```
   cat <<EOF> deploy_nvme_k8s_volume_fallback.yaml
   apiVersion: inference.sagemaker.aws.amazon.com/v1
   kind: InferenceEndpointConfig
   metadata:
     name: nvme-k8s-volume-fallback
     namespace: default
   spec:
     endpointName: nvme-k8s-volume-fallback
     modelName: Qwen2.5-VL-7B-Instruct
     invocationEndpoint: v1/chat/completions
     replicas: 1
     modelSourceConfig:
       modelSourceType: kubernetesVolume
     kubernetes:
       serviceAccountName: <YOUR_SERVICE_ACCOUNT>
       initContainers:
         - name: smart-loader
           image: public.ecr.aws/aws-cli/aws-cli:latest
           command: ["/bin/bash", "-c"]
           args:
             - |
               if [ "$(ls -A /model)" ]; then
                 echo "NVMe hit — model already present ($(du -sh /model | cut -f1))"
               else
                 echo "NVMe miss — downloading from S3"
                 aws s3 sync s3://<YOUR_BUCKET>/<YOUR_MODEL>/ /model/
               fi
           volumeMounts:
             - name: model-weights
               mountPath: /model
       volumes:
         - name: model-weights
           hostPath:
             path: /opt/dlami/nvme/<YOUR_MODEL>
             type: DirectoryOrCreate
     loadBalancer:
       healthCheckPath: /health
     worker:
       image: lmcache/vllm-openai:latest
       args:
         - /opt/ml/model
         - --max-model-len
         - "15000"
         - --tensor-parallel-size
         - "1"
       modelInvocationPort:
         containerPort: 8000
         name: http
       modelVolumeMount:
         name: model-weights
         mountPath: /opt/ml/model
       resources:
         limits:
           nvidia.com/gpu: "1"
         requests:
           cpu: "6"
           memory: 30Gi
           nvidia.com/gpu: "1"
       environmentVariables:
         - name: PYTHONHASHSEED
           value: "123"
   EOF
   ```
**Note**  
Pour configurer la mise en cache KV et le routage intelligent afin d'améliorer les performances, consultez[Configuration de la mise en cache KV et du routage intelligent](sagemaker-hyperpod-model-deployment-caching-routing.md#sagemaker-hyperpod-model-deployment-deploy-ftm-cache-route).

1. Déployez le`InferenceEndpointConfig`.

   ```
   kubectl apply -f deploy_nvme_k8s_volume_fallback.yaml
   ```

1. Vérifiez l'état du déploiement.

   ```
   kubectl describe InferenceEndpointConfig nvme-k8s-volume-fallback -n default
   ```

## Déployez à l'aide d'Amazon S3 avec Prefetch et NVMe Fallback
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-s3-prefetch"></a>

Utilisez cette approche lorsque vous souhaitez inférer les performances en répartissant les poids du modèle dans la RAM, avec un retour automatique vers Amazon S3 si le modèle n'est pas mis en cache localement sur NVMe.

Lorsque vous définissez `modelSourceType: s3` avec`prefetchEnabled: true`, l'opérateur crée automatiquement deux volumes :
+ Un volume nommé d'après votre `modelVolumeMount.name` (généralement`model-weights`) : un support de fusible Amazon S3 CSI contenant votre modèle
+ `model-weights-copy`— un RAM-backed `emptyDir` endroit où le travailleur lit un extrait de

Vous ajoutez un `nvme-cache` volume personnalisé pointant vers le stockage NVMe local du nœud et un volume personnalisé `initContainer` qui :
+ Si le modèle existe sur NVMe, copie de NVMe vers la RAM (`model-weights-copy`), en ignorant complètement le réseau.
+ Si le modèle est absent, recommence à copier depuis le support Amazon S3 (`model-weights`) vers la RAM (`model-weights-copy`). Copie éventuellement vers NVMe afin que les démarrages ultérieurs du pod sur le même nœud utilisent le chemin local rapide.

**Important**  
Ne l'utilisez pas `model-weights` en `kubernetes.volumes` cas d'utilisation de cette approche. L'opérateur crée un `model-weights` pointage vers le volume Amazon S3 CSI. Le fait de le remplacer supprime le volume provisionné par l'opérateur dont votre InitContainer a besoin pour se replier. Utilisez un nom de volume distinct (par exemple`nvme-cache`) pour votre NVMe HostPath.

**Important**  
Ne pas inclure `model-weights-copy` dans`kubernetes.volumes`. Il s'agit d'un nom réservé créé automatiquement par l'opérateur. Votre InitContainer peut le référencer `volumeMounts` mais ne doit pas le déclarer comme un volume.

1. Créez le fichier `InferenceEndpointConfig` YAML. Remplacez les valeurs des espaces réservés par vos identifiants de ressources réels.

   ```
   cat <<EOF> deploy_nvme_s3_prefetch_fallback.yaml
   apiVersion: inference.sagemaker.aws.amazon.com/v1
   kind: InferenceEndpointConfig
   metadata:
     name: nvme-s3-prefetch-fallback
     namespace: default
   spec:
     endpointName: nvme-s3-prefetch-fallback
     modelName: Qwen2.5-VL-7B-Instruct
     invocationEndpoint: v1/chat/completions
     replicas: 1
     modelSourceConfig:
       modelSourceType: s3
       s3Storage:
         bucketName: <YOUR_BUCKET>
         region: <YOUR_REGION>
       prefetchEnabled: true
     kubernetes:
       serviceAccountName: <YOUR_SERVICE_ACCOUNT>
       initContainers:
         - name: smart-loader
           image: public.ecr.aws/aws-cli/aws-cli:latest
           command: ["/bin/bash", "-c"]
           args:
             - |
               # Check NVMe first, fall back to S3 mount, then copy to RAM
               if [ "$(ls -A /nvme)" ]; then
                 echo "NVMe hit ($(du -sh /nvme | cut -f1))"
                 echo "Copying model from NVMe to RAM..."
                 cp -r /nvme/* /model/
               else
                 echo "NVMe miss — copying from S3 mount to NVMe, then NVMe to RAM"
                 cp -r /s3-model/* /nvme/
                 cp -r /nvme/* /model/
               fi
               echo "Done. $(du -sh /model | cut -f1) in RAM."
           volumeMounts:
             - name: model-weights
               mountPath: /s3-model
             - name: nvme-cache
               mountPath: /nvme
             - name: model-weights-copy
               mountPath: /model
       volumes:
         - name: nvme-cache
           hostPath:
             path: /opt/dlami/nvme/<YOUR_MODEL>
             type: DirectoryOrCreate
     loadBalancer:
       healthCheckPath: /health
     worker:
       image: lmcache/vllm-openai:latest
       args:
         - /opt/ml/model
         - --max-model-len
         - "15000"
         - --tensor-parallel-size
         - "1"
       modelInvocationPort:
         containerPort: 8000
         name: http
       modelVolumeMount:
         name: model-weights
         mountPath: /opt/ml/model
       resources:
         limits:
           nvidia.com/gpu: "1"
         requests:
           cpu: "6"
           memory: 30Gi
           nvidia.com/gpu: "1"
       environmentVariables:
         - name: PYTHONHASHSEED
           value: "123"
         - name: VLLM_REQUEST_TIMEOUT
           value: "600"
   EOF
   ```
**Note**  
Pour configurer la mise en cache KV et le routage intelligent afin d'améliorer les performances, consultez[Configuration de la mise en cache KV et du routage intelligent](sagemaker-hyperpod-model-deployment-caching-routing.md#sagemaker-hyperpod-model-deployment-deploy-ftm-cache-route).

1. Déployez le`InferenceEndpointConfig`.

   ```
   kubectl apply -f deploy_nvme_s3_prefetch_fallback.yaml
   ```

1. Vérifiez l'état du déploiement.

   ```
   kubectl describe InferenceEndpointConfig nvme-s3-prefetch-fallback -n default
   ```

## Comprendre les pondérations des modèles et les pondérations des modèles avec Prefetch
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-prefetch-volumes"></a>

Lors de l'utilisation de la fonction prefetch, l'opérateur crée deux volumes liés au modèle :
+ Un volume nommé d'après votre `modelVolumeMount.name` (généralement`model-weights`) : un support de fusible Amazon S3 CSI contenant votre modèle
+ `model-weights-copy`— un RAM-backed EmptyDir où le travailleur lit réellement à partir de

Dans votre`InferenceEndpointConfig`, vous définissez :

```
modelVolumeMount:
    name: model-weights
    mountPath: /opt/ml/model
```

Pendant que vous faites référence`model-weights`, quand`prefetchEnabled: true`, c'est en fait `model-weights-copy` ce qui est monté `/opt/ml/model` dans le conteneur de travail. Lorsque vous utilisez un InitContainer personnalisé, assurez-vous de copier les données dans le volume appelé`model-weights-copy`, c'est là que le travailleur s'attend à les trouver.

Quand `prefetchEnabled: false` il n'y a qu'un seul volume (nommé d'après le vôtre`modelVolumeMount.name`) et qu'il est monté directement sur`/opt/ml/model`.

## Configurer un compte de service personnalisé
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa"></a>

Vous pouvez attribuer un Kubernetes personnalisé ServiceAccount à vos pods de points de terminaison d'inférence à l'aide du champ du`spec.kubernetes.serviceAccountName`. `InferenceEndpointConfig` Cela est utile pour fournir des AWS informations d'identification via IRSA (IAM Roles for Service Accounts) à vos conteneurs de travail ou à vos conteneurs d'initialisation, par exemple pour télécharger les pondérations des modèles depuis Amazon S3 dans un scénario de repli.

**Important**  
La prise en charge des comptes de service personnalisés est désactivée par défaut et doit être explicitement activée par un administrateur de cluster avant utilisation. Pour obtenir des instructions, consultez [Activer les comptes de service personnalisés](#sagemaker-hyperpod-model-deployment-deploy-nvme-sa-enable).

Si vous ne spécifiez pas de ServiceAccount, la valeur par défaut de l'espace de noms ServiceAccount est utilisée.

### Activer les comptes de service personnalisés
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa-enable"></a>

La prise en charge des comptes de service personnalisés est désactivée par défaut. Un administrateur de cluster doit l'activer dans la configuration Helm de l'opérateur pour que les utilisateurs puissent faire référence à la personnalisation ServiceAccounts dans leur`InferenceEndpointConfig`.
+ Mettez à jour les valeurs Helm de l'opérateur pour activer la fonctionnalité. Si vous avez déployé l'opérateur via Helm, effectuez la mise à niveau avec le drapeau suivant :

  ```
  helm upgrade hyperpod-inference-operator <CHART_PATH> \
    --set enableCustomServiceAccounts=true \
    --reuse-values
  ```
+ Si vous avez déployé l'opérateur en tant que module complémentaire Amazon EKS, mettez à jour la configuration du module complémentaire pour l'inclure `enableCustomServiceAccounts: true` dans les paramètres de configuration avancés.
+ Vérifiez que la variable d'environnement est définie dans le module opérateur :

  ```
  kubectl get deployment hyperpod-inference-controller-manager \
    -n hyperpod-inference-system \
    -o jsonpath='{.spec.template.spec.containers[0].env}' | jq '.[] | select(.name=="ENABLE_CUSTOM_SERVICE_ACCOUNTS")'
  ```

  Vous devriez voir :

  ```
  {
    "name": "ENABLE_CUSTOM_SERVICE_ACCOUNTS",
    "value": "true"
  }
  ```

**Important**  
Si cette fonctionnalité n'est pas activée, tout `InferenceEndpointConfig` ce qui `kubernetes.serviceAccountName` est spécifié est rejeté avec un `DeploymentFailed` statut et le message :`kubernetes.serviceAccountName is not enabled. Requires addon configuration (enableCustomServiceAccounts: true)`.

### Étiquetez le compte de service
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa-label"></a>

Avant de pouvoir référencer une personnalisation ServiceAccount, un administrateur de cluster doit l'étiqueter comme étant assignable par l'utilisateur :

```
kubectl label serviceaccount <your-service-account> \
  sagemaker.amazonaws.com/user-assignable=true \
  -n <namespace>
```

Ce n'est qu' ServiceAccounts avec cette étiquette que les points de terminaison d'inférence peuvent être référencés. Il s'agit d'un contrôle de sécurité destiné à empêcher toute escalade de privilèges non autorisée.

### Spécifiez le compte de service dans votre configuration
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa-spec"></a>

Ajoutez le `serviceAccountName` champ ci-dessous `spec.kubernetes` dans votre `InferenceEndpointConfig` :

```
apiVersion: inference.sagemaker.aws.amazon.com/v1
kind: InferenceEndpointConfig
metadata:
  name: my-inference-endpoint
  namespace: my-namespace
spec:
  kubernetes:
    serviceAccountName: my-inference-sa
  # ... rest of your config
```

### Règles de validation
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa-validation"></a>

L'opérateur valide le `serviceAccountName` champ lors des opérations de création et de mise à jour. Votre déploiement sera rejeté avec un `DeploymentFailed` statut si l'une des conditions suivantes est remplie :
+ Le ServiceAccount n'existe pas dans l'espace de noms — `serviceAccountName "X" not found in namespace "Y"`
+  ServiceAccount Il manque l'étiquette requise — `serviceAccountName "X" is not labeled as user-assignable (requires label sagemaker.amazonaws.com/user-assignable=true)`
+  ServiceAccount C'est le système de l'opérateur ServiceAccount — `serviceAccountName must not reference the operator's service account`

**Note**  
Tous les conteneurs du pod d'inférence (worker, conteneurs d'initialisation et sidecars) héritent des autorisations du conteneur spécifié. ServiceAccount Si le ServiceAccount est annoté avec`eks.amazonaws.com/role-arn`, le pod reçoit des AWS informations d'identification temporaires pour ce rôle IAM. Les administrateurs de cluster ne doivent étiqueter ServiceAccounts comme pouvant être attribués par l'utilisateur qu'après avoir examiné les rôles RBAC et les autorisations IAM associés.

**Note**  
Si a ServiceAccount est supprimé alors que an `InferenceEndpointConfig` est déjà en cours d'exécution, les pods existants continuent de fonctionner avec leurs informations d'identification actuelles jusqu'à ce qu'ils soient redémarrés. Cependant, la création d'un nouveau pod (par exemple, lors de la mise à l'échelle ou de la replanification) échouera car il ServiceAccount n'existe plus. L'opérateur valide le ServiceAccount moment où le déploiement est créé pour la première fois et la date à laquelle la spécification IEC est mise à jour ; il ne surveille pas en permanence le ServiceAccount. La mise à jour de la spécification IEC après la suppression de la SA entraînera un `DeploymentFailed` statut.

### Meilleures pratiques de sécurité pour les comptes de service personnalisés
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa-security"></a>

Lorsque vous utilisez une configuration personnalisée ServiceAccount avec des points de terminaison d'inférence, l'opérateur d' HyperPod inférence crée des déploiements en votre nom. Tous les conteneurs du module d'inférence, y compris le worker, les conteneurs d'initialisation et les sidecars, héritent des autorisations des éléments spécifiés. ServiceAccount Suivez ces bonnes pratiques pour sécuriser votre cluster.

**Verrouiller les autorisations RBAC **
+ Créez une charge de travail dédiée ServiceAccount à chaque charge de travail d'inférence. Ne les réutilisez pas ServiceAccounts sur des charges de travail indépendantes.
+ Liez uniquement les autorisations RBAC minimales requises. Par exemple, si votre conteneur d'initialisation doit uniquement lire depuis Amazon S3, il ne ServiceAccount doit pas être autorisé à répertorier ou à modifier les ressources Kubernetes.

  ```
  # Example: minimal Role for an inference workload that only needs S3 access via IRSA
  # No Kubernetes API permissions needed — IRSA provides AWS credentials directly
  apiVersion: v1
  kind: ServiceAccount
  metadata:
    name: my-inference-sa
    namespace: my-namespace
    labels:
      sagemaker.amazonaws.com/user-assignable: "true"
    annotations:
      eks.amazonaws.com/role-arn: arn:aws:iam::<ACCOUNT_ID>:role/<SCOPED_ROLE_NAME>
  ```
+ Évitez d'accorder des autorisations à l'échelle du cluster (ClusterRoleBindings) aux pods d' ServiceAccounts inférence utilisés.

**Champ d'application des rôles IAM de l'IRSA **
+ Lorsque vous annotez un ServiceAccount with`eks.amazonaws.com/role-arn`, assurez-vous que le rôle IAM respecte les principes du moindre privilège.
+ Étendez les autorisations Amazon S3 au compartiment et au préfixe spécifiques contenant les poids de vos modèles.

  ```
  {
    "Version": "2012-10-17",		 	 	 
    "Statement": [{
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::<YOUR_BUCKET>",
        "arn:aws:s3:::<YOUR_BUCKET>/<YOUR_MODEL_PREFIX>/*"
      ]
    }]
  }
  ```
+ N'utilisez pas de politiques de gestion générales, comme `AmazonS3FullAccess` dans le cas de la production. Utilisez `AmazonS3ReadOnlyAccess` ou une politique personnalisée adaptée à votre compartiment de modèles.

**Protégez l'étiquette assignable par l'utilisateur **
+ Seuls les administrateurs de cluster peuvent ajouter ou supprimer l'`sagemaker.amazonaws.com/user-assignable=true`étiquette. Utilisez Kubernetes RBAC pour limiter les personnes autorisées à modifier les ServiceAccount étiquettes dans votre espace de noms.
+ Passez en revue les rôles RBAC et les autorisations IAM associés à un élément ServiceAccount avant de le qualifier d'attribuable par l'utilisateur.
+ Auditez périodiquement ServiceAccounts ceux qui portent l'`user-assignable`étiquette.

  ```
  kubectl get serviceaccounts -n <NAMESPACE> -l sagemaker.amazonaws.com/user-assignable=true
  ```
+ Assurez-vous que les rôles non-administrateurs n'incluent pas de `patch``update`, ou de `create` verbes sur ServiceAccount les ressources. L'opérateur valide l'`user-assignable`étiquette au moment du déploiement, mais n'empêche pas les utilisateurs non autorisés d'ajouter l'étiquette à un ServiceAccount. Restreindre les personnes autorisées à modifier ServiceAccounts via RBAC est le principal contrôle pour protéger cette étiquette. Non-admin les utilisateurs ne devraient avoir `get` et `list` accéder qu'à :

  ```
  # Example: RBAC Role for non-admin users — read-only access to ServiceAccounts
  apiVersion: rbac.authorization.k8s.io/v1
  kind: Role
  metadata:
    name: sa-read-only
    namespace: <NAMESPACE>
  rules:
    - apiGroups: [""]
      resources: ["serviceaccounts"]
      verbs: ["get", "list"]
  ```

**Important**  
L'opérateur HyperPod d'inférence agit en tant qu'intermédiaire qui crée des déploiements pour le compte des utilisateurs. Contrairement aux charges de travail Kubernetes standard dans lesquelles l'appelant crée directement des espaces, l'opérateur attribue les éléments spécifiés aux espaces qu'il crée. ServiceAccount Cela signifie que toutes les autorisations accordées à un objet assignable par l'utilisateur ServiceAccount sont effectivement disponibles pour quiconque peut en créer un `InferenceEndpointConfig` dans cet espace de noms. Assurez-vous que le RBAC au niveau de l'espace de noms contrôle qui peut créer et mettre à jour des ressources. `InferenceEndpointConfig`

## Préchargez les poids du modèle dans NVMe
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-preload"></a>

Si vous devez préremplir NVMe sur des nœuds spécifiques avant le déploiement, vous pouvez utiliser un module unique pour effectuer la synchronisation depuis Amazon S3.

**Note**  
Cette approche cible un nœud spécifique via `nodeName` et ne fonctionne pas avec la mise à l'échelle automatique. Pour les scénarios de dimensionnement automatique, utilisez le volume Kubernetes avec repli ou Amazon S3 avec des approches de prélecture, qui gèrent automatiquement les modèles manquants via la logique de repli InitContainer.

1. Créez le fichier YAML du pod de préchargement. Remplacez les valeurs des espaces réservés par vos identifiants de ressources réels.

   ```
   cat <<EOF> nvme-s3-copy.yaml
   apiVersion: v1
   kind: Pod
   metadata:
     name: nvme-s3-copy
     namespace: default
   spec:
     nodeName: <TARGET_NODE>
     restartPolicy: Never
     containers:
       - name: s3-copy
         image: public.ecr.aws/aws-cli/aws-cli:latest
         command: ["/bin/bash", "-c"]
         args:
           - |
             echo "=== Starting S3 sync to NVMe ==="
             aws s3 sync s3://<YOUR_BUCKET>/<YOUR_MODEL>/ /nvme/<YOUR_MODEL>/ --region <YOUR_REGION>
             echo "=== Sync complete ==="
             ls -la /nvme/<YOUR_MODEL>/
             du -sh /nvme/<YOUR_MODEL>/
             echo "=== Done ==="
         volumeMounts:
           - name: nvme-storage
             mountPath: /nvme
     serviceAccountName: default
     volumes:
       - name: nvme-storage
         hostPath:
           path: /opt/dlami/nvme
           type: Directory
   EOF
   ```

1. Appliquez le module et surveillez la progression de la synchronisation.

   ```
   kubectl apply -f nvme-s3-copy.yaml
   kubectl get pod nvme-s3-copy -w
   kubectl logs nvme-s3-copy -f
   ```

1. Nettoyez le module une fois la synchronisation terminée.

   ```
   kubectl delete pod nvme-s3-copy
   ```

## Noms de volumes réservés
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-reserved-volumes"></a>

L'opérateur gère plusieurs volumes internes qui ne peuvent pas être remplacés via. `kubernetes.volumes` L'utilisation de l'un de ces noms entraîne la création d'une `KubernetesVolumeValidationFailed` condition.


**Noms de volumes réservés**  

| \# | Nom | Objectif | 
| --- | --- | --- | 
| 1 | shm | Mémoire partagée (/dev/shm) pour la communication entre processus | 
| 2 | model-weights-copy | RAM-backed EmptyDir utilisé lorsque prefetchEnabled: true | 
| 3 | parallel-copy-configmap | ConfigMap pour un script de copie parallèle (prefetch) | 
| 4 | lmcache-config | Volume de configuration LMCache | 
| 5 | gated-model-downloader-configmap | ConfigMap pour le script de téléchargement de modèles fermés | 

## Choses à retenir
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-things-to-remember"></a>
+ **N'utilisez pas de noms de volumes réservés. ** L'opérateur gère plusieurs volumes internes (voir[Noms de volumes réservés](#sagemaker-hyperpod-model-deployment-deploy-nvme-reserved-volumes)). L'utilisation de l'un de ces noms `kubernetes.volumes` entraîne la création d'une `KubernetesVolumeValidationFailed` condition.
+ **Les noms des volumes doivent correspondre. ** L'opérateur obtient le nom du volume à partir de`modelVolumeMount.name`. Lors de l'utilisation`modelSourceType: kubernetesVolume`, `kubernetes.volumes` doit contenir un volume portant le même nom.
+ **Montez les volumes au bon endroit dans votre InitContainer. ** Assurez-vous que tout volume que vous créez est monté sur le chemin correct dans votre InitContainer.
+ **Aucun compte de service personnalisé n'est nécessaire pour S3/FSx. ** Si vous ne parvenez pas à créer des comptes de service personnalisés ou si vous préférez ne pas le faire, vous pouvez utiliser `modelSourceType: s3` ou`fsx`. L'opérateur approvisionne S3/FSx les volumes automatiquement. Vous pouvez toujours ajouter des volumes personnalisés `initContainers` et des volumes de remplacement en plus du stockage géré par l'opérateur.
+ **Les informations d'identification IRSA sont injectées dans tous les conteneurs. ** Lorsque vous définissez un compte `kubernetes.serviceAccountName` de service avec une annotation IRSA, Amazon EKS injecte des AWS informations d'identification (`aws-iam-token`volume,,`AWS_WEB_IDENTITY_TOKEN_FILE`) dans tous les conteneurs`AWS_ROLE_ARN`, y compris vos InitContainers personnalisés.
+ **Ne pas régler `modelLocation` lors de l'utilisation`kubernetesVolume`. ** Le trajet du volume est contrôlé par`kubernetes.volumes`. `modelSourceType`Le fait de définir `modelLocation` quand `kubernetesVolume` entraîne une erreur de validation.
+ **Comprenez comment `model-weights-copy` fonctionne `model-weights` vs avec Prefetch. ** Lorsque `prefetchEnabled: true` l'opérateur crée deux volumes liés au modèle :
  + `model-weights`— le volume source (depuis Amazon S3/Amazon FSx PVC ou votre remplacement)
  + `model-weights-copy`— un RAM-backed EmptyDir où le travailleur lit réellement à partir de
+ Pendant que vous `model-weights` faites référence dans votre configuration`prefetchEnabled: true`, c'est en fait `model-weights-copy` ce qui est monté `/opt/ml/model` dans le conteneur de travail. Lorsque vous utilisez un InitContainer personnalisé, assurez-vous de copier les données dans le volume appelé`model-weights-copy`, c'est là que le travailleur s'attend à les trouver. Quand `prefetchEnabled: false` il n'y a qu'un seul volume (nommé d'après le vôtre`modelVolumeMount.name`) et qu'il est monté directement sur`/opt/ml/model`.

## Résolution des problèmes
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-troubleshooting"></a>

Utilisez ces commandes de débogage si votre déploiement ne fonctionne pas comme prévu.
+ Vérifiez l'`InferenceEndpointConfig`état pour connaître l'état de déploiement de haut niveau et les éventuels problèmes de configuration.

  ```
  kubectl describe InferenceEndpointConfig <ENDPOINT_NAME> -n <NAMESPACE>
  ```
+ Vérifiez le statut du déploiement de Kubernetes.

  ```
  kubectl describe deployment <ENDPOINT_NAME> -n <NAMESPACE>
  ```
+ Vérifiez l'état de tous les objets Kubernetes de votre espace de noms.

  ```
  kubectl get pods,svc,deployment,InferenceEndpointConfig,sagemakerendpointregistration -n <NAMESPACE>
  ```
+ Consultez les journaux InitContainer si l'étape de chargement du modèle échoue.

  ```
  kubectl logs <POD_NAME> -c smart-loader -n <NAMESPACE>
  ```
+ Si le déploiement échoue avec « introuvable dans l'espace de noms », vérifiez ServiceAccount qu'il existe :

  ```
  kubectl get serviceaccount <name> -n <namespace>
  ```
+ Si le déploiement échoue avec le message « non étiqueté comme assignable par l'utilisateur », demandez à votre administrateur de cluster d'ajouter l'étiquette requise :

  ```
  kubectl label serviceaccount <name> sagemaker.amazonaws.com/user-assignable=true -n <namespace>
  ```
+ Si le déploiement échoue avec le message « ne doit pas faire référence au compte de service de l'opérateur », créez un compte distinct ServiceAccount pour votre charge de travail. Vous ne pouvez pas utiliser le propre ServiceAccount opérateur d' HyperPod inférence.