以非 root 使用者身份執行 Kubernetes 節點元件

特性狀態: Kubernetes v1.22 [alpha]

本文件描述瞭如何透過使用使用者名稱空間,以非 root 許可權執行 kubelet、CRI、OCI 和 CNI 等 Kubernetes 節點元件。

此技術也稱為_無根模式_。

準備工作

你的 Kubernetes 伺服器必須是 1.22 或更高版本。

要檢查版本,請輸入 kubectl version

在無根 Docker/Podman 中執行 Kubernetes

kind

kind 支援在無根 Docker 或無根 Podman 中執行 Kubernetes。

請參閱使用無根 Docker 執行 kind

minikube

minikube 也支援在無根 Docker 或無根 Podman 中執行 Kubernetes。

請參閱 Minikube 文件

在非特權容器中執行 Kubernetes

sysbox

Sysbox 是一個開源容器執行時(類似於 "runc"),支援在透過 Linux 使用者名稱空間隔離的非特權容器中執行 Docker 和 Kubernetes 等系統級工作負載。

有關更多資訊,請參閱Sysbox 快速入門指南:Kubernetes-in-Docker

Sysbox 支援在非特權容器中執行 Kubernetes,而無需 Cgroup v2,也無需 KubeletInUserNamespace Feature Gate。它透過在容器內部公開特殊製作的 /proc/sys 檔案系統以及其他幾種高階作業系統虛擬化技術來實現這一點。

直接在主機上執行無根 Kubernetes

K3s

K3s 實驗性地支援無根模式。

有關用法,請參閱以無根模式執行 K3s

Usernetes

Usernetes 是 Kubernetes 的參考發行版,無需 root 許可權即可安裝在 $HOME 目錄下。

Usernetes 同時支援 containerd 和 CRI-O 作為 CRI 執行時。Usernetes 支援使用 Flannel (VXLAN) 的多節點叢集。

有關用法,請參閱Usernetes 倉庫

手動部署在使用者名稱空間中執行 kubelet 的節點

本節提供了在使用者名稱空間中手動執行 Kubernetes 的提示。

建立使用者名稱空間

第一步是建立使用者名稱空間

如果你嘗試在無根 Docker/Podman 或 LXC/LXD 等使用者名稱空間容器中執行 Kubernetes,則已配置完成,可以進入下一小節。

否則,你必須透過使用 CLONE_NEWUSER 呼叫 unshare(2) 來自行建立使用者名稱空間。

使用者名稱空間也可以透過使用命令列工具(例如)取消共享

在取消共享使用者名稱空間後,你還需要取消共享其他名稱空間,例如掛載名稱空間。

在取消共享掛載名稱空間後,你_不需要_呼叫 chroot()pivot_root(),但是,你必須在名稱空間_內部_的幾個目錄上掛載可寫檔案系統。

至少,以下目錄需要_在_名稱空間_內部_可寫(而不是_在名稱空間_之外_)

  • /etc
  • /run
  • /var/logs
  • /var/lib/kubelet
  • /var/lib/cni
  • /var/lib/containerd(針對 containerd)
  • /var/lib/containers(針對 CRI-O)

建立委託的 cgroup 樹

除了使用者名稱空間,你還需要一個具有 cgroup v2 的可寫 cgroup 樹。

如果你嘗試在基於 systemd 的主機上執行無根 Docker/Podman 或 LXC/LXD 中的 Kubernetes,則已配置完成。

否則,你必須建立一個帶有 Delegate=yes 屬性的 systemd 單元,以委託一個具有寫入許可權的 cgroup 樹。

在你的節點上,systemd 必須已配置為允許委託;有關更多詳細資訊,請參閱無根容器文件中的cgroup v2

配置網路

節點元件的網路名稱空間必須具有一個非迴環介面,例如可以使用 slirp4netnsVPNKitlxc-user-nic(1) 進行配置。

Pod 的網路名稱空間可以使用常規的 CNI 外掛進行配置。對於多節點網路,Flannel (VXLAN, 8472/UDP) 已知可以工作。

kubelet 埠 (10250/TCP) 和 NodePort 服務埠等埠必須透過外部埠轉發器(例如 RootlessKit、slirp4netns 或 socat(1))從節點網路名稱空間暴露給主機。

你可以使用 K3s 的埠轉發器。有關更多詳細資訊,請參閱在無根模式下執行 K3s。該實現可以在 k3s 的 pkg/rootlessports中找到。

配置 CRI

kubelet 依賴於容器執行時。你應該部署一個容器執行時(例如 containerd 或 CRI-O),並確保它在 kubelet 啟動之前在使用者名稱空間中執行。

containerd 的 CRI 外掛在使用者名稱空間中執行自 containerd 1.4 起受支援。

在使用者名稱空間中執行 containerd 需要以下配置。

version = 2

[plugins."io.containerd.grpc.v1.cri"]
# Disable AppArmor
  disable_apparmor = true
# Ignore an error during setting oom_score_adj
  restrict_oom_score_adj = true
# Disable hugetlb cgroup v2 controller (because systemd does not support delegating hugetlb controller)
  disable_hugetlb_controller = true

[plugins."io.containerd.grpc.v1.cri".containerd]
# Using non-fuse overlayfs is also possible for kernel >= 5.11, but requires SELinux to be disabled
  snapshotter = "fuse-overlayfs"

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
# We use cgroupfs that is delegated by systemd, so we do not use SystemdCgroup driver
# (unless you run another systemd in the namespace)
  SystemdCgroup = false

配置檔案的預設路徑是 /etc/containerd/config.toml。可以使用 containerd -c /path/to/containerd/config.toml 指定路徑。

CRI-O 在使用者名稱空間中執行自 CRI-O 1.22 起受支援。

CRI-O 需要設定環境變數 _CRIO_ROOTLESS=1

還建議進行以下配置

[crio]
  storage_driver = "overlay"
# Using non-fuse overlayfs is also possible for kernel >= 5.11, but requires SELinux to be disabled
  storage_option = ["overlay.mount_program=/usr/local/bin/fuse-overlayfs"]

[crio.runtime]
# We use cgroupfs that is delegated by systemd, so we do not use "systemd" driver
# (unless you run another systemd in the namespace)
  cgroup_manager = "cgroupfs"

配置檔案的預設路徑是 /etc/crio/crio.conf。可以使用 crio --config /path/to/crio/crio.conf 指定路徑。

配置 kubelet

在使用者名稱空間中執行 kubelet 需要以下配置

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
  KubeletInUserNamespace: true
# We use cgroupfs that is delegated by systemd, so we do not use "systemd" driver
# (unless you run another systemd in the namespace)
cgroupDriver: "cgroupfs"

KubeletInUserNamespace 特性門啟用時,kubelet 會忽略在節點上設定以下 sysctl 值時可能發生的錯誤。

  • vm.overcommit_memory
  • vm.panic_on_oom
  • kernel.panic
  • kernel.panic_on_oops
  • kernel.keys.root_maxkeys
  • kernel.keys.root_maxbytes.

在使用者名稱空間中,kubelet 還會忽略嘗試開啟 /dev/kmsg 時引發的任何錯誤。此特性門還允許 kube-proxy 在設定 RLIMIT_NOFILE 時忽略錯誤。

KubeletInUserNamespace 特性門在 Kubernetes v1.22 中引入,狀態為 "alpha"。

在使用者名稱空間中執行 kubelet 而不使用此特性門也是可能的,方法是掛載一個經過特殊製作的 proc 檔案系統(如 Sysbox 所做),但不受官方支援。

配置 kube-proxy

在使用者名稱空間中執行 kube-proxy 需要以下配置

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "iptables" # or "userspace"
conntrack:
# Skip setting sysctl value "net.netfilter.nf_conntrack_max"
  maxPerCore: 0
# Skip setting "net.netfilter.nf_conntrack_tcp_timeout_established"
  tcpEstablishedTimeout: 0s
# Skip setting "net.netfilter.nf_conntrack_tcp_timeout_close"
  tcpCloseWaitTimeout: 0s

注意事項

  • 大多數“非本地”卷驅動程式(例如 nfsiscsi)不起作用。localhostPathemptyDirconfigMapsecretdownwardAPI 等本地卷已知可以工作。

  • 某些 CNI 外掛可能不起作用。Flannel (VXLAN) 已知可以工作。

有關更多資訊,請參閱 rootlesscontaine.rs 網站上的注意事項和未來工作頁面。

另請參閱

本頁上的專案引用了提供 Kubernetes 所需功能的第三方產品或專案。Kubernetes 專案的作者不對這些第三方產品或專案負責。有關更多詳細資訊,請參閱 CNCF 網站指南

在提議新增額外第三方連結的更改之前,你應該閱讀內容指南

上次修改時間:2023 年 1 月 11 日上午 11:12 PST:更新 /tasks/administer-cluster 部分的頁面權重 (b1202c78ff)