使用者命名空間
Kubernetes v1.30 [beta]
本頁說明如何在 Kubernetes Pod 中使用使用者命名空間。使用者命名空間將容器內執行的使用者與主機中的使用者隔離。
以容器中的 root 身分執行的程序可以在主機中以不同的(非 root)使用者身分執行;換句話說,程序在使用者命名空間內的操作具有完整權限,但在命名空間外的操作則不具備權限。
您可以使用此功能來減少受入侵的容器可能對主機或相同節點中的其他 Pod 造成的損害。有 數個安全性漏洞 被評為高或嚴重,但在使用者命名空間啟用的情況下無法被利用。預計使用者命名空間也將減輕未來的一些漏洞。
開始之前
這是一個僅限 Linux 的功能,Linux 需要在使用的檔案系統上支援 idmap 掛載。這表示
- 在節點上,您用於
/var/lib/kubelet/pods/
的檔案系統,或您為此設定的自訂目錄,需要 idmap 掛載支援。 - Pod Volume 中使用的所有檔案系統都必須支援 idmap 掛載。
實際上,這表示您至少需要 Linux 6.3,因為 tmpfs 在該版本中開始支援 idmap 掛載。這通常是必要的,因為多個 Kubernetes 功能使用 tmpfs(預設掛載的服務帳戶權杖使用 tmpfs,密鑰使用 tmpfs 等)
在 Linux 6.3 中支援 idmap 掛載的一些常見檔案系統包括:btrfs、ext4、xfs、fat、tmpfs、overlayfs。
此外,容器執行期及其底層 OCI 執行期必須支援使用者命名空間。以下 OCI 執行期提供支援
注意
某些 OCI 執行期不包含在 Linux Pod 中使用使用者命名空間所需之支援。如果您使用託管的 Kubernetes,或已從套件下載並設定它,則叢集中的節點可能使用不包含此支援的執行期。若要在 Kubernetes 中使用使用者命名空間,您也需要使用 CRI 容器執行期,才能將此功能與 Kubernetes Pod 搭配使用
- containerd:2.0 版(及更高版本)支援容器的使用者命名空間。
- CRI-O:1.25 版(及更高版本)支援容器的使用者命名空間。
您可以在 GitHub 上的 issue 中查看 cri-dockerd 中使用者命名空間支援的狀態追蹤。
簡介
使用者命名空間是 Linux 功能,可將容器中的使用者對應到主機中不同的使用者。此外,在使用者命名空間中授予 Pod 的功能僅在命名空間內有效,在命名空間外則無效。
Pod 可以透過將 pod.spec.hostUsers
欄位設定為 false
來選擇加入使用使用者命名空間。
kubelet 將選取 Pod 對應到的主機 UID/GID,並以確保同一節點上的任何兩個 Pod 不使用相同對應的方式進行。
pod.spec
中的 runAsUser
、runAsGroup
、fsGroup
等欄位,一律參照容器內的使用者。
當此功能啟用時,有效的 UID/GID 範圍為 0-65535。這適用於檔案和程序 (runAsUser
、runAsGroup
等)。
使用此範圍以外 UID/GID 的檔案將被視為屬於溢位 ID,通常為 65534(在 /proc/sys/kernel/overflowuid
和 /proc/sys/kernel/overflowgid
中設定)。然而,即使以 65534 使用者/群組身分執行,也無法修改這些檔案。
大多數需要以 root 身分執行,但不存取其他主機命名空間或資源的應用程式,如果啟用使用者命名空間,應可繼續正常執行,無需任何變更。
了解 Pod 的使用者命名空間
幾個容器執行期環境及其預設配置(如 Docker Engine、containerd、CRI-O)使用 Linux 命名空間進行隔離。也存在其他技術,可以與這些執行期環境一起使用(例如,Kata Containers 使用 VM 而非 Linux 命名空間)。此頁面適用於使用 Linux 命名空間進行隔離的容器執行期環境。
建立 Pod 時,預設情況下,會使用幾個新的命名空間進行隔離:網路命名空間用於隔離容器的網路,PID 命名空間用於隔離程序的視圖等等。如果使用使用者命名空間,這將隔離容器中的使用者與節點中的使用者。
這表示容器可以以 root 身分執行,並對應到主機上的非 root 使用者。在容器內部,程序會認為它以 root 身分執行(因此像 apt
、yum
等工具可以正常運作),但實際上,程序在主機上沒有權限。您可以驗證這一點,例如,如果您從主機執行 ps aux
來檢查容器程序正在哪個使用者下執行。ps
顯示的使用者與您在容器內部執行命令 id
所看到的使用者不同。
這種抽象化限制了可能發生的情況,例如,如果容器設法逃逸到主機。鑑於容器在主機上以非特權使用者身分執行,它可以對主機執行的操作受到限制。
此外,由於每個 Pod 上的使用者將對應到主機中不同的非重疊使用者,因此它們可以對其他 Pod 執行的操作也受到限制。
授予 Pod 的 capabilities 也僅限於 Pod 使用者命名空間,並且在命名空間外大多無效,有些甚至完全失效。以下是兩個範例
- 如果授予使用使用者命名空間的 Pod
CAP_SYS_MODULE
,則不會有任何效果,Pod 無法載入核心模組。 CAP_SYS_ADMIN
僅限於 Pod 的使用者命名空間,在命名空間外無效。
如果不使用使用者命名空間,以 root 身分執行的容器,在容器逃逸的情況下,將在節點上擁有 root 權限。並且如果授予容器某些 capability,則這些 capability 在主機上也有效。當我們使用使用者命名空間時,這些情況都不成立。
如果您想了解更多關於使用使用者命名空間時的變更詳情,請參閱 man 7 user_namespaces
。
設定節點以支援使用者命名空間
預設情況下,kubelet 會根據主機的檔案和程序使用 0-65535 範圍內的 UID/GID 這個假設,為 Pod 指派高於 0-65535 範圍的 UID/GID,這對於大多數 Linux 發行版來說是標準做法。這種方法可防止主機的 UID/GID 與 Pod 的 UID/GID 之間發生任何重疊。
避免重疊對於減輕諸如 CVE-2021-25741 之類漏洞的影響非常重要,在該漏洞中,Pod 可能可以讀取主機中的任意檔案。如果 Pod 和主機的 UID/GID 不重疊,則 Pod 可以執行的操作將受到限制:Pod UID/GID 將與主機的檔案擁有者/群組不符。
kubelet 可以為 Pod 使用自訂的使用者 ID 和群組 ID 範圍。若要設定自訂範圍,節點需要具備
- 系統中名為
kubelet
的使用者(您不能在此處使用任何其他使用者名稱) - 已安裝二進位檔案
getsubids
(屬於 shadow-utils 的一部分)並位於 kubelet 二進位檔案的PATH
中。 - 為
kubelet
使用者設定從屬 UID/GID(請參閱man 5 subuid
和man 5 subgid
)。
此設定僅收集 UID/GID 範圍配置,不會變更執行 kubelet
的使用者。
您必須遵循為 kubelet
使用者指派的從屬 ID 範圍的一些限制
啟動 Pod 的 UID 範圍的從屬使用者 ID,**必須**是 65536 的倍數,並且必須大於或等於 65536。換句話說,您不能為 Pod 使用 0-65535 範圍內的任何 ID;kubelet 強加此限制是為了使其難以建立意外不安全的配置。
從屬 ID 計數必須是 65536 的倍數
從屬 ID 計數必須至少為
65536 x <maxPods>
,其中<maxPods>
是可在節點上執行的 Pod 最大數量。您必須為使用者 ID 和群組 ID 指派相同的範圍,即使其他使用者的使用者 ID 範圍與群組 ID 範圍不一致也沒關係。
任何指派的範圍都不應與任何其他指派重疊。
從屬配置必須只有一行。換句話說,您不能有多個範圍。
例如,您可以定義 /etc/subuid
和 /etc/subgid
,使其都具有針對 kubelet
使用者的這些條目
# The format is
# name:firstID:count of IDs
# where
# - firstID is 65536 (the minimum value possible)
# - count of IDs is 110 (default limit for number of) * 65536
kubelet:65536:7208960
與 Pod 安全性許可控制檢查整合
Kubernetes v1.29 [alpha]
對於啟用使用者命名空間的 Linux Pod,Kubernetes 以受控方式放寬了 Pod 安全性標準的應用。此行為可以由 功能閘道 UserNamespacesPodSecurityStandards
控制,這允許終端使用者提前選擇加入。管理員必須確保叢集中所有節點都啟用了使用者命名空間,才能使用此功能閘道。
如果您啟用相關的功能閘道並建立使用使用者命名空間的 Pod,即使在強制執行 Baseline 或 Restricted Pod 安全性標準的環境中,以下欄位也不會受到約束。此行為不會構成安全疑慮,因為具有使用者命名空間的 Pod 內部的 root
實際上是指容器內的使用者,永遠不會對應到主機上的特權使用者。以下是未針對這些情況下的 Pod 檢查的欄位清單
spec.securityContext.runAsNonRoot
spec.containers[*].securityContext.runAsNonRoot
spec.initContainers[*].securityContext.runAsNonRoot
spec.ephemeralContainers[*].securityContext.runAsNonRoot
spec.securityContext.runAsUser
spec.containers[*].securityContext.runAsUser
spec.initContainers[*].securityContext.runAsUser
spec.ephemeralContainers[*].securityContext.runAsUser
限制
當 Pod 使用使用者命名空間時,不允許使用其他主機命名空間。特別是,如果您設定 hostUsers: false
,則不允許設定以下任何一項
hostNetwork: true
hostIPC: true
hostPID: true
下一步
- 請參閱 搭配 Pod 使用使用者命名空間
此頁面上的項目參照了第三方產品或專案,這些產品或專案提供了 Kubernetes 所需的功能。Kubernetes 專案作者不對這些第三方產品或專案負責。有關更多詳細資訊,請參閱 CNCF 網站指南。
在提出新增額外第三方連結的變更之前,您應閱讀內容指南。