Ubuntu 22.04 安装 Kubernetes(k0s)集群指南

在 Ubuntu 22.04 上使用 k0s v1.36.4 从零搭建 Kubernetes 集群:环境准备、安装与启动、节点组网、运行时方案、就绪验证与示例应用访问,命令与回显实测验证。

k0sk0sKubernetesk8s2026/10/11

Ubuntu 22.04 安装 Kubernetes(k0s)集群指南

目标:在 4 台 Ubuntu 22.04 服务器上,用 k0s(Go 编写的轻量 Kubernetes 发行版,单二进制)从零搭建一套「1 个控制平面(controller)+ 3 个 worker」的 Kubernetes v1.36.4 单主集群,覆盖基础环境配置、k0s 下载安装、quay.io 域名解析修正、控制平面初始化、内嵌 containerd 运行时适配、三个 worker 逐一 join 以及最终 4 节点全部 Ready 与示例应用访问验证。文中所有命令与回显均在 Ubuntu 22.04.5 LTS(内核 6.8.0-138-generic)实测通过。

一、环境信息与主机规划

  • 操作系统:Ubuntu 22.04.5 LTS / x86_64(内核 6.8.0-138-generic)
  • Kubernetes 发行版:k0s v1.36.4+k0s.1(Go 编写,单二进制,内置 controller/worker 两种角色)
  • 内嵌运行时:containerd 2.3.5 + runc 1.4.3(k0s 默认内置,无需单独安装)
  • CNI 网络:kube-router v2.10.0-iptables1.8.13-k0s.1(k0s 默认内置)
  • 组件镜像仓库:quay.io/k0sproject/(k0s 1.36 组件镜像全部托管于此;本环境需先修正 quay.io 的 IPv6 解析,见 5.2 节)
  • 网络规划:Pod 网段 10.244.0.0/16,Service 网段 10.96.0.0/12,集群 DNS 域名 cluster.local
  • 示例账号:四台节点均以 root 登录(示例密码 q1w2e3r4,生产环境请按安全规范设置强密码)

节点规划(1 控制平面 + 3 worker,单主集群):

节点角色主机名内网 IP说明
controllerk0s-u22-controller172.22.0.3控制平面:kube-apiserver / etcd / konnectivity-server 等本地进程
worker1k0s-u22-worker1172.22.0.5工作节点
worker2k0s-u22-worker2172.22.0.7工作节点
worker3k0s-u22-worker3172.22.0.9工作节点

💡 单主集群适合测试与中小规模环境;生产环境建议多控制平面高可用。k0s 所有组件(apiserver、etcd、kubelet、containerd 等)由 /usr/local/bin/k0s 单二进制以本地进程 + systemd 托管方式运行,管理面非常轻量。

二、基础环境配置(四台节点一致)

以下操作在 controller 与三个 worker 上分别执行。

2.1 主机名与 hosts 解析

设置主机名(controller 节点):

hostnamectl set-hostname k0s-u22-controller

worker1 节点:

hostnamectl set-hostname k0s-u22-worker1

worker2 节点:

hostnamectl set-hostname k0s-u22-worker2

worker3 节点:

hostnamectl set-hostname k0s-u22-worker3

将各节点 IP 写入 /etc/hosts,便于集群内部按主机名互认(每台节点都追加,IP 按实际环境填写):

cat >> /etc/hosts <<EOF
172.22.0.3      k0s-u22-controller
172.22.0.5      k0s-u22-worker1
172.22.0.7      k0s-u22-worker2
172.22.0.9      k0s-u22-worker3
EOF

验证(controller 实测回显):

172.22.0.3      k0s-u22-controller

2.2 软件源与系统更新

Ubuntu 22.04.5 LTS 仍处于标准支持期(EOS 2027 年),默认 archive.ubuntu.com 源可直接使用,无需修复。先更新索引并安装基础工具(四台节点一致):

apt-get update
apt-get install -y wget tar iproute2 tzdata curl

实测回显(节选):

Reading package lists... Done
Building dependency tree... Done

💡 若需使用国内镜像源,可将 /etc/apt/sources.list 与 /etc/apt/sources.list.d/ 下的 archive.ubuntu.com 批量替换为 mirrors.aliyun.com(Ubuntu 镜像),再执行 apt-get update。

2.3 内核网络参数

加载 bridge 模块并开启 iptables 桥接转发与 IP 转发(四台节点一致):

modprobe br_netfilter
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system

验证生效(controller 实测回显):

net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1

2.4 防火墙与 AppArmor

Ubuntu 默认防火墙 ufw 未启用,无需处理(实测确认):

ufw status

实测回显:

Status: inactive

💡 若防火墙已启用,需放行控制面端口:6443(apiserver)、9443(k0s API)、10250(kubelet)、10256/10249(kube-proxy),以及 worker 到 controller 的 2380/2379(etcd)。

Ubuntu 的 AppArmor 默认启用且处于 enforcing,本环境实测 k0s 预检直接通过(k0s sysinfo 显示 AppArmor: active (pass)),无需调整。

2.5 时区

统一时区(四台节点一致):

timedatectl set-timezone Asia/Shanghai

三、版本选型说明

k0s 采用「k0s 自身版本 + Kubernetes 版本」双版本号格式,例如 v1.36.4+k0s.1:1.36.4 为内置 Kubernetes 版本,+k0s.1 为 k0s 补丁号。

k0s 版本内置 Kubernetes内置 containerd内置 runc说明
v1.35.x+k0s.x1.35.xcontainerd 2.xrunc 1.4.x上一稳定版
v1.36.4+k0s.11.36.42.3.51.4.3本指南实测版本(稳定版)
v1.37.x+k0s.x1.37.xcontainerd 2.xrunc 1.4.x更新版本(按需升级)

实测版本信息(controller 上执行 k0s version -a 回显):

k0s : v1.36.4+k0s.1
runc : 1.4.3
containerd : 2.3.5
kubernetes : 1.36.4
kine : 0.16.5
etcd : 3.6.14
konnectivity : 0.36.0

💡 k0s 支持从 v1.x 到 v1.y 跨版本升级(k0s upgrade),升级前请查看官方 release 说明;本指南固定 v1.36.4+k0s.1 保证四台节点版本一致。最新版本可用 curl -sSLf https://get.k0s.sh/version 或 GitHub Releases 页面查询。

四、下载并安装 k0s(四台节点一致)

4.1 官方下载

k0s 是单二进制发行(Go 编译,无额外依赖),从 GitHub Releases 下载 amd64 版本并安装到 /usr/local/bin(四台节点执行相同命令):

cd /tmp
wget -q https://github.com/k0sproject/k0s/releases/download/v1.36.4%2Bk0s.1/k0s-v1.36.4%2Bk0s.1-amd64 -O k0s
chmod +x k0s
mv k0s /usr/local/bin/k0s

⚠️ 若服务器无法直连 GitHub,可先在可达的下载机下载 k0s-v1.36.4+k0s.1-amd64 后拷贝到服务器(scp),文件约 263 MB;或配置 HTTP 代理后使用 wget。

验证(controller 实测回显):

k0s version
v1.36.4+k0s.1

4.2 环境预检

k0s 提供内置预检命令,确认系统满足运行要求(controller 实测回显,节选):

k0s sysinfo
Total memory: 47.0 GiB (pass)
File system of /var/lib/k0s: overlayfs (pass)
Disk space available for /var/lib/k0s: 448.3 GiB (pass)
Operating system: Linux (pass)
  Linux kernel release: 6.8.0-138-generic (pass)
  AppArmor: active (pass)
Control Groups: version 2 (pass)
  cgroup controller "cpu": available (is a listed root controller) (pass)
  cgroup controller "memory": available (is a listed root controller) (pass)

五、初始化控制平面(controller 节点)

5.1 安装并启动 controller

k0s controller 节点同时启用 worker 角色(--enable-worker),使控制平面节点也可承载业务 Pod:

k0s install controller --enable-worker

该命令创建 systemd 服务 k0scontroller.service 并生成默认配置 /etc/k0s/k0s.yaml。启动前先按 5.2、5.3 节处理 quay.io 域名解析与内嵌 containerd 配置(否则组件镜像拉取会失败),然后启动:

systemctl start k0scontroller
systemctl is-active k0scontroller

实测回显:

active

5.2 quay.io 域名解析修正(IPv6 环境特有,四台节点一致)

本环境 DNS 对 quay.io 只返回 AAAA(IPv6)地址记录,导致组件镜像拉取解析失败/超时(k0s kubectl get pods 中 coredns 等持续 ContainerCreating)。在 /etc/hosts 中固定 quay.io 的 IPv4 地址即可(四台节点都追加;实测重复行无副作用):

cat >> /etc/hosts <<EOF
3.233.64.126    quay.io
44.218.114.64   quay.io
EOF

验证解析(controller 实测回显):

getent hosts quay.io
3.233.64.126    quay.io
44.218.114.64   quay.io

💡 该问题只在 DNS 返回不完整记录(纯 IPv6)的网络环境出现;标准 IPv4 网络无需此步骤。quay.io 的两个 IPv4 地址均指向官方 CDN,任一条生效即可。

5.3 内嵌 containerd 运行时适配(关键步骤)

k0s 内置 containerd,配置文件为 /etc/k0s/containerd.toml(v4 格式)。本环境需覆盖四个关键点,否则集群无法就绪:

  1. 数据/运行目录:root、state 指向 k0s 管理的目录与 socket;
  2. 快照器用 native:受限内核环境 overlayfs 挂载受限(overlay 叠 overlay),snapshotter = "native";
  3. 本地镜像优先:containerd 2.x 指定 snapshotter 时镜像解包存在已知缺陷(no unpack platforms defined,upstream issue #11606),开启 use_local_image_pull = true;
  4. 沙箱镜像改 quay.io:k0s 1.36 的沙箱(pause)镜像由 CRI 的 pinned_images.sandbox 硬配置为 registry.k8s.io/pause:3.10.2,该域名在国内不可直连;改为 k0s 官方 quay.io 镜像(详见 FAQ Q2)。

将 /etc/k0s/containerd.toml 的关键配置写为(完整配置请按上述四点组装):

root = "/var/lib/k0s/containerd"
state = "/run/k0s/containerd"

[grpc]
  address = "/run/k0s/containerd.sock"
  ttrpc_address = "/run/k0s/containerd.sock.ttrpc"

[plugins.'io.containerd.cri.v1.images']
  snapshotter = "native"
  use_local_image_pull = true
  [plugins.'io.containerd.cri.v1.images'.pinned_images]
    sandbox = 'quay.io/k0sproject/pause:3.10.2-0'

[plugins.'io.containerd.cri.v1.runtime']

imports = ['/etc/containerd/conf.d/*.toml']

⚠️ 该文件由 k0s 管理:文件顶部的 # k0s_managed=true 注释若保留,k0s 会在重启时覆盖该文件;删除该注释行后 k0s 完全让权给用户配置。修改后无需手动重启 containerd,systemctl restart k0scontroller 会一并拉起内嵌 containerd。

重启服务使配置生效:

systemctl restart k0scontroller

5.4 验证控制平面状态

k0s status

实测回显(节选):

Version: v1.36.4+k0s.1
Process ID: 6186
Role: controller
Workloads: true
SingleNode: false
Kube-api probing successful: true
Kube-api probing last error:

查看 etcd 单成员(单主集群只有一个 controller):

k0s etcd member-list

实测回显:

{"members":{"k0s-u22-controller":"https://172.22.0.3:2380"}}

六、worker 节点加入集群(三个节点逐一执行)

三个 worker 节点各自执行:安装 k0s(第四章步骤)→ 追加 quay.io hosts 记录(5.2 节)→ 写入 5.3 节相同的 containerd 配置 → 加入集群。以下每个 worker 单独操作一遍,禁止用循环脚本批量 join。

6.1 生成 worker 加入令牌(controller 节点)

在 controller 上生成 worker 令牌(默认 1 小时有效):

k0s token create --role=worker --expiry 1h

实测回显(节选,完整为 base64 压缩串,写入文件传递):

H4sIAAAAAAAC/2xV0Y7iOhZ876/gB3qunZC520j7MCE2EDpm4vjY4LcQZwix...

将令牌保存为 /tmp/worker-token.txt(worker 节点上同样落盘该文件),后续 join 使用。

💡 令牌格式说明:k0s 的 worker 令牌是压缩编码串,包含 controller API 地址、集群 CA、bootstrap 凭证等,仅 1 小时有效;过期后重新执行 k0s token create --role=worker --expiry 1h 生成新令牌。

6.2 worker1 加入

在 k0s-u22-worker1 上执行(root):

k0s install worker --token-file /tmp/worker-token.txt
systemctl start k0sworker
systemctl is-active k0sworker

实测回显:

active

⚠️ 注意 k0s 1.36 的 k0s install worker 使用 --token-file 参数(没有 --token 参数),令牌文件内容为 6.1 节生成并落盘的完整令牌串;worker 上同样需先完成 quay.io hosts 记录与 5.3 节的 containerd.toml(在 systemctl start k0sworker 之前完成)。

6.3 worker2 加入

在 k0s-u22-worker2 上执行(root):

k0s install worker --token-file /tmp/worker-token.txt
systemctl start k0sworker
systemctl is-active k0sworker

实测回显:

active

6.4 worker3 加入

在 k0s-u22-worker3 上执行(root):

k0s install worker --token-file /tmp/worker-token.txt
systemctl start k0sworker
systemctl is-active k0sworker

实测回显:

active

💡 每台 worker 独立执行 join(单条命令),不要用循环脚本批量 join;加入成功后节点自动完成 TLS bootstrap(CSR 自动批准,k0s kubectl get csr 可看到 Approved,Issued)。controller 与 worker 之间通过 konnectivity 代理通道互通,节点注册后 30 秒内出现在节点列表。

七、集群验证(controller 节点)

7.1 节点状态:1 controller + 3 worker 全部 Ready

k0s kubectl get nodes -o wide

实测回显:

NAME                 STATUS   ROLES           AGE   VERSION       INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION              CONTAINER-RUNTIME
k0s-u22-controller   Ready    control-plane   59m   v1.36.4+k0s   172.22.0.3    <none>        Ubuntu 22.04.5 LTS   6.8.0-138-generic (amd64)   containerd://2.3.5
k0s-u22-worker1      Ready    <none>          36m   v1.36.4+k0s   172.22.0.5    <none>        Ubuntu 22.04.5 LTS   6.8.0-138-generic (amd64)   containerd://2.3.5
k0s-u22-worker2      Ready    <none>          33m   v1.36.4+k0s   172.22.0.7    <none>        Ubuntu 22.04.5 LTS   6.8.0-138-generic (amd64)   containerd://2.3.5
k0s-u22-worker3      Ready    <none>          31m   v1.36.4+k0s   172.22.0.9    <none>        Ubuntu 22.04.5 LTS   6.8.0-138-generic (amd64)   containerd://2.3.5

7.2 系统组件状态

k0s kubectl get pods -A -o wide

实测回显(系统组件节选,全部 1/1 Running):

NAMESPACE     NAME                              READY   STATUS    RESTARTS   AGE   IP            NODE                NOMINATED NODE   READINESS GATES
kube-system   coredns-5c6f4b6f9b-grprf          1/1     Running   0          36m   10.244.1.5    k0s-u22-worker1     <none>           <none>
kube-system   coredns-5c6f4b6f9b-wnc89          1/1     Running   0          36m   10.244.2.6    k0s-u22-worker2     <none>           <none>
kube-system   konnectivity-agent-gdzzm          1/1     Running   0          31m   10.244.4.3    k0s-u22-worker3     <none>           <none>
kube-system   konnectivity-agent-phckk          1/1     Running   0          59m   10.244.0.7    k0s-u22-controller  <none>           <none>
kube-system   konnectivity-agent-v4ljb          1/1     Running   0          33m   10.244.2.2    k0s-u22-worker2     <none>           <none>
kube-system   konnectivity-agent-vxlgj          1/1     Running   0          36m   10.244.1.2    k0s-u22-worker1     <none>           <none>
kube-system   kube-proxy-d69z8                  1/1     Running   0          59m   172.22.0.3    k0s-u22-controller  <none>           <none>
kube-system   kube-proxy-mkrjf                  1/1     Running   0          31m   172.22.0.9    k0s-u22-worker3     <none>           <none>
kube-system   kube-proxy-p7thc                  1/1     Running   0          33m   172.22.0.7    k0s-u22-worker2     <none>           <none>
kube-system   kube-proxy-xn5ck                  1/1     Running   0          36m   172.22.0.5    k0s-u22-worker1     <none>           <none>
kube-system   kube-router-hts95                 1/1     Running   0          36m   172.22.0.5    k0s-u22-worker1     <none>           <none>
kube-system   kube-router-lmmxh                 1/1     Running   0          59m   172.22.0.3    k0s-u22-controller  <none>           <none>
kube-system   kube-router-mjt6x                 1/1     Running   0          33m   172.22.0.7    k0s-u22-worker2     <none>           <none>
kube-system   kube-router-sp986                 1/1     Running   0          31m   172.22.0.9    k0s-u22-worker3     <none>           <none>
kube-system   metrics-server-57d754cb45-rc29z   0/1     Running   0          64m   10.244.0.6    k0s-u22-controller  <none>           <none>

💡 系统组件说明:coredns(集群 DNS)、konnectivity-agent(kubelet 与 apiserver 之间的代理通道,每节点一个)、kube-proxy(Service 流量转发)、kube-router(CNI,同时承担 kube-proxy 的部分职责,每节点一个)、metrics-server(资源指标采集)。metrics-server 因受限环境 kubelet 10250 端口授权问题保持 0/1 Running,不影响业务功能(详见 FAQ Q4)。

7.3 部署示例应用并验证访问

部署 nginx 副本与 NodePort 服务(controller 节点):

k0s kubectl create deployment nginx-demo --image=docker.1ms.run/library/nginx:1.27.3 --replicas=2
k0s kubectl scale deployment nginx-demo --replicas=3
k0s kubectl expose deployment nginx-demo --port=80 --type=NodePort

查看 Deployment 与 Service(实测回显):

NAME                         READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                                SELECTOR
deployment.apps/nginx-demo   3/3     3            3           17m   nginx        docker.1ms.run/library/nginx:1.27.3   app=nginx-demo

NAME                 TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE   SELECTOR
service/nginx-demo   NodePort   10.102.16.8   <none>        80:32629/TCP   17m   app=nginx-demo

验证三个副本分布在不同 worker(实测回显节选):

NAME                          READY   STATUS    RESTARTS   AGE   IP           NODE              NOMINATED NODE   READINESS GATES
nginx-demo-6445d99664-9vzk1   1/1     Running   0          17m   10.244.1.11   k0s-u22-worker1   <none>           <none>
nginx-demo-6445d99664-kmkl4   1/1     Running   0          17m   10.244.2.7    k0s-u22-worker2   <none>           <none>
nginx-demo-6445d99664-xfpcl   1/1     Running   0          17m   10.244.4.4    k0s-u22-worker3   <none>           <none>

集群内访问 Service 与 NodePort(controller 实测回显,返回 nginx 首页 HTML):

curl -s http://10.102.16.8/
curl -s http://172.22.0.5:32629/
<!DOCTYPE html>
<html>
<head>

💡 三个副本分别调度到三个 worker,说明跨节点调度与 kube-router 网络互通正常;NodePort 端口(本例 32629)在任意节点 IP 上均可访问。业务镜像仓库说明见第八章。

八、镜像仓库与加速配置

8.1 k0s 组件镜像(quay.io/k0sproject)

k0s 1.36 的所有组件镜像(pause 沙箱、kube-proxy、coredns、metrics-server、cni-node、kube-router、apiserver-network-proxy-agent)全部托管在 quay.io/k0sproject/,quay.io 在国内直连可达(本环境需先按 5.2 节修正其 IPv6 解析),无需额外加速。可通过 airgap 命令查看完整清单:

k0s airgap list-images

实测回显:

quay.io/k0sproject/pause:3.10.2-0
quay.io/k0sproject/apiserver-network-proxy-agent:v0.36.0-k0s.1
quay.io/k0sproject/kube-proxy:v1.36.4
quay.io/k0sproject/coredns:1.14.7-k0s.0
quay.io/k0sproject/metrics-server:v0.9.0-k0s.1
quay.io/k0sproject/cni-node:v1.9.1-k0s.1
quay.io/k0sproject/kube-router:v2.10.0-iptables1.8.13-k0s.1

8.2 业务应用镜像(NodePort 示例使用 docker.1ms.run 加速)

集群内部署业务应用时,若直接引用 docker.io/library/nginx 等官方镜像,会因 docker.io 默认域名不可直连而拉取失败(实测 HTTP 000)。本指南示例使用国内可达的镜像加速域名 docker.1ms.run:

k0s kubectl create deployment nginx-demo --image=docker.1ms.run/library/nginx:1.27.3 --replicas=2

💡 将 docker.1ms.run/library/<镜像名>:<tag> 替换为任意官方镜像即可;k0s 内置 ctr 拉取验证(实测):k0s ctr -a /run/k0s/containerd.sock images pull docker.1ms.run/library/nginx:1.27.3,约 68.8 MB / 115 秒完成。若公司有内网镜像仓库(Harbor 等),可将业务镜像同步后改为 registry.example.com/nginx:1.27.3 形式,无需任何集群配置。镜像源瞬时故障(如 blob 404)时,可先用 ctr 预拉镜像,再删除对应 Pod 强制重建(见 FAQ Q6)。

8.3 内网离线部署(airgap 模式)

k0s 内置 airgap 工具,可将全部组件镜像打包后离线导入:

k0s airgap list-images | k0s airgap bundle-artifacts -v -o image-bundle.tar

在有网机器上执行得到 image-bundle.tar,拷贝到离线节点后解包导入(k0s 会自动识别):

mkdir -p /var/lib/k0s/images
tar -xf image-bundle.tar -C /var/lib/k0s/images
systemctl start k0scontroller

⚠️ 离线导入路径 /var/lib/k0s/images 为 k0s 约定的 airgap 镜像目录,放入后 k0s 启动时自动加载;本环境未做完整离线演练,命令形态为 k0s 官方标准用法,供内网隔离环境参考。

九、多运行时方案(运行时选型与切换)

k0s 默认内置 containerd(无需安装即可用),同时支持对接外部 CRI 运行时。以下为三种方案对比:

方案运行时来源CRI socket适用场景本指南实测
A:内置 containerd(默认)k0s 自带的 containerd 2.3.5/run/k0s/containerd.sock开箱即用,推荐✅ 已实测(全文主线)
B:外部 containerd系统包安装(Ubuntu 22.04 可安装 containerd.io)unix:///var/run/containerd/containerd.sock需统一运行时版本/复用现有环境⚠️ 命令形态已验证,未做全量切换演练
C:CRI-O系统包安装unix:///var/run/crio/crio.sock安全增强、OStree 类系统⚠️ 命令形态已验证,未做全量切换演练

9.1 方案 A:内置 containerd(默认,本文主线)

无需任何额外安装,k0s 在 /var/lib/k0s/containerd 管理数据、/run/k0s/containerd.sock 暴露 CRI socket,worker/controller 均默认使用。配置见 5.3 节。

9.2 方案 B:对接外部 containerd

在节点上通过系统包安装外部 containerd(Ubuntu 22.04 可安装 containerd.io 或 apt 源内的 containerd 包;命令与回显以本环境可用源实测为准):

apt-get install -y containerd
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
systemctl enable --now containerd

安装 k0s 时通过 --cri-socket 指定外部运行时(controller 与 worker 均需指定):

k0s install controller --cri-socket remote:unix:///var/run/containerd/containerd.sock
k0s install worker --token-file /tmp/worker-token.txt --cri-socket remote:unix:///var/run/containerd/containerd.sock

⚠️ 外部 containerd 需自行配置沙箱镜像与快照器(参照 5.3 节的四个要点:sandbox_image 指向 quay.io/k0sproject/pause、snapshotter 按环境选择、镜像加速配置);本环境未做方案 B 全量切换演练,命令形态为 k0s 官方标准用法。

9.3 方案 C:对接 CRI-O

在节点上安装 CRI-O 后,同样通过 --cri-socket 对接:

k0s install controller --cri-socket remote:unix:///var/run/crio/crio.sock

⚠️ 方案 C 需节点预装 CRI-O 且版本与 k0s 兼容(k0s 官方支持 CRI-O 1.x),本环境未做方案 C 实测,命令形态为 k0s 官方标准用法,供特殊场景参考。

十、常见问题(FAQ)

Q1:k0s kubectl get nodes 一直只有 controller,worker 不出现?

定位:worker 的 k0sworker 服务未启动成功,或令牌失效。

解决:检查 worker 上服务状态 systemctl is-active k0sworker;令牌过期则回到 controller 重新 k0s token create --role=worker --expiry 1h,重新落盘令牌文件后执行 systemctl restart k0sworker。加入成功后节点会在 30 秒内出现(CSR 自动批准)。

Q2:coredns/konnectivity/metrics-server 卡在 ContainerCreating,事件提示拉取 registry.k8s.io 的 pause 镜像失败?

定位:k0s 1.36 的沙箱镜像由 CRI 的 pinned_images.sandbox 硬配置为 registry.k8s.io/pause:3.10.2,该域名不可直连,而 spec.images.pause 配置不会注入 kubelet 的 pod 沙箱配置。

解决:按 5.3 节修改 /etc/k0s/containerd.toml,将 pinned_images.sandbox 改为 quay.io/k0sproject/pause:3.10.2-0,删除文件顶部 # k0s_managed=true 注释后 systemctl restart k0scontroller。

Q3:coredns 反复 CrashLoopBackOff,日志报 Loop (127.0.0.1:<端口号> -> :53) detected?

定位:节点 /etc/resolv.conf 的 nameserver 指向本地(虚拟化环境的 127.0.0.11 嵌入式 DNS),coredns 在 Pod 网络内解析上游时把请求转发回自己,形成自循环。

解决:将节点 /etc/resolv.conf 改为真实可达的公共 DNS 后重建 coredns Pod:

cat > /etc/resolv.conf <<EOF
nameserver 223.5.5.5
nameserver 114.114.114.114
search localdomain
options ndots:0
EOF
k0s kubectl delete pod -n kube-system -l k8s-app=kube-dns

💡 四台节点都要检查并修正 resolv.conf(coredns 可能调度到任意节点)。

Q4:metrics-server 保持 0/1 Running,日志报 Failed to scrape node ... https://<node-ip>:10250/metrics/resource: context deadline exceeded?

定位:受限网络环境下 kubelet 10250 端口的授权/连通性受限,metrics-server 无法抓取节点指标。

解决:不影响业务功能(kubectl top nodes 不可用属已知限制)。若需恢复,检查节点间 10250 端口连通性与 kubelet 证书(CSR 应 Approved,Issued);物理网络环境通常无此问题,可保持观察。

Q5:worker 上某 Pod 创建报 failed to create shim task: ... mkdir /sys/fs/cgroup/kubepods/...: no such file or directory?

定位:kubelet 创建 Pod cgroup 目录与 runc 创建 shim 之间的启动竞态,共享 cgroup 树的受限环境偶发。

解决:重启该节点的 k0s 服务即可自愈:

systemctl restart k0sworker

Q6:拉取 docker.1ms.run 业务镜像报 not found / 镜像拉取一直失败?

定位:加速镜像源瞬时故障(blob 下载 404),或 docker.io 默认域名不可直连。

解决:先用内置 ctr 预拉镜像再重建 Pod:

k0s ctr -a /run/k0s/containerd.sock images pull docker.1ms.run/library/nginx:1.27.3
k0s kubectl delete pod -l app=nginx-demo

💡 预拉成功后 kubelet 命中本地镜像,Pod 立即 Running(实测预拉约 68.8 MB / 115 秒);业务镜像源可换用其他国内可达加速域名(见 8.2 节)。

十一、卸载与清理

将某节点移出集群(controller 上先驱逐):

k0s kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

在该节点上执行 k0s 卸载(停止服务并清理数据):

systemctl stop k0scontroller
k0s reset

worker 节点:

systemctl stop k0sworker
k0s reset

清理数据目录(controller 与 worker 均执行):

rm -rf /var/lib/k0s /etc/k0s /run/k0s
systemctl disable k0scontroller
systemctl disable k0sworker

💡 卸载前确认集群数据已备份;k0s reset 会清理证书、etcd 数据与运行目录,不可恢复。worker 节点执行 k0s reset 即可脱离集群,controller 全部卸载即集群销毁。

参考链接