共用方式為


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

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

概觀

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

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

如需更細微的容器動作控制,您可以使用內建的Linux安全性功能,例如 AppArmorseccomp

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

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

注意

目前,Kubernetes 環境對於惡意多租使用者使用並不完全安全。 其他安全性功能,例如 Microsoft適用於容器的 Defender、AppArmorseccompPod 安全性許可適用於節點的 Kubernetes RBAC,有效率地封鎖惡意探索。

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

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

App Armor

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

在 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。 某些工作負載可能需要比其他工作負載少一些 syscall 限制。 這表示它們可以在運行時間期間使用 『RuntimeDefault』 設定文件失敗。 若要減輕這類失敗,您可以指定 Unconfined 配置檔。 如果您的工作負載需要自定義配置檔,請參閱 設定自定義 seccomp 配置檔

限制

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

重要

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

註冊 KubeletDefaultSeccompProfilePreview 功能旗標

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

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

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

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

    az feature show --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
    
  3. 當狀態顯示為「已註冊」時,請使用 az provider register 命令,重新整理 Microsoft.ContainerService 資源提供者的註冊。

    az provider register --namespace Microsoft.ContainerService
    

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

1.請遵循步驟,藉由指定 "seccompDefault": "RuntimeDefault",在 kubelet 設定中套用 seccomp 配置檔。

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

2.檢查是否已套用設定。

您可以連線 到主機 ,並確認已在文件系統上進行組態變更,以確認這些設定已套用至節點。

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

啟用 SeccompDefault 時,預設會針對節點上排程的所有工作負載使用容器運行時間預設 seccomp 配置檔。 這可能會導致工作負載因為封鎖的 syscalls 而失敗。 如果工作負載失敗發生,您可能會看到錯誤,例如:

  • 啟用功能之後,工作負載會意外存在,並出現「許可權遭拒」錯誤。
  • 您也可以在稽核或 syslog 中看到 Seccomp 錯誤訊息,方法是將SCMP_ACT_ERRNO取代為預設配置檔中的SCMP_ACT_LOG。

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

設定自訂 seccomp 設定檔

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

  • 使用篩選要允許或拒絕的動作來定義。
  • 在 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 會回報錯誤。
    • 命令 chmod 無法由 seccomp 篩選條件執行,如範例輸出所示:
    kubectl get pods
    
    NAME                      READY     STATUS    RESTARTS   AGE
    chmod-prevented           0/1       Error     0          7s
    

Seccomp 安全性設定檔選項

Seccomp 安全性設定檔是一組已定義的 syscalls,允許或限制。 大部分的容器運行時間都有預設 seccomp 配置檔,如果與 Docker 所使用的配置檔不同,則類似。 如需可用配置檔的詳細資訊,請參閱 DockercontainerD 預設 seccomp 配置檔。

當您使用自定義節點組態設定 seccomp 時,AKS 會針對 RuntimeDefault 使用 containerD default seccomp 配置檔。

默認配置文件封鎖的重大 syscalls

DockercontainerD 都會維護安全 syscalls 的 allowlist。 下表列出有效封鎖的重大(但並非全部)syscalls,因為它們不在允許清單中。 如果您的工作負載需要任何封鎖的 syscalls,請勿使用 RuntimeDefault seccomp 配置檔。

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

封鎖的 syscall 描述
acct 帳戶 syscall 可讓容器停用自己的資源限制或處理會計。 也由 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 設定的 Syscall。 已經由 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 追蹤/分析 syscall,這可能會洩漏主機上的資訊。 也由 CAP_SYS_ADMIN閘道。
mbind 修改核心記憶體和 NUMA 設定的 Syscall。 已經由 CAP_SYS_NICE閘道。
mount 拒絕掛接,已由閘道 CAP_SYS_ADMIN
move_pages 修改核心記憶體和 NUMA 設定的 Syscall。
nfsservctl 拒絕與核心 nfs 精靈的互動。 自 Linux 3.1 起已過時。
open_by_handle_at 舊容器中斷的原因。 也由 CAP_DAC_READ_SEARCH閘道。
perf_event_open 追蹤/分析 syscall,這可能會洩漏主機上的資訊。
personality 防止容器啟用 BSD 模擬。 並非本質上是危險的,但測試不佳,有可能是核心巨魔。
pivot_root 拒絕pivot_root,應該是特殊許可權作業。
process_vm_readv 藉由卸 CAP_SYS_PTRACE除 來限制已封鎖的進程檢查功能。
process_vm_writev 藉由卸 CAP_SYS_PTRACE除 來限制已封鎖的進程檢查功能。
ptrace 追蹤/分析 syscall。 在 4.8 之前的 Linux 核心版本中封鎖,以避免 seccomp 略過。 追蹤/分析任意進程已經遭到封鎖,因為可能會洩漏主機上的資訊CAP_SYS_PTRACE。
query_module 拒絕核心模組上的操作和函式。 已過時。
quotactl 配額 syscall 可讓容器停用自己的資源限制或處理會計。 也由 CAP_SYS_ADMIN閘道。
reboot 不要讓容器重新啟動主機。 也由 CAP_SYS_BOOT閘道。
request_key 防止容器使用非命名空間的核心索引鍵器。
set_mempolicy 修改核心記憶體和 NUMA 設定的 Syscall。 已經由 CAP_SYS_NICE閘道。
setns 拒絕將線程與命名空間產生關聯。 也由 CAP_SYS_ADMIN閘道。
settimeofday 時間/日期不是命名空間。 也由 CAP_SYS_TIME閘道。
stime 時間/日期不是命名空間。 也由 CAP_SYS_TIME閘道。
swapon 拒絕開始/停止交換至檔案/裝置。 也由 CAP_SYS_ADMIN閘道。
swapoff 拒絕開始/停止交換至檔案/裝置。 也由 CAP_SYS_ADMIN閘道。
sysfs 過時的 syscall。
_sysctl 已過時,由 /proc/sys 取代。
umount 應該是特殊許可權作業。 也由 CAP_SYS_ADMIN閘道。
umount2 應該是特殊許可權作業。 也由 CAP_SYS_ADMIN閘道。
unshare 拒絕複製進程的新命名空間。 此外,除了 unshare --user 之外,也會受到 CAP_SYS_ADMIN閘道。
uselib 與共享連結庫相關的舊版 syscall,長時間未使用。
userfaultfd Userspace 頁面錯誤處理,基本上需要處理移轉。
ustat 過時的 syscall。
vm86 在核心 x86 實際模式虛擬機中。 也由 CAP_SYS_ADMIN閘道。
vm86old 在核心 x86 實際模式虛擬機中。 也由 CAP_SYS_ADMIN閘道。

下一步

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