概述
你在一家智能制造公司干运维。工厂车间里有 200 台边缘网关,每台跑着数据采集和实时质检的服务。之前用裸 Docker 部署,每次更新都得写脚本逐台 SSH 上去拉镜像、重启容器。200 台机器跑一轮,半小时过去了,中间还经常有几台网络抖动导致更新失败。
你心想:这不就是 Kubernetes 要解决的问题吗?编排、调度、滚动更新、自愈——全都有了。但真去装 K8s 的时候傻眼了:车间网关用的是 ARM 架构的工控机,2 核 CPU、2G 内存,光 etcd 就吃掉 500M,kube-apiserver、kube-scheduler、kube-controller-manager 一堆组件跑起来,系统资源所剩无几。
这时候 K3s 登场了。它是 Rancher 开发的轻量级 Kubernetes 发行版,把所有控制面组件打包成一个 50MB 的二进制文件,内存占用不到 512M,支持 ARM64/x86_64,自带 containerd 运行时、Flannel 网络、CoreDNS、Traefik Ingress——开箱即用。在树莓派上都能跑起来,工控机更不在话下。
这篇文章聊聊 K3s 在边缘计算场景下的实战:从架构原理到集群搭建,从网络方案到边缘自治,从监控告警到故障排查。不是入门教程的复述,而是生产环境踩坑后的经验总结。
K3s 架构:为什么它能在 512M 内存上跑起来
和 K8s 的关键差异
K3s 不是 K8s 的阉割版——这个说法太粗暴了。它是一个为资源受限环境重新设计的 Kubernetes 发行版。核心区别在以下几方面:
| 特性 | K8s | K3s |
|---|---|---|
| 二进制大小 | ~300MB(多组件) | ~50MB(单二进制) |
| 最低内存 | 2GB | 512MB |
| 存储后端 | etcd(必须) | SQLite(默认)/ etcd / MySQL / PostgreSQL |
| 运行时 | 需单独安装 containerd/Docker | 内置 containerd |
| 网络 CNI | 需手动安装 | 内置 Flannel |
| Ingress | 需手动安装 | 内置 Traefik |
| DNS | 需手动安装 | 内置 CoreDNS |
| Alpha/Beta 特性 | 全部包含 | 剔除 |
| 云厂商专用代码 | 全部包含 | 剔除 |
| 架构支持 | x86_64 / ARM64 | x86_64 / ARM64 / ARMv7 |
K3s 的核心设计哲学是:在边缘场景下,你需要的是 K8s 的编排能力,而不是它的全部复杂性。去掉 alpha/beta 特性和云厂商专用代码后,K3s 保留了 K8s 的核心 API 和功能——Pod、Deployment、Service、ConfigMap、HPA、CronJob 这些你日常用的资源全都在,kubectl 命令完全兼容。
单二进制架构
K3s 把以下组件打包到一个二进制文件中:
k3s 二进制
├── kube-apiserver # API 服务
├── kube-scheduler # 调度器
├── kube-controller-manager # 控制器管理器
├── kubelet # 节点代理
├── kube-proxy # 网络代理
├── containerd # 容器运行时
├── flannel # CNI 网络插件
├── coredns # DNS 服务
├── traefik # Ingress 控制器
├── servicelb # 服务负载均衡器
└── local-path-provisioner # 本地存储卷分配器
这意味着你不需要像 K8s 那样分别安装和配置十几个组件。一个二进制文件,一条命令启动,全搞定。
存储后端选择
K3s 默认使用 SQLite 作为存储后端,这对单节点集群是完美的——零额外依赖、零资源开销。但 SQLite 不支持多副本写入,所以多节点 Server 集群需要换存储后端:
| 存储后端 | 适用场景 | 资源开销 | 高可用 |
|---|---|---|---|
| SQLite(默认) | 单节点 Server | 极低 | 不支持 |
| etcd | 多节点 Server,生产环境 | 中等 | 支持 |
| MySQL | 已有 MySQL 基础设施 | 中等 | 支持 |
| PostgreSQL | 已有 PG 基础设施 | 中等 | 支持 |
我的建议:边缘场景下如果只需要单节点 Server,用默认的 SQLite 就够了。如果需要高可用多 Server,用嵌入式 etcd(K3s 支持以 --cluster-init 模式启动内置 etcd)。
单节点集群搭建:5 分钟上手
环境准备
以 Ubuntu 22.04 LTS 为例(ARM64 和 x86_64 均可):
# 基础环境准备
sudo apt update && sudo apt upgrade -y
# 安装时间同步(K8s 组件对时间敏感)
sudo apt install chrony -y
sudo systemctl enable --now chrony
# 关闭 swap(Kubelet 不支持 swap)
sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab
# 加载必要的内核模块
sudo modprobe overlay
sudo modprobe br_netfilter
# 持久化内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
# 内核参数调整
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
一键安装
# 安装 K3s Server(国内环境用镜像加速)
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-installation.sh | \
INSTALL_K3S_MIRROR=cn sh -s - \
--write-kubeconfig-mode 644 \
--disable traefik \
--node-label "node-type=edge"
# 检查安装状态
sudo k3s kubectl get nodes
sudo k3s kubectl get pods -A
解释几个关键参数:
--write-kubeconfig-mode 644:让非 root 用户也能读取 kubeconfig--disable traefik:如果你不用 Ingress,可以禁用 Traefik 省资源--node-label:给节点打标签,方便后续调度
安装完成后,K3s 的 kubeconfig 文件在 /etc/rancher/k3s/k3s.yaml,把它复制到 ~/.kube/config 就可以用标准 kubectl 了:
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
国内镜像加速
边缘场景的设备通常在国内,拉 Docker Hub 镜像慢得让人抓狂。K3s 用 containerd 而不是 Docker,所以配置方式和 Docker 不一样:
# 创建 containerd 镜像加速配置
sudo mkdir -p /etc/rancher/k3s
cat <<EOF | sudo tee /etc/rancher/k3s/registries.yaml
mirrors:
docker.io:
endpoint:
- "https://registry.cn-hangzhou.aliyuncs.com"
gcr.io:
endpoint:
- "https://registry.cn-hangzhou.aliyuncs.com"
quay.io:
endpoint:
- "https://quay.mirrors.ustc.edu.cn"
configs:
"registry.cn-hangzhou.aliyuncs.com":
auth:
username: "your-aliyun-account"
password: "your-password"
EOF
# 重启 K3s 使配置生效
sudo systemctl restart k3s
多节点集群:Server + Agent 架构
架构设计
边缘场景下,多节点集群通常是这样设计的:
┌─────────────────────────────────────┐
│ 边缘机房 / 工厂车间 │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ K3s Server│ │ K3s Agent│ │
│ │ (管理节点) │ │ (工作节点)│ │
│ │ 2C/4G │ │ 2C/2G │ │
│ └─────┬────┘ └─────┬────┘ │
│ │ │ │
│ │ ┌──────────┐│ │
│ └───┤ K3s Agent ├┘ │
│ │ (工作节点) │ │
│ │ 2C/2G │ │
│ └──────────┘ │
│ │
└─────────────────────────────────────┘
Server 节点跑控制面 + 可以跑工作负载。Agent 节点只跑工作负载。一个 Server 管十几个 Agent,在边缘场景下完全够用。
部署 Server 节点
# 在 Server 节点执行
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-installation.sh | \
INSTALL_K3S_MIRROR=cn sh -s - \
--write-kubeconfig-mode 644 \
--node-label "node-type=server" \
--node-label "location=edge-room-1"
# 获取 Agent 加入 token
cat /var/lib/rancher/k3s/server/node-token
# 输出类似:K10xxxxxxxxxxxx::server:xxxxxxxxxxxx
部署 Agent 节点
# 在 Agent 节点执行
# 把 <SERVER_IP> 替换为 Server 节点的 IP
# 把 <NODE_TOKEN> 替换为上一步获取的 token
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-installation.sh | \
INSTALL_K3S_MIRROR=cn sh -s - agent \
--server https://<SERVER_IP>:6443 \
--token <NODE_TOKEN> \
--node-label "node-type=agent" \
--node-label "location=edge-room-1"
# 验证 Agent 加入
sudo k3s kubectl get nodes
离线安装:边缘场景的刚需
很多边缘设备根本没有外网——工厂车间的网络是封闭的,镜像只能从内网 registry 拉。这时候需要离线安装 K3s。
# 步骤1:在有网络的机器上下载 K3s 二进制文件
# 下载地址:https://github.com/k3s-io/k3s/releases
# 选择对应架构的 binary(amd64 或 arm64)
wget https://github.com/k3s-io/k3s/releases/download/v1.30.0%2Bk3s1/k3s-arm64
# 注意:ARM64 设选用 k3s-arm64,x86_64 选用 k3s
# 步骤2:下载 K3s 依赖的系统镜像包
wget https://github.com/k3s-io/k3s/releases/download/v1.30.0%2Bk3s1/k3s-airgap-images-arm64.tar.zst
# 步骤3:把文件传到边缘设备
scp k3s-arm64 edge-device:/usr/local/bin/k3s
scp k3s-airgap-images-arm64.tar.zst edge-device:/tmp/
# 步骤4:在边缘设备上执行离线安装
ssh edge-device << 'EOF'
sudo chmod +x /usr/local/bin/k3s
# 导入系统镜像
sudo mkdir -p /var/lib/rancher/k3s/agent/images/
sudo cp /tmp/k3s-airgap-images-arm64.tar.zst /var/lib/rancher/k3s/agent/images/
# 下载 K3s 安装脚本(也需要在有网络的机器上下载后传入)
# 假设安装脚本已经放在 /tmp/k3s-install.sh
sudo chmod +x /tmp/k3s-install.sh
sudo /tmp/k3s-install.sh
EOF
离线安装的关键是把 K3s 二进制文件和 airgap 镜像包提前放到正确的目录。安装脚本会检测到本地已有镜像,不再尝试从网上拉取。
网络方案选型:边缘场景的取舍
K3s 内置网络方案
K3s 默认使用 Flannel(VXLAN 模式)作为 CNI。在大多数边缘场景下这够用了,但有几个需要注意的点:
| 网络模式 | 适用场景 | 性能 | 复杂度 |
|---|---|---|---|
| Flannel VXLAN(默认) | 通用场景 | 中等 | 低 |
| Flannel Host-GW | 同子网节点 | 高 | 低 |
| Calico | 需要网络策略 | 高 | 中 |
| Cilium | 需要高级网络功能 | 高 | 高 |
边缘场景下我推荐用默认的 Flannel VXLAN。原因很简单:边缘设备的网络拓扑经常变化,VXLAN 对底层网络的要求最低——只要节点之间 IP 可达就行。Host-GW 模式虽然性能更好,但要求所有节点在同一个二层网络,这在跨车间的场景下很难满足。
自定义 Flannel 网段
默认情况下 K3s 使用的 Pod CIDR 是 10.42.0.0/16,Service CIDR 是 10.43.0.0/16。如果你的边缘网络恰好用了这些网段,需要修改:
# 安装时指定自定义网段
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-installation.sh | \
INSTALL_K3S_MIRROR=cn sh -s - \
--cluster-cidr 172.20.0.0/16 \
--service-cidr 172.21.0.0/16 \
--cluster-dns 172.21.0.10
边缘网络不稳定的问题
边缘场景最大的痛点是网络不稳定——车间网关和 Server 之间的网络可能时断时续。K3s Agent 掉线后会发生什么?
- Pod 继续运行:Agent 掉线不影响已运行的 Pod,容器还在 containerd 里跑着
- 无法调度新 Pod:Server 认为 Agent 不可达,不会往上面调度新 Pod
- 状态上报中断:Pod 状态、节点资源使用情况无法上报到 Server
K3s 有一个边缘场景的关键特性——边缘自治(Edge Autonomy)。当 Agent 和 Server 断连后,Agent 本地的 kubelet 继续管理已有 Pod,不会因为连不上 Server 就把 Pod 杀掉。等网络恢复后,Agent 自动重连,状态同步。
但默认的 Pod 驱逐策略需要调优,否则 Agent 重连后可能触发大规模 Pod 重建:
# 调整 kubelet 驱逐策略,容忍更长的断连时间
# 在 Agent 节点上创建配置
cat <<EOF | sudo tee /etc/rancher/k3s/agent.yaml
kubelet-arg:
- "node-status-update-frequency=30s"
- "node-monitor-period=30s"
- "node-monitor-grace-period=5m"
- "pod-eviction-timeout=5m"
EOF
# 重启 Agent
sudo systemctl restart k3s-agent
这几个参数的含义:
node-status-update-frequency:Agent 每 30 秒上报一次状态(默认 10s,边缘场景可以降低频率省带宽)node-monitor-grace-period:Server 允许 Agent 5 分钟不上报(默认 40s,边缘场景需要拉长)pod-eviction-timeout:超过 5 分钟才标记 Pod 驱逐(默认 5m)
边缘应用部署实战
部署一个数据采集服务
apiVersion: apps/v1
kind: Deployment
metadata:
name: data-collector
namespace: edge-apps
labels:
app: data-collector
spec:
replicas: 3
selector:
matchLabels:
app: data-collector
template:
metadata:
labels:
app: data-collector
spec:
# 只调度到 Agent 节点
nodeSelector:
node-type: agent
# 资源限制(边缘设备资源有限)
containers:
- name: collector
image: registry.cn-hangzhou.aliyuncs.com/edge/data-collector:v1.2.0
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
# 边缘场景必须配存活探针,确保网络抖动时 Pod 能自动重启
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 30
failureThreshold: 5 # 允许 5 次失败(150s),容忍网络抖动
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 15
# 边缘场景的配置通过 ConfigMap 注入
env:
- name: COLLECT_INTERVAL
valueFrom:
configMapKeyRef:
name: collector-config
key: interval
- name: MQTT_BROKER
valueFrom:
configMapKeyRef:
name: collector-config
key: mqtt-broker
volumeMounts:
- name: data-volume
mountPath: /data
volumes:
- name: data-volume
hostPath:
path: /var/edge-data
type: DirectoryOrCreate
---
apiVersion: v1
kind: ConfigMap
metadata:
name: collector-config
namespace: edge-apps
data:
interval: "5s"
mqtt-broker: "tcp://mqtt.internal:1883"
---
apiVersion: v1
kind: Service
metadata:
name: data-collector
namespace: edge-apps
spec:
selector:
app: data-collector
ports:
- port: 8080
targetPort: 8080
# ClusterIP 足够,不需要对外暴露
type: ClusterIP
滚动更新策略
边缘设备的带宽有限,拉镜像可能比较慢。调整滚动更新参数,避免一次性拉太多镜像把带宽打满:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 # 每次只更新 1 个 Pod
maxSurge: 0 # 不创建额外 Pod,先减后增
镜像预分发
200 台边缘设备同时拉镜像,不管 registry 带多宽都会堵。更好的做法是镜像预分发——在业务低峰期把镜像提前拉到每台设备上:
#!/bin/bash
# 镜像预分发脚本
# 在每台 Agent 节点上执行,提前拉取下一版本镜像
IMAGES=(
"registry.cn-hangzhou.aliyuncs.com/edge/data-collector:v1.3.0"
"registry.cn-hangzhou.aliyuncs.com/edge/data-processor:v2.0.0"
)
for image in "${IMAGES[@]}"; do
echo "[$(date)] 拉取镜像: $image"
# K3s 使用 containerd,用 crictl 拉镜像
sudo k3s crictl pull "$image"
if [ $? -eq 0 ]; then
echo "[$(date)] ✓ 拉取成功"
else
echo "[$(date)] ✗ 拉取失败,稍后重试"
fi
done
echo "镜像预分发完成。下次部署时将直接使用本地缓存。"
然后通过 Ansible 批量执行:
# ansible playbook: 镜像预分发
- name: Pre-distribute images to edge nodes
hosts: edge-agents
become: yes
tasks:
- name: Copy pre-pull script
copy:
src: pre-pull-images.sh
dest: /tmp/pre-pull-images.sh
mode: '0755'
- name: Run pre-pull script
shell: /tmp/pre-pull-images.sh
async: 600 # 最长等待 10 分钟
poll: 0 # 异步执行,不阻塞
- name: Check pre-pull status
async_status:
jid: "{{ ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 30
delay: 20
监控与告警:边缘集群的可观测性
资源受限下的监控方案
标准的 Prometheus + Grafana 监控栈在边缘设备上太重了——Prometheus 自己就要吃 500M+ 内存。边缘场景需要更轻量的方案。
推荐方案:K3s 内置 metrics-server + 轻量 Prometheus Agent + 远程存储
边缘集群 云端
┌─────────────────┐ ┌──────────────────┐
│ K3s 集群 │ │ Prometheus + │
│ │ │ Grafana │
│ metrics-server │ │ │
│ (资源指标) │ │ (集中查询+告警) │
│ │ │ │
│ Prometheus Agent├────────→│ Remote Write │
│ (采集+转发) │ │ │
└─────────────────┘ └──────────────────┘
Prometheus Agent 模式只负责采集和转发,不做本地存储,资源占用极低(~50M 内存)。所有指标通过 remote_write 发送到云端的 Prometheus 做集中存储和查询。
# Prometheus Agent 配置(边缘节点)
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-agent-config
namespace: monitoring
data:
prometheus.yml: |
global:
scrape_interval: 30s # 边缘场景降低采集频率
evaluation_interval: 30s
# Agent 模式:只采集和转发,不做本地存储
remote_write:
- url: "https://cloud-prometheus.example.com/api/v1/write"
# 边缘网络不稳定,配置重试
queue_config:
capacity: 500
max_shards: 2
min_shards: 1
max_samples_per_send: 100
batch_send_deadline: 30s
scrape_configs:
# 采集 K3s 节点指标
- job_name: 'k3s-node'
static_configs:
- targets: ['localhost:10250']
scheme: https
tls_config:
ca_file: /var/lib/rancher/k3s/agent/client-ca.crt
cert_file: /var/lib/rancher/k3s/agent/client-kubelet.crt
key_file: /var/lib/rancher/k3s/agent/client-kubelet.key
bearer_token_file: /var/lib/rancher/k3s/agent/client-kubelet.token
# 采集容器指标
- job_name: 'k3s-containers'
static_configs:
- targets: ['localhost:10250']
scheme: https
tls_config:
ca_file: /var/lib/rancher/k3s/agent/client-ca.crt
cert_file: /var/lib/rancher/k3s/agent/client-kubelet.crt
key_file: /var/lib/rancher/k3s/agent/client-kubelet.key
bearer_token_file: /var/lib/rancher/k3s/agent/client-kubelet.token
metrics_path: /metrics/cadvisor
关键告警规则
边缘场景的告警规则和云端不同,需要特别关注网络断连和资源耗尽:
# 边缘集群关键告警规则
groups:
- name: edge-cluster-alerts
rules:
# Agent 节点离线
- alert: EdgeNodeOffline
expr: up{job="k3s-node"} == 0
for: 5m
labels:
severity: P1
annotations:
summary: "边缘节点 {{ $labels.instance }} 离线超过 5 分钟"
description: "检查节点网络连通性和 K3s Agent 进程状态"
# 节点内存使用率过高
- alert: EdgeNodeMemoryHigh
expr: |
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 85
for: 10m
labels:
severity: P2
annotations:
summary: "节点 {{ $labels.instance }} 内存使用率超过 85%"
description: "边缘设备内存有限,需要检查是否有异常 Pod 占用过多内存"
# 磁盘空间不足
- alert: EdgeNodeDiskSpaceLow
expr: |
(1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} /
node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) * 100 > 80
for: 15m
labels:
severity: P2
annotations:
summary: "节点 {{ $labels.instance }} 磁盘使用率超过 80%"
description: "检查容器日志和镜像是否需要清理"
# Pod 重启次数过多
- alert: EdgePodRestartLoop
expr: increase(kube_pod_container_status_restarts_total[1h]) > 5
for: 5m
labels:
severity: P2
annotations:
summary: "Pod {{ $labels.pod }} 在 1 小时内重启超过 5 次"
description: "可能是应用崩溃或 OOM,检查容器日志"
# K3s Server 不可达
- alert: K3sServerDown
expr: up{job="k3s-apiserver"} == 0
for: 2m
labels:
severity: P0
annotations:
summary: "K3s API Server 不可达"
description: "检查 K3s Server 进程和 etcd/SQLite 存储"
故障排查:边缘场景常见问题
问题一:Agent 节点加入失败
现象:Agent 安装后,kubectl get nodes 看不到节点。
排查步骤:
# 1. 检查 Agent 日志
sudo journalctl -u k3s-agent -f --no-pager | tail -50
# 2. 常见原因:token 不对
# 确认 Server 上的 token 和 Agent 使用的一致
cat /var/lib/rancher/k3s/server/node-token
# 3. 常见原因:网络不通
# 从 Agent 节点测试到 Server 的连通性
curl -k https://<SERVER_IP>:6443/readyz
# 4. 常见原因:防火墙拦截
# K3s Server 需要开放以下端口:
# 6443/tcp - K8s API
# 8472/udp - Flannel VXLAN
# 51820/udp - Flannel WireGuard(如果启用)
# 10250/tcp - Kubelet
# 5. 常见原因:时间不同步
# K8s 组件对时间敏感,时间差超过 30 秒会导致 TLS 证书验证失败
timedatectl status
问题二:Pod 一直处于 ContainerCreating
现象:部署 Pod 后一直卡在 ContainerCreating 状态。
# 查看 Pod 事件
kubectl describe pod <pod-name> -n <namespace>
# 常见原因1:镜像拉不下来
# 检查 containerd 镜像拉取日志
sudo crictl logs $(sudo crictl ps -a --name <container-name> -q)
# 常见原因2:CNI 网络插件没就绪
# 检查 Flannel Pod
kubectl get pods -n kube-system | grep flannel
# 常见原因3:磁盘满了
df -h
# 清理无用镜像
sudo k3s crictl rmi --prune
问题三:边缘节点频繁掉线
现象:节点频繁在 Ready 和 NotReady 之间切换。
# 1. 检查网络稳定性
ping -c 100 <SERVER_IP>
# 如果丢包率 > 5%,说明网络质量差
# 2. 调整 K3s Agent 的重连参数
# 编辑 /etc/rancher/k3s/agent.yaml
cat <<EOF | sudo tee /etc/rancher/k3s/agent.yaml
server: https://<SERVER_IP>:6443
token: <NODE_TOKEN>
kubelet-arg:
- "node-status-update-frequency=30s"
EOF
sudo systemctl restart k3s-agent
# 3. 检查节点资源是否耗尽
# 如果内存不足,kubelet 可能无法正常上报
free -h
问题四:SQLite 数据库锁死
单节点 K3s 用 SQLite 存储时,偶发数据库锁死导致 API Server 无响应:
# 检查 K3s Server 状态
sudo systemctl status k3s
# 如果卡住,查看日志
sudo journalctl -u k3s --no-pager | tail -100
# 典型的锁死日志:
# "database is locked" 或 "SQLITE_BUSY"
# 紧急恢复:重启 K3s
sudo systemctl restart k3s
# 长期方案:迁移到嵌入式 etcd
# 停止当前 K3s
sudo /usr/local/bin/k3s-uninstall.sh
# 用 etcd 模式重新安装
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-installation.sh | \
INSTALL_K3S_MIRROR=cn sh -s - \
--cluster-init \
--cluster-cidr 10.42.0.0/16 \
--service-cidr 10.43.0.0/16
多集群管理:云端统管边缘集群
边缘场景通常有几十上百个 K3s 集群分布在不同的机房和车间。手动管理每个集群的 kubectl context 根本不现实。这时候需要多集群管理工具。
方案对比
| 工具 | 维护方 | 适用规模 | 资源开销 | 功能 |
|---|---|---|---|---|
| Rancher | SUSE | 中大型 | 较高 | 全功能多集群管理 |
| kubecm | 开源 | 小型 | 零 | 仅 context 切换 |
| Cluster API | CNCF | 大型 | 中 | 集群生命周期管理 |
| Fleet | SUSE | 大型 | 中 | GitOps + 多集群 |
小型部署用 kubecm 够了——它就是一个帮你管理 kubeconfig context 的 CLI 工具:
# 安装 kubecm
curl -sLo kubecm.tar.gz https://github.com/sunny0826/kubecm/releases/latest/download/kubecm_Linux_x86_64.tar.gz
tar -zxvf kubecm.tar.gz kubecm
sudo mv kubecm /usr/local/bin/
# 添加集群 context
kubecm add edge-factory-1 --kubeconfig /path/to/factory-1-kubeconfig
# 切换集群
kubecm switch edge-factory-1
# 查看所有集群
kubecm list
如果集群数量超过 20 个,建议上 Rancher。Rancher 可以统一管理 K3s 和 K8s 集群,提供 Web 界面和 RBAC:
# 在云端安装 Rancher(用 Docker 快速部署)
docker run -d --restart=unless-stopped \
-p 80:80 -p 443:443 \
--name rancher \
rancher/rancher:v2.9.0
# 然后在每个 K3s 集群中注册 Agent
# Rancher 会生成一条 kubectl apply 命令
# 在 K3s Server 上执行即可
性能调优:榨干边缘设备的每一滴资源
资源分配策略
边缘设备的资源有限,必须精打细算。以下是典型的资源分配建议(以 2C/4G 的工控机为例):
总资源:2 vCPU / 4GB RAM / 32GB Disk
─────────────────────────────────────
系统保留: 0.3 vCPU / 512MB
K3s 系统组件: 0.3 vCPU / 512MB
- kubelet
- containerd
- Flannel
- CoreDNS
- metrics-server
应用可用: 1.4 vCPU / 3GB
─────────────────────────────────────
K3s Server 调优
# K3s Server 启动参数调优
# 编辑 /etc/systemd/system/k3s.service
# 在 ExecStart 行添加以下参数:
# --kube-apiserver-arg="default-watch-cache-size=100" # 降低 watch cache 内存
# --kube-apiserver-arg="max-requests-inflight=200" # 限制并发请求
# --kube-controller-manager-arg="node-sync-period=30s" # 降低同步频率
# --kube-controller-manager-arg="concurrent-deployments=2" # 降低并发
# --etcd-arg="quota-backend-bytes=17179869184" # 限制 etcd 存储 16GB
# 示例配置
ExecStart=/usr/local/bin/k3s server \
--kube-apiserver-arg="default-watch-cache-size=100" \
--kube-apiserver-arg="max-requests-inflight=200" \
--kube-controller-manager-arg="node-sync-period=30s" \
--kube-controller-manager-arg="concurrent-deployments=2" \
--write-kubeconfig-mode 644
容器运行时调优
# containerd 配置调优
# 编辑 /var/lib/rancher/k3s/agent/etc/containerd/config.toml.tmpl
# 关键调优项:
# - 限制日志大小
# - 降低垃圾回收频率
# - 限制并发下载
[plugins."io.containerd.grpc.v1.cri"]
# 限制容器日志大小
max_container_log_line_size = 16384
# 降低镜像拉取并发
[plugins."io.containerd.grpc.v1.cri".image_decryption]
key_model = "node"
# 日志限制
[plugins."io.containerd.runtime.v1.linux"]
# 每个容器最多保留 3 个日志文件
# 每个日志文件最大 10MB
log_rotation = true
log_max_size = "10MB"
log_max_files = 3
磁盘清理自动化
边缘设备磁盘空间有限,容器日志和镜像会逐渐占满磁盘。需要定期清理:
#!/bin/bash
# K3s 边缘节点磁盘清理脚本
# 建议用 cron 每天执行一次
set -euo pipefail
LOG_FILE="/var/log/k3s-disk-cleanup.log"
THRESHOLD=75 # 磁盘使用率超过 75% 时触发清理
echo "[$(date)] 开始磁盘清理..." >> "$LOG_FILE"
# 检查磁盘使用率
DISK_USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
echo "[$(date)] 当前磁盘使用率: ${DISK_USAGE}%" >> "$LOG_FILE"
if [ "$DISK_USAGE" -lt "$THRESHOLD" ]; then
echo "[$(date)] 磁盘使用率未超阈值,跳过清理" >> "$LOG_FILE"
exit 0
fi
# 1. 清理未使用的容器镜像
echo "[$(date)] 清理未使用镜像..." >> "$LOG_FILE"
sudo k3s crictl rmi --prune >> "$LOG_FILE" 2>&1
# 2. 清理容器日志(保留最近 3 天)
echo "[$(date)] 清理容器日志..." >> "$LOG_FILE"
find /var/lib/rancher/k3s/agent/containerd/logs -name "*.log" -mtime +3 -delete >> "$LOG_FILE" 2>&1
# 3. 清理 K3s 日志
echo "[$(date)] 清理 K3s 日志..." >> "$LOG_FILE"
sudo journalctl --vacuum-time=3d >> "$LOG_FILE" 2>&1
# 4. 清理临时文件
echo "[$(date)] 清理临时文件..." >> "$LOG_FILE"
find /tmp -type f -mtime +7 -delete >> "$LOG_FILE" 2>&1
# 检查清理后的磁盘使用率
DISK_USAGE_AFTER=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
echo "[$(date)] 清理后磁盘使用率: ${DISK_USAGE_AFTER}%" >> "$LOG_FILE"
echo "[$(date)] 磁盘清理完成" >> "$LOG_FILE"
# 添加 cron 任务
# echo "0 3 * * * /usr/local/bin/k3s-disk-cleanup.sh" | sudo tee /etc/cron.d/k3s-cleanup
安全加固:边缘设备的特殊风险
边缘设备部署在物理上不可控的环境中(车间、户外机柜),安全风险比机房服务器更高。需要特别注意以下几点:
1. K3s API Server 认证
# 不要在生产环境使用 --write-kubeconfig-mode 644
# 应该使用更严格的权限
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-installation.sh | \
INSTALL_K3S_MIRROR=cn sh -s - \
--write-kubeconfig-mode 600
2. 网络隔离
# 用 iptables 限制 K3s API 只允许管理网段访问
sudo iptables -A INPUT -p tcp --dport 6443 -s 10.0.0.0/8 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 6443 -j DROP
# 持久化 iptables 规则
sudo apt install iptables-persistent -y
sudo netfilter-persistent save
3. 镜像签名验证
边缘设备容易被物理接触,攻击者可能替换镜像。启用镜像签名验证:
# K3s containerd 配置镜像验证
# /var/lib/rancher/k3s/agent/etc/containerd/config.toml.tmpl
[plugins."io.containerd.grpc.v1.cri".containerd]
# 启用镜像拉取验证
default_runtime_name = "runc"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
# 配置只信任私有 registry
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
总结
K3s 在边缘计算场景下的价值不是说它"轻"——而是它在保持 K8s API 完全兼容的前提下,把部署和运维的复杂度降了一个数量级。你用 kubectl 管理边缘集群和管理云端 K8s 集群的操作完全一样,但资源开销只有后者的四分之一。
实际生产中需要关注的几个关键点:
架构选型上,单节点 Server + SQLite 适合小规模边缘部署(≤20 个 Agent)。大规模场景用嵌入式 etcd 多 Server 集群。如果已有 MySQL/PG 基础设施也可以复用。
网络方案上,默认的 Flannel VXLAN 对边缘场景最友好——对底层网络要求低,容忍跨子网。但要注意调整 kubelet 的断连容忍参数,否则网络抖动会导致 Pod 频繁重建。
应用部署上,边缘场景的核心约束是带宽和资源。镜像预分发比实时拉取更靠谱。资源 limit 必须设置——一台 2G 内存的设备上跑一个不设 limit 的 Pod,分分钟 OOM。
监控告警上,别在边缘设备上跑完整的 Prometheus。用 Agent 模式只采集转发,集中存储放到云端。告警规则重点关注节点离线、磁盘空间和 Pod 重启。
安全加固上,边缘设备的物理安全不可控,网络隔离和镜像验证是必修课。K3s API 端口不要暴露到公网。
最后说一句实践层面的体会:K3s 的安装确实是一行命令的事,但生产环境的边缘集群运维远不止安装。网络不稳定、资源受限、设备分散、镜像分发——这些才是真正的挑战。把这些问题都解决了,你的边缘 K3s 集群才算真正能上生产。
参考资料与致谢
本文在撰写过程中参考了以下资料,感谢原作者的贡献:
- K3s - 轻量级 Kubernetes(官方文档) — Rancher 官方,提供了 K3s 架构设计、安装配置和功能特性的权威说明
- 云原生环境中的边缘计算:从K3s到边缘节点的全栈部署 — CSDN,提供了 K3s 与 KubeEdge、OpenYurt 的对比分析和边缘应用部署实践
- 如何在 Ubuntu 22.04 LTS 上配置并调优 K3s 轻量级 Kubernetes 集群 — 腾讯云开发者社区,提供了边缘场景下的硬件选型、系统优化和 K3s 调优参数
- 轻量级k8s:适配边缘计算场景的轻量级的k8s-k3s入门与实战 — CSDN,提供了 K3s 与 K8s 的详细特性对比和资源占用数据
- 2026年Edge AI全面爆发:端侧小模型推理与K3s边缘部署实战全解析 — 51CTO博客,提供了 K3s 在 Edge AI 场景下的部署实践和容器化模型部署方案