

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 kubectl 从本地 NVMe 存储中部署模型
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme"></a>

本主题向您展示如何在亚马逊上部署推理终端节点，这些终端节点 SageMaker HyperPod可以从节点的本地 NVMe 存储中加载模型权重，而不是通过网络从 Amazon S3 或 Amazon FSx 提取模型权重。在本地读取权重可以消除 Pod 启动期间的网络跳跃，从而缩短推理 pod 的冷启动时间，并且对于自动缩放事件、从零扩展的工作负载和对延迟敏感的故障转移非常有用。对于无需考虑冷启动延迟的工作负载，请使用`modelSourceType: s3`或`fsx`并跳过此主题。

本地 NVMe 是节点本地的，而且是短暂的：更换节点时，例如在现场中断、硬件故障或 AMI 刷新期间，NVMe 上的数据会丢失。本主题中的方法对此的处理方式有所不同 — 有些方法要求您预先填充每个节点，而另一些方法则在模型未在本地缓存时自动回退到 Amazon S3。本地 NVMe 实例存储通常存在于 P、G 和 Trn 实例系列中。请参阅 [Amazon EC2 实例存储规格](https://docs.aws.amazon.com/ec2/latest/instancetypes/ac.html#ac_instance-store)以验证您的实例类型的可用性。

您可以根据自己的存储要求从以下方法中进行选择：


**NVMe 部署方法**  

| \# | 方法 | 说明 | 
| --- | --- | --- | 
| 1 | Kubernetes 音量（无后备） | 当 NVMe 上的每个节点上都存在模型权重时使用。设置最简单，无需亚马逊 S3、亚马逊 FSx 或 InitContainers。 PV/PVC | 
| 2 | 带后备功能的 Kubernetes 音量 | 当模型可能不存在于每个节点上的 NVMe 上时使用。如果缺少模型initContainer，则可以先检查 NVMe，然后使用 IRSA 凭证从 Amazon S3 下载。 | 
| 3 | 具有预取和后备功能的 Amazon S3 | 当你想将模型权重暂存到 RAM 以启动 pod 时使用。您可以提供一个自定义initContainer，它会先检查 NVMe，如果模型未在本地缓存，则回退到从操作员配置的 Amazon S3 挂载中进行复制。 | 

## 先决条件
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-prereqs"></a>

在开始之前，请确认您已经：
+ 在您的 Amazon SageMaker HyperPod 集群上设置推理功能。有关更多信息，请参阅 [设置 HyperPod 集群以进行模型部署](sagemaker-hyperpod-model-deployment-setup.md)。
+ 安装了 [kubectl](https://kubernetes.io/docs/reference/kubectl/) 实用程序并在终端中配置了 [jq](https://jqlang.org/)。
+ Pre-populated 目标节点本地 NVMe 存储上的模型权重（有关说明，[将模型权重预加载到 NVMe](#sagemaker-hyperpod-model-deployment-deploy-nvme-preload)请参阅）。

## 选择您的部署方法
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-choose"></a>

使用以下决策流程来确定哪种方法适合您的用例。

```
                  ┌────────────────────────────┐
                  │ 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.   │  └──────────────────────┘
                  └──────────────────┘
```

## 使用 Kubernetes 卷进行部署（无后备）
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-volume"></a>

当您在每个节点上的 NVMe 上都有模型权重并且想要最简单的设置时，请使用这种方法 — 没有 Amazon S3 或 Amazon FSx 配置，没有， PV/PVC也没有 initContainers。

设置后`modelSourceType: kubernetesVolume`，操作员将完全跳过 PV/PVC 创建。不使用 CSI 驱动程序、亚马逊 S3 保险丝支架或亚马逊 FSx 支架。客户提供的`model-weights`卷直接用于 pod 规范，工作人员从 NVMe 读取模型数据。`/opt/ml/model`

**重要**  
使用时`modelSourceType: kubernetesVolume`，操作员会从您的工作器配置`modelVolumeMount.name`中派生出预期的卷名。 `kubernetes.volumes`必须包含同名的卷。如果找不到匹配的卷，操作员会对此进行验证，并附带`KubernetesVolumeValidationFailed`条件拒绝部署。在以下示例中，两者都使用`model-weights`。

1. 创建 `InferenceEndpointConfig` YAML 文件。将占位符值替换为您的实际资源标识符。

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

1. 部署`InferenceEndpointConfig`。

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

1. 验证部署状态。

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

## 使用带后备功能的 Kubernetes 卷进行部署
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-fallback"></a>

当模型可能位于也可能不在给定节点上的 NVMe 上时，请使用这种方法。`hostPath`卷只能在数据存在的节点上起作用——在其他节点上调度的 pod 会挂载一条空路径或不存在的路径，从而导致模型服务器出现故障。

在这种方法中，您可以设置`modelSourceType: kubernetesVolume`并提供一个自定义，`initContainer`即首先检查 NVMe，如果模型缺失，则使用 IRSA 凭证从 Amazon S3 下载。

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

在部署之前，请配置服务账户的 IAM 角色 (IRSA)，以向您的 pod 提供从 Amazon S3 下载的证书。

1. 获取您的集群的 OIDC 提供商 ID。

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

1. 创建 IAM 信任策略。将以下内容另存为`trust-policy.json`，替换占位符值。

   ```
   {
     "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"
         }
       }
     }]
   }
   ```
**警告**  
始终将信任策略的范围限定为特定的命名空间和 ServiceAccount 名称。切勿在主题条件中使用通配符（例如`system:serviceaccount:*:*`），因为这将允许任何命名空间 ServiceAccount 中的任何人代入该角色。

1. 创建 IAM 角色并为您的模型存储桶附加限定范围的 Amazon S3 读取策略。

   ```
   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. 使用 IRSA 注释创建 Kubernetes 服务账户。

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

### 部署模型
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-fallback-deploy"></a>

1. 创建 `InferenceEndpointConfig` YAML 文件。将占位符值替换为您的实际资源标识符。

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

1. 部署`InferenceEndpointConfig`。

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

1. 验证部署状态。

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

## 使用带预取和 NVMe 后备功能的 Amazon S3 进行部署
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-s3-prefetch"></a>

如果您希望通过将模型权重暂存到 RAM 来获得推理性能，请使用此方法；如果模型未在 NVMe 上本地缓存，则可以自动回退到 Amazon S3。

设置为时 `modelSourceType: s3``prefetchEnabled: true`，操作员会自动创建两个卷：
+ 以您的`modelVolumeMount.name`（通常`model-weights`）命名的卷 — 包含您的型号的 Amazon S3 CSI 保险丝支架
+ `model-weights-copy`— a 工作人员 RAM-backed`emptyDir`从中读取内容

您可以添加一个指向节点本地 NVMe 存储的自定义`nvme-cache`卷，以及一个自定义卷，`initContainer`该卷具有以下特征：
+ 如果模型存在于 NVMe 上，则从 NVMe 复制到 RAM (`model-weights-copy`)，则完全跳过网络。
+ 如果模型丢失，则回退到从 Amazon S3 挂载 (`model-weights`) 复制到 RAM (`model-weights-copy`)。（可选）复制到 NVMe，以便后续在同一节点上启动的 pod 使用快速本地路径。

**重要**  
使用此方法`kubernetes.volumes`时`model-weights`，请勿重写。操作员创建`model-weights`指向 Amazon S3 CSI 卷的指向。覆盖它会移除你的 initContainer 进行备用所需的操作员配置的卷。为您的 NVMe HostPath 使用单独的卷名（例如`nvme-cache`）。

**重要**  
请勿包含`model-weights-copy`在`kubernetes.volumes`。它是操作员自动创建的保留名称。你的 initContainer 可以在中引用它，`volumeMounts`但不能将其声明为卷。

1. 创建 `InferenceEndpointConfig` YAML 文件。将占位符值替换为您的实际资源标识符。

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

1. 部署`InferenceEndpointConfig`。

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

1. 验证部署状态。

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

## 通过预取了解模型权重和模型权重复制
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-prefetch-volumes"></a>

使用预取时，操作员会创建两个与模型相关的卷：
+ 以您的`modelVolumeMount.name`（通常`model-weights`）命名的卷 — 包含您的型号的 Amazon S3 CSI 保险丝支架
+ `model-weights-copy`— 一个 RAM-backed emptyDir，工作人员实际上是从中读取的

在你的`InferenceEndpointConfig`，你可以定义：

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

当你引用时 `model-weights``prefetchEnabled: true`，它`model-weights-copy`实际上是在工作器容器`/opt/ml/model`中安装的。使用自定义 InitContainer 时，请确保将数据复制到名`model-weights-copy`为的卷中，这是工作人员期望找到数据的地方。

当`prefetchEnabled: false`，只有一个卷（以你的名字命名`modelVolumeMount.name`）并且它直接安装在`/opt/ml/model`。

## 配置自定义服务账号
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa"></a>

您可以使用中的字段为推理终端节点 pod 分配自定义 Kubernetes ServiceAccount 。`spec.kubernetes.serviceAccountName` `InferenceEndpointConfig`这对于通过 IRSA（服务账户的 IAM 角色）向您的工作容器或初始化容器提供 AWS 证书非常有用，例如，在后备场景中从 Amazon S3 下载模型权重。

**重要**  
默认情况下，自定义服务帐户支持处于禁用状态，并且必须由集群管理员明确启用才能使用。有关说明，请参阅[启用自定义服务账号](#sagemaker-hyperpod-model-deployment-deploy-nvme-sa-enable)：

如果未指定 ServiceAccount，则使用命名空间的 ServiceAccount默认值。

### 启用自定义服务账号
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa-enable"></a>

默认情况下，自定义服务帐户支持处于禁用状态。集群管理员必须先在操作员的 Helm 配置中启用它，然后用户才能 ServiceAccounts 在自己的配置中引用自定义`InferenceEndpointConfig`。
+ 更新运算符 Helm 值以启用该功能。如果您通过 Helm 部署操作员，请使用以下标志进行升级：

  ```
  helm upgrade hyperpod-inference-operator <CHART_PATH> \
    --set enableCustomServiceAccounts=true \
    --reuse-values
  ```
+ 如果您将操作员部署为 Amazon EKS 附加组件，请更新插件配置以包含`enableCustomServiceAccounts: true`在高级配置设置中。
+ 验证操作员 pod 是否设置了环境变量：

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

  你应该看到：

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

**重要**  
如果未启用此功能，则任何指定的`InferenceEndpointConfig``kubernetes.serviceAccountName`内容都将被拒绝，并显示`DeploymentFailed`状态和消息：`kubernetes.serviceAccountName is not enabled. Requires addon configuration (enableCustomServiceAccounts: true)`。

### 为服务帐号加标签
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa-label"></a>

集群管理员必须先将其标记为可由用户分配 ServiceAccount，然后才能引用自定义：

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

只有 ServiceAccounts 带有此标签的推理端点才能引用。这是一种安全控制措施，用于防止未经授权的权限升级。

### 在您的配置中指定服务帐号
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa-spec"></a>

在你的`InferenceEndpointConfig`:下`spec.kubernetes`方添加`serviceAccountName`字段

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

### 验证规则
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa-validation"></a>

操作员在创建和更新操作中验证该`serviceAccountName`字段。如果满足以下任一条件，您的部署将被拒绝并`DeploymentFailed`显示状态：
+ 命名空间中 ServiceAccount 不存在 — `serviceAccountName "X" not found in namespace "Y"`
+  ServiceAccount 缺少所需的标签 — `serviceAccountName "X" is not labeled as user-assignable (requires label sagemaker.amazonaws.com/user-assignable=true)`
+  ServiceAccount 这是操作员的系统 ServiceAccount —— `serviceAccountName must not reference the operator's service account`

**注意**  
推理容器中的所有容器（工作容器、初始化容器和边车）都继承指定容器的权限。 ServiceAccount如果标注 ServiceAccount 为`eks.amazonaws.com/role-arn`，则 Pod 将收到该 IAM 角色的临时 AWS 证书。集群管理员只有在查看关联的 RBAC 角色和 IAM 权限后，才应 ServiceAccounts 将其标记为可由用户分配。

**注意**  
如果在 a 已在运行时被删除， ServiceAccount 则现有 pod 将继续使用其当前凭据运行，直到它们重新启动。`InferenceEndpointConfig`但是，新 pod 的创建（例如，在缩放或重新调度期间）将失败，因为它们已 ServiceAccount 不存在。操作员会验证部署 ServiceAccount 何时创建以及何时更新 IEC 规范，但不会持续监控。 ServiceAccount删除 SA 后更新 IEC 规范将生成`DeploymentFailed`状态。

### 自定义服务帐号的安全最佳实践
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa-security"></a>

当你使用 ServiceAccount 带有推理终端节点的自定义时， HyperPod 推理运算符会代表你创建部署。推理容器中的所有容器（包括工作器、初始化容器和边车）都继承指定容器的权限。 ServiceAccount请遵循以下最佳实践来保护您的集群。

**锁定 RBAC 权限**
+  ServiceAccount 为每个推理工作负载创建专用。不要在不相关的工作负载 ServiceAccounts 之间重复使用。
+ 仅绑定所需的最低 RBAC 权限。例如，如果您的初始化容器只需要从 Amazon S3 读取，则 ServiceAccount不应有权列出或修改 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>
  ```
+ 避免向推理 ServiceAccounts pod 授予集群范围的权限 (ClusterRoleBindings)。

**范围 IRSA IAM 角色的范围**
+  ServiceAccount 使用注释时`eks.amazonaws.com/role-arn`，请确保 IAM 角色遵循最低权限原则。
+ 将 Amazon S3 权限范围限定为包含您的模型权重的特定存储桶和前缀。

  ```
  {
    "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>/*"
      ]
    }]
  }
  ```
+ 不要使用广泛的托管策略，例如`AmazonS3FullAccess`在生产环境中。使用`AmazonS3ReadOnlyAccess`或自定义策略范围限于您的模型存储桶。

**保护用户可分配的标签**
+ 只有集群管理员才能添加或删除`sagemaker.amazonaws.com/user-assignable=true`标签。使用 Kubernetes RBAC 来限制谁可以修改 ServiceAccount 你的命名空间中的标签。
+ 在将其标记为可由用户分配 ServiceAccount 之前，请查看与关联的 RBAC 角色和 IAM 权限。
+ 定期对带有`user-assignable`标签的 ServiceAccounts 内容进行审计。

  ```
  kubectl get serviceaccounts -n <NAMESPACE> -l sagemaker.amazonaws.com/user-assignable=true
  ```
+ 确保非管理员角色在资源上不包含`patch``update`、或`create`动词。 ServiceAccount操作员在部署时验证`user-assignable`标签，但不会阻止未经授权的用户将标签添加到。 ServiceAccount限制谁可以 ServiceAccounts 通过 RBAC 进行修改是保护此标签的主要控制措施。 Non-admin 用户只能拥有`get`并`list`访问：

  ```
  # 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"]
  ```

**重要**  
 HyperPod 推理运算符充当中介，代表用户创建部署。与调用者直接创建 Pod 的标准 Kubernetes 工作负载不同，运算符会将指定的 pod 分配 ServiceAccount 给它创建的 Pod。这意味着，任何能够在该命名空间`InferenceEndpointConfig`中创建的人都可以有效地使用授予用户分配 ServiceAccount 的任何权限。确保命名空间级别的 RBAC 控制谁可以创建和更新资源。`InferenceEndpointConfig`

## 将模型权重预加载到 NVMe
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-preload"></a>

如果您需要在部署之前在特定节点上预先填充 NVMe，则可以使用一次性容器从 Amazon S3 进行同步。

**注意**  
这种方法通过定位特定的节点`nodeName`，不适用于自动缩放。对于自动扩展场景，请使用带后备功能的 Kubernetes 卷或带有预取方法的 Amazon S3，后者通过 initContainer 回退逻辑自动处理丢失的模型。

1. 创建预加载的 pod YAML 文件。将占位符值替换为您的实际资源标识符。

   ```
   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. 应用 pod 并监控同步进度。

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

1. 同步完成后清理 pod。

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

## 保留卷名
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-reserved-volumes"></a>

操作员管理多个无法通过覆盖的内部卷。`kubernetes.volumes`使用这些名称中的任何一个都会产生`KubernetesVolumeValidationFailed`条件。


**保留卷名**  

| \# | Name | 用途 | 
| --- | --- | --- | 
| 1 | shm | 用于进程间通信的共享内存 (/dev/shm) | 
| 2 | model-weights-copy | RAM-backed emptyDir 在以下情况下使用 prefetchEnabled: true | 
| 3 | parallel-copy-configmap | ConfigMap 用于并行复制脚本（预取） | 
| 4 | lmcache-config | lmCache 配置卷 | 
| 5 | gated-model-downloader-configmap | ConfigMap 用于门控模型下载脚本 | 

## 要记住的事情
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-things-to-remember"></a>
+ **请勿使用保留的卷名。**操作员管理多个内部卷（参见[保留卷名](#sagemaker-hyperpod-model-deployment-deploy-nvme-reserved-volumes)）。在中使用这些名称中的任何一个都会`kubernetes.volumes`产生一个`KubernetesVolumeValidationFailed`条件。
+ **卷名必须匹配。**操作员从中派生出卷名。`modelVolumeMount.name`使用时`modelSourceType: kubernetesVolume`，`kubernetes.volumes`必须包含具有相同名称的卷。
+ **将卷装载到 InitContainer 中的正确位置。**确保您创建的任何卷都已安装到 initContainer 中的正确路径上。
+ **不需要自定义服务帐户 S3/FSx。**如果您无法创建自定义服务帐号或者不想创建自定义服务帐号，则可以使用`modelSourceType: s3`或`fsx`。操作员会自动 S3/FSx 配置音量。您仍然可以在操作员管理的存储空间之上添加自定义卷`initContainers`和覆盖卷。
+ **IRSA 凭证已注入所有容器。**当您设置`kubernetes.serviceAccountName`带有 IRSA 注释的服务账户时，Amazon EKS 会将 AWS 凭证（`aws-iam-token`卷、、`AWS_WEB_IDENTITY_TOKEN_FILE`）注入所有容器`AWS_ROLE_ARN`，包括您的自定义 initContainers。
+ **使用`modelLocation`时请勿设置`kubernetesVolume`。**音量路径由控制`kubernetes.volumes`。设置`modelLocation`何`modelSourceType`时会`kubernetesVolume`导致验证错误。
+ **了解 `model-weights` v `model-weights-copy` s 是如何使用预取的。**何时`prefetchEnabled: true`，操作员创建两个与模型相关的卷：
  + `model-weights`— 源音量（来自亚马逊 S3/Amazon FSx PVC 或您的替代卷）
  + `model-weights-copy`— 一个 RAM-backed emptyDir，工作人员实际上是从中读取的
+ 当你`model-weights`在配置中引用时`prefetchEnabled: true`，它实际上`model-weights-copy`是在工作器容器`/opt/ml/model`中安装的。使用自定义 InitContainer 时，请确保将数据复制到名`model-weights-copy`为的卷中，这是工作人员期望找到数据的地方。当`prefetchEnabled: false`，只有一个卷（以你的名字命名`modelVolumeMount.name`）并且它直接安装在`/opt/ml/model`。

## 问题排查
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-troubleshooting"></a>

如果部署无法按预期工作，请使用以下调试命令。
+ 检查`InferenceEndpointConfig`状态以查看高级部署状态和任何配置问题。

  ```
  kubectl describe InferenceEndpointConfig <ENDPOINT_NAME> -n <NAMESPACE>
  ```
+ 检查 Kubernetes 部署状态。

  ```
  kubectl describe deployment <ENDPOINT_NAME> -n <NAMESPACE>
  ```
+ 检查命名空间中所有 Kubernetes 对象的状态。

  ```
  kubectl get pods,svc,deployment,InferenceEndpointConfig,sagemakerendpointregistration -n <NAMESPACE>
  ```
+ 如果模型加载步骤失败，请查看 InitContainer 日志。

  ```
  kubectl logs <POD_NAME> -c smart-loader -n <NAMESPACE>
  ```
+ 如果部署失败并显示 “未在命名空间中找到”，请验证是否 ServiceAccount 存在：

  ```
  kubectl get serviceaccount <name> -n <namespace>
  ```
+ 如果部署失败并显示 “未标记为可由用户分配”，请您的集群管理员添加所需的标签：

  ```
  kubectl label serviceaccount <name> sagemaker.amazonaws.com/user-assignable=true -n <namespace>
  ```
+ 如果部署失败并显示 “不得引用操作员的服务帐户”，请 ServiceAccount 为您的工作负载单独创建一个帐户。你不能使用推理运算符自己的 HyperPod ServiceAccount推理运算符。