16.4.6 负载均衡与流量调度
在 Kubernetes 中,负载均衡与流量调度覆盖 Service 四层与 Ingress 七层入口,是确保请求稳定、可控、可观测的关键。本节从原理、安装与配置、验证、排错与练习串起完整链路,便于落地。
一、Service 四层负载均衡原理与配置示例#
Service 由 kube-proxy 转发,核心是 Endpoints 与 iptables/IPVS 规则。推荐生产使用 IPVS。
1.1 kube-proxy 切换 IPVS 模式(示例)#
# 查看当前模式
kubectl -n kube-system get cm kube-proxy -o yaml | grep mode
# 修改为 ipvs 并重启 kube-proxy
kubectl -n kube-system edit cm kube-proxy
# 将 mode: "" 改为 mode: "ipvs"
kubectl -n kube-system delete pod -l k8s-app=kube-proxy
命令解释:
- edit cm kube-proxy 修改转发模式
- 删除 pod 触发重建以加载新配置
- IPVS 规则更适合大规模集群(性能与规则可控性)
1.2 Service 示例(ClusterIP)#
/root/k8s/service-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-demo
spec:
replicas: 2
selector:
matchLabels:
app: web-demo
template:
metadata:
labels:
app: web-demo
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: web-demo-svc
spec:
selector:
app: web-demo
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
kubectl apply -f /root/k8s/service-demo.yaml
kubectl get svc web-demo-svc -o wide
kubectl get ep web-demo-svc
预期效果:
- svc 显示 ClusterIP
- endpoints 有两个 Pod IP
1.3 NodePort 访问验证#
kubectl patch svc web-demo-svc -p '{"spec":{"type":"NodePort","ports":[{"port":80,"targetPort":80,"nodePort":30080}]}}'
kubectl get svc web-demo-svc
# 在集群任一节点访问
curl -I http://<NodeIP>:30080
命令解释:
- patch 修改服务类型
- NodePort 直接映射节点端口
二、Ingress 七层路由与流量调度#
2.1 安装 Nginx Ingress Controller(简化版)#
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
kubectl -n ingress-nginx get pods
kubectl -n ingress-nginx get svc
说明:
- ingress-nginx-controller 默认暴露为 LoadBalancer/NodePort
- 生产需结合云 LB 或 MetalLB
2.2 Ingress 规则示例#
/root/k8s/ingress-demo.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-demo-ing
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: demo.example.com
http:
paths:
- path: /web
pathType: Prefix
backend:
service:
name: web-demo-svc
port:
number: 80
kubectl apply -f /root/k8s/ingress-demo.yaml
kubectl get ingress web-demo-ing
访问验证:
# 将域名解析到 Ingress Controller 对外IP
curl -H "Host: demo.example.com" http://<IngressIP>/web
命令解释:
- ingressClassName 指定控制器
- rewrite-target 重写路径
三、外部负载均衡(MetalLB 示例)#
3.1 安装 MetalLB(裸金属)#
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml
kubectl -n metallb-system get pods
3.2 配置地址池#
/root/k8s/metallb-pool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: demo-pool
namespace: metallb-system
spec:
addresses:
- 192.168.10.200-192.168.10.210
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: demo-l2
namespace: metallb-system
kubectl apply -f /root/k8s/metallb-pool.yaml
kubectl get svc -A | grep LoadBalancer
预期效果:
LoadBalancer 类型 Service 获得外部 IP
四、流量调度策略示例#
4.1 会话保持(Session Affinity)#
kubectl patch svc web-demo-svc -p '{"spec":{"sessionAffinity":"ClientIP"}}'
kubectl describe svc web-demo-svc | grep -i affinity
说明:
- ClientIP 让同一客户端固定到同一后端
4.2 权重灰度(通过 Ingress 多后端)#
/root/k8s/ingress-canary.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-demo-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
ingressClassName: nginx
rules:
- host: demo.example.com
http:
paths:
- path: /web
pathType: Prefix
backend:
service:
name: web-demo-svc-canary
port:
number: 80
说明:
- 20% 流量进入 canary 服务
4.3 超时与重试(Ingress 注解)#
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-connect-timeout: "3"
nginx.ingress.kubernetes.io/proxy-read-timeout: "10"
nginx.ingress.kubernetes.io/proxy-send-timeout: "10"
五、就绪探针与流量控制#
/root/k8s/readiness-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-ready
spec:
replicas: 2
selector:
matchLabels:
app: web-ready
template:
metadata:
labels:
app: web-ready
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 3
命令解释:
- Readiness 未通过时 Pod 不进入 Endpoints
- 防止未就绪实例接收流量
六、排错清单(常见故障)#
6.1 Service 无法访问#
kubectl get svc,ep web-demo-svc
kubectl get pod -l app=web-demo -o wide
排错要点:
- Endpoints 为空:标签选择器不匹配
- Pod Ready=0:探针失败
6.2 Ingress 无法路由#
kubectl describe ingress web-demo-ing
kubectl -n ingress-nginx logs deploy/ingress-nginx-controller | tail -n 50
排错要点:
- 规则未生效:ingressClassName 错误
- 503/404:后端服务名/端口错误
6.3 MetalLB 无法分配 IP#
kubectl -n metallb-system get ipaddresspools,l2advertisements
kubectl -n metallb-system logs deploy/controller | tail -n 50
排错要点:
- 地址池与节点网段冲突
- ARP 被交换机策略阻断
七、练习题(动手验证)#
- 将
web-demo-svc从 ClusterIP 改为 LoadBalancer,并通过 MetalLB 获得外部 IP。 - 为同一域名创建两个版本服务,配置 canary 权重 10%,验证流量比例。
- 手动制造一个 Pod 探针失败,观察 Endpoints 是否自动剔除。
- 切换 kube-proxy 到 IPVS,使用
ipvsadm -Ln查看规则(需在节点执行)。
# 节点执行:查看 IPVS 规则
sudo ipvsadm -Ln
通过以上示例与排错链路,可以系统理解 Service 与 Ingress 的负载均衡方式,并掌握基础的流量调度与可观测性实践。