运维知识
悠悠
2026年2月28日

K3s保姆级实战:从单机“点亮”到生产集群搭建,别再对着官方文档发呆了

上一篇咱们聊了K3s的定位,后台有不少兄弟私信我:“老哥,道理我都懂,但到底怎么装?官方文档那一堆参数看得我脑仁疼,能不能来点直接能抄作业的?”

没问题。今天这篇咱们不整虚的,直接开搞。

我把话放这儿:只要你有一台能联网的Linux机器(甚至虚拟机),跟着我这篇走,半小时内你要是跑不起来一个带Ingress、带存储的K8s集群,我把键盘吃了。

但这不仅仅是简单的安装教程。我是做运维的,我知道咱们在生产环境会遇到什么——内网隔离、镜像拉不动、证书过期、节点死活加不进去。这些坑,我都替你们填平了。

准备好了吗?打开你的终端,咱们开始。

第一阶段:环境准备(别跳过,这是血泪史)

很多新手上来就跑安装脚本,结果报错报得怀疑人生。其实90%的问题都是环境没收拾干净。

在跑任何K3s命令之前,你先检查这几样东西:

1. 你的 Hostname(主机名)
K3s(以及K8s)对主机名非常敏感。别用 localhost 这种名字,也别用带下划线 _ 的奇葩名字。
乖乖地,改成标准的DNS兼容格式,比如 node-1k3s-master

hostnamectl set-hostname k3s-master-01
# 改完记得退出重进一下终端,或者 source /etc/profile

2. 关闭防火墙和 Swap
虽然K3s声称支持Swap,但为了稳妥(特别是新手),我建议还是关了。
防火墙是大坑。如果你不是网络专家,搞不定iptables那些复杂的转发规则,就把 firewalld 或者 ufw 关了。

systemctl stop firewalld
systemctl disable firewalld
swapoff -a
# 记得去 /etc/fstab 里把 swap 那行注释掉,不然重启又回来了

3. 时间同步
这个我强调过无数次了。集群节点之间时间误差超过几秒,认证证书直接失效,节点状态全是 NotReady。装个 chrony 也就是一分钟的事儿。

第二阶段:单机急速部署(Hello World 级别)

如果你只是想在笔记本虚拟机或者开发环境试水,用这个模式。

官方给的脚本是 curl -sfL https://get.k3s.io | sh -
但是! 如果你在国内,直接跑这个脚本,你可能会卡在下载二进制文件那一步,或者卡在拉取 pause 镜像那一步。

咱们用个“魔改版”的命令,利用国内的镜像加速:

curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
  INSTALL_K3S_MIRROR=cn \
  sh -

这就完了?对,这就完了。
但是,作为一个老鸟,我通常会加几个参数,让它更符合我的使用习惯:

curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
  INSTALL_K3S_MIRROR=cn \
  INSTALL_K3S_EXEC="--write-kubeconfig-mode 644 --disable-cloud-controller" \
  sh -

解释一下这几个参数(这都是经验):

  • --write-kubeconfig-mode 644:这个太重要了。默认情况下,生成的 kubeconfig 文件只有 root 能读。你稍微切个普通用户想跑 kubectl,直接 Permission denied。加上这个,省去后续 chmod 的麻烦。
  • --disable-cloud-controller:因为咱们是在裸机或者虚拟机跑,不需要去连AWS或者阿里云的云控制器,禁用了能省点内存。

验证一下:
装完后,等个几十秒(取决于你的网速拉镜像快慢),运行:

kubectl get nodes

如果看到状态是 Ready,恭喜你,你的单节点K3s集群已经活了。

第三阶段:生产级集群搭建(Server + Agent 模式)

好,现在咱们来点真格的。假设你有三台机器:

  • 192.168.1.10 (Master/Server)
  • 192.168.1.11 (Worker/Agent)
  • 192.168.1.12 (Worker/Agent)

1. 启动 Master 节点

在 1.10 上执行:

curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
  INSTALL_K3S_MIRROR=cn \
  INSTALL_K3S_EXEC="--node-ip 192.168.1.10 --flannel-iface eth0" \
  sh -
  • --node-ip:指定节点IP,防止多网卡环境K3s识别错了。
  • --flannel-iface:指定Flannel网络走哪个网口。这个极其重要!我看过太多集群不通,就是因为Flannel自动选了个虚拟网卡或者错误的内网卡。

2. 获取 Token

Master 起来后,我们需要一个“通关密令”才能让 Worker 加入进来。
在 Master 上执行:

cat /var/lib/rancher/k3s/server/node-token

你会得到一串长长的字符串,类似 K10xxxxx::server:xxxx。复制它。

3. 加入 Worker 节点

在 1.11 和 1.12 上,分别执行:

# 替换下面的 IP 和 TOKEN
export K3S_URL=https://192.168.1.10:6443
export K3S_TOKEN=上面复制的那串字符

curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
  INSTALL_K3S_MIRROR=cn \
  sh -

这时候,你回到 Master 节点,狂敲 kubectl get nodes,你会看到那两个兄弟慢慢地从 NotReady 变成 Ready

这就组建完成了一个分布式的K8s集群。是不是比 kubeadm 简单了一万倍?

第四阶段:实战使用(别光看着,动起来)

集群搭好了如果不跑应用,那就是浪费电。咱们来一套标准的组合拳:部署 Nginx + 发布服务 + 挂载存储

1. 部署一个简单的 Nginx

别整那些复杂的 Helm Chart,咱们手写个 YAML,这才是运维的基本功。
创建一个文件 my-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-demo
  labels:
    app: nginx
spec:
  replicas: 2  # 跑两个副本,看看负载均衡
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

执行部署:

kubectl apply -f my-nginx.yaml

查看状态:

kubectl get pods -o wide

你应该能看到两个 Pod 分布在不同的节点上(如果调度正常的话)。

2. 暴露服务(Traefik Ingress 的妙用)

K3s 默认集成了 Traefik Ingress Controller。这玩意儿好用就好用在,你不需要额外安装 Nginx Ingress 了。

直接写一个 Ingress 规则文件 ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    # 这一行很重要,告诉K8s不要用默认的class,而是明确指定traefik
    kubernetes.io/ingress.class: "traefik"
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80

执行 kubectl apply -f ingress.yaml

现在,神奇的事情发生了。
打开你浏览器的,输入 任意一个节点 的 IP 地址(比如 http://192.168.1.10)。
你应该能看到 Nginx 的“Welcome”页面。

为什么?因为 K3s 的 Service LoadBalancer 默认也是开的(svclb),Traefik 默认监听宿主机的 80 和 443 端口。这就是“开箱即用”的爽点。你不需要搞 NodePort 那个丑陋的端口号(比如 30080)。

3. 存储实战(Local Path Provisioner)

K8s 最头疼的是存储。你得有 NFS、Ceph 或者云盘。
但在 K3s 里,它自带了一个 local-path 的 StorageClass。说白了,就是把 Pod 的数据存在 宿主机的某个目录下

咱们来试一下。创建一个 PVC(持久化卷声明)文件 pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: local-path-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 1Gi

Apply 它,然后 kubectl get pvc。你会发现状态立马变成了 Bound
不需要你手动创建 PV,不需要你配置 NFS Server。
数据存在哪?默认在宿主机的 /var/lib/rancher/k3s/storage/ 下面。

这对于跑数据库测试、或者简单的文件存储,简直不要太方便。

第五阶段:那些让你怀疑人生的“坑”(进阶必读)

要是文章只写到上面,那也就是个入门教程。下面这些才是我在生产环境摸爬滚打出来的经验。

1. 离线安装(Airgap)怎么搞?
企业内网通常是不通外网的。你跑那个 install.sh 脚本绝对报错。
你需要做三件事:

  1. 去 GitHub Releases 页面下载 k3s 二进制文件。
  2. 下载 k3s-airgap-images-amd64.tar 镜像包。
  3. 下载 install.sh 脚本。

关键步骤:
k3s 二进制扔到 /usr/local/bin/ 并给执行权限。
把镜像包扔到 /var/lib/rancher/k3s/agent/images/ 目录下(目录不存在就创建)。
然后执行脚本的时候加个参数:INSTALL_K3S_SKIP_DOWNLOAD=true
这样,K3s 启动时会自动导入那个 tar 包里的镜像,完全不需要联网。

2. Docker 还是 Containerd?
K3s 默认用 Containerd。很多兄弟习惯了 docker ps,进来一看傻眼了,命令没了。
你可以用 crictl 代替。
crictl ps 就是 docker ps
crictl images 就是 docker images
如果你非要用 Docker(比如有些老旧的 CI/CD 脚本依赖 docker.sock),你可以在安装时加上 --docker 参数。但我强烈建议你适应 Containerd,这才是 K8s 的未来。

3. 证书过期了怎么办?
K3s 的证书有效期默认是一年。以前这是个大坑,集群跑了一年突然挂了,日志全是 x509 报错。
好消息是,现在的 K3s 版本在服务重启时会自动轮转证书。
只要你不是一年都不重启 K3s 服务,基本上不会遇到这个问题。如果不放心,可以在 crontab 里加个计划任务,每个月重启一次 systemctl restart k3s

4. 卸载(重头再来)
折腾坏了?环境乱了?
K3s 极其贴心地提供了一键卸载脚本。
Master 节点运行:/usr/local/bin/k3s-uninstall.sh
Agent 节点运行:/usr/local/bin/k3s-agent-uninstall.sh
跑完之后,干干净净,就像什么都没发生过一样。

总结:动起来才是硬道理

兄弟们,K3s 真的是个好东西。它把 K8s 拉下了神坛,让咱们每个人都能在哪怕几百块钱的服务器上玩转云原生。

别光收藏不练。今晚回去,找个虚拟机,按照我上面的步骤跑一遍。当你看到 Nginx 页面弹出来的那一刻,你会发现 K8s 其实也没那么可怕。

如果在安装过程中遇到什么奇葩报错,或者想聊聊更高级的玩法(比如 K3s 高可用数据库对接),欢迎在评论区留言。

我是那个在机房里给你填坑的老哥,咱们下篇见!


公众号:运维躬行录
个人博客:躬行笔记

文章目录

博主介绍

热爱技术的云计算运维工程师,Python全栈工程师,分享开发经验与生活感悟。
欢迎关注我的微信公众号@运维躬行录,领取海量学习资料

微信二维码