k8s部署

基于 K3s 的 Kubernetes 边缘计算实战:从三节点集群到 Nginx 边缘调度

01. 背景与动机

其实动机是正好有这个实验^ ^

1.1 从容器编排到边缘计算

Kubernetes 早已成为容器编排的事实标准,但原生 K8s 组件繁重,对资源有一定要求。当场景从数据中心扩展到边缘侧——比如 IoT 网关、工控机或小型边缘节点时,一个轻量、易维护、完全兼容 K8s API 的发行版就显得至关重要。本次实验的目标,正是使用 K3s 快速构建一个包含 master + worker + edge 的三节点集群,并通过调度策略将工作负载精准落地到边缘节点,为后续云边协同框架(如 KubeEdge)的引入铺路。

1.2 为什么选择 K3s

相较于完整的 Kubernetes,K3s 将所有组件打包进一个不足 100 MB 的二进制文件,默认以 SQLite 替代 etcd,内存占用常低于 1 GB。它专为边缘、IoT 及开发测试环境设计,同时通过了 CNCF 认证,所有 Kubernetes 核心功能——调度、服务发现、滚动更新、RBAC 等——均可在 K3s 上直接使用。在本实验中,我们利用 K3s 的轻量特性在三台 Ubuntu 虚拟机中快速拉起集群,并体验原生 nodeSelector 的边缘调度能力。

02. 实验环境概览

2.1 硬件与网络

  • 宿主机:macOS + OrbStack
  • 虚拟机模板:Ubuntu 24.04 × 3
  • 网络:OrbStack 内部可路由网络,各节点在同一二层可达

2.2 节点角色规划

主机名 IP 地址 角色
master 192.168.139.65 K3s Server(控制面)
slave1 192.168.139.246 K3s Agent(普通工作节点)
edge 192.168.139.24 K3s Agent(边缘节点)

我们将 edge 节点标记为边缘角色,后续通过标签实现工作负载定向调度。

03. 环境准备与连通性验证

3.1 查看各节点 IP

在三台虚拟机终端分别执行 ip a,确认各自主 IP 与规划表一致。以 master 为例,其 eth0 接口地址为 192.168.139.65/24,其他节点类似。这一步确保虚拟机网络配置正确。

3.2 全互联 ping 测试

为证明节点间二层无阻断,按以下矩阵执行 ICMP 探测,每次发送 3 个包:

  • master → slave1 (192.168.139.246)、edge (192.168.139.24)
  • slave1 → master (192.168.139.65)、edge (192.168.139.24)
  • edge → master (192.168.139.65)、slave1 (192.168.139.246)

所有测试结果均为 0% packet loss,RTT 在毫秒级。可靠的内网连通性是集群后续正常工作的基石。

04. K3s 集群搭建

4.1 安装 K3s Server(master 节点)

在 master 终端执行一键安装脚本,添加 --write-kubeconfig-mode 644 以便非 root 用户直接使用 kubectl:

1
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--write-kubeconfig-mode 644" sh -

安装结束后立即查看节点,此时只有 master 自身:

1
2
3
sudo kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane 48s v1.35.4+k3s1

STATUSReady 表明控制平面已正常启动。

4.2 获取 Agent 加入 Token

K3s Server 生成静态 Token 用于节点认证,执行:

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

记录输出(示例):

1
K10db9ac453d435180b7471b86bb41adcfc06972c9082394917e2b63ba23ff97ea0::server:ca91568897ca46f0891ea228a7559628

后续 Agent 节点需凭借此 Token 安全加入集群。

4.3 加入 Agent 节点:slave1 和 edge

分别在 slave1edge 上执行相同格式的命令,指定 Server 地址及 Token:

1
curl -sfL https://get.k3s.io | K3S_URL=https://192.168.139.65:6443 K3S_TOKEN=K10db9ac453d435180b7471b86bb41adcfc06972c9082394917e2b63ba23ff97ea0::server:ca91568897ca46f0891ea228a7559628 sh -

脚本会自动安装 k3s-agent 并注册到 Server。网络正常的情况下,约 30 秒即可完成。

05. 集群状态验证

在 master 节点执行宽格式输出,检查所有节点:

1
sudo kubectl get nodes -o wide

预期三节点 STATUS 均为 ReadyROLES 中 master 显示 control-plane,其余为空。输出类似:

1
2
3
4
NAME     STATUS   ROLES           AGE   VERSION         INTERNAL-IP
master Ready control-plane 2m v1.35.4+k3s1 192.168.139.65
slave1 Ready <none> 1m v1.35.4+k3s1 192.168.139.246
edge Ready <none> 1m v1.35.4+k3s1 192.168.139.24

三节点就绪,标志着基础 Kubernetes 集群搭建成功。

06. 边缘调度配置与 Nginx 应用部署

6.1 为边缘节点赋予标识标签

为了让调度器能够将 Pod 绑定到 edge,我们为其打上自定义标签 node-role=edge

1
sudo kubectl label node edge node-role=edge

此时可通过 kubectl describe node edge 查看 Labels 字段已包含该标签。

6.2 编写 Deployment,使用 nodeSelector 锁定边缘节点

创建 nginx-edge.yaml,核心是通过 nodeSelector 强制 Pod 只调度到具有 node-role=edge 标签的节点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-edge
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
nodeSelector:
node-role: edge
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80

应用并观察滚动状态:

1
2
sudo kubectl apply -f nginx-edge.yaml
sudo kubectl rollout status deployment/nginx-edge

rollout status 返回 successfully rolled out 后,说明 Deployment 已就绪且 Pod 已被成功调度。

6.3 创建 NodePort 服务暴露应用

为了让集群内外都能访问 Nginx,我们创建类型为 NodePort 的 Service,并指定 nodePort: 30080(合法范围 30000-32767):

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080

执行 sudo kubectl apply -f nginx-service.yaml。Service 创建后,集群所有节点都会在 30080 端口监听,并将流量转发到标签为 app: nginx 的 Pod。

07. 结果验证与调度原理分析

7.1 确认 Pod 精确落在 edge 节点

在 master 上查询 Pod 宽信息:

1
sudo kubectl get pods -o wide

输出应明确显示 nginx-edge 所在 NODE 列为 edge,例如:

1
2
NAME                          READY   STATUS    RESTARTS   AGE   IP           NODE
nginx-edge-xxxxxxxxxx-xxxxx 1/1 Running 0 30s 10.42.2.5 edge

这验证了 nodeSelector 生效,Pod 被严格限定在边缘节点。

7.2 从普通工作节点访问边缘服务

在 slave1 终端,使用 curl 直接请求边缘节点 IP 的 30080 端口:

1
curl http://192.168.139.24:30080

立即返回 Nginx 欢迎页 HTML,包含 <h1>Welcome to nginx!</h1> 等元素,响应码 200。这说明:

  • NodePort 服务成功将流量路由到 edge 节点上的 Pod;
  • 即使请求的是边缘节点 IP,服务也能被任意节点(包括 slave1)访问,体现了 Service 的跨节点转发能力。

7.3 深度解析:nodeSelector 与 NodePort 协作

nodeSelector 是 Kubernetes 中最简单的亲和性调度策略。当 Pod 模板中指定后,调度器在过滤阶段只会考虑带有匹配标签的节点。在本实验中,只有 edge 节点带有 node-role=edge,因此 Deployment 唯一的副本必然落在 edge 上。如果没有节点满足条件,Pod 将处于 Pending 状态,事件日志会提示 didn't match Pod's node affinity/selector

NodePort 的实现机制:kube-proxy 在每个节点上打开相同的 nodePort,并维护 iptables 规则。当请求到达任一节点的 30080 端口时,kube-proxy 会将其 DNAT 到目标 Pod(无论 Pod 是否在本节点)。因此从 slave1 访问 edge_IP:30080slave1_IP:30080 都能成功,只是后者可能多一跳转发。这正是 Kubernetes 简化服务暴露、实现负载均衡的关键设计。

08. 总结与云边协同展望

通过本次实践,完成了以下任务(算是吧):

  • 使用 K3s 在 3 分钟内搭建起一个包含控制面和两个 Agent 节点的 Kubernetes 集群;
  • 利用标签和 nodeSelector 将 Nginx 工作负载精准部署到标记为 edge 的节点;
  • 通过 NodePort 服务验证了跨节点的服务可达性。

这套环境完全兼容 Kubernetes API,意味着后续可以无缝集成 KubeEdge 等边缘计算框架。KubeEdge 能将云上的编排能力延伸到边缘,实现边端设备管理、边缘自治和云边消息通道。我们当前用 K3s 打下的基础,正是云边协同架构中“边缘 Kubernetes 底座”的典型形态:轻量化、标准化,能承载业务容器并接受云端统一调度。未来,可以进一步部署边缘 AI 推理、实时数据处理等负载,并结合 KubeEdge 的云端核心组件,构建完整的云边协同解决方案。