以非 root 用户运行 Kubernetes 节点组件
Kubernetes v1.22 [alpha]本文档描述了如何使用用户命名空间,以非 root 权限运行 Kubernetes 节点组件,例如 kubelet、CRI、OCI 和 CNI。
此技术也被称为rootless 模式。
开始之前
您的 Kubernetes 服务器必须是 1.22 版本或更高版本。
要检查版本,请输入 kubectl version。
- 启用 Cgroup v2
- 启用带有用户会话的 systemd
- 根据主机 Linux 发行版配置几个 sysctl 值
- 确保您的非特权用户已列在
/etc/subuid和/etc/subgid中 - 启用
KubeletInUserNamespace功能门
在 Rootless Docker/Podman 中运行 Kubernetes
kind
kind 支持在 Rootless Docker 或 Rootless Podman 中运行 Kubernetes。
请参阅使用 Rootless Docker 运行 kind。
minikube
minikube 也支持在 Rootless Docker 或 Rootless Podman 中运行 Kubernetes。
请参阅 Minikube 文档
在非特权容器中运行 Kubernetes
sysbox
Sysbox 是一个开源容器运行时(类似于“runc”),支持在未授权容器中运行系统级工作负载,例如 Docker 和 Kubernetes,这些容器使用 Linux 用户命名空间进行隔离。
请参阅Sysbox 快速入门指南:Kubernetes-in-Docker 以获取更多信息。
Sysbox 支持在非特权容器中运行 Kubernetes,而无需 Cgroup v2,也无需 KubeletInUserNamespace 功能门。它通过在容器内部暴露专门设计的 /proc 和 /sys 文件系统,以及其他高级操作系统虚拟化技术来实现这一点。
直接在主机上运行 Rootless Kubernetes
K3s
K3s 实验性地支持 rootless 模式。
请参阅使用 Rootless 模式运行 K3s 以获取用法说明。
Usernetes
Usernetes 是 Kubernetes 的一个参考发行版,可以安装在 $HOME 目录中,而无需 root 权限。
Usernetes 支持 containerd 和 CRI-O 作为 CRI 运行时。Usernetes 支持使用 Flannel (VXLAN) 的多节点集群。
请参阅Usernetes 仓库 以获取用法说明。
手动部署在用户命名空间中运行 kubelet 的节点
本节提供了在用户命名空间中手动运行 Kubernetes 的提示。
说明
本节旨在供 Kubernetes 发行版开发人员阅读,而非最终用户。创建用户命名空间
第一步是创建一个用户命名空间。
如果您尝试在用户命名空间容器(例如 Rootless Docker/Podman 或 LXC/LXD)中运行 Kubernetes,那么您已经准备就绪,可以转到下一小节。
否则,您必须通过调用 unshare(2) 并使用 CLONE_NEWUSER 来创建用户命名空间。
可以使用命令行工具来取消共享用户命名空间,例如
取消共享用户命名空间后,您还需要取消共享其他命名空间,例如挂载命名空间。
您不需要在取消共享挂载命名空间后调用 chroot() 也不需要调用 pivot_root(),但是,您必须在命名空间中以可写方式挂载几个目录内部(而不是外部)。
至少,以下目录需要在命名空间内部(而不是外部)中可写:
/etc/run/var/logs/var/lib/kubelet/var/lib/cni/var/lib/containerd(对于 containerd)/var/lib/containers(对于 CRI-O)
创建委托的 cgroup 树
除了用户命名空间之外,您还需要具有可写的 cgroup 树和 cgroup v2。
说明
Kubernetes 对在用户命名空间中运行节点组件的支持需要 cgroup v2。不支持 cgroup v1。如果您尝试在基于 systemd 的主机上的 Rootless Docker/Podman 或 LXC/LXD 中运行 Kubernetes,那么您已经准备就绪。
否则,您必须使用 Delegate=yes 属性创建一个 systemd 单元,以委托具有可写权限的 cgroup 树。
在您的节点上,systemd 必须已经配置为允许委托;有关更多详细信息,请参阅 Rootless Containers 文档中的cgroup v2。
配置网络
节点组件的网络命名空间必须具有非环回接口,例如可以使用 slirp4netns、VPNKit 或 lxc-user-nic(1) 进行配置。
可以使用常规 CNI 插件来配置 Pod 的网络命名空间。对于多节点网络,Flannel (VXLAN, 8472/UDP) 已知可以工作。
例如 kubelet 端口 (10250/TCP) 和 NodePort 服务端口必须从节点网络命名空间暴露到主机,使用外部端口转发器,例如 RootlessKit、slirp4netns 或 socat(1)。
您可以使用 K3s 的端口转发器。有关更多详细信息,请参阅以 Rootless 模式运行 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_memoryvm.panic_on_oomkernel.panickernel.panic_on_oopskernel.keys.root_maxkeyskernel.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 网站指南。
在提出添加额外的第三方链接的更改之前,您应该阅读 内容指南。