以非 root 用户身份运行 Kubernetes 节点组件
Kubernetes v1.22 [alpha]
本文档描述了如何通过使用 用户命名空间,在没有 root 权限的情况下运行 Kubernetes 节点组件,例如 kubelet、CRI、OCI 和 CNI。
此技术也称为 *无根模式*。
注意
本文档描述了如何以非 root 用户身份运行 Kubernetes 节点组件(以及由此产生的 Pod)。
如果您只想了解如何以非 root 用户身份运行 Pod,请参阅 SecurityContext。
开始之前
您的 Kubernetes 服务器必须是 1.22 版本或更高版本。要检查版本,请输入 kubectl version
。
- 启用 Cgroup v2
- 启用带有用户会话的 systemd
- 根据主机 Linux 发行版配置几个 sysctl 值
- 确保您的非特权用户在
/etc/subuid
和/etc/subgid
中列出 - 启用
KubeletInUserNamespace
功能开关
在无根 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
功能开关。它通过在容器内公开经过特殊制作的 /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)
来自己创建用户命名空间。
还可以通过使用以下命令行工具来取消共享用户命名空间:
在取消共享用户命名空间后,您还需要取消共享其他命名空间,例如挂载命名空间。
您 *不需要* 在取消共享挂载命名空间后调用 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,那么您已经设置好了。
否则,您必须创建一个带有 Delegate=yes
属性的 systemd 单元,以委托具有可写权限的 cgroup 树。
在您的节点上,systemd 必须已经配置为允许委托;有关更多详细信息,请参阅 Rootless Containers 文档中的 cgroup v2。
配置网络
节点组件的网络命名空间必须具有非回环接口,可以使用例如 slirp4netns、VPNKit 或 lxc-user-nic(1) 配置。
可以使用常规 CNI 插件配置 Pod 的网络命名空间。对于多节点网络,已知 Flannel(VXLAN,8472/UDP)有效。
必须使用外部端口转发器(例如 RootlessKit、slirp4netns 或 socat(1))将节点网络命名空间中的端口(例如 kubelet 端口(10250/TCP)和 NodePort
服务端口)暴露到主机。
您可以使用 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”。
也可以通过挂载经过特殊制作的 proc 文件系统(如 Sysbox 所做的那样)在不使用此功能开关的情况下在用户命名空间中运行 kubelet,但这不受官方支持。
配置 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 网站指南 以了解更多详细信息。
在提出添加第三方链接的更改之前,您应该阅读内容指南。