《Kubernetes 网络进阶、调度策略与自动扩缩容实战精要》
本总结覆盖 Kubernetes 网络模型(CNI/CNM) 、跨主机网络方案对比 、Calico 网络策略(NetworkPolicy) 、Pod 调度控制(nodeName / nodeSelector / 亲和性 / 污点容忍) 、节点维护(cordon/drain) 、Metrics Server 部署 以及 HPA(水平 Pod 自动伸缩) 的完整配置与实验代码,所有核心知识点均配有详细注释,可直接用于生产环境参考。
一、Kubernetes 网络模型概览
1.1 单主机网络(Docker / Containerd)
- 容器使用 veth pair 连接至宿主机网桥(如
docker0),通过 Linux 内核直接复制数据包 实现高效通信,无需经过外部物理网络。 - 外部访问需通过 端口映射(hostPort 或 NodePort)。
1.2 跨主机网络方案对比(重点)
| CNI方案 | 网络模型(Underlay/Overlay) | 性能 | 支持 NetworkPolicy | 适用场景 |
|---|---|---|---|---|
| Flannel | host-gw (Underlay) / VXLAN (Overlay) | host-gw 高,VXLAN 有封装开销 | ❌ | 中小集群,简单连通需求 |
| Calico | BGP (Underlay) / IPIP/VXLAN (Overlay) | BGP 最优,IPIP 有开销 | ✅ 原生支持 | 生产环境,需要网络策略 |
| Weave Net | UDP 隧道 (Overlay) | 较低 | ✅ | 小规模测试 |
| Macvlan | Underlay(直连物理网络) | 极高(无封装) | 依赖配套插件 | Pod 需要独立 MAC/IP,低延迟 |
核心结论:
- Underlay 性能优于 Overlay(无隧道封装)。
- 若需 网络策略(NetworkPolicy),必须选择 Calico 或 Weave 等支持方案。
- 生产环境推荐 Calico(BGP 模式)。
二、容器网络接口模型(CNM vs CNI)
| 模型 | 提出者 | 最小单元 | 依赖 | 特点 |
|---|---|---|---|---|
| CNM(Container Network Model) | Docker | 容器(Container) | 依赖 dockerd 及 libnetwork | Docker 原生,使用较少 |
| CNI(Container Network Interface) | Google / CoreOS | Pod(一组容器) | 无守护进程,插件化 | Kubernetes 标准,插件可替换 |
- CNI 工作流程:kubelet 调用 CNI 插件(如 Calico)为 Pod 创建网络命名空间、分配 IP 并设置路由。
- IPAM 插件 :负责 IP 地址分配(如
calico-ipam)。
三、Calico 网络实战(容器网络策略与 IP 池)
3.1 Calico 架构要点
- 纯三层方案 :每个节点作为路由器,通过 BGP 交换 Pod 路由,无 NAT 和隧道(默认 BGP 模式)。
- 支持 NetworkPolicy:通过 Profile 和 Policy 规则精细化控制 Pod 间流量。
- IP 池可定制:支持预定义子网或手动指定 IP。
3.2 部署 Calico(Docker 环境示例,带注释)
bash
# 下载 calicoctl 工具
wget -O /usr/local/bin/calicoctl https://github.com/projectcalico/calicoctl/releases/download/v1.0.2/calicoctl
chmod +x /usr/local/bin/calicoctl
# 配置 calicoctl 连接 etcd(需提前部署 etcd)
mkdir /etc/calico
cat << EOF > /etc/calico/calicoctl.cfg
apiVersion: v1
kind: calicoApiConfig
metadata:
spec:
etcdEndpoints: "http://10.1.8.30:2379"
EOF
# 启动 calico-node(以容器运行)
calicoctl node run
# 此时 calico 自动发现其他节点,并建立 BGP 连接
3.3 创建 Calico 网络(Docker 网络驱动)
bash
# 创建一个名为 cal_net1 的 Calico 网络,使用 calico 驱动和 calico-ipam IPAM
docker network create --driver calico --ipam-driver calico-ipam cal_net1
3.4 定制 Network Policy(允许跨网络访问)
场景 :允许 cal_net2 中的 Pod 访问 cal_web 网络中 Web 服务的 80 端口。
yaml
# web.yml - 修改 cal_web 的 profile,开放 ingress 规则
- apiVersion: v1
kind: profile
metadata:
name: cal_web # 对应 cal_web 网络
spec:
ingress:
- action: allow
protocol: tcp
destination:
ports:
- 80 # 允许访问 80 端口
source:
tag: cal_net2 # 仅允许来自 cal_net2 网络(标签)的源
应用策略:
bash
calicoctl apply -f web.yml
3.5 定制 IP 池
bash
# 定义 IP Pool(CIDR 为 17.2.0.0/16)
cat << EOF > ipPool.yml
- apiVersion: v1
kind: ipPool
metadata:
cidr: 17.2.0.0/16
EOF
calicoctl create -f ipPool.yml
# 创建网络时指定子网
docker network create --driver calico --ipam-driver calico-ipam --subnet=17.2.0.0/16 my_net
四、Kubernetes NetworkPolicy(网络策略)
NetworkPolicy 通过 标签选择器 控制 Pod 的入站(Ingress)和出站(Egress)流量。需要支持 CNI(如 Calico)。
4.1 规约结构(带注释)
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector: # 策略作用的 Pod 选择器
matchLabels:
role: db
policyTypes: # 必填,指定 Ingress / Egress
- Ingress
- Egress
ingress: # 入站规则白名单
- from:
- ipBlock: # 允许来源 IP 段
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector: # 允许来自特定命名空间(标签)
matchLabels:
project: myproject
- podSelector: # 允许来自同命名空间内特定 Pod
matchLabels:
role: frontend
ports: # 允许访问的端口
- protocol: TCP
port: 6379
egress: # 出站规则
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
4.2 实战示例(按条件限制访问)
① 限制同一 Namespace 内特定 Pod 访问(podSelector)
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-test-to-web1
namespace: web
spec:
podSelector:
matchLabels:
run: web1 # 作用于 web1 Pod
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: test # 只允许标签 run=test 的 Pod 访问
ports:
- protocol: TCP
port: 80
② 允许同一 Namespace 所有 Pod 访问(podSelector: {})
yaml
ingress:
- from:
- podSelector: {} # 空选择器,匹配该 namespace 所有 Pod
ports:
- port: 80
③ 允许来自特定 Namespace(namespaceSelector)
yaml
ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject # 只有标签为 project=myproject 的 namespace 内的 Pod 可访问
ports:
- port: 80
④ 根据 IP 段(ipBlock)控制
yaml
ingress:
- from:
- ipBlock:
cidr: 10.1.8.0/24
except:
- 10.1.8.128/26 # 排除子网
ports:
- port: 80
⑤ 限制所有端口(不指定 ports)
yaml
ingress:
- from:
- podSelector:
matchLabels:
run: test
# 未指定 ports,表示允许所有端口(包括 ICMP)
⑥ 多条件组合(满足任一即可)
yaml
ingress:
- from:
- ipBlock: { cidr: 10.1.1.0/24 }
- namespaceSelector: { matchLabels: { project: myproject } }
- podSelector: { matchLabels: { run: test } }
# 任一条件满足即可
4.3 默认策略(隔离所有流量)
yaml
# 默认拒绝所有入站
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
# 默认拒绝所有出站
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- Egress
注意:NetworkPolicy 无法实现"显式拒绝",只能通过允许白名单间接拒绝。
五、Pod 调度控制
调度器通过 过滤(Filter) 和 打分(Score) 选择最佳节点。
5.1 nodeName(强制指定节点)
yaml
spec:
nodeName: worker32.laoma.cloud # 直接指定节点名称,优先级最高,但不推荐
5.2 nodeSelector(基于标签的简单约束)
bash
# 给节点打标签
kubectl label node worker31.laoma.cloud disktype=ssd
# Pod 配置
spec:
nodeSelector:
disktype: ssd # 必须匹配节点标签
5.3 节点亲和性(nodeAffinity)
支持 硬性(required) 和 软性(preferred) 规则。
YAML 示例(带注释):
yaml
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬性要求
nodeSelectorTerms:
- matchExpressions:
- key: CPU
operator: In
values:
- L1
- L2
preferredDuringSchedulingIgnoredDuringExecution: # 软性偏好(带权重)
- weight: 1
preference:
matchExpressions:
- key: MEM
operator: In
values:
- L1
- L2
operator支持:In、NotIn、Exists、DoesNotExist、Gt、Lt。- 若同时使用
nodeSelector和nodeAffinity,需同时满足。
5.4 Pod 间亲和性与反亲和性(inter-pod affinity/anti-affinity)
基于 已有 Pod 标签 决定调度位置,需指定 topologyKey(节点标签键)。
亲和性(Pod 尽量调度到同一拓扑域):
yaml
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web1
topologyKey: topology.kubernetes.io/zone # 节点必须具有该标签键
反亲和性(Pod 尽量分散到不同拓扑域):
yaml
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: kubernetes.io/hostname # 每个节点只能运行一个
示例(Redis 部署,每个节点最多一个副本):
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: store
spec:
replicas: 3
selector:
matchLabels:
app: store
template:
metadata:
labels:
app: store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: kubernetes.io/hostname
containers:
- name: nginx
image: nginx
注意:Pod 亲和/反亲和在大规模集群中消耗性能,建议节点数 < 500。
六、污点(Taint)与容忍度(Toleration)
- Taint 设置在节点上,用于 排斥 不匹配的 Pod。
- Toleration 设置在 Pod 上,允许被调度到有匹配污点的节点。
6.1 管理污点
bash
# 添加污点(key=value:effect)
kubectl taint nodes worker31.laoma.cloud CPU=L1:NoSchedule
# 移除污点(key:effect-)
kubectl taint nodes worker31.laoma.cloud CPU:NoSchedule-
Effect 类型:
NoSchedule:硬性排斥,新 Pod 不调度。PreferNoSchedule:软性排斥,尽量不调度。NoExecute:立即驱逐不能容忍该污点的已有 Pod,且不调度新 Pod。
6.2 配置 Pod 容忍度
yaml
spec:
tolerations:
- key: "CPU"
operator: "Equal" # 或 "Exists"
value: "L1"
effect: "NoSchedule"
tolerationSeconds: 3600 # 仅在 NoExecute 时有效,指定容忍时间
匹配规则:
- 多个污点,Pod 必须容忍所有
NoSchedule污点才能被调度。 - 存在任意
NoExecute污点未容忍,则 Pod 被驱逐(或无法调度)。
6.3 内置污点与自动容忍
- 节点状态异常时,控制器会自动添加污点:
node.kubernetes.io/not-readynode.kubernetes.io/unreachablenode.kubernetes.io/memory-pressure等
- Kubernetes 会自动为 Pod 添加容忍度(如
not-ready容忍 300s),DaemonSet 的 Pod 则容忍无限长。
七、节点维护:cordon、drain、uncordon
7.1 cordon(标记不可调度)
bash
kubectl cordon worker31.laoma.cloud # 节点状态变为 SchedulingDisabled,新 Pod 不再调度到该节点
7.2 drain(驱逐 Pod + 标记不可调度)
bash
kubectl drain worker31.laoma.cloud --ignore-daemonsets
# 会驱逐该节点上的所有非 DaemonSet Pod,并标记为不可调度
# 可添加 --pod-selector 过滤要驱逐的 Pod
7.3 uncordon(恢复调度)
bash
kubectl uncordon worker31.laoma.cloud
八、Pod 优先级与抢占(PriorityClass)
- 通过 PriorityClass 定义优先级值,值越大优先级越高。
- 高优先级 Pod 可 抢占(Preempt) 低优先级 Pod 的资源(默认行为)。
- 可设置
preemptionPolicy: Never禁止抢占。
PriorityClass 示例:
yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "用于重要服务"
Pod 引用:
yaml
spec:
priorityClassName: high-priority
九、Metrics Server 部署与 HPA(水平 Pod 自动伸缩)
9.1 部署 Metrics Server(带注释)
bash
# 下载部署文件(已修改镜像源及添加 --kubelet-insecure-tls 参数)
wget -O components.yaml http://example.com/metrics-server-components-v0.7.1.yaml
# 查看关键部分,确保添加了 --kubelet-insecure-tls(如证书问题)
# 修改镜像地址为私有仓库
sed -i 's/registry.k8s.io/hub.laoma.cloud/g' components.yaml
# 部署
kubectl apply -f components.yaml
验证:
bash
kubectl top nodes
kubectl top pods -n kube-system
9.2 HPA(Horizontal Pod Autoscaler)
基于 CPU 使用率伸缩
bash
# 创建 Deployment(需设置资源 requests/limits)
kubectl create deployment web --image=nginx
kubectl set resources deployment web --limits=cpu=100m,memory=200Mi
# 创建 HPA(最小 2,最大 5,目标 CPU 利用率 80%)
kubectl autoscale deployment web --min=2 --max=5 --cpu-percent=80
生成的 HPA YAML(带注释):
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
minReplicas: 2
maxReplicas: 5
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
metrics:
- resource:
name: cpu
target:
type: Utilization
averageUtilization: 80 # CPU 利用率目标
type: Resource
基于内存使用率伸缩
yaml
metrics:
- resource:
name: memory
target:
type: Utilization
averageUtilization: 60 # 内存利用率目标
压力测试(生成 CPU 负载)
bash
# 暴露 Service
kubectl expose deployment web --port=80
# 使用 ab 压测(需安装 apache2-utils)
while true; do ab -n 300000 -c 100 http://<Service-IP>/; sleep 1; done
- HPA 会监控指标,当 CPU 超过 80% 时逐步扩容 Pod(最多 5 个)。
- 停止压测后,因缩容冷却时间(默认 5 分钟),Pod 数量会逐步降回最小值。
调整扩缩容冷却参数(kube-controller-manager)
yaml
# 编辑 /etc/kubernetes/manifests/kube-controller-manager.yaml
spec:
containers:
- command:
- --horizontal-pod-autoscaler-sync-period=10s # 指标采样周期
- --horizontal-pod-autoscaler-initial-readiness-delay=20s # Pod 就绪等待
- --horizontal-pod-autoscaler-downscale-stabilization=60s # 缩容冷却
修改后,静态 Pod 自动重启生效。
十、VPA(Vertical Pod Autoscaler)简介
- VPA 自动调整 Pod 的 requests 和 limits,不改变副本数。
- 需要重启 Pod 才能生效(通常配合 VPA 的
updateMode)。 - 不能与 HPA 同时使用(会冲突)。
- 适用于资源配置不合理、长期稳定的服务。
十一、环境清理
bash
kubectl delete ns network # 清理网络策略实验
kubectl delete ns scheduler # 清理调度实验
kubectl delete ns metric # 清理自动扩缩容实验
以上内容涵盖 Kubernetes 网络、调度、节点维护和自动扩缩容的核心知识点