在 Azure Kubernetes Service (AKS) 中使用 Pod 安全性原則來保護叢集 (預覽)

重要

Pod 安全性原則功能已在 2023 年 8 月 1 日棄用,並從 AKS 1.25 版和更新版本中移除。

建議您移轉至 Pod 安全性許可控制器Azure 原則,以保留在 Azure 支援內。 Pod 安全性許可為適用於單一叢集實作之內建原則解決方案。 如果您要尋找企業級原則,則 Azure 原則是較佳的選擇。

開始之前

  • 本文假設您具有現有 AKS 叢集。 如果您需要 AKS 叢集,則請使用 Azure CLIAzure PowerShellAzure 入口網站予以建立。
  • 您必須安裝並設定 Azure CLI 版本 2.0.61 或更新版本。 執行 az --version 以尋找版本。 如果您需要安裝或升級,請參閱安裝 Azure CLI

安裝 aks-preview Azure CLI 延伸模組

重要

AKS 預覽功能可透過自助服務,以加入方式使用。 預覽會以「現狀」和「可供使用時」提供,其其不受服務等級協定和有限瑕疵擔保所保護。 客戶支援部門會盡最大努力,部分支援 AKS 預覽。 因此,這些功能不適合實際執行用途。 如需詳細資訊,請參閱下列支援文章:

  1. 使用 az extension add 命令,來安裝 aks-preview 延伸模組。

    az extension add --name aks-preview
    
  2. 使用 az extension update 命令,以更新為延伸模組最新版。

    az extension update --name aks-preview
    

註冊 PodSecurityPolicyPreview 功能旗標

  1. 使用 az feature register 命令註冊 PodSecurityPolicyPreview 功能旗標。

    az feature register --namespace "Microsoft.ContainerService" --name "PodSecurityPolicyPreview"
    

    狀態需要幾分鐘的時間才會顯示「已註冊」

  2. 使用 az feature show 命令確認註冊狀態。

    az feature show --namespace "Microsoft.ContainerService" --name "PodSecurityPolicyPreview"
    
  3. 當狀態反映 [已註冊] 時,請使用 az provider register 命令來重新整理 Microsoft.ContainerService 資源提供者的註冊。

    az provider register --namespace Microsoft.ContainerService
    

Pod 安全性原則概觀

Kubernetes 叢集使用許可控制器,以在要建立資源時攔截對 API 伺服器的要求。 然後,許可控制器可以根據一組規則來「驗證」資源要求,或「變動」資源,以變更部署參數。

PodSecurityPolicy 是許可控制器,可驗證 Pod 規格是否符合您定義的需求。 這些需求可能會限制使用特殊權限的容器、存取特定類型的儲存體,或容器可執行身分的使用者或群組。 當您嘗試在 Pod 規格不符合 Pod 安全性原則中所述需求的情況下部署資源時,會拒絕要求。 控制 AKS 叢集中可排程哪些 Pod 的能力,可防止某些可能的安全性弱點或權限提升。

當您在 AKS 叢集中啟用 Pod 安全性原則時,會套用一些預設原則。 這些原則提供現成的體驗,以定義可排程的 Pod。 不過,除非您定義自己的原則,否則可能會在部署 Pod 時遇到問題。 建議方法是:

  1. 建立 AKS 叢集。
  2. 定義您自己的 Pod 安全性原則。
  3. 啟用 Pod 安全性原則功能。

Pod 安全性原則與 Azure 原則之間的行為變更

案例 Pod 安全性原則 Azure 原則
安裝 啟用 Pod 安全性原則功能 啟用 Azure 原則附加元件
部署原則 部署 Pod 安全性原則資源 將 Azure 原則指派給訂閱或資源群組範圍。 Kubernetes 資源應用程式需要 Azure 原則附加元件。
預設原則 在 AKS 中啟用 Pod 安全性原則時,會套用預設的「特殊權限」和「不受限制」的原則。 啟用 Azure 原則附加元件,不會套用預設原則。 您必須在 Azure 原則中明確啟用原則。
誰可以建立並指派原則 叢集管理員可建立 Pod 安全性原則資源 使用者必須具備 AKS 叢集資源群組上「擁有者」或「資源原則參與者」權限的最低角色。 - 透過 API,使用者可以在 AKS 叢集資源範圍指派原則。 使用者在 AKS 叢集資源上,至少應具有「擁有者」或「資源原則參與者」權限。 - 在 Azure 入口網站中,原則可以在管理群組/訂閱/資源群組層級指派。
授權原則 使用者和服務帳戶需要明確的權限才能使用 Pod 安全性原則。 授權原則不需要額外的指派。 在 Azure 中指派原則之後,所有叢集使用者皆可使用這些原則。
原則適用性 管理使用者會略過 Pod 安全性原則的強制執行。 所有使用者 (系統管理員和非系統管理員) 都會看到相同的原則。 使用者沒有特殊大小寫。 原則應用程式可以在命名空間層級排除。
原則範圍 未設定 Pod 安全性原則的命名空間 Azure 原則所使用的條件約束範本未設定命名空間。
拒絕/稽核/變動動作 Pod 安全性原則僅支援拒絕動作。 您可以在建立要求上使用預設值來完成變動。 驗證可以在更新要求期間完成。 Azure 原則同時支援稽核和拒絕動作。 尚未支援變動。
Pod 安全性原則合規性 啟用 Pod 安全性原則之前,沒有 Pod 合規性的可見度。 啟用 Pod 安全性原則之後建立之不符合規範的 Pod 會遭到拒絕。 套用 Azure 原則之前存在的不符合規範的 Pod 會顯示在原則違規中。 如果原則設定為拒絕效果,則啟用 Azure 原則之後建立的不符合規範 Pod 會遭到拒絕。
如何在叢集上檢視原則 kubectl get psp kubectl get constrainttemplate - 會傳回所有原則。
Pod 安全性原則標準 - 特殊權限 啟用此功能時,預設會建立具特殊權限的 Pod 安全性原則資源。 具特殊權限模式表示沒有限制,因此等同於沒有任何 Azure 原則指派。
Pod 安全性原則標準 - 基準/預設 使用者安裝 Pod 安全性原則基準資源。 Azure 原則提供內建的基準方案,其對應至基準 Pod 安全性原則。
Pod 安全性原則標準 - 受限制 使用者安裝 Pod 安全性原則受限制資源。 Azure 原則提供內建受限制的方案,其對應至受限制的 Pod 安全性原則。

在 AKS 叢集上啟用 Pod 安全性原則

注意

針對實際用途,除非您定義自己的自訂原則,則請不要啟用 Pod 安全性原則。 在本文中,我們會啟用 Pod 安全性原則作為第一個步驟,以查看預設原則如何限制 Pod 部署。

  • 使用 az aks update 命令來啟用 Pod 安全性原則。

    az aks update \
        --resource-group myResourceGroup \
        --name myAKSCluster \
        --enable-pod-security-policy
    

預設 AKS 原則

當您啟用 Pod 安全性原則時,AKS 會建立一個名為「特殊權限」的預設原則。 請勿編輯或移除預設原則。 請改為建立您自己的原則,以定義您想要控制的設定。 讓我們先看看這些預設原則如何影響 Pod 部署。

  1. 使用 kubectl get psp 命令來檢視可用的原則。

    kubectl get psp
    

    您的輸出看起來會與下列範例輸出類似:

    NAME         PRIV    CAPS   SELINUX    RUNASUSER          FSGROUP     SUPGROUP    READONLYROOTFS   VOLUMES
    privileged   true    *      RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *     configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim
    

    特殊權限 Pod 安全性原則會套用至 AKS 叢集中的任何已驗證使用者。 此指派是由 ClusterRolesClusterRoleBindings 所控制。

  2. 使用 kubectl get rolebindings 命令,以在 kube-system 命名空間中搜尋 default:privileged: 繫結。

    kubectl get rolebindings default:privileged -n kube-system -o yaml
    

    下列簡要範例輸出會顯示將 psp:privilegedClusterRole 指派給任何 system:authenticated 使用者。 此功能提供基本層級的權限,而不需要定義您自己的原則。

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      [...]
      name: default:privileged
      [...]
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: psp:privileged
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: Group
      name: system:masters
    

請務必先了解這些預設原則如何與使用者要求互動,以排程 Pod,再開始建立您自己的 Pod 安全性原則。 在接下來的幾節中,我們排程一些 Pod 來查看預設原則的運作情形。

在 AKS 叢集中建立測試使用者

當您使用 az aks get-credentials 命令時,預設會將 AKS 叢集的 admin 認證新增至您的 kubectl 設定。 管理使用者會略過 Pod 安全性原則的強制執行。 如果您使用 AKS 叢集的 Microsoft Entra 整合,則可以使用非系統管理員使用者的認證來登入,以查看強制執行原則的運作情形。

  1. 使用 kubectl create namespace 命令,以針對測試資源建立名為 psp-aks 的範例命名空間。

    kubectl create namespace psp-aks
    
  2. 使用 kubectl create serviceaccount 命令建立名為 nonadmin-user 的服務帳戶。

    kubectl create serviceaccount --namespace psp-aks nonadmin-user
    
  3. 使用 kubectl create rolebinding 命令,針對 nonadmin-user 來建立 RoleBinding,以在命名空間中執行基本動作。

    kubectl create rolebinding \
        --namespace psp-aks \
        psp-aks-editor \
        --clusterrole=edit \
        --serviceaccount=psp-aks:nonadmin-user
    

為管理員和非管理使用者建立別名命令

使用 kubectl 時,您可以建立兩個命令列別名,來醒目顯示一般系統管理員使用者與非系統管理員使用者之間的差異:

  1. kubectl-admin 別名適用於一般系統管理員使用者,而且範圍設定為 psp-aks 命名空間。
  2. kubectl-nonadminuser 別名適用於上一個步驟中所建立的 nonadmin-user,而且範圍設定為 psp-aks 命名空間。
  • 使用下列命令來建立這兩個別名。

    alias kubectl-admin='kubectl --namespace psp-aks'
    alias kubectl-nonadminuser='kubectl --as=system:serviceaccount:psp-aks:nonadmin-user --namespace psp-aks'
    

測試建立具特殊權限的 Pod

請測試當您使用 privileged: true 的資訊安全內容來排程 Pod 時會發生什麼情況。 此資訊安全內容會提升 Pod 的權限。 預設「權限」AKS 安全性原則應該會拒絕此要求。

  1. 建立名為 nginx-privileged.yaml 的檔案,並貼入下列 YAML 資訊清單的內容。

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-privileged
    spec:
      containers:
        - name: nginx-privileged
          image: mcr.microsoft.com/oss/nginx/nginx:1.14.2-alpine
          securityContext:
            privileged: true
    
  2. 使用 kubectl apply 命令來建立 Pod,並指定 YAML 資訊清單的名稱。

    kubectl-nonadminuser apply -f nginx-privileged.yaml
    

    下列範例輸出會顯示無法排程 Pod:

    Error from server (Forbidden): error when creating "nginx-privileged.yaml": pods "nginx-privileged" is forbidden: unable to validate against any pod security policy: []
    

    因為 Pod 不會到達排程階段,所以在您繼續之前,不會有任何需要刪除的資源。

測試建立不具特殊權限的 Pod

在上一個範例中,Pod 規格要求特殊權限提升。 預設權限 Pod 安全性原則已拒絕此要求,因此無法排程 Pod。 請嘗試執行相同的 NGINX Pod,而不需要權限提升要求。

  1. 建立名為 nginx-unprivileged.yaml 的檔案,並貼入下列 YAML 資訊清單的內容。

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-unprivileged
    spec:
      containers:
        - name: nginx-unprivileged
          image: mcr.microsoft.com/oss/nginx/nginx:1.14.2-alpine
    
  2. 使用 kubectl apply 命令來建立 Pod,並指定 YAML 資訊清單的名稱。

    kubectl-nonadminuser apply -f nginx-unprivileged.yaml
    

    下列範例輸出會顯示無法排程 Pod:

    Error from server (Forbidden): error when creating "nginx-unprivileged.yaml": pods "nginx-unprivileged" is forbidden: unable to validate against any pod security policy: []
    

    因為 Pod 不會到達排程階段,所以在您繼續之前,不會有任何需要刪除的資源。

使用特定使用者內容測試 Pod 的建立

在上一個範例中,容器映像會自動嘗試使用根來將 NGINX 繫結至連接埠 80。 預設權限 Pod 安全性原則已拒絕此要求,因此無法啟動 Pod。 請嘗試使用特定使用者內容來執行相同的 NGINX Pod,例如 runAsUser: 2000

  1. 建立名為 nginx-unprivileged-nonroot.yaml 的檔案,並貼入下列 YAML 資訊清單。

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-unprivileged-nonroot
    spec:
      containers:
        - name: nginx-unprivileged
          image: mcr.microsoft.com/oss/nginx/nginx:1.14.2-alpine
          securityContext:
            runAsUser: 2000
    
  2. 使用 kubectl apply 命令來建立 Pod,並指定 YAML 資訊清單的名稱。

    kubectl-nonadminuser apply -f nginx-unprivileged-nonroot.yaml
    

    下列範例輸出會顯示無法排程 Pod:

    Error from server (Forbidden): error when creating "nginx-unprivileged-nonroot.yaml": pods "nginx-unprivileged-nonroot" is forbidden: unable to validate against any pod security policy: []
    

    因為 Pod 不會到達排程階段,所以在您繼續之前,不會有任何需要刪除的資源。

建立自訂 Pod 安全性原則

既然您已了解預設 Pod 安全性原則的行為,讓我們提供一種方式,讓 nonadmin-user 成功排程 Pod。

我們將建立原則來拒絕可要求具特殊權限存取權的 Pod。 其他選項,例如 runAsUser 或允許的磁碟區,不會明確限制。 此類型的原則會拒絕具特殊權限存取的要求,但在其他方面允許叢集執行所要求的 Pod。

  1. 建立名為 psp-deny-privileged.yaml 的檔案,並貼入下列 YAML 資訊清單。

    apiVersion: policy/v1beta1
    kind: PodSecurityPolicy
    metadata:
      name: psp-deny-privileged
    spec:
      privileged: false
      seLinux:
        rule: RunAsAny
      supplementalGroups:
        rule: RunAsAny
      runAsUser:
        rule: RunAsAny
      fsGroup:
        rule: RunAsAny
      volumes:
     - '*'
    
  2. 使用 kubectl apply 命令來建立原則,並指定 YAML 資訊清單的名稱。

    kubectl apply -f psp-deny-privileged.yaml
    
  3. 使用 kubectl get psp 命令來檢視可用的原則。

    kubectl get psp
    

    在下列範例輸出中,比較 psp-deny-privileged 原則與先前範例中強制執行以建立 Pod 的預設「權限」原則。 您的原則只會拒絕使用 PRIV 升級。 對於 psp-deny-privileged 原則,使用者或群組沒有任何限制。

    NAME                  PRIV    CAPS   SELINUX    RUNASUSER          FSGROUP     SUPGROUP    READONLYROOTFS   VOLUMES
    privileged            true    *      RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
    psp-deny-privileged   false          RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *          
    

允許使用者帳戶使用自訂 Pod 安全性原則

在上一個步驟中,您已建立 Pod 安全性原則來拒絕要求特殊權限存取的 Pod。 若要允許使用原則,您可以建立 Role 或 ClusterRole。 然後,您會使用 RoleBinding 或 ClusterRoleBinding,將其中一個角色建立關聯。 在此範例中,我們將建立 ClusterRole,以讓您使用上一個步驟中建立的psp-deny-privileged 原則。

  1. 建立名為 psp-deny-privileged-clusterrole.yaml 的檔案,並貼入下列 YAML 資訊清單。

    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: psp-deny-privileged-clusterrole
    rules:
    - apiGroups:
      - extensions
       resources:
      - podsecuritypolicies
       resourceNames:
      - psp-deny-privileged
       verbs:
      - use
    
  2. 使用 kubectl apply 命令來建立 ClusterRole,並指定 YAML 資訊清單的名稱。

    kubectl apply -f psp-deny-privileged-clusterrole.yaml
    
  3. 建立名為 psp-deny-privileged-clusterrolebinding.yaml 的檔案,並貼入下列 YAML 資訊清單。

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: psp-deny-privileged-clusterrolebinding
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: psp-deny-privileged-clusterrole
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: Group
      name: system:serviceaccounts
    
  4. 使用 kubectl apply 命令來建立 ClusterRoleBinding,並指定 YAML 資訊清單的名稱。

    kubectl apply -f psp-deny-privileged-clusterrolebinding.yaml
    

注意

在本文中的第一個步驟中,已在 AKS 叢集上啟用 Pod 安全性原則功能。 建議做法是在定義自己的原則之後,只啟用 Pod 安全性原則功能。 這是您會啟用 Pod 安全性原則功能的階段。 已定義一或多個自訂原則,且使用者帳戶已與這些原則建立關聯。 您可以安全地啟用 Pod 安全性原則功能,並將預設原則所造成的問題降到最低。

再次測試建立不具特殊權限的 Pod

套用自訂 Pod 安全性原則,以及使用者帳戶使用原則的繫結後,讓我們嘗試再次建立不具特殊權限的 Pod。

此範例示範如何建立自訂 Pod 安全性原則,以定義不同使用者或群組的 AKS 叢集存取權。 預設 AKS 原則提供 Pod 可執行的嚴格控制,因此,請建立您自己的自訂原則,然後正確定義您需要的限制。

  1. 使用 nginx-privileged.yaml 資訊清單,以使用 kubectl apply 命令來建立 Pod。

    kubectl-nonadminuser apply -f nginx-unprivileged.yaml
    
  2. 使用 kubectl get pods 命令來檢查 Pod 的狀態。

    kubectl-nonadminuser get pods
    

    下列範例輸出會顯示已成功排程 Pod 並且「正在執行」

    NAME                 READY   STATUS    RESTARTS   AGE
    nginx-unprivileged   1/1     Running   0          7m14s
    
  3. 使用 kubectl delete 命令來刪除 NGINX 不具特殊權限的 Pod,並指定 YAML 資訊清單的名稱。

    kubectl-nonadminuser delete -f nginx-unprivileged.yaml
    

清除資源

  1. 使用 az aks update 命令來停用 Pod 安全性原則。

    az aks update \
        --resource-group myResourceGroup \
        --name myAKSCluster \
        --disable-pod-security-policy
    
  2. 使用 kubectl delete 命令來刪除 ClusterRole 和 ClusterRoleBinding。

    kubectl delete -f psp-deny-privileged-clusterrole.yaml
    
  3. 使用 kubectl delete 命令來刪除 ClusterRoleBinding。

    kubectl delete -f psp-deny-privileged-clusterrolebinding.yaml
    
  4. 使用 kubectl delete 命令來刪除安全性原則,並指定 YAML 資訊清單的名稱。

    kubectl delete -f psp-deny-privileged.yaml
    
  5. 使用 kubectl delete 命令來刪除 psp-aks 命名空間。

    kubectl delete namespace psp-aks
    

下一步

本文說明如何建立 Pod 安全性原則,以防止使用特殊權限存取。 原則可以強制執行許多功能,例如磁碟區類型或 RunAs 使用者。 如需可用選項的詳細資訊,請參閱 Kubernetes Pod 安全性原則參考文件

如需限制 Pod 網路流量的詳細資訊,請參閱在 AKS 中使用網路原則來保護 Pod 之間的流量