

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 kubectl 從本機 NVMe 儲存體部署模型
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme"></a>

本主題說明如何在 Amazon SageMaker HyperPod 上部署推論端點，以從節點的本機 NVMe 儲存體載入模型權重，而不是從 Amazon S3 或 Amazon FSx 透過網路提取模型權重。本機讀取權重可在 Pod 啟動期間消除網路跳轉，可縮短推論 Pod 冷啟動時間，並適用於自動擴展事件、scale-from-zero工作負載和延遲敏感型容錯移轉。對於不考慮冷啟動延遲的工作負載，請使用 `modelSourceType: s3`或 `fsx`並略過此主題。

本機 NVMe 是節點本機和暫時性：取代節點時，NVMe 上的資料會遺失，例如在 Spot 中斷、硬體故障或 AMI 重新整理期間。本主題中的方法處理方式不同：有些需要您預先填入每個節點，有些則不會在本機快取模型時自動回到 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 上存在模型權重時，請使用 。最簡單的設定，不需要 Amazon S3、Amazon FSx、PV/PVC 或 initContainers。 | 
| 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/)。
+ 在目標節點的本機 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 驅動程式、Amazon S3 融合掛載或 Amazon 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>

部署之前，請設定服務帳戶 (IRSA) 的 IAM 角色，提供 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` — 工作者讀取來源`emptyDir`的 RAM 後端

您新增一個指向節點本機 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
   ```

## 了解具有預先擷取的模型權重和model-weights-copy
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-prefetch-volumes"></a>

使用預先擷取時，運算子會建立兩個與模型相關的磁碟區：
+ 以您的 命名的磁碟區 `modelVolumeMount.name`（通常為 `model-weights`) — 包含模型的 Amazon S3 CSI 保險絲掛載
+ `model-weights-copy` — RAM 後端的 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>

您可以使用 中的 `spec.kubernetes.serviceAccountName` 欄位，將自訂 Kubernetes ServiceAccount 指派給推論端點 Pod`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>

在 `spec.kubernetes`的 下新增 `serviceAccountName` 欄位`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
```

### 驗證規則
<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`

**注意**  
推論 Pod 中的所有容器 （工作者、初始化容器和附屬） 都會繼承指定 ServiceAccount 的許可。如果 ServiceAccount 以 標註`eks.amazonaws.com/role-arn`，Pod 會收到該 IAM 角色的臨時 AWS 登入資料。叢集管理員在檢閱相關聯的 RBAC 角色和 IAM 許可後，只應將 ServiceAccounts 標記為使用者可指派。

**注意**  
如果在 `InferenceEndpointConfig` 已執行時刪除 ServiceAccount，現有的 Pod 會使用其目前的登入資料繼續執行，直到重新啟動為止。不過，新的 Pod 建立 （例如，在擴展或重新排程期間） 將會失敗，因為 ServiceAccount 不再存在。運算子會在第一次建立部署和更新 IEC 規格時驗證 ServiceAccount，不會持續監控 ServiceAccount。在刪除 SA 之後更新 IEC 規格將導致 `DeploymentFailed` 狀態。

### 自訂服務帳戶的安全最佳實務
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-sa-security"></a>

當您搭配推論端點使用自訂 ServiceAccount 時，HyperPod 推論運算子會代表您建立部署。推論 Pod 中的所有容器，包括工作者、初始化容器和附屬容器，都會繼承指定 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>
  ```
+ 避免將整個叢集的許可 (ClusterRoleBindings) 授予推論 Pod 使用的 ServiceAccounts。

**範圍 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 標記為使用者可指派之前，請檢閱與 ServiceAccount 相關聯的 RBAC 角色和 IAM 許可。
+ 定期稽核哪些 ServiceAccounts 帶有`user-assignable`標籤。

  ```
  kubectl get serviceaccounts -n <NAMESPACE> -l sagemaker.amazonaws.com/user-assignable=true
  ```
+ 確保非管理員角色不包含 ServiceAccount 資源上的 `patch``update`、 `create` 或動詞。運算子會在部署時間驗證`user-assignable`標籤，但不會防止未經授權的使用者將標籤新增至 ServiceAccount。限制誰可以透過 RBAC 修改 ServiceAccounts 是保護此標籤的主要控制項。非管理員使用者應僅具有 `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 工作負載不同，運算子會將指定的 ServiceAccount 指派給其建立的 Pod。這表示授予使用者指派的 ServiceAccount 的任何許可，都可以有效地提供給可在該命名空間`InferenceEndpointConfig`中建立 的任何人使用。確保命名空間層級的 RBAC 控制誰可以建立和更新`InferenceEndpointConfig`資源。

## 將模型權重預先載入至 NVMe
<a name="sagemaker-hyperpod-model-deployment-deploy-nvme-preload"></a>

如果您需要在特定節點上預先填入 NVMe 再部署，您可以使用一次性 Pod 從 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`條件。


**預留磁碟區名稱**  

| \# | 名稱 | 用途 | 
| --- | --- | --- | 
| 1 | shm | 用於程序間通訊的共用記憶體 (/dev/shm) | 
| 2 | model-weights-copy | RAM 後端 emptyDir 用於 prefetchEnabled: true | 
| 3 | parallel-copy-configmap | 適用於平行複製指令碼的 ConfigMap （預先擷取） | 
| 4 | lmcache-config | LMCache 組態磁碟區 | 
| 5 | gated-model-downloader-configmap | gated 模型下載指令碼的 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_ROLE_ARN`、、`AWS_WEB_IDENTITY_TOKEN_FILE`) 注入所有容器，包括您的自訂 initContainers。
+ **使用 `modelLocation`時請勿設定 `kubernetesVolume`。**磁碟區路徑由 控制`kubernetes.volumes`。將 `modelLocation` `modelSourceType` 設為 `kubernetesVolume`會導致驗證錯誤。
+ **了解 `model-weights` 與 `model-weights-copy` 如何使用預先擷取。**當 時`prefetchEnabled: true`，運算子會建立兩個與模型相關的磁碟區：
  + `model-weights` — 來源磁碟區 （來自 Amazon S3/Amazon FSx PVC 或您的覆寫）
  + `model-weights-copy` — RAM 後端的 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。