以非 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)