本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
使用者名稱字空間:現在支援在 Alpha 階段執行有狀態 Pod!
Kubernetes v1.25 引入了對使用者名稱字空間的支援,但僅限於無狀態 Pod。在 1.27 版本中進行了一些設計更改後,Kubernetes 1.28 取消了該限制。
此功能的美妙之處在於
- 它非常容易採用(你只需要在 Pod 規約中設定一個布林值)
- 對於大多數應用程式,不需要任何更改
- 透過顯著增強容器的隔離性並緩解被評為高危和嚴重級別的 CVE,提高了安全性。
本文解釋了使用者名稱字空間的基礎知識,並展示了
- 最近 Kubernetes v1.28 版本中帶來的變化
- 一個被評為高危漏洞的演示,該漏洞在使用使用者名稱字空間時無法被利用
- 使用此功能所需的執行時要求
- 在未來版本中,你可以期待關於使用者名稱字空間的哪些內容。
什麼是使用者名稱字空間?
使用者名稱字空間是一項 Linux 功能,它將容器的使用者和組識別符號(UID 和 GID)與主機上的識別符號隔離開來。容器中的識別符號可以對映到主機上的識別符號,使得用於不同容器的主機 UID/GID 永遠不會重疊。更重要的是,這些識別符號可以對映到主機上無特權的、不重疊的 UID 和 GID。這基本上意味著兩件事
由於不同容器的 UID 和 GID 對映到主機上不同的 UID 和 GID,即使容器逃逸了容器邊界,它們也很難相互攻擊。例如,如果容器 A 在主機上執行的 UID 和 GID 與容器 B 不同,那麼它對容器 B 的檔案和程序可以執行的操作是有限的:只能讀取/寫入檔案允許其他人訪問的內容,因為它永遠不會擁有所有者或組的許可權(主機上的 UID/GID 保證對於不同容器是不同的)。
由於 UID 和 GID 對映到主機上的無特權使用者,如果一個容器逃逸了容器邊界,即使它在容器內以 root 身份執行,它在主機上也沒有特權。這極大地保護了它能讀/寫哪些主機檔案,能向哪些程序傳送訊號等。
此外,授予的能力僅在使用者名稱字空間內有效,在主機上無效。
不使用使用者名稱字空間,以 root 身份執行的容器在發生容器逃逸的情況下,在節點上擁有 root 許可權。如果授予了容器某些能力,這些能力在主機上同樣有效。當使用使用者名稱字空間時,這些情況都不會發生(當然,除了 bug 🙂)。
1.28 的變化
如前所述,從 1.28 開始,Kubernetes 支援有狀態 Pod 的使用者名稱字空間。這意味著具有使用者名稱字空間的 Pod 可以使用任何型別的卷,它們不再像以前那樣僅限於某些卷型別。
用於啟用此功能的特性門控已重新命名,不再是 UserNamespacesStatelessPodsSupport
,從 1.28 開始,你應該使用 UserNamespacesSupport
。進行了許多更改,對節點主機的要求也發生了變化。因此,在 Kubernetes 1.28 中,特性標誌被重新命名以反映這一點。
演示
Rodrigo 建立了一個演示,利用了 CVE 2022-0492,並展示了在沒有使用者名稱字空間的情況下如何發生漏洞利用。他還展示了在容器使用此功能的 Pod 中無法使用此漏洞。
該漏洞被評為高危,並允許一個沒有特殊許可權的容器讀/寫主機上的任何路徑,並在主機上以 root 身份啟動程序。
如今,容器中的大多數應用程式都以 root 身份或半可預測的非 root 使用者(使用者 ID 65534 是一個相當普遍的選擇)執行。當你執行一個使用 userns 的容器的 Pod 時,Kubernetes 會將這些容器作為無特權使用者執行,而無需對你的應用程式進行任何更改。
這意味著兩個以使用者 65534 身份執行的容器實際上將被對映到主機上的不同使用者,從而限制了它們在逃逸時可以對彼此做什麼,如果它們以 root 身份執行,則在主機上的許可權將降低為無特權使用者的許可權。
節點系統要求
要使用此功能,對 Linux 核心版本和容器執行時都有要求。
在 Linux 上,你需要 Linux 6.3 或更高版本。這是因為該功能依賴於一個名為 idmap 掛載的核心特性,並且在 Linux 6.3 中合併了對 tmpfs 使用 idmap 掛載的支援。
如果你正在使用帶有 crun 的 CRI-O,CRI-O 1.28.1 和 crun 1.9 或更高版本支援此功能。如果你正在使用帶有 runc 的 CRI-O,則尚不支援。
containerd 的支援目前計劃在 containerd 2.0 中實現;無論你使用 crun 還是 runc,可能都不會有影響。
請注意,containerd 1.7 增加了對 Kubernetes 1.25 和 1.26 中實現的使用者名稱字空間的實驗性支援。1.27 中完成的重新設計不受 containerd 1.7 支援,因此,就使用者名稱字空間支援而言,它僅適用於 Kubernetes 1.25 和 1.26。
containerd 1.7 中存在一個限制,即在 Pod 啟動期間,它需要更改容器映象內每個檔案和目錄的所有權。這意味著它有儲存開銷,並可能顯著影響容器啟動延遲。Containerd 2.0 可能會包含一個實現,該實現將消除增加的啟動延遲和儲存開銷。如果你計劃在生產中使用 containerd 1.7 和使用者名稱字空間,請考慮這一點。
這些 containerd 的限制都不適用於 CRI-O 1.28。
下一步是什麼?
展望 Kubernetes 1.29,計劃是與 SIG Auth 合作,將使用者名稱字空間整合到 Pod 安全標準(PSS)和 Pod 安全准入中。目前,計劃是在使用使用者名稱字空間時放寬 PSS 策略中的檢查。這意味著欄位 spec[.*].securityContext
中的 runAsUser
、runAsNonRoot
、allowPrivilegeEscalation
和 capabilities
在使用使用者名稱字空間時不會觸發違規。該行為可能會透過使用 API Server 特性門控來控制,例如 UserNamespacesPodSecurityStandards
或類似名稱。
我如何參與?
你可以透過多種方式聯絡 SIG Node
- Slack: #sig-node
- 郵件列表
- 開放的社群問題/PR
你也可以直接聯絡我們:
- GitHub: @rata @giuseppe @saschagrunert
- Slack: @rata @giuseppe @sascha