《生产级 K8s 网络与调度全解:kube-proxy、七层网关、网络隔离、亲和污点实操大全》
第一部分:Service 与服务发现
一、Service 概述
解决的问题: Pod 是临时资源,IP 会变化,Deployment 动态创建销毁 Pod,客户端无法直接追踪 Pod 地址。
Service 的核心作用:
- 提供固定的虚拟 IP 和端口
- 为 Pod 提供负载均衡
- 屏蔽后端 Pod 变化,对客户端透明
二、Service 基本管理
创建 Deployment:
kubectl create deployment web --image=httpd --replicas=3
创建 ClusterIP 类型 Service:
kubectl create service clusterip web --tcp=8080:80
# --tcp=8080:80 表示访问 Service 的 8080 端口转发到 Pod 的 80 端口
验证负载均衡:
# 修改每个 Pod 主页后,循环访问查看分发情况
for i in {1..60}; do curl -s 10.103.19.150:8080; done | sort | uniq -c
关键点:
- Service 通过 Selector(标签选择器) 关联 Pod
- 只要 Pod 标签匹配,无论通过 Deployment 还是
kubectl run创建,都会被 Service 纳入后端 kubectl expose可通过--selector指定标签选择器
三、Service 发现的三种方式
1. 通过 IP 访问
直接使用 Service 的 ClusterIP:Port 访问。
2. 通过环境变量访问
Service 创建后,Kubernetes 会向 Pod 注入环境变量:
MYSQL_SERVICE_HOST=10.111.69.45
MYSQL_SERVICE_PORT=3306
Pod 中可通过 $(MYSQL_SERVICE_HOST) 引用。
限制: Service 必须先于 Pod 创建,环境变量才会注入。
3. 通过 DNS 名称访问(推荐)
CoreDNS 为 Service 自动添加 DNS 记录:
<SERVICE_NAME>.<NAMESPACE>.svc.cluster.local
同一 namespace 可简写为:<SERVICE_NAME>
四、Service 类型
| 类型 | 说明 | 适用场景 |
|---|---|---|
| ClusterIP | 仅集群内部访问(默认) | 内部服务通信 |
| NodePort | 通过节点物理端口暴露(30000-32767) | 外部访问、测试环境 |
| LoadBalancer | 云厂商 LB + ClusterIP + NodePort | 生产环境外部访问 |
| ExternalName | DNS CNAME 映射到外部域名 | 访问外部服务 |
| Headless | ClusterIP=None,无负载均衡 | StatefulSet 直接访问 Pod |
NodePort 端口说明:
nodePort:节点监听的端口(物理机端口)port:ClusterIP 监听的端口targetPort:Pod 监听的端口
五、会话保持(Session Affinity)
配置方式:
kubectl patch svc web -p '{"spec":{"sessionAffinity":"ClientIP"}}'
工作原理:
- 首次访问记录客户端 IP 与 Pod 的映射关系
- 后续请求转发到同一个 Pod
- 默认超时时间 10800 秒(3 小时)
适用场景: 有状态服务(Web 登录状态、WebSocket、购物车)
六、金丝雀发布
核心思路: 通过标签区分版本,Service 通过标签选择器同时关联稳定版和灰度版,通过调整副本数控制流量比例。
# 稳定版标签 track: stable
# 灰度版标签 track: canary
# Service 选择器:app: web, tier: frontend
流量比例控制:
kubectl scale deployment web-28 --replicas=8 # 稳定版 80% 流量
kubectl scale deployment web-29 --replicas=2 # 灰度版 20% 流量
第二部分:kube-proxy 工作原理
一、三种工作模式对比
| 模式 | 地位 | 性能 | 适用场景 |
|---|---|---|---|
| iptables | 默认模式 | 中(服务数 < 1000) | 小规模集群 |
| IPVS | 推荐模式 | 极高(服务数 10w+) | 中大规模生产 |
| Userspace | 已废弃 | 低 | 仅兼容旧版 |
二、IPVS 模式(生产推荐)
特点:
- 基于内核哈希表,查找效率 O(1)
- 支持多种调度算法:
rr(轮询)、wrr(加权轮询)、lc(最少连接)、sh(源地址哈希)
切换 IPVS 模式:
# 修改 ConfigMap
kubectl edit configmap -n kube-system kube-proxy
# 将 mode 改为 "ipvs"
# 重启 kube-proxy
kubectl rollout restart daemonset -n kube-system kube-proxy
# 验证
kubectl logs -n kube-system kube-proxy-xxx | grep "Using ipvs Proxier"
查看 IPVS 规则:
ipvsadm -Lnt <Service-IP>:<Port>
调度算法与 sessionAffinity 的关系:
- Service 配置
sessionAffinity: ClientIP→ IPVS 自动使用sh算法 - 不配置时使用
scheduler指定的算法(如rr)
三、iptables 模式(默认)
核心流程: 客户端访问 ClusterIP → KUBE-SERVICES 链 → KUBE-SVC-XXX 服务链(概率负载均衡)→ KUBE-SEP-XXX 端点链(DNAT)→ 后端 Pod
性能瓶颈: 每增加一个 Service/Endpoint 就增加规则,超过 1000 个服务时规则链膨胀,CPU 飙升。
第三部分:Ingress
一、Ingress 概述
解决的问题: NodePort 端口有限且不便于管理,LoadBalancer 成本高,需要七层路由能力(域名、路径分流)。
核心概念:
- Ingress 资源: 定义路由规则(相当于 Nginx 配置)
- Ingress Controller: 实际处理流量的负载均衡器(相当于 Nginx 进程)
- 工作流程:Controller 监听 Ingress 资源变化 → 生成 Nginx 配置 → reload
二、Ingress 规则实践
1. 多域名虚拟主机
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host-ingress
spec:
ingressClassName: nginx
rules:
- host: webapp01.laoma.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp01
port:
number: 80
- host: webapp02.laoma.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp02
port:
number: 80
2. 同一域名多路径分流
rules:
- host: www.laoma.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp01
port:
number: 80
- path: /games
pathType: Prefix
backend:
service:
name: webapp02
port:
number: 80
3. 路径重写(生产常用)
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- host: www.laoma.cloud
http:
paths:
- path: /webapp01/(.*)
pathType: ImplementationSpecific
backend:
service:
name: webapp01
port:
number: 80
4. HTTPS + 强制跳转
# 生成自签名证书
openssl genrsa -out www.key 2048
openssl req -new -key www.key -out www.csr -subj "/CN=www.laoma.cloud"
openssl x509 -req -days 3650 -in www.csr -signkey www.key -out www.crt
# 创建 Secret
kubectl create secret tls www-tls --cert=www.crt --key=www.key
metadata:
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
tls:
- hosts:
- www.laoma.cloud
secretName: www-tls
rules:
- host: www.laoma.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp01
port:
number: 80
三、生产常用注解速查
| 注解 | 作用 |
|---|---|
force-ssl-redirect: "true" |
80 端口强制跳转 HTTPS |
rewrite-target: /$1 |
路径重写,剥离路由前缀 |
whitelist-source-range: "10.0.0.0/8" |
IP 白名单访问控制 |
limit-rps: "20" |
单 IP 每秒请求数限流 |
limit-connections: "50" |
单 IP 最大并发连接数 |
enable-cors: "true" |
开启跨域 |
proxy-read-timeout: "60" |
读超时设置 |
x-forwarded-for: "true" |
透传真实客户端 IP |
第四部分:Kubernetes 网络策略(NetworkPolicy)
一、核心概念
默认行为: 所有 Pod 入站和出站流量都允许(非隔离)。
隔离机制: 一旦 Pod 被 NetworkPolicy 选中,该方向的流量默认变为拒绝,只放行策略中明确允许的流量。
策略相加性: 多个 NetworkPolicy 的规则是累加的,不会冲突。
二、核心字段
spec:
podSelector: # 策略作用的 Pod(空表示 namespace 所有 Pod)
matchLabels:
role: db
policyTypes: # Ingress 入站 / Egress 出站
- Ingress
- Egress
ingress: # 入站规则
- from: # 来源
- podSelector: {} # 同 namespace 的 Pod
- namespaceSelector: {} # 其他 namespace 的 Pod
- ipBlock: # IP 网段
cidr: 10.0.0.0/16
except:
- 10.0.1.0/24
ports: # 端口限制
- protocol: TCP
port: 6379
egress: # 出站规则
- to:
- ipBlock:
cidr: 10.0.0.0/24
三、常见场景配置
1. 允许特定 Pod 访问(同 namespace)
ingress:
- from:
- podSelector:
matchLabels:
run: test
ports:
- protocol: TCP
port: 80
2. 允许特定 namespace 访问
ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject
ports:
- protocol: TCP
port: 80
3. 允许所有 namespace 访问
ingress:
- from:
- namespaceSelector: {}
4. IP 网段限制
ingress:
- from:
- ipBlock:
cidr: 10.1.8.0/24
except:
- 10.1.8.128/26
5. 默认拒绝所有入站流量
spec:
podSelector: {}
policyTypes:
- Ingress
# 不配置 ingress 规则,默认全部拒绝
四、注意事项
- 需要支持 NetworkPolicy 的网络插件(如 Calico)
- 策略是白名单机制,只能添加允许规则,不能显式拒绝
ipBlock对 Service IP 可能失效(因为 SNAT/DNAT 发生在策略评估之前)- 无法阻塞 localhost 或节点到 Pod 的流量
第五部分:Pod 调度(Scheduler)
一、调度流程
- 过滤(Filter): 找到满足 Pod 资源、端口、选择器等需求的节点
- 打分(Score): 对候选节点按规则评分,选最高分节点
- 绑定(Bind): 将 Pod 绑定到选中的节点
二、控制 Pod 运行位置的四种方式
| 方式 | 优先级 | 说明 |
|---|---|---|
nodeName |
最高 | 直接指定节点名,不推荐 |
nodeSelector |
推荐 | 基于节点标签的简单选择 |
| 节点亲和性 | 灵活 | 支持软硬约束、复杂表达式 |
| Pod 亲和性/反亲和性 | 高级 | 基于已有 Pod 的调度约束 |
三、节点亲和性(nodeAffinity)
两种类型:
requiredDuringSchedulingIgnoredDuringExecution:硬约束,必须满足preferredDuringSchedulingIgnoredDuringExecution:软约束,尽量满足
示例:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: CPU
operator: In
values:
- L1
- L2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: MEM
operator: In
values:
- L1
- L2
支持的操作符: In、NotIn、Exists、DoesNotExist、Gt、Lt
四、Pod 间亲和性/反亲和性
关键概念:
topologyKey:拓扑域标签(如kubernetes.io/hostname、topology.kubernetes.io/zone)labelSelector:匹配已有 Pod 的标签
**示例:Pod 反亲和性(每个节点最多一个副本)**r
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
五、污点(Taint)与容忍度(Toleration)
关系类比: nodeAffinity = Pod 选 Node,Taint = Node 选 Pod
污点效果(effect):
| 值 | 说明 |
|---|---|
NoSchedule |
新 Pod 不能调度上来,已有 Pod 不受影响 |
PreferNoSchedule |
软性 NoSchedule,尽量不调度 |
NoExecute |
新 Pod 不能调度,已有不匹配 Pod 立即驱逐 |
设置污点:
kubectl taint nodes worker31 CPU=L1:NoSchedule
kubectl taint nodes worker31 CPU:NoSchedule- # 移除
Pod 容忍度:
tolerations:
- key: "CPU"
operator: "Equal"
value: "L1"
effect: "NoSchedule"
多污点匹配规则: 过滤掉匹配的污点后,剩余污点中存在任一 NoSchedule 则 Pod 不能调度到该节点。
内置污点(自动添加):
node.kubernetes.io/not-ready:节点未就绪node.kubernetes.io/unreachable:节点不可达node.kubernetes.io/memory-pressure:内存压力node.kubernetes.io/disk-pressure:磁盘压力
六、节点维护操作
| 命令 | 作用 |
|---|---|
kubectl cordon NODE |
标记节点不可调度(新 Pod 不会调度上来) |
kubectl uncordon NODE |
恢复节点可调度 |
kubectl drain NODE |
驱逐节点上所有 Pod + cordon,用于维护 |
drain 常用选项:
kubectl drain worker31 --ignore-daemonsets # 忽略 DaemonSet 管理的 Pod
kubectl drain worker31 --pod-selector='app=web' # 只驱逐特定 Pod
第六部分:Metrics Server
一、功能与定位
用途:
- 收集 Node 和 Pod 的 CPU、内存资源使用指标
- 通过 Metrics API 提供给 HPA(水平自动扩缩容)使用
- 支持
kubectl top命令查看资源使用
定位: 仅用于自动扩缩容,不适用于监控告警系统。
二、部署
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.7.1/components.yaml
# 添加 kubelet-insecure-tls 跳过证书验证
sed -i '/metric-resolution/a\ - --kubelet-insecure-tls' components.yaml
# 替换镜像地址
sed -i 's/registry.k8s.io/hub.laoma.cloud/g' components.yaml
kubectl apply -f components.yaml
三、使用
# 查看节点资源使用
kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master30.laoma.cloud 97m 4% 1328Mi 35%
# 查看 Pod 资源使用
kubectl top pods -n kube-system
单位说明: 1 CPU = 1000m(毫核)
环境清理命令汇总
kubectl delete ns services
kubectl delete ns network web laoma
kubectl delete ns scheduler
kubectl delete ns metric
kubectl delete ns ingress
核心命令速查
| 命令 | 说明 |
|---|---|
kubectl create service clusterip NAME --tcp=port:targetPort |
创建 ClusterIP Service |
kubectl expose deployment NAME --port=port --target-port=targetPort --type=Type |
暴露 Service |
kubectl get svc |
查看 Service |
kubectl describe svc NAME |
查看 Service 详情(含 Endpoints) |
kubectl patch svc NAME -p '{"spec":{"sessionAffinity":"ClientIP"}}' |
开启会话保持 |
kubectl get cm -n kube-system kube-proxy -o yaml |
查看 kube-proxy 配置 |
kubectl get netpol |
查看 NetworkPolicy |
kubectl label nodes NODE KEY=VALUE |
给节点打标签 |
kubectl taint nodes NODE KEY=VALUE:EFFECT |
给节点打污点 |
kubectl cordon/drain/uncordon NODE |
节点维护操作 |
kubectl top node/pod |
查看资源使用(需 Metrics Server) |
更多推荐



所有评论(0)