节点与调度
yldm 是一个 K3s HA 集群(v1.33.5+k3s1),由 3 个 master + 4 个 worker 共 7 台虚拟机组成,分布在 4 台 Proxmox VE 主机上。物理层之上的 VM 拓扑由 pve-infra 用 Terraform 管理;本页讲的是 K3s 这一层的节点角色和工作负载怎么落到哪个节点上。
workload 节点标签(system / cicd / app / database / infra)。改了某个服务往哪调度,本质就是改它选哪个 workload 值;而集群事实来源以仓库 README.md 为准。节点拓扑
4 台 PVE 主机各承载若干 K3s 节点,外加 Synology NAS 上以 Docker 运行的 corosync-qnetd 提供 PVE 集群第 5 票仲裁(ffsplit 算法),合计 5 票,可容忍任意 2 节点同时离线。下表是 7 个 K3s 节点的分布、配置与标签。
| 主机名 | IP | 宿主 PVE | 配置 (核/内存/盘) | 角色 | 节点标签 |
|---|---|---|---|---|---|
| k8s-master1 | 192.168.88.101 | PVE1 (N100) | 2c / 6GB / 100GB | Control Plane | workload=system |
| k8s-master2 | 192.168.88.102 | PVE2 (N100) | 2c / 6GB / 100GB | Control Plane | workload=system |
| k8s-master3 | 192.168.88.103 | PVE3 (i9-12900H) | 2c / 6GB / 100GB | Control Plane | workload=system |
| k8s-worker1 | 192.168.88.111 | PVE1 (N100) | 4c / 20GB / 100GB | CI/CD Worker | workload=cicd |
| k8s-worker2 | 192.168.88.112 | PVE2 (N100) | 4c / 20GB / 300GB | App Worker | workload=app |
| k8s-worker3 | 192.168.88.113 | PVE3 (i9-12900H) | 12c / 48GB / 500GB | Database + Infra Worker | node-role=database, workload=infra |
| k8s-worker4 | 192.168.88.114 | PVE4 (N100) | 4c / 8GB / 100GB | App Worker | workload=app |
控制平面是 master1/2/3 三节点(etcd 3 成员)。worker3 是配置最高的节点(12c/48GB/500GB),独占数据库层与基础设施层两类职责。PVE4 与 NAS QDevice 是 2026-06 新增;同期旧的 pve3 infra 节点合并进 worker3 后销毁,新的 worker4(app)落在 pve4 上。集群物理资源合计约 32 线程 / 144GB 内存。
workload 调度键
workload 是主要调度键,单值,取值固定为以下五种之一:
- Name
- system
- Description
- 三个 master 节点,承载 K3s 控制面(etcd / API server)。
- Name
- cicd
- Description
- worker1,专跑 GitHub Actions Runner(ARC v2,scale-set
yldm-backend-runners,2-12 副本)。
- Name
- app
- Description
- worker2 + worker4 两节点,承载 app 与 platform 命名空间的业务微服务。
- Name
- database
- Description
- worker3,由
node-role=database标记,仅数据库层 StatefulSet 使用(PV 钉在本节点本地盘)。
- Name
- infra
- Description
- worker3,由
workload=infra标记,承载全部基础设施组件。
node-role: infra 统一迁移到 workload: infra(PR #888)—— 因为 node-role 是单值标签,无法让一个节点同时承担数据库和 infra 两种角色。node-role=database 仍保留,专供数据库 StatefulSet 钉盘用。k3s 内置组件的调度定制方式不一:traefik 走 Git 管理的 applications/networking/traefik/helmchartconfig-traefik.yaml(worker 间软打散,HPA 2-5 副本);coredns / metrics-server 则是集群内直接 patch 成 workload: infra,k3s 重启可能回到默认值,属已知事项。
worker3 双职责
worker3 同时打了 node-role=database 和 workload=infra 两个标签,因此一个节点承担两类职责:
- 数据库层(local-path,PV 钉本节点):PostgreSQL 主从、Redis、MongoDB、RabbitMQ、Meilisearch ×2、MinIO(800GB)、NATS、Consul、Tempo。
- 基础设施层(
workload=infra,可调度):GitOps(ArgoCD 全家桶)、监控日志(Prometheus / Grafana / Loki / Alertmanager / kube-state-metrics)、网络(MetalLB controller / Cloudflare Tunnel / External-DNS / Cert-Manager)、安全(Vault / External-Secrets / Dex OIDC / Kyverno)、备份(Velero)。
因为有状态数据库的 PV 通过 local-path 钉死在 worker3 本地盘,这些 StatefulSet 无法漂移到其他节点 —— worker3 是集群的单点,宕机处置另见运维手册。数据层细节参见 集群架构 - 数据层。
app 层双节点
worker2 与 worker4 都打 workload=app,构成应用层的双节点:
- app 命名空间:magicbox、aidict、creativestore、kubepocket、myetc、kamify 等。
- platform 命名空间:analytics、auth、commerce、engagement、gateway、management、media、notification、scheduler、social、user。
多副本服务通过反亲和分布在这两个节点上,单节点故障不再让某服务全部副本一起挂掉。这是 2026-06 加入 worker4(pve4)后才有的能力 —— 在此之前 app 层只有 worker2 单节点。
反亲和与 PDB 规则
两条调度硬约定,新增或修改服务时必须遵守:
- Name
- 多副本 — podAntiAffinity
- Description
- 多副本服务必须配
podAntiAffinity,并带上matchLabelKeys: pod-template-hash,避免滚动更新时新副本被旧副本挤到同一节点,保证副本真正打散在 worker2 / worker4 上。
- Name
- 单副本 — PDB maxUnavailable: 1
- Description
- 单副本服务的 PodDisruptionBudget 一律用
maxUnavailable: 1。不要用minAvailable: 1—— 那会让节点 drain 永久卡死(PR #895)。
main 几分钟后 ArgoCD 就会自动同步进集群,没有手动 kubectl apply 这一步。调度相关改动(标签、亲和、PDB)合错了会直接影响 Pod 落点甚至卡死 drain,合并前务必用仓库 CI 的 kustomize build 校验。详见 GitOps 工作流。