从 Calico 微隔离到 HPA 与节点自动扩容:制造业 Kubernetes 生产平台实战
本文基于一次脱敏后的制造业 Kubernetes 平台改造经历,以及一套本地 Minikube 实验整理而成。重点不是堆砌命令,而是说明生产环境中安全隔离、Pod 弹性和节点弹性之间如何配合。
一、项目背景
该制造业集团原有订单、供应链和设备管理系统主要运行在虚拟机上,之后逐步完成微服务化和容器化。生产平台承载用户中心、订单、库存、支付、供应商协同和设备管理等核心业务。
脱敏后的规模如下:
-
3 套 Kubernetes 集群;
-
核心交易集群约 80 个工作节点;
-
设备管理集群约 45 个工作节点;
-
运维及公共服务集群约 20 个工作节点;
-
总计约 1,500 个 Pod、120 多个微服务;
-
核心交易高峰约 3,000 QPS;
-
核心业务可用性目标为 99.95%。
集群运行在企业私有云的三个资源区。控制平面和 etcd 均采用三节点高可用部署,容器运行时为 containerd,网络使用 Calico,有状态服务通过 CSI 对接分布式块存储。监控采用 Prometheus、Grafana 和 Alertmanager,日志由 Fluent Bit 采集至 Elasticsearch。
入口链路为:
外部用户 → 负载均衡 → WAF → Nginx Ingress Controller → Service → Pod
二、安全改造:从“内网默认可信”转向最小权限
平台最初虽然已经容器化,但安全模型仍接近传统内网:集群内部默认互通、不同命名空间缺乏网络边界、运维人员接入 VPN 后可感知较大的内网范围,而且业务依赖关系不完整。
需要特别注意:命名空间只是资源管理边界,不会天然形成网络隔离。没有 NetworkPolicy 时,Pod 默认可以接收入站和发起出站通信。Kubernetes NetworkPolicy 官方文档
1. 先建立身份,再编写策略
策略对象不应该长期绑定易变化的 Pod IP,而应该使用稳定的命名空间和标签。我们统一要求工作负载至少包含以下信息:
-
应用名称;
-
业务系统;
-
环境;
-
应用角色;
-
数据敏感等级;
-
负责人。
例如:
metadata:
labels:
app: order
role: backend
env: prod
2. 先观察真实流量
我们结合 Calico 流量日志、Ingress 日志、应用调用日志和防火墙日志,观察约两周,形成业务访问矩阵:谁访问谁、协议和端口是什么、是否跨命名空间、是否访问集群外数据库,以及该连接是持续依赖还是临时运维行为。
不能确认的流量先标记,不直接永久放行。生产微隔离最危险的两种做法分别是“直接全量拒绝”和“为了恢复业务放行整个网段、全部端口”。
3. 五层策略模型
我们将策略划分为五层:
-
全局基线:普通业务 Pod 禁止访问 etcd、kubelet、宿主机管理端口等敏感目标;
-
命名空间默认拒绝:完成依赖梳理后再启用 ingress/egress default deny;
-
公共基础服务:统一放行 DNS、时间同步、日志、监控、证书校验等必要依赖;
-
业务白名单:按命名空间、标签、协议和端口精确放行;
-
临时运维规则:绑定工单和有效期,到期自动回收。
NetworkPolicy 的规则是叠加生效的:多个策略选中同一 Pod 时,允许集合取并集,不存在传统防火墙那种依靠规则先后顺序覆盖的逻辑。NetworkPolicy API 说明
因此,给具体 Pod 下发灰度规则时,可以先给少量 Pod 增加标签:
metadata:
labels:
policy-canary: "true"
再让新策略只选择这些 Pod。确认成功率、P99 延迟和拒绝日志正常后,逐步扩大标签覆盖范围。
三、一次 DNS 被误拦截的生产故障
支付命名空间实施 egress 微隔离后,最初几分钟 CPU、内存和 Pod 状态都正常,但约十分钟后支付接口 P99 延迟升高,成功率从约 99.9% 降至约 92%。
排查过程分为四步:
-
立即停止后续发布并回滚策略,优先恢复业务;
-
检查节点、Pod、Ingress、数据库连接和外部风控服务,缩小故障范围;
-
查看 Calico deny 日志,发现支付 Pod 到 CoreDNS 的 UDP 53 和 TCP 53 被拒绝;
-
补充 DNS 规则,先对两个带灰度标签的支付 Pod 验证,再逐批扩大范围。
故障没有立即全量出现,是因为部分 Pod 仍有 DNS 缓存,不同 Pod 的缓存过期时间并不完全一致。
这个事件说明:启用 egress default deny 时,DNS 是必须显式处理的基础依赖;官方文档也明确提醒,默认拒绝出站会同时阻断 DNS。Kubernetes 默认拒绝策略说明
故障后,我们补充了基础依赖策略模板、观察—告警—阻断三阶段机制、自动连通性测试、拒绝流量 Grafana 看板、策略 Git 评审以及限时授权回收机制。
四、SDP、RBAC 和微隔离分别解决什么问题
三者不是互相替代,而是控制不同层面:
-
SDP:谁使用什么设备、在什么条件下可以连接管理入口;
-
Kubernetes RBAC:连接集群后允许执行哪些 API 操作;
-
微隔离:工作负载之间以及工作负载与外部资源之间如何通信。
运维人员先经过身份、多因素认证、设备合规和工单校验,再获得到指定堡垒机、Grafana、Dashboard 或 API 地址的加密通道;进入 Kubernetes 后,仍然受到 RBAC 约束。这样才能把传统“进入一大片内网”的权限收敛到具体用户、设备、应用和操作。
五、HPA 的指标和计算原理
HPA 不只支持 CPU 和内存。使用 autoscaling/v2 时还可以使用:
-
Resource:CPU、内存;
-
Pods:每个 Pod 的自定义指标;
-
Object:某个 Kubernetes 对象关联的指标;
-
External:队列长度、消息积压、QPS 等外部指标。
CPU 和内存通常由 Metrics Server 提供,自定义和外部指标一般需要对应的 Metrics Adapter。
HPA 的核心公式可以简化为:
期望副本数 = ceil(当前副本数 × 当前指标值 ÷ 目标指标值)
例如当前有 6 个 Pod,平均 CPU 利用率为 58%,目标值为 50%:
ceil(6 × 58% ÷ 50%)= ceil(6.96)= 7
如果平均 CPU 是 60%,结果则是:
ceil(6 × 60% ÷ 50%)= ceil(7.2)= 8
因此,“期望副本为什么是 7”必须结合当时 HPA 实际采集到的平均值判断,不能只看某一个 Pod 的瞬时 CPU。
当使用 averageUtilization 时,CPU 百分比的分母是容器的 CPU request,而不是节点总 CPU,也不是 CPU limit。例如 Pod 的 request 是 1 核,实际使用 0.6 核,对 HPA 来说就是 60%。
如果同时配置 CPU 和内存指标,HPA 会分别计算建议副本数,然后取最大的结果,以避免任意一个指标仍然超标;并不是取最小值。HPA v2 API 说明
一个常见配置如下:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: payment
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: payment
minReplicas: 6
maxReplicas: 30
behavior:
scaleDown:
stabilizationWindowSeconds: 300
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
负载降低后,HPA 会重新计算较小的期望副本数,但不会一定立即下降。容忍区间、指标刷新周期和 scaleDown.stabilizationWindowSeconds 都会抑制抖动。
六、容量到底怎样算
假设支付服务配置如下:
-
HPA:6~30 个 Pod;
-
每个 Pod request:1 核、1 GiB;
-
支付节点池:3~10 台;
-
每台节点可供业务使用 8 核;
-
当前节点池已经分配了大部分资源。
调度器判断一个 Pod 能否落到节点上,主要依据 request 和其他调度约束,而不是 Pod 当前的真实使用量。
假设整个节点池还剩 10 核 CPU、8 GiB 内存,每个新 Pod 申请 1 核、1 GiB:
CPU 最多容纳:10 ÷ 1 = 10 个 Pod
内存最多容纳:8 ÷ 1 = 8 个 Pod
最终可调度数量:min(10, 8)= 8 个 Pod
所以即使 CPU 还能放 10 个,内存只能放 8 个,最终也只能新增 8 个。除此之外还要考虑 DaemonSet、系统预留、亲和性、污点容忍、拓扑分布、存储约束和单节点碎片。
生产 request 不建议只凭感觉设置。可以查看一段足够代表业务周期的 Prometheus 历史数据,结合 P95/P99、启动峰值和安全余量确定。CPU 可适度超卖,内存则应更保守,因为超过节点可用内存可能触发 OOM。
七、Pod 弹性与节点弹性如何衔接
完整链路如下:
业务流量升高
→ Pod 平均指标超过 HPA 目标
→ HPA 增加 Deployment 副本
→ 集群剩余 request 不足,新 Pod Pending
→ 节点自动伸缩器识别不可调度 Pod
→ 云平台或虚拟化平台创建新节点
→ 新节点加入并 Ready
→ 调度器把 Pending Pod 放到新节点
流量下降时则反向运行:HPA 减少 Pod,节点自动伸缩器确认节点可安全排空后执行整合或删除。
节点自动伸缩器重点关注 Pending Pod 的 request 和调度约束,而不是简单看到“节点 CPU 超过 60%”就直接加机器。Kubernetes 官方也说明,节点伸缩器通过创建或删除云平台资源来提供和整合节点,因此必须与具体基础设施 API 集成。Kubernetes 节点自动伸缩
八、本地验证:从 1 个节点自动扩到 2 个
为了理解完整链路,我使用 Windows、VMware Workstation 和 Minikube 搭建了一套实验环境。
测试 Deployment 创建 5 个副本,每个 Pod 请求 1 核 CPU、256 MiB 内存。单节点只能容纳其中 2 个,结果为:
2 个 Pod:Running
3 个 Pod:Pending(Insufficient cpu)
首先确认 Pending 原因:
kubectl get pods -n node-scale-lab -o wide
kubectl describe pod <Pending-Pod名称> -n node-scale-lab
本地监控脚本发现 Insufficient cpu 后执行 minikube node add。新增节点完成 kubeadm 加入和 CNI 初始化并变成 Ready 后,原来的 3 个 Pending Pod 全部自动调度到新节点:
hpa-lab Ready control-plane
hpa-lab-m02 Ready worker
主节点:2 个业务 Pod
新节点:3 个业务 Pod
Minikube 本身支持多节点实验,但本地 host-path 存储在多节点环境有明确限制,不能把这个实验直接等同于生产架构。Minikube 多节点教程
节点缩容测试中,先把业务副本降到 2 个,再依次执行:
cordon → drain → 删除 worker
最终集群恢复为 1 个 Ready 节点,2 个业务 Pod 在主节点正常运行。
本地重复实验命令:
kubectl apply -f C:\Users\Administrator\hpa-lab\node-scale-test.yaml
powershell -ExecutionPolicy Bypass -File C:\Users\Administrator\hpa-lab\local-node-scale-up.ps1
powershell -ExecutionPolicy Bypass -File C:\Users\Administrator\hpa-lab\local-node-scale-down.ps1
这里的 PowerShell 监控器只是对生产节点伸缩链路的本地模拟。生产环境应使用 Cluster Autoscaler、Karpenter 或私有云平台支持的节点伸缩组件,并接入真实节点池 API。
九、生产落地建议
-
HPA、Pod request 和节点伸缩必须一起设计;只配置 HPA 而没有节点容量,最终只会得到更多 Pending Pod。
-
request 决定调度和节点扩容判断,应基于历史指标、压测和安全余量持续校准。
-
核心服务设置合理的 minReplicas、PodDisruptionBudget、反亲和或拓扑分布,避免缩容破坏高可用。
-
节点池设置最小值、最大值和不同规格,限制成本与扩容边界。
-
监控从“CPU 高不高”扩展到 Pending Pod、调度失败原因、HPA conditions、扩容耗时、节点 Ready 耗时和业务 SLO。
-
NetworkPolicy 先观察、再告警、最后阻断;基础依赖尤其是 UDP/TCP 53 的 DNS 规则必须纳入模板。
-
所有安全策略和伸缩配置进入 Git,经过评审、灰度验证并保留快速回滚能力。
十、总结
Kubernetes 弹性伸缩并不是“CPU 到 60% 就增加节点”这么简单。HPA 负责根据业务指标调整 Pod 数量,调度器根据 request 和约束寻找节点,节点伸缩器再为不可调度 Pod 提供基础设施容量。
安全改造同样不是 NetworkPolicy 写得越多越好。真正困难的是掌握真实业务依赖,并把身份、最小权限、可观测性、灰度发布、自动测试和快速回滚组合成一套可以长期运营的工程体系。
只有把安全边界、资源模型、Pod 弹性和节点弹性连起来,Kubernetes 平台才能同时具备安全性、稳定性和成本效率。