项目文档:kt 文档
新系统配新版本,是运维最不愿意同时碰上的两件事。
操作系统刚发新版,内核、cgroup、包管理都换了代;k8s 又往前推了一版,容器运行时、CNI、etcd 得跟着对齐版本。这两件事叠在一起,通常意味着一整个下午的搜索和反复的环境排错。
再叠上离线,就更麻烦。内网和信创场景里,服务器连不上公网镜像源,装一个集群要先把十几个组件的镜像一个个搬进去。镜像全不全、版本对不对、证书链通不通,任何一环出岔子都得从头再来。
具体到这次的环境:Ubuntu 26.04 是今年上半年发布的长期支持版本,内核已经到 7.0.0,cgroup v2 也是默认配置——这恰好是 k8s 新版本所要求的两样东西。而 k8s 1.37.1 又是目前最新的稳定版。两个“新”撞在一起,正好能检验一套部署工具跟版本跟得快不快。
这篇文章记录的,就是在全新的 Ubuntu 26.04 上,用 kt 离线装出 k8s 1.37.1 + KubeSphere 4.1.3 的完整过程。
先用一句话概括:k8s 两条命令,KubeSphere 一条命令,全程不联网也能装完。
顺便给个比喻——在线装 k8s 像点外卖,镜像随时能拉;离线装 k8s 像自己备菜,油盐酱醋得一次性配齐,少一样就得回头跑一趟。所以下文里“离线制品”这个包,是整件事的命门。
1. 先说这次的更新
kt 是什么
kt 是 kk(KubeKey)的二次开发版本。kk 是 KubeSphere 团队做的集群部署工具,把 kubeadm 那一整套前置检查、容器运行时安装、镜像搬运都收敛成了“配置文件驱动”;kt 在它基础上继续往下走,重点加快了新版本适配、把离线体验做顺。
这次发布的是 kt 3.2.2。
支持最新 k8s
k8s 跟到 1.37.1,同时组件版本整体前移:etcd 升到 v3.7.2、Calico 升到 v3.32.2、crictl 升到 v1.37.0、Docker 升到 29.8.1、Helm 升到 v3.22.0,cri-dockerd、buildx、hybridnet、Docker Compose 也都同步做了升级。版本齐,是离线部署能不能一次跑通的前提。
国产 CPU 的兼容性
这一版解决了两处国产 CPU 的指令集兼容性问题:海光 7 系列和飞腾 2000。这两个平台在国内信创项目里很常见,做国产化适配的读者可以优先看这一条。
etcd 部署的优化
3.2.2 大幅优化了 etcd 的部署流程,尤其是 all-in-one 的离线场景。etcd 是集群里最容易“起不来”的一环——数据目录有残留、peer URL 对不上、发现阶段拿不到集群信息,都会卡在这里。把这块理顺,离线安装的成功率会明显好看。
版本要求
有一个前提要提前说清楚:k8s 从 1.35 开始,对内核和 cgroup 有了要求——内核 5.10 以上、cgroup v2。本文使用的 Ubuntu 26.04 内核为 7.0.0,默认满足。
如果你用的是其他操作系统,需要自行升级内核和 cgroup,别跳过这一步。
2. 环境准备
服务器信息
| 主机名 | 用途 | OS | 内核 | 配置 | IP |
|---|---|---|---|---|---|
| node1 | all-in-one | Ubuntu 26.04 | 7.0.0 | 4核8G | 10.0.0.13 |
本文用腾讯云轻量服务器做 all-in-one 部署。演示环境:k8s.tx1st.cn,用户名 test,密码 P@88w0rd,只提供基础查看功能。
要准备的文件
一共三样东西,上传到同一台节点,后续所有操作都在这个节点上完成:
- 离线制品:
artifact-x86-k8s1371-ks413-core.tar.gz - 集群配置文件:
config-sample.yaml - kt 二进制文件
这里有个容易踩的坑:建议使用全新的操作系统。操作系统不需要预装 docker,不需要设置 selinux,也不需要关 swap——kt 会自己处理。反过来,如果机器上已经有残留的 k8s 组件、旧版 containerd,或者手工改过一堆内核参数,环境一乱,各种奇怪问题都会冒出来。

3. 改配置文件
按实际的服务器信息,把内容填进 config-sample.yaml:
kind: Cluster
metadata:
name: sample
spec:
hosts:
- {name: node1, address: 10.0.0.13, internalAddress: 10.0.0.13, user: root, password: "123213"}
roleGroups:
etcd:
- node1
control-plane:
- node1
worker:
- node1
# 如需使用 kk 自动部署镜像仓库,请设置该主机组 (建议仓库与集群分离部署,减少相互影响)
# 如果需要部署 harbor 并且 containerManager 为 containerd 时,由于部署 harbor 依赖 docker,建议单独节点部署 harbor
registry:
- node1
controlPlaneEndpoint:
## Internal loadbalancer for apiservers
internalLoadbalancer: haproxy
domain: lb.kubesphere.local
address: ""
port: 6443
kubernetes:
version: v1.37.1
clusterName: cluster.local
autoRenewCerts: true
containerManager: containerd
etcd:
type: kubekey
network:
plugin: calico
kubePodsCIDR: 10.233.64.0/18
kubeServiceCIDR: 10.233.0.0/18
## multus support. https://github.com/k8snetworkplumbingwg/multus-cni
multusCNI:
enabled: false
registry:
type: harbor
registryMirrors: []
insecureRegistries: []
privateRegistry: "dockerhub.kubekey.local"
namespaceOverride: "kubesphereio"
auths: # if docker add by `docker login`, if containerd append to `/etc/containerd/config.toml`
"dockerhub.kubekey.local":
username: "admin"
password: Harbor@123 # 此处可自定义,kk3.1.8新特性
skipTLSVerify: true # Allow contacting registries over HTTPS with failed TLS verification.
plainHTTP: false # Allow contacting registries over HTTP.
certsPath: "/etc/docker/certs.d/dockerhub.kubekey.local"
addons: []
节点与角色
hosts 里填节点的连接信息,roleGroups 决定每台机器扮演什么角色。单节点下 etcd、control-plane、worker、registry 全压在 node1 上,看起来粗暴,但这就是 all-in-one 的意义——用一台机器跑通全流程,验证完再往多节点铺。
k8s 与网络
version 指定 v1.37.1,containerManager 用 containerd。controlPlaneEndpoint 里开了 haproxy 做 ApiServer 的内部负载均衡,这是为多 control-plane 预留的,单节点也照样能用。
网络插件选的是 calico,Pod 网段 10.233.64.0/18,Service 网段 10.233.0.0/18——这两段不要和你的内网、VPC 网段撞上。
私有仓库
registry.type 设为 harbor,privateRegistry 指向 dockerhub.kubekey.local,镜像统一落在 kubesphereio 这个 namespace 下。auths 里的账号密码会在初始化时自动写进 containerd 的配置里。
配置里那两行注释值得读一遍:registry 建议和集群分离部署,减少相互影响;而 Harbor 本身依赖 docker,如果集群的 containerManager 是 containerd,最好单独拿一台机器放 Harbor。
4. 建镜像仓库
./kt init registry -f config-sample.yaml -a artifact-x86-k8s1371-ks413-core.tar.gz
这条命令会在 Harbor 节点自动安装 docker 和 docker-compose,添加证书信任链,并把需要存放镜像的项目建好。

稍等一会儿,全部执行成功:

5. 创建 k8s 集群
./kt create cluster -f config-sample.yaml -a artifact-x86-k8s1371-ks413-core.tar.gz --with-local-storage
节点初始化、容器运行时安装、镜像推送、集群拉起,这条命令一次做完,中间不需要人工介入。--with-local-storage 顺带把本地存储的 StorageClass 装好,省得后面再补。
节点数量多的时候,可以先把初始化单独跑一遍:
./kt init-os -f config-sample.yaml
失败的话多执行几次,再往下走创建集群。
执行后会有一条确认提示,输入 yes 或 y 继续:

等一段时间,看到安装成功的消息:

6. 安装 KubeSphere
集群好了,接着装 KubeSphere:
helm upgrade --install -n kubesphere-system --create-namespace ks-core ks-core-1.1.5.tgz \
--set global.imageRegistry=dockerhub.kubekey.local/ks \
--set extension.imageRegistry=dockerhub.kubekey.local/ks \
--set ksExtensionRepository.image.tag=v1.1.5 \
--debug \
--wait
镜像地址同样指向本地的 Harbor,--wait 会一直等到所有资源就绪。

7. 验证与登录
用命令行确认
图形界面前,先用命令行确认一遍更直接:
kubectl get nodes -o wide
kubectl get pods -n kube-system
节点应该是 Ready;kube-system 下的 Pod 除个别一次性 Job 外应全部 Running;CONTAINER-RUNTIME 一列显示为 containerd://。
打开控制台
KubeSphere 已经起来了:


安装监控服务
默认安装不含监控,需要的时候在扩展里装:

安装到 host 集群:

装完之后重新登录:

看节点
节点已经就绪:

节点详情里能看到容器运行时和内核信息:

8. 总结与提醒
不论 x86 还是 arm,不论在线还是离线,不论国际发行版还是国产操作系统,用 kt 加对应的离线安装包,装 k8s 和 KubeSphere 都是同一套动作。
最后提醒一句:演示环境 k8s.tx1st.cn 只开了基础查看权限,正式环境请务必改掉默认密码,并把 Harbor 的账号密码换成自己的。
项目文档:https://tx1st.cn/kt
评论区