以非 root 用户运行 Kubernetes 节点组件

功能状态: Kubernetes v1.22 [alpha]

本文档描述了如何使用用户命名空间,以非 root 权限运行 Kubernetes 节点组件,例如 kubelet、CRI、OCI 和 CNI。

此技术也被称为rootless 模式

开始之前

您的 Kubernetes 服务器必须是 1.22 版本或更高版本。

要检查版本,请输入 kubectl version

在 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 的提示。

创建用户命名空间

第一步是创建一个用户命名空间

如果您尝试在用户命名空间容器(例如 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。

如果您尝试在基于 systemd 的主机上的 Rootless Docker/Podman 或 LXC/LXD 中运行 Kubernetes,那么您已经准备就绪。

否则,您必须使用 Delegate=yes 属性创建一个 systemd 单元,以委托具有可写权限的 cgroup 树。

在您的节点上,systemd 必须已经配置为允许委托;有关更多详细信息,请参阅 Rootless Containers 文档中的cgroup v2

配置网络

节点组件的网络命名空间必须具有非环回接口,例如可以使用 slirp4netnsVPNKitlxc-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_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 AM PST:更新 /tasks/administer-cluster 部分的页面权重 (b1202c78ff)