跳至主要内容

高级选项/配置

本节包含有关运行和管理 K3s 的不同方法以及准备主机操作系统以供 K3s 使用所需步骤的高级信息。

证书管理

证书颁发机构证书

K3s 在第一个服务器节点启动期间生成自签名证书颁发机构 (CA) 证书。这些 CA 证书有效期为 10 年,不会自动续订。

有关使用自定义 CA 证书或续订自签名 CA 证书的信息,请参阅k3s certificate rotate-ca 命令文档

客户端和服务器证书

K3s 客户端和服务器证书从其发行日期起有效期为 365 天。任何已过期或在 90 天内将要过期的证书都会在每次 K3s 启动时自动续订。

有关手动轮换客户端和服务器证书的信息,请参阅k3s certificate rotate 命令文档

令牌管理

默认情况下,K3s 使用单个静态令牌用于服务器和代理。创建集群后,此令牌无法更改。可以启用第二个静态令牌,该令牌只能用于加入代理,或者创建自动过期的临时 kubeadm 样式加入令牌。有关更多信息,请参阅k3s token 命令文档

配置 HTTP 代理

如果您在仅通过 HTTP 代理具有外部连接的环境中运行 K3s,则可以在 K3s systemd 服务上配置您的代理设置。然后,这些代理设置将在 K3s 中使用并传递给嵌入式 containerd 和 kubelet。

如果存在,K3s 安装脚本将自动获取 HTTP_PROXYHTTPS_PROXYNO_PROXY,以及 CONTAINERD_HTTP_PROXYCONTAINERD_HTTPS_PROXYCONTAINERD_NO_PROXY 变量来自当前 shell,并将它们写入 systemd 服务的环境文件,通常为

  • /etc/systemd/system/k3s.service.env
  • /etc/systemd/system/k3s-agent.service.env

当然,您也可以通过编辑这些文件来配置代理。

K3s 将自动将集群内部 Pod 和 Service IP 范围以及集群 DNS 域名添加到 NO_PROXY 条目的列表中。您应确保 Kubernetes 节点本身使用的 IP 地址范围(即节点的公有和私有 IP)包含在 NO_PROXY 列表中,或者节点可以通过代理访问。

HTTP_PROXY=http://your-proxy.example.com:8888
HTTPS_PROXY=http://your-proxy.example.com:8888
NO_PROXY=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

如果您想配置 containerd 的代理设置而不影响 K3s 和 Kubelet,则可以在变量前面加上 CONTAINERD_

CONTAINERD_HTTP_PROXY=http://your-proxy.example.com:8888
CONTAINERD_HTTPS_PROXY=http://your-proxy.example.com:8888
CONTAINERD_NO_PROXY=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

使用 Docker 作为容器运行时

K3s 包含并默认为containerd,这是一种行业标准的容器运行时。从 Kubernetes 1.24 开始,Kubelet 不再包含 dockershim,该组件允许 kubelet 与 dockerd 通信。K3s 1.24 及更高版本包含cri-dockerd,它允许从早期版本的 K3s 无缝升级,同时继续使用 Docker 容器运行时。

要使用 Docker 代替 containerd

  1. 在 K3s 节点上安装 Docker。可以使用 Rancher 的Docker 安装脚本之一来安装 Docker

    curl https://releases.rancher.com/install-docker/20.10.sh | sh
  2. 使用 --docker 选项安装 K3s

    curl -sfL https://get.k3s.io | sh -s - --docker
  3. 确认集群可用

    $ sudo k3s kubectl get pods --all-namespaces
    NAMESPACE NAME READY STATUS RESTARTS AGE
    kube-system local-path-provisioner-6d59f47c7-lncxn 1/1 Running 0 51s
    kube-system metrics-server-7566d596c8-9tnck 1/1 Running 0 51s
    kube-system helm-install-traefik-mbkn9 0/1 Completed 1 51s
    kube-system coredns-8655855d6-rtbnb 1/1 Running 0 51s
    kube-system svclb-traefik-jbmvl 2/2 Running 0 43s
    kube-system traefik-758cd5fc85-2wz97 1/1 Running 0 43s
  4. 确认 Docker 容器正在运行

    $ sudo docker ps
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    3e4d34729602 897ce3c5fc8f "entry" About a minute ago Up About a minute k8s_lb-port-443_svclb-traefik-jbmvl_kube-system_d46f10c6-073f-4c7e-8d7a-8e7ac18f9cb0_0
    bffdc9d7a65f rancher/klipper-lb "entry" About a minute ago Up About a minute k8s_lb-port-80_svclb-traefik-jbmvl_kube-system_d46f10c6-073f-4c7e-8d7a-8e7ac18f9cb0_0
    436b85c5e38d rancher/library-traefik "/traefik --configfi…" About a minute ago Up About a minute k8s_traefik_traefik-758cd5fc85-2wz97_kube-system_07abe831-ffd6-4206-bfa1-7c9ca4fb39e7_0
    de8fded06188 rancher/pause:3.1 "/pause" About a minute ago Up About a minute k8s_POD_svclb-traefik-jbmvl_kube-system_d46f10c6-073f-4c7e-8d7a-8e7ac18f9cb0_0
    7c6a30aeeb2f rancher/pause:3.1 "/pause" About a minute ago Up About a minute k8s_POD_traefik-758cd5fc85-2wz97_kube-system_07abe831-ffd6-4206-bfa1-7c9ca4fb39e7_0
    ae6c58cab4a7 9d12f9848b99 "local-path-provisio…" About a minute ago Up About a minute k8s_local-path-provisioner_local-path-provisioner-6d59f47c7-lncxn_kube-system_2dbd22bf-6ad9-4bea-a73d-620c90a6c1c1_0
    be1450e1a11e 9dd718864ce6 "/metrics-server" About a minute ago Up About a minute k8s_metrics-server_metrics-server-7566d596c8-9tnck_kube-system_031e74b5-e9ef-47ef-a88d-fbf3f726cbc6_0
    4454d14e4d3f c4d3d16fe508 "/coredns -conf /etc…" About a minute ago Up About a minute k8s_coredns_coredns-8655855d6-rtbnb_kube-system_d05725df-4fb1-410a-8e82-2b1c8278a6a1_0
    c3675b87f96c rancher/pause:3.1 "/pause" About a minute ago Up About a minute k8s_POD_coredns-8655855d6-rtbnb_kube-system_d05725df-4fb1-410a-8e82-2b1c8278a6a1_0
    4b1fddbe6ca6 rancher/pause:3.1 "/pause" About a minute ago Up About a minute k8s_POD_local-path-provisioner-6d59f47c7-lncxn_kube-system_2dbd22bf-6ad9-4bea-a73d-620c90a6c1c1_0
    64d3517d4a95 rancher/pause:3.1 "/pause"

使用 etcdctl

etcdctl 提供了一个用于与 etcd 服务器交互的 CLI。K3s 不捆绑 etcdctl。

如果您想使用 etcdctl 与 K3s 的嵌入式 etcd 交互,请使用官方文档安装 etcdctl。

ETCD_VERSION="v3.5.5"
ETCD_URL="https://github.com/etcd-io/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz"
curl -sL ${ETCD_URL} | sudo tar -zxv --strip-components=1 -C /usr/local/bin

然后,您可以通过将其配置为使用 K3s 管理的证书和密钥进行身份验证来使用 etcdctl

sudo etcdctl version \
--cacert=/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt \
--cert=/var/lib/rancher/k3s/server/tls/etcd/client.crt \
--key=/var/lib/rancher/k3s/server/tls/etcd/client.key

配置 containerd

K3s 将在 /var/lib/rancher/k3s/agent/etc/containerd/config.toml 中为 containerd 生成 config.toml。

对于此文件的高级自定义,您可以在同一目录中创建另一个名为 config.toml.tmpl 的文件,它将被使用。

config.toml.tmpl 将被视为 Go 模板文件,并且 config.Node 结构正在传递到模板中。有关如何使用该结构自定义配置文件的 Linux 和 Windows 示例,请参阅此文件夹。config.Node golang 结构定义此处

基本模板

版本门

从 2023 年 9 月发布版本开始提供:v1.24.17+k3s1、v1.25.13+k3s1、v1.26.8+k3s1、v1.27.5+k3s1、v1.28.1+k3s1

您可以扩展 K3s 基本模板,而不是从 K3s 源代码中复制粘贴完整的库存模板。如果您需要在现有配置的基础上构建并在末尾添加几行额外内容,这将非常有用。

#/var/lib/rancher/k3s/agent/etc/containerd/config.toml.tmpl

{{ template "base" . }}

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes."custom"]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes."custom".options]
BinaryName = "/usr/bin/custom-container-runtime"

替代容器运行时支持

如果 K3s 启动时存在其他容器运行时,K3s 将自动检测它们。支持的容器运行时为

crun, lunatic, nvidia, nvidia-cdi, nvidia-experimental, slight, spin, wasmedge, wasmer, wasmtime, wws

NVIDIA GPU 需要安装 NVIDIA 容器运行时才能在 Pod 中调度和运行加速工作负载。要在 K3s 中使用 NVIDIA GPU,请执行以下步骤

  1. 按照以下说明在节点上安装 nvidia-container 软件包存储库:
    https://nvidia.github.io/libnvidia-container/
  2. 安装 nvidia 容器运行时软件包。例如
    apt install -y nvidia-container-runtime cuda-drivers-fabricmanager-515 nvidia-headless-515-server
  3. 安装 K3s,或者如果已安装则重新启动它。
  4. 确认 k3s 已找到 nvidia 容器运行时
    grep nvidia /var/lib/rancher/k3s/agent/etc/containerd/config.toml

如果正确执行了这些步骤,则 K3s 会根据找到的运行时可执行文件自动将 NVIDIA 运行时添加到 containerd 配置中。

版本门

--default-runtime 标志和内置 RuntimeClass 资源从 2023 年 12 月发布版本开始提供:v1.29.0+k3s1、v1.28.5+k3s1、v1.27.9+k3s1、v1.26.12+k3s1
在这些版本之前,您必须为要在 Pod 规范中引用的任何运行时部署自己的 RuntimeClass 资源。

K3s 包含所有支持的替代运行时的 Kubernetes RuntimeClass 定义。您可以选择其中一个替换 runc 作为节点上的默认运行时,方法是通过 k3s CLI 或配置文件设置 --default-runtime 值。

如果您没有更改 GPU 节点上的默认运行时,则必须通过在 Pod 规范中设置 runtimeClassName: nvidia 来显式请求 NVIDIA 运行时

apiVersion: v1
kind: Pod
metadata:
name: nbody-gpu-benchmark
namespace: default
spec:
restartPolicy: OnFailure
runtimeClassName: nvidia
containers:
- name: cuda-container
image: nvcr.io/nvidia/k8s/cuda-sample:nbody
args: ["nbody", "-gpu", "-benchmark"]
resources:
limits:
nvidia.com/gpu: 1
env:
- name: NVIDIA_VISIBLE_DEVICES
value: all
- name: NVIDIA_DRIVER_CAPABILITIES
value: all

请注意,NVIDIA 容器运行时也经常与NVIDIA 设备插件一起使用,并进行修改以确保 pod 规范包含 runtimeClassName: nvidia,如上所述。

运行无代理服务器(实验性)

警告:此功能处于实验阶段。

使用 --disable-agent 标志启动时,服务器不会运行 kubelet、容器运行时或 CNI。它们不会在集群中注册节点资源,也不会出现在 kubectl get nodes 输出中。由于它们没有托管 kubelet,因此它们无法运行 Pod 或由依赖于枚举集群节点的操作符管理,包括嵌入式 etcd 控制器和系统升级控制器。

如果您想隐藏控制平面节点不被代理和工作负载发现,则运行无代理服务器可能是有利的,但代价是由于缺乏集群操作符支持而导致的管理开销增加。

默认情况下,无代理服务器上的 apiserver 将无法建立到集群内运行的准入 Webhook 或聚合 apiservices 的出站连接。要解决此问题,请将 --egress-selector-mode 服务器标志设置为 podcluster。如果您在现有集群上更改此标志,则需要重新启动集群中的所有节点才能使该选项生效。

运行无根服务器(实验性)

警告:此功能处于实验阶段。

无根模式允许以非特权用户身份运行 K3s 服务器,从而保护主机上的真实根用户免受潜在的容器突破攻击。

请访问 https://rootlesscontaine.rs/ 了解有关 Rootless Kubernetes 的更多信息。

Rootless 模式下的已知问题

  • 端口

    在运行 Rootless 时,会创建一个新的网络命名空间。这意味着 K3s 实例在网络方面与主机相对隔离。从主机访问 K3s 中运行的服务的唯一方法是将端口转发到 K3s 网络命名空间。Rootless K3s 包含一个控制器,该控制器会自动将 6443 和 1024 以下的服务端口绑定到主机,并偏移 10000。

    例如,端口 80 上的服务将在主机上变为 10080,但 8080 将保持 8080,没有任何偏移。目前,只有 LoadBalancer 服务会自动绑定。

  • 控制组

    不支持 Cgroup v1 和 Hybrid v1/v2;仅支持纯 Cgroup v2。如果 K3s 由于运行 Rootless 时缺少控制组而无法启动,则可能是您的节点处于混合模式,并且“缺少”的控制组仍绑定到 v1 控制器。

  • 多节点/多进程集群

    目前不支持多节点 Rootless 集群或同一节点上的多个 Rootless k3s 进程。有关更多详细信息,请参阅 #6488

启动 Rootless 服务器

  • 启用 cgroup v2 委派,请参阅 https://rootlesscontaine.rs/getting-started/common/cgroup2/。此步骤是必需的;如果没有正确委派的控制组,Rootless kubelet 将无法启动。

  • https://github.com/k3s-io/k3s/blob/<VERSION>/k3s-rootless.service 下载 k3s-rootless.service。确保使用相同版本的 k3s-rootless.servicek3s

  • k3s-rootless.service 安装到 ~/.config/systemd/user/k3s-rootless.service。不支持将此文件作为系统范围的服务安装(/etc/systemd/...)。根据 k3s 二进制文件的路径,您可能需要修改文件的 ExecStart=/usr/local/bin/k3s ... 行。

  • 运行 systemctl --user daemon-reload

  • 运行 systemctl --user enable --now k3s-rootless

  • 运行 KUBECONFIG=~/.kube/k3s.yaml kubectl get pods -A,并确保 Pod 正在运行。

注意:不要尝试在终端上运行 k3s server --rootless,因为终端会话不允许 cgroup v2 委派。如果您确实需要在终端上尝试,请使用 systemd-run --user -p Delegate=yes --tty k3s server --rootless 将其包装在 systemd 范围中。

高级 Rootless 配置

Rootless K3s 使用 rootlesskitslirp4netns 在主机和用户网络命名空间之间进行通信。rootlesskit 和 slirp4nets 使用的一些配置可以通过环境变量设置。设置这些变量的最佳方法是将它们添加到 k3s-rootless systemd 单元的 Environment 字段中。

变量默认值描述
K3S_ROOTLESS_MTU1500设置 slirp4netns 虚拟接口的 MTU。
K3S_ROOTLESS_CIDR10.41.0.0/16设置 slirp4netns 虚拟接口使用的 CIDR。
K3S_ROOTLESS_ENABLE_IPV6自动检测启用 slirp4netns IPv6 支持。如果未指定,则在 K3s 配置为双栈操作时自动启用。
K3S_ROOTLESS_PORT_DRIVERbuiltin选择 Rootless 端口驱动程序;可以是 builtinslirp4netns。Builtin 更快,但会伪造入站数据包的原始源地址。
K3S_ROOTLESS_DISABLE_HOST_LOOPBACKtrue控制是否启用通过网关接口访问主机的环回地址。出于安全原因,建议不要更改此设置。

Rootless 故障排除

  • 运行 systemctl --user status k3s-rootless 检查守护进程状态
  • 运行 journalctl --user -f -u k3s-rootless 查看守护进程日志
  • 另请参阅 https://rootlesscontaine.rs/

节点标签和污点

可以使用选项 --node-label--node-taint 配置 K3s 代理,这些选项会向 kubelet 添加标签和污点。这两个选项仅在 注册时 添加标签和/或污点,因此只能在节点首次加入集群时设置。

所有当前版本的 Kubernetes 都限制节点使用 kubernetes.iok8s.io 前缀注册大多数标签,特别是包括 kubernetes.io/role 标签。如果尝试使用不允许的标签启动节点,K3s 将无法启动。正如 Kubernetes 作者所述

节点不允许声明自己的角色标签。节点角色通常用于识别特权或控制平面类型的节点,并且允许节点将自身标记到该池中,这使得受损节点可以轻松吸引授予更高权限凭据的负载(如控制平面 DaemonSet)。

有关更多信息,请参阅 SIG-Auth KEP 279

如果要在节点注册后更改节点标签和污点,或添加保留标签,则应使用 kubectl。有关如何添加 污点节点标签 的详细信息,请参阅 Kubernetes 官方文档。

使用安装脚本启动服务

安装脚本将自动检测您的操作系统是否使用 systemd 或 openrc,并在安装过程中启用和启动服务。

  • 在使用 openrc 运行时,日志将创建在 /var/log/k3s.log 中。
  • 在使用 systemd 运行时,日志将创建在 /var/log/syslog 中,并使用 journalctl -u k3s(或代理上的 journalctl -u k3s-agent)查看。

禁用安装脚本的自动启动和服务启用的示例

curl -sfL https://get.k3s.io | INSTALL_K3S_SKIP_START=true INSTALL_K3S_SKIP_ENABLE=true sh -

在 Docker 中运行 K3s

有几种方法可以在 Docker 中运行 K3s

k3d 是一个旨在轻松地在 Docker 中运行多节点 K3s 集群的实用程序。

k3d 使在 docker 中创建单节点和多节点 k3s 集群变得非常容易,例如用于 Kubernetes 的本地开发。

有关如何安装和使用 k3d 的更多信息,请参阅 安装 文档。

SELinux 支持

版本门

从 v1.19.4+k3s1 开始可用

如果在默认情况下启用 SELinux 的系统上安装 K3s(例如 CentOS),则必须确保已安装正确的 SELinux 策略。

如果在兼容系统上且未执行断开连接的安装,则 安装脚本 将自动从 Rancher RPM 存储库安装 SELinux RPM。可以通过设置 INSTALL_K3S_SKIP_SELINUX_RPM=true 跳过自动安装。

启用 SELinux 强制

要利用 SELinux,请在启动 K3s 服务器和代理时指定 --selinux 标志。

此选项也可以在 K3s 配置文件 中指定。

selinux: true

在 SELinux 下不支持使用自定义 --data-dir。要自定义它,您很可能需要编写自己的自定义策略。作为指导,您可以参考 containers/container-selinux 存储库,其中包含容器运行时的 SELinux 策略文件,以及 k3s-io/k3s-selinux 存储库,其中包含 K3s 的 SELinux 策略。

启用 eStargz 的延迟拉取(实验性)

什么是延迟拉取和 eStargz?

拉取镜像被认为是容器生命周期中耗时的步骤之一。根据 Harter 等人 的说法,

拉取包占容器启动时间的 76%,但其中只有 6.4% 的数据被读取

为了解决此问题,k3s 实验性地支持镜像内容的延迟拉取。这允许 k3s 在拉取整个镜像之前启动容器。相反,必要的内容块(例如单个文件)将按需获取。特别是对于大型镜像,此技术可以缩短容器启动延迟。

要启用延迟拉取,目标镜像需要格式化为 eStargz。这是一种 OCI 替代方案,但 100% 兼容 OCI 的镜像格式,用于延迟拉取。由于兼容性,eStargz 可以推送到标准容器注册表(例如 ghcr.io),并且即使在与 eStargz 无关的运行时中仍然可以运行

eStargz 基于 Google CRFS 项目提出的 stargz 格式 开发,但具有包括内容验证和性能优化在内的实用功能。有关延迟拉取和 eStargz 的更多详细信息,请参阅 Stargz Snapshotter 项目存储库

配置 k3s 以延迟拉取 eStargz

如下所示,k3s 服务器和代理需要 --snapshotter=stargz 选项。

k3s server --snapshotter=stargz

使用此配置,您可以对 eStargz 格式的镜像执行延迟拉取。以下示例 Pod 清单使用 eStargz 格式的 node:13.13.0 镜像(ghcr.io/stargz-containers/node:13.13.0-esgz)。当启用 stargz 快照程序时,K3s 会对此镜像执行延迟拉取。

apiVersion: v1
kind: Pod
metadata:
name: nodejs
spec:
containers:
- name: nodejs-estargz
image: ghcr.io/stargz-containers/node:13.13.0-esgz
command: ["node"]
args:
- -e
- var http = require('http');
http.createServer(function(req, res) {
res.writeHead(200);
res.end('Hello World!\n');
}).listen(80);
ports:
- containerPort: 80

其他日志来源

Rancher 日志记录 可在不使用 Rancher 的情况下安装到 K3s 中。请执行以下说明进行操作

helm repo add rancher-charts https://charts.rancher.io
helm repo update
helm install --create-namespace -n cattle-logging-system rancher-logging-crd rancher-charts/rancher-logging-crd
helm install --create-namespace -n cattle-logging-system rancher-logging --set additionalLoggingSources.k3s.enabled=true rancher-charts/rancher-logging

其他网络策略日志记录

可以记录网络策略丢弃的数据包。数据包被发送到 iptables NFLOG 操作,该操作显示数据包详细信息,包括阻止它的网络策略。

如果流量很大,日志消息的数量可能会非常高。要按策略控制日志速率,请通过向相关网络策略添加以下注释来设置 limitlimit-burst iptables 参数

  • kube-router.io/netpol-nflog-limit=<LIMIT-VALUE>
  • kube-router.io/netpol-nflog-limit-burst=<LIMIT-BURST-VALUE>

默认值为 limit=10/minutelimit-burst=10。有关这些字段的格式和可能值的更多信息,请查看 iptables 手册

要将 NFLOG 数据包转换为日志条目,请安装 ulogd2 并配置 [log1] 以在 group=100 上读取。然后,重新启动 ulogd2 服务以提交新配置。当数据包被网络策略规则阻止时,日志消息将出现在 /var/log/ulog/syslogemu.log 中。

也可以使用 tcpdump 或 tshark 等命令行工具读取发送到 NFLOG netlink 套接字的数据包。

tcpdump -ni nflog:100

虽然 tcpdump 更容易获得,但它不会显示阻止数据包的网络策略的名称。请改用 wireshark 的 tshark 命令来显示完整的 NFLOG 数据包标头,包括包含策略名称的 nflog.prefix 字段。