以非 root 用户身份运行 Kubernetes 节点组件
Kubernetes v1.22 [alpha]
本文档介绍了如何通过使用用户命名空间的方式,无需 root 权限即可运行 Kubernetes 节点组件,例如 kubelet、CRI、OCI 和 CNI。
这项技术也称为无根模式(rootless mode)。
准备工作
你的 Kubernetes 服务器版本必须是 1.22 或更高。
要检查版本,请运行 kubectl version
命令。
- 启用 Cgroup v2
- 为用户会话启用 systemd
- 根据主机 Linux 发行版配置多个 sysctl 值
- 确保你的非特权用户列在
/etc/subuid
和/etc/subgid
中 - 启用
KubeletInUserNamespace
特性门控
在无根 Docker/Podman 中运行 Kubernetes
kind
kind 支持在无根 Docker 或无根 Podman 中运行 Kubernetes。
minikube
minikube 也支持在无根 Docker 或无根 Podman 中运行 Kubernetes。
请参阅 Minikube 文档
在非特权容器中运行 Kubernetes
sysbox
Sysbox 是一个开源容器运行时(类似于 "runc"),它支持在通过 Linux 用户命名空间隔离的非特权容器中运行 Docker 和 Kubernetes 等系统级负载。
有关更多信息,请参阅Sysbox 快速入门指南:Docker 中的 Kubernetes。
Sysbox 支持在非特权容器中运行 Kubernetes,而无需 Cgroup v2 且无需 KubeletInUserNamespace
特性门控。它通过在容器内暴露经过特殊处理的 /proc
和 /sys
文件系统以及其他一些高级操作系统虚拟化技术来实现这一点。
在主机上直接运行无根 Kubernetes
K3s
K3s 实验性地支持无根模式。
有关用法,请参阅使用无根模式运行 K3s。
Usernetes
Usernetes 是 Kubernetes 的一个参考发行版,可以在 $HOME
目录下安装而无需 root 权限。
Usernetes 同时支持 containerd 和 CRI-O 作为 CRI 运行时。Usernetes 支持使用 Flannel (VXLAN) 的多节点集群。
有关用法,请参阅Usernetes 仓库。
手动部署在用户命名空间中运行 kubelet 的节点
本节提供了在用户命名空间中手动运行 Kubernetes 的提示。
注意
本节供 Kubernetes 发行版的开发者阅读,不面向最终用户。创建用户命名空间
第一步是创建一个用户命名空间。
如果你尝试在用户命名空间的容器(如无根 Docker/Podman 或 LXC/LXD)中运行 Kubernetes,则已准备就绪,可以跳到下一小节。
否则,你必须通过调用带有 CLONE_NEWUSER
参数的 unshare(2)
来自己创建一个用户命名空间。
用户命名空间也可以通过使用命令行工具来 unshare,例如
在 unshare 用户命名空间后,你还需要 unshare 其他命名空间,例如 mount 命名空间。
在 unshare mount 命名空间后,你不需要调用 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 树。
注意
Kubernetes 支持在用户命名空间中运行节点组件需要 cgroup v2。不支持 cgroup v1。如果你尝试在基于 systemd 的主机上运行无根 Docker/Podman 或 LXC/LXD 中的 Kubernetes,则已准备就绪。
否则,你必须创建一个带有 Delegate=yes
属性的 systemd Unit,以委托具有可写权限的 cgroup 树。
在你的节点上,systemd 必须已配置为允许委托;有关更多详细信息,请参阅 Rootless Containers 文档中的cgroup v2。
配置网络
节点组件的网络命名空间必须具有非回环接口,例如可以使用 slirp4netns、VPNKit 或 lxc-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 1.4 版本起,支持在用户命名空间中运行 containerd 的 CRI 插件。
在用户命名空间内运行 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 1.22 版本起,支持在用户命名空间中运行 CRI-O。
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
注意事项
大多数“非本地”卷驱动程序,例如
nfs
和iscsi
,无法工作。已知本地卷如local
、hostPath
、emptyDir
、configMap
、secret
和downwardAPI
可以工作。某些 CNI 插件可能无法工作。已知 Flannel (VXLAN) 可以工作。
有关更多信息,请参阅 rootlesscontaine.rs 网站上的注意事项和未来工作页面。
另请参阅
本页上的项目指的是提供 Kubernetes 所需功能的第三方产品或项目。Kubernetes 项目作者不对这些第三方产品或项目负责。有关更多详细信息,请参阅 CNCF 网站指南。
在提议添加额外第三方链接的更改之前,你应该阅读内容指南。