Ubuntu 22.04 安装 Kubernetes(k0s)集群指南
在 Ubuntu 22.04 上使用 k0s v1.36.4 从零搭建 Kubernetes 集群:环境准备、安装与启动、节点组网、运行时方案、就绪验证与示例应用访问,命令与回显实测验证。
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 | 说明 |
|---|---|---|---|
| controller | k0s-u22-controller | 172.22.0.3 | 控制平面:kube-apiserver / etcd / konnectivity-server 等本地进程 |
| worker1 | k0s-u22-worker1 | 172.22.0.5 | 工作节点 |
| worker2 | k0s-u22-worker2 | 172.22.0.7 | 工作节点 |
| worker3 | k0s-u22-worker3 | 172.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.x | 1.35.x | containerd 2.x | runc 1.4.x | 上一稳定版 |
| v1.36.4+k0s.1 | 1.36.4 | 2.3.5 | 1.4.3 | 本指南实测版本(稳定版) |
| v1.37.x+k0s.x | 1.37.x | containerd 2.x | runc 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 格式)。本环境需覆盖四个关键点,否则集群无法就绪:
- 数据/运行目录:
root、state指向 k0s 管理的目录与 socket; - 快照器用 native:受限内核环境 overlayfs 挂载受限(overlay 叠 overlay),
snapshotter = "native"; - 本地镜像优先:containerd 2.x 指定 snapshotter 时镜像解包存在已知缺陷(
no unpack platforms defined,upstream issue #11606),开启use_local_image_pull = true; - 沙箱镜像改 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 全部卸载即集群销毁。
参考链接
- k0s 官方文档:https://docs.k0sproject.io/
- k0s 安装说明(安装/系统要求):https://docs.k0sproject.io/v1.36.4+k0s.1/install/
- k0s GitHub Releases:https://github.com/k0sproject/k0s/releases
- k0s 配置参考(k0s.yaml):https://docs.k0sproject.io/v1.36.4+k0s.1/configuration/
- k0s airgap 离线部署:https://docs.k0sproject.io/v1.36.4+k0s.1/airgap-install/
- k0s 运行时对接说明(--cri-socket):https://docs.k0sproject.io/v1.36.4+k0s.1/runtime/
- containerd 官方配置文档:https://github.com/containerd/containerd/blob/main/docs/cri/config.md