共用方式為


使用內建 Linux 安全性功能對資源的安全性容器存取

在本文中,您將了解如何保護對您的 Azure Kubernetes Service (AKS) 工作負載資源的容器存取。

重要事項

2025 年 11 月 30 日開始,AKS 將不再支援或提供 Azure Linux 2.0 的安全性更新。 從 2026 年 3 月 31 日開始,節點映像將會移除,而且您將無法調整節點集區。 將 節點集區升級 至支援的 Kubernetes 版本,或移轉至 osSku AzureLinux3,以升級至受支援的 Azure Linux 版本。 如需詳細資訊,請參閱 AKS 上的 [淘汰] Azure Linux 2.0 節點集區

概觀

就如同您應授與使用者或群組所需的最低權限一樣,也應限制容器只能執行必要動作和流程。 為了將攻擊風險降到最低,請避免設定需要提升權限或根存取的應用程式和容器。

您可以使用內建的 Kubernetes Pod 安全性內容來定義更多的權限,例如要以其身分執行的使用者或群組、要公開的 Linux 功能,或在 Pod 資訊清單中設定 allowPrivilegeEscalation: false。 如需最佳做法詳細資訊,請參閱保護 Pod 對資源的存取

若要改善主機隔離並減少 Linux 上的橫向移動,您可以使用 使用者命名空間

若要針對容器動作進行更細微的控制,您可以使用內建的 Linux 安全性功能,例如 AppArmorseccomp

  1. 在節點層級定義 Linux 安全性功能。
  2. 透過 Pod 資訊清單實作功能。

內建 Linux 安全性功能僅適用於 Linux 節點和 Pod。

附註

目前,如果惡意使用多租用戶,則 Kubernetes 環境並非完全安全。 其他安全性功能,例如 適用於容器的 Microsoft DefenderAppArmorseccomp使用者命名空間Pod 安全性許可,或 適用於節點的 Kubernetes RBAC,有效率地封鎖惡意探索。

執行惡意多租用戶工作負載時,若要真正確保安全性,應該只信任 Hypervisor。 Kubernetes 的安全性網域會成為整個叢集,而非個別節點。

對於這些類型的惡意多租用戶工作負載,您應使用實際隔離的叢集。

使用者命名空間

Linux Pod 預設會使用數個命名空間執行:用來隔離網路識別的網路命名空間,以及用來隔離進程的 PID 命名空間。 使用者命名空間會將容器內的使用者與主機上的用戶隔離。 它也會限制功能和 Pod 與系統其餘部分的互動範圍。

容器內的UID和 GID 會對應至主機上的無許可權使用者,因此所有與主機其餘部分的互動都會發生,因為這些不具特殊許可權的UID和 GID。 例如,容器內的根目錄 (UID 0) 可以對應至主機上的使用者 65536。 Kubernetes 會建立對應,以確保它不會與其他 Pod 重疊,而使用系統上的使用者命名空間。

Kubernetes 實作有一些主要優點:

  • 增加主機隔離:如果容器逸出 Pod 界限,即使容器以根目錄的形式執行,它也沒有主機上的許可權。 原因是容器的 UID 和 GID 會對應至主機上的無許可權使用者。 如果有容器逸出,使用者命名空間可大幅保護容器可以讀取/寫入主機上哪些檔案,而該容器可以傳送訊號的程式。 授與的功能只能在使用者命名空間內有效,而不是在主機上。

  • 防止橫向移動:當不同容器的 UID 和 GID 對應至主機上的不同、非重疊 UID 和 GID 時,容器會更難互相攻擊。 例如,假設容器 A 在主機上以不同於容器 B 的不同 UID 和 GID 執行。如果是容器中斷,它可以在容器 B 的檔案和處理程式上執行的作業有限:只有檔案允許其他人讀取/寫入。 但即使最終也不可能,因為 Pod 根磁碟區的父目錄有額外的預防,以確保只有 Pod GID 可以存取它。

  • 接受最低許可權原則:由於UID和 GID 會對應至主機上的未特殊許可權使用者,只有需要主機許可權的使用者才能取得該原則(並停用使用者命名空間)。 如果沒有使用者命名空間,容器的使用者與主機的用戶之間就不會有任何區隔。 當主機需要容器內的許可權時,我們無法避免將許可權授與不需要它的進程。

  • 啟用新的使用案例:使用者命名空間可讓容器在自己的使用者命名空間內取得特定功能,而不會影響主機。 限制為 Pod 的功能會解除鎖定新的可能性,例如執行需要特殊許可權作業的應用程式,而不授與主機上的完整根存取權。 可以安全地實作的新使用案例包括:執行巢狀容器和無特殊許可權的容器組建。

  • 非特殊許可權的容器設定:大部分的容器建立和設定不會以根目錄的形式在主機上執行,這可大幅限制許多 CVE 的影響。

未使用使用者命名空間時,這些都不是真的。 如果容器以根目錄執行,則未使用使用者命名空間時,進程會以根目錄在主機上執行,這些功能在主機上有效,而且容器設定會在主機上以根目錄方式執行。

開始之前

開始之前,請確定您有下列專案:

限制

啟用使用者命名空間

不需要設定才能使用這項功能。 如果使用必要的 AKS 版本,所有專案都已現成運作。

  1. 建立名為 mypod.yaml 的檔案,然後將下列資訊清單複製進來:

    若要使用使用者命名空間,yaml 必須具有 欄位 hostUsers: false

    apiVersion: v1
    kind: Pod
    metadata:
      name: userns
    spec:
      hostUsers: false
      containers:
      - name: shell
        command: ["sleep", "infinity"]
        image: debian
    
  2. 使用 kubectl apply 命令來部署應用程式,並指定 YAML 資訊清單的名稱。

    kubectl apply -f mypod.yaml
    
  3. 使用 kubectl get pods 命令檢視已部署 Pod 的狀態。

    kubectl get pods
    
  4. Exec 進入 Pod,以使用 /proc/self/uid_map 命令進行檢查kubectl exec

    kubectl exec -ti userns -- bash
    # Now inside the pod run
    cat /proc/self/uid_map
    

輸出在最後一個數據行中應該有 65536。 例如:

0  833617920      65536

已降低 CVE

以下是一些完全/部分降低使用者命名空間的 CVE。

請記住,清單並不詳盡,只是一系列高分的 CVE,可減輕:

若要深入瞭解,請閱讀此 部落格文章 ,其中包含有關使用者命名空間的其他資訊。

應用程式裝甲

若要限制容器動作,您可以使用 AppArmor Linux 核心安全性模組。 AppArmor 提供用來作為基礎 AKS 節點 OS 的組件,且預設為啟用。 您可以建立 AppArmor 設定檔來限制讀取、寫入或執行動作,也可以限制系統功能,例如裝載檔案系統。 預設的 AppArmor 設定檔會限制存取各種 /proc/sys 位置,並提供方法以邏輯方式從基礎節點隔離容器。 AppArmor 適用於任何在 Linux 上執行的應用程式,而不只是 Kubernetes Pod。

附註

Azure Linux 3.0 不提供 AppArmor 支援。 針對 Azure Linux 3.0 節點,建議您利用 SELinux 而不是 AppArmor 進行強制存取控制。

在 AKS 叢集中使用 AppArmor 設定檔限制容器動作

若要了解 AppArmor 如何運作,下列範例會建立防止寫入檔案的設定檔。

  1. AKS 節點的 SSH

  2. 建立名為 deny-write.profile 的檔案。

  3. 複製並貼上下列內容:

    #include <tunables/global>
    profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
      #include <abstractions/base>
    
      file,
      # Deny all file writes.
      deny /** w,
    }
    

使用 apparmor_parser 命令新增 AppArmor 設定檔。

  1. 將設定檔新增至 AppArmor。

  2. 指定在上個步驟中所建立設定檔的名稱:

    sudo apparmor_parser deny-write.profile
    

    如果設定檔已正確剖析並套用至 AppArmor,則不會看到任何輸出,而且您將返回到命令提示字元。

  3. 現在,在本機電腦上建立名為 aks-apparmor.yaml 的 Pod 資訊清單。 此資訊清單:

    • 定義 container.apparmor.security.beta.kubernetes 的註釋。
    • 參考在前面步驟中建立的 deny-write 設定檔。
    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-apparmor
      annotations:
        container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
    spec:
      containers:
      - name: hello
        image: mcr.microsoft.com/dotnet/runtime-deps:6.0
        command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
    
  4. 部署 Pod 後,請執行下列命令來確認 hello-apparmor Pod 會顯示執行狀態:

    kubectl get pods
    
    NAME             READY   STATUS    RESTARTS   AGE
    aks-ssh          1/1     Running   0          4m2s
    hello-apparmor   0/1     Running   0          50s
    

如需 AppArmor 的詳細資訊,請參閱 Kube 中的 AppArmor 設定檔

安全運算 (seccomp)

AppArmor 適用於任何的 Linux 應用程式,而 seccomp (算) 則是在處理程序層級運作。 Seccomp 也是 Linux 核心安全性模組,且 AKS 節點使用的 containerd 執行階段原生支援。 使用 seccomp,您可以限制容器的系統呼叫。 seccomp 會針對惡意執行者進行的常見系統呼叫弱點建立額外的保護層,並可讓您為節點中的所有工作負載指定預設設定檔。

設定預設 seccomp 設定檔 (預覽)

您可以在建立新的 Linux 節點集區時,使用自訂節點設定來套用預設 seccomp 設定檔。 AKS 支援兩個值:RuntimeDefaultUnconfined。 某些工作負載可能需要比其他工作負載少一些的系統呼叫限制。 這表示它們在執行階段期間可能會因為使用 'RuntimeDefault' 設定檔而失敗。 若要緩解這類失敗,您可以指定 Unconfined 設定檔。 如果您的工作負載需要自訂設定檔,請參閱設定自訂 seccomp 設定檔

限制

  • SeccompDefault 不是 Windows 節點集區支援的參數。
  • SeccompDefault 從 2024-09-02-preview API 開始提供。

重要事項

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

註冊 KubeletDefaultSeccompProfilePreview 功能旗標

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

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

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

  2. 使用 az feature show 命令驗證註冊狀態。

    az feature show --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
    
  3. 當狀態反映「已註冊」時,使用 (部分機器翻譯) 命令,重新整理 az provider register 資源提供者的註冊。

    az provider register --namespace Microsoft.ContainerService
    

使用 seccomp 限制容器的系統呼叫

RuntimeDefault 會使用 containerd 的預設 seccomp 設定檔,限制特定系統呼叫來增強安全性。 受限制的系統呼叫將會失敗。 如需詳細資訊,請參閱 containerD 預設 seccomp 設定檔

2. 檢查是否已套用設定

您可以連線到主機並驗證已在檔案系統上進行設定變更,以確認這些設定已套用至節點。

3. 針對工作負載失敗進行疑難排解

啟用 SeccompDefault 時,預設會針對節點上排程的所有工作負載使用容器執行階段預設 seccomp 設定檔。 這可能會因為系統呼叫被封鎖而導致工作負載失敗。 如果發生工作負載失敗,您可能會看到錯誤,例如:

  • 啟用功能之後,工作負載會非預期地存在,並出現「拒絕權限」錯誤。
  • 您也可以在 auditd 或 syslog 中看到 seccomp 錯誤訊息,方法是將預設設定檔中的 SCMP_ACT_ERRNO 取代為 SCMP_ACT_LOG。

如果您遇到錯誤,建議將 seccomp 設定檔變更為 UnconfinedUnconfined 不會對系統呼叫施加限制,允許所有系統呼叫,這會減少安全性。

設定自訂 seccomp 設定檔

使用自訂 seccomp 設定檔,您可以更細微地控制受限制的系統呼叫。 符合只授與容器最小執行權限的最佳做法:

  • 使用篩選要允許或拒絕的動作來定義。
  • 在 Pod YAML 資訊清單內標註,以與 seccomp 篩選建立關聯。

若要看 Seccomp 實際運作,請建立一個防止變更檔案權限的篩選。

  1. AKS 節點的 SSH

  2. 建立名為 /var/lib/kubelet/seccomp/prevent-chmod 的 seccomp 篩選。

  3. 複製並貼上下列內容:

    {
      "defaultAction": "SCMP_ACT_ALLOW",
      "syscalls": [
        {
          "name": "chmod",
          "action": "SCMP_ACT_ERRNO"
        },
        {
          "name": "fchmodat",
          "action": "SCMP_ACT_ERRNO"
        },
        {
          "name": "chmodat",
          "action": "SCMP_ACT_ERRNO"
        }
      ]
    }
    

    在版本 1.19 和更新版本中,您需要設定:

    {
      "defaultAction": "SCMP_ACT_ALLOW",
      "syscalls": [
        {
          "names": ["chmod","fchmodat","chmodat"],
          "action": "SCMP_ACT_ERRNO"
        }
      ]
    }
    
  4. 在本機電腦上建立名為 aks-seccomp.yaml 的 Pod 資訊清單,然後貼上下列內容。 此資訊清單:

    • 定義 seccomp.security.alpha.kubernetes.io 的註釋。
    • 參考在上一步中建立的 prevent-chmod 篩選條件。
    apiVersion: v1
    kind: Pod
    metadata:
      name: chmod-prevented
      annotations:
        seccomp.security.alpha.kubernetes.io/pod: localhost/prevent-chmod
    spec:
      containers:
      - name: chmod
        image: mcr.microsoft.com/dotnet/runtime-deps:6.0
        command:
          - "chmod"
        args:
         - "777"
         - /etc/hostname
      restartPolicy: Never
    

    在版本 1.19 和更新版本中,您需要設定:

    apiVersion: v1
    kind: Pod
    metadata:
      name: chmod-prevented
    spec:
      securityContext:
        seccompProfile:
          type: Localhost
          localhostProfile: prevent-chmod
      containers:
      - name: chmod
        image: mcr.microsoft.com/dotnet/runtime-deps:6.0
        command:
          - "chmod"
        args:
         - "777"
         - /etc/hostname
      restartPolicy: Never
    
  5. 使用 kubectl apply 命令部署範例 Pod:

    kubectl apply -f ./aks-seccomp.yaml
    
  6. 使用 kubectl get pods 命令檢視 Pod 的狀態。

    • Pod 會回報錯誤。
    • seccomp 篩選會防止執行 chmod 命令,如範例輸出所示:
    kubectl get pods
    
    NAME                      READY     STATUS    RESTARTS   AGE
    chmod-prevented           0/1       Error     0          7s
    

如需協助針對 seccomp 配置檔進行疑難排解,請參閱 在 Azure Kubernetes Service 中排解 seccomp 配置檔組態問題

Seccomp 安全性設定檔選項

seccomp 安全性設定檔是允許或限制的一組已定義的系統呼叫。 大部分的容器執行階段都有預設的 seccomp 設定檔,如果與 Docker 所使用的設定檔不同,也會是類似的。 如需可用設定檔的詳細資訊,請參閱 DockercontainerD 預設 seccomp 設定檔。

當您使用自訂節點組態設定 seccomp 時,AKS 會針對我們的 RuntimeDefault 使用 containerD 的預設 seccomp 設定檔。

預設設定檔封鎖的重要系統呼叫

DockercontainerD 都維護著安全系統呼叫的允許清單。 下表列出了由於不在允許清單上而被有效封鎖的重要 (但非全部) 系統呼叫。 如果您的工作負載需要任何被封鎖的系統呼叫,請不要使用 RuntimeDefault seccomp 設定檔。

DockercontainerD 進行變更時,AKS 會更新其預設設定以便相符。 對此清單的更新可能會導致工作負載失敗。 如需版本更新,請參閱 AKS 版本資訊

已封鎖的系統呼叫 描述
acct 計量的系統呼叫,其可以讓容器停用自己的資源限制或處理程序計量。 也受到 CAP_SYS_PACCT 的限制。
add_key 防止容器使用沒有命名空間的核心金鑰環。
bpf 拒絕將可能持續存在的 bpf 程式載入到核心中,已經受到 CAP_SYS_ADMIN 的限制。
clock_adjtime 時間/日期沒有命名空間。 也受到 CAP_SYS_TIME 的限制。
clock_settime 時間/日期沒有命名空間。 也受到 CAP_SYS_TIME 的限制。
clone 拒絕複製新的命名空間。 也受到 CAP_SYS_ADMIN for CLONE_* 旗標的限制 (除了 CLONE_NEWUSER 之外)。
create_module 拒絕核心模組上的操作和函式。 已過時。 也受到 CAP_SYS_MODULE 的限制。
delete_module 拒絕核心模組上的操作和函式。 也受到 CAP_SYS_MODULE 的限制。
finit_module 拒絕核心模組上的操作和函式。 也受到 CAP_SYS_MODULE 的限制。
get_kernel_syms 拒絕擷取匯出的核心和模組符號。 已過時。
get_mempolicy 修改核心記憶體和 NUMA 設定的系統呼叫。 已經也受到 CAP_SYS_NICE 的限制。
init_module 拒絕核心模組上的操作和函式。 也受到 CAP_SYS_MODULE 的限制。
ioperm 防止容器修改核心 I/O 權限等級。 已經也受到 CAP_SYS_RAWIO 的限制。
iopl 防止容器修改核心 I/O 權限等級。 已經也受到 CAP_SYS_RAWIO 的限制。
kcmp 限制處理程序檢查功能,已透過捨棄 CAP_SYS_PTRACE 而被封鎖。
kexec_file_load kexec_load 的同等系統呼叫,執行相同的動作,稍微不同的引數。 也受到 CAP_SYS_BOOT 的限制。
kexec_load 拒絕載入新的核心供稍後執行。 也受到 CAP_SYS_BOOT 的限制。
keyctl 防止容器使用沒有命名空間的核心金鑰環。
lookup_dcookie 追蹤/分析系統呼叫,其可能洩漏主機上的資訊。 也受到 CAP_SYS_ADMIN 的限制。
mbind 修改核心記憶體和 NUMA 設定的系統呼叫。 已經也受到 CAP_SYS_NICE 的限制。
mount 拒絕掛接,已經也受到 CAP_SYS_ADMIN 的限制。
move_pages 修改核心記憶體和 NUMA 設定的系統呼叫。
nfsservctl 拒絕與核心 NFS 精靈的互動。 自 Linux 3.1 起已過時。
open_by_handle_at 舊容器突破的原因。 也受到 CAP_DAC_READ_SEARCH 的限制。
perf_event_open 追蹤/分析系統呼叫,其可能洩漏主機上的資訊。
personality 防止容器啟用 BSD 模擬。 本質上並非危險,但若測試不佳,則可能是核心漏洞。
pivot_root 拒絕 pivot_root,應該是特殊權限作業。
process_vm_readv 限制處理程序檢查功能,已透過捨棄 CAP_SYS_PTRACE 而被封鎖。
process_vm_writev 限制處理程序檢查功能,已透過捨棄 CAP_SYS_PTRACE 而被封鎖。
ptrace 追蹤/分析系統呼叫。 在 4.8 之前的 Linux 核心版本中封鎖,以避免 seccomp 略過。 透過捨棄 CAP_SYS_PTRACE 已經封鎖對任意處理程序的追蹤/分析 (因為它可能會洩漏主機上的資訊)。
query_module 拒絕核心模組上的操作和函式。 已過時。
quotactl 配額系統呼叫,其可以讓容器停用自己的資源限制或處理程序計量。 也受到 CAP_SYS_ADMIN 的限制。
reboot 不要讓容器重新啟動主機。 也受到 CAP_SYS_BOOT 的限制。
request_key 防止容器使用沒有命名空間的核心金鑰環。
set_mempolicy 修改核心記憶體和 NUMA 設定的系統呼叫。 已經也受到 CAP_SYS_NICE 的限制。
setns 拒絕將執行緒與命名空間產生關聯。 也受到 CAP_SYS_ADMIN 的限制。
settimeofday 時間/日期沒有命名空間。 也受到 CAP_SYS_TIME 的限制。
stime 時間/日期沒有命名空間。 也受到 CAP_SYS_TIME 的限制。
swapon 拒絕啟動/停止交換到檔案/裝置。 也受到 CAP_SYS_ADMIN 的限制。
swapoff 拒絕啟動/停止交換到檔案/裝置。 也受到 CAP_SYS_ADMIN 的限制。
sysfs 已過時的系統呼叫。
_sysctl 已過時,由 /proc/sys 取代。
umount 應是特殊權限的作業。 也受到 CAP_SYS_ADMIN 的限制。
umount2 應是特殊權限的作業。 也受到 CAP_SYS_ADMIN 的限制。
unshare 拒絕複製程序的新命名空間。 也受到 CAP_SYS_ADMIN 的限制,但 unshare --user 除外。
uselib 與共用程式庫相關的舊版系統呼叫,一段時間未使用。
userfaultfd 使用者空間頁面錯誤處理,主要需用於處理程序移轉。
ustat 已過時的系統呼叫。
vm86 在核心 x86 真實模式虛擬機器中。 也受到 CAP_SYS_ADMIN 的限制。
vm86old 在核心 x86 真實模式虛擬機器中。 也受到 CAP_SYS_ADMIN 的限制。

後續步驟

如需相關聯的最佳做法,請參閱 AKS 中叢集安全性和升級的最佳做法以及 AKS 中 Pod 安全性的最佳做法