一、网络模型基础
1. Kubernetes的网络模型有哪些基本要求?
答案:
Kubernetes网络模型基于以下核心原则:
所有Pod可以相互通信
- 不使用NAT,Pod之间可以直接通过IP通信
- 跨节点的Pod也能直接访问
- 简化了网络拓扑,避免端口映射复杂性
所有节点可以与所有Pod通信
- 节点可以直接访问任何Pod的IP
- Pod也可以直接访问节点
- 双向通信无需NAT转换
Pod看到的IP就是其他Pod看到的IP
- Pod具有真实的IP地址
- 不存在IP伪装或地址转换
- 简化了服务发现和负载均衡
网络隔离通过NetworkPolicy实现
- 默认所有Pod可以相互访问
- 通过NetworkPolicy实现细粒度控制
- 支持入站和出站流量规则
实现原理示意:
Node1 (10.0.1.0/24) Node2 (10.0.2.0/24)
├── Pod A (10.244.1.5) ├── Pod C (10.244.2.8)
└── Pod B (10.244.1.6) └── Pod D (10.244.2.9)
Pod A可以直接访问10.244.2.8 (Pod C)
无需通过Node IP或端口映射
常见CNI插件实现方式:
Flannel
- 使用Overlay网络(VXLAN/UDP)
- 简单易用,适合小规模集群
- 性能相对较低
Calico
- 使用BGP路由协议
- 性能优秀,支持NetworkPolicy
- 适合大规模生产环境
Weave Net
- 使用网状路由
- 支持加密通信
- 配置简单
Cilium
- 基于eBPF技术
- 高性能,支持L7策略
- 可观测性强
2. Service的工作原理是什么?有哪些类型?
答案:
Service是Kubernetes提供的抽象层,为一组Pod提供稳定的网络访问入口。
核心工作机制:
虚拟IP(ClusterIP)
- Service被分配一个集群内部的虚拟IP
- 该IP在Service生命周期内保持不变
- 请求发送到ClusterIP会被负载均衡到后端Pod
Endpoint控制器
- 监控符合Selector的Pod
- 动态维护Endpoints列表
- Pod变化时自动更新Endpoint
kube-proxy实现
Client Request → Service ClusterIP → kube-proxy规则 → 后端Pod
Service类型详解:
1. ClusterIP(默认类型)
yaml
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
type: ClusterIP
selector:
app: backend
ports:
- protocol: TCP
port: 80 # Service暴露的端口
targetPort: 8080 # Pod监听的端口
特点:
- 仅集群内部可访问
- 分配集群内唯一的虚拟IP
- 适合内部服务间调用
2. NodePort
yaml
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
type: NodePort
selector:
app: frontend
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30080 # 可选,不指定则自动分配30000-32767范围内端口
特点:
- 在每个节点上开放指定端口
- 外部可通过
<NodeIP>:<NodePort>访问 - 适合开发测试环境
访问方式:
外部请求 → 任意节点IP:30080 → Service → Pod
3. LoadBalancer
yaml
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
type: LoadBalancer
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 8080
特点:
- 在云平台上自动创建外部负载均衡器
- 分配外部可访问的IP地址
- 适合生产环境对外暴露服务
工作流程:
外部请求 → 云LB外部IP → NodePort → Service → Pod
4. ExternalName
yaml
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: mysql.external.com
特点:
- 返回CNAME记录
- 用于引用外部服务
- 无需创建Endpoint
Headless Service(无头服务)
yaml
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
spec:
clusterIP: None # 关键:设置为None
selector:
app: mysql
ports:
- port: 3306
使用场景:
- StatefulSet的网络标识
- 客户端需要直接连接特定Pod
- DNS返回所有Pod的IP地址列表
负载均衡算法:
kube-proxy支持的代理模式:
iptables模式(默认)
- 使用iptables规则实现负载均衡
- 随机选择后端Pod
- 性能较好,但规则数量过多时性能下降
IPVS模式
- 使用Linux IPVS模块
- 支持多种负载均衡算法:rr(轮询)、lc(最少连接)、sh(源地址哈希)
- 性能优于iptables,适合大规模集群
3. Ingress是什么?与Service有什么区别?
答案:
Ingress是Kubernetes的API对象,管理外部访问集群服务的HTTP和HTTPS路由。
Ingress vs Service对比:
| 特性 | Service | Ingress |
|---|---|---|
| 层级 | L4(传输层) | L7(应用层) |
| 协议支持 | TCP/UDP | HTTP/HTTPS |
| 路由能力 | 简单端口转发 | 基于域名和路径的路由 |
| SSL/TLS | 需要额外配置 | 原生支持证书管理 |
| 成本 | 每个Service可能需要LoadBalancer | 单个入口可服务多个Service |
Ingress架构:
Internet
↓
Ingress Controller (Nginx/Traefik)
↓
Ingress Rules
├── foo.example.com/api → Service A → Pod A
├── foo.example.com/web → Service B → Pod B
└── bar.example.com/* → Service C → Pod C
基础Ingress配置:
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: www.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /web
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
tls:
- hosts:
- www.example.com
secretName: tls-secret
TLS证书配置:
yaml
apiVersion: v1
kind: Secret
metadata:
name: tls-secret
type: kubernetes.io/tls
data:
tls.crt: <base64编码的证书>
tls.key: <base64编码的私钥>
常见Ingress Controller:
Nginx Ingress Controller
- 最流行的选择
- 功能丰富,性能稳定
- 支持丰富的注解配置
Traefik
- 动态配置,无需重启
- 原生支持Let's Encrypt
- 内置监控面板
HAProxy Ingress
- 高性能
- 企业级特性
- 复杂的负载均衡策略
Istio Gateway
- 服务网格方案
- 流量管理能力强
- 可观测性好
高级特性示例:
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: advanced-ingress
annotations:
# 限流配置
nginx.ingress.kubernetes.io/limit-rps: "10"
# 认证配置
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
# 跨域配置
nginx.ingress.kubernetes.io/enable-cors: "true"
# 会话亲和性
nginx.ingress.kubernetes.io/affinity: "cookie"
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
最佳实践:
- 使用命名空间隔离不同环境的Ingress
- 为生产环境配置TLS证书
- 设置合理的限流和超时参数
- 使用注解实现高级功能
- 监控Ingress Controller的性能指标
4. 如何实现Pod之间的网络隔离?
答案:
通过NetworkPolicy实现Pod之间的网络访问控制,类似于防火墙规则。
NetworkPolicy工作原理:
- 基于Label Selector选择目标Pod
- 定义允许或拒绝的流量规则
- 支持入站(Ingress)和出站(Egress)控制
- 需要CNI插件支持(如Calico、Cilium)
默认拒绝所有入站流量:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: production
spec:
podSelector: {} # 空选择器表示应用于所有Pod
policyTypes:
- Ingress
允许特定Pod访问:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
tier: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
允许特定命名空间访问:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-monitoring
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 9090
限制出站流量:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-egress
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 3306
- to: # 允许DNS解析
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53
复杂场景:多层访问控制
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: multi-tier-policy
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
# 允许来自frontend命名空间的frontend Pod
- namespaceSelector:
matchLabels:
env: production
podSelector:
matchLabels:
app: frontend
# 允许来自API Gateway
- podSelector:
matchLabels:
app: api-gateway
ports:
- protocol: TCP
port: 8080
egress:
- to:
# 允许访问数据库
- podSelector:
matchLabels:
app: mysql
ports:
- protocol: TCP
port: 3306
- to:
# 允许访问Redis缓存
- podSelector:
matchLabels:
app: redis
ports:
- protocol: TCP
port: 6379
- to:
# 允许DNS查询
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
最佳实践:
采用白名单策略
- 默认拒绝所有流量
- 显式声明允许的连接
- 最小权限原则
分层设计
- 网络隔离与应用架构对齐
- 前端、后端、数据层分别控制
- 使用命名空间隔离环境
监控与审计
- 定期审查NetworkPolicy配置
- 监控被拒绝的连接尝试
- 结合日志分析异常流量
测试验证
bash
# 测试Pod间连接性
kubectl exec -it frontend-pod -- curl backend-service:8080
# 查看NetworkPolicy应用情况
kubectl describe networkpolicy allow-frontend-to-backend
# 验证规则生效
kubectl get networkpolicy -A
二、DNS与服务发现
5. Kubernetes中的DNS解析是如何工作的?
答案:
Kubernetes通过CoreDNS提供集群内部的DNS服务发现能力。
DNS记录格式:
Service DNS记录
<service-name>.<namespace>.svc.cluster.local
示例:
# 同命名空间访问
curl http://backend-service
# 跨命名空间访问
curl http://backend-service.production.svc.cluster.local
Pod DNS记录
<pod-ip-with-dashes>.<namespace>.pod.cluster.local
示例:
# Pod IP: 10.244.1.5
10-244-1-5.default.pod.cluster.local
Headless Service DNS
<pod-name>.<service-name>.<namespace>.svc.cluster.local
示例:
# StatefulSet Pod
mysql-0.mysql-service.default.svc.cluster.local
mysql-1.mysql-service.default.svc.cluster.local
CoreDNS配置:
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
DNS解析流程:
Pod发起DNS请求
↓
kubelet配置的/etc/resolv.conf
↓
指向CoreDNS Service (kube-dns)
↓
CoreDNS解析
├── 集群内部域名 → 返回ClusterIP或Pod IP
└── 外部域名 → 转发到上游DNS服务器
↓
返回解析结果给Pod
Pod DNS配置:
yaml
apiVersion: v1
kind: Pod
metadata:
name: custom-dns-pod
spec:
containers:
- name: app
image: nginx
dnsPolicy: "None" # 自定义DNS配置
dnsConfig:
nameservers:
- 8.8.8.8
- 8.8.4.4
searches:
- custom.local
- default.svc.cluster.local
options:
- name: ndots
value: "2"
DNS策略类型:
Default
- 继承节点的DNS配置
- 适合需要访问集群外部服务的场景
ClusterFirst(默认)
- 优先使用集群DNS
- 未匹配的域名转发到节点DNS
ClusterFirstWithHostNet
- 使用hostNetwork的Pod使用此策略
None
- 完全自定义DNS配置
- 需要手动指定nameservers
DNS调试技巧:
bash
# 测试DNS解析
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup backend-service
# 查看Pod的DNS配置
kubectl exec -it pod-name -- cat /etc/resolv.conf
# 查看CoreDNS日志
kubectl logs -n kube-system -l k8s-app=kube-dns
# 测试完整域名解析
kubectl exec -it pod-name -- nslookup backend-service.production.svc.cluster.local
性能优化:
- 调整CoreDNS副本数以应对高负载
- 配置合理的DNS缓存TTL
- 使用NodeLocal DNSCache减少跨节点DNS查询
- 监控CoreDNS的查询延迟和错误率
6. 如何实现服务的灰度发布和蓝绿部署?
答案:
Kubernetes支持多种发布策略,实现零停机更新和风险控制。
1. 滚动更新(RollingUpdate)- 默认策略
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2 # 最多超出期望副本数2个
maxUnavailable: 1 # 最多1个副本不可用
template:
metadata:
labels:
app: web
version: v2
spec:
containers:
- name: web
image: web:v2
readinessProbe: # 重要:确保新Pod就绪后才接收流量
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
流程:
初始状态: v1 Pod x10
步骤1: 创建v2 Pod x2 (maxSurge=2)
步骤2: v2 Pod就绪后,删除v1 Pod x1 (maxUnavailable=1)
步骤3: 重复直到所有Pod更新为v2
2. 蓝绿部署
yaml
# 蓝色环境(当前生产)
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-blue
spec:
replicas: 3
selector:
matchLabels:
app: web
version: blue
template:
metadata:
labels:
app: web
version: blue
spec:
containers:
- name: web
image: web:v1
---
# 绿色环境(新版本)
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-green
spec:
replicas: 3
selector:
matchLabels:
app: web
version: green
template:
metadata:
labels:
app: web
version: green
spec:
containers:
- name: web
image: web:v2
---
# Service初始指向蓝色环境
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
version: blue # 切换时改为green
ports:
- port: 80
targetPort: 8080
切换流程:
bash
# 1. 部署绿色环境
kubectl apply -f deployment-green.yaml
# 2. 验证绿色环境
kubectl exec -it test-pod -- curl http://web-green:8080
# 3. 切换Service到绿色环境
kubectl patch service web-service -p '{"spec":{"selector":{"version":"green"}}}'
# 4. 验证无误后删除蓝色环境
kubectl delete deployment web-blue
3. 金丝雀发布(Canary Deployment)
yaml
# 稳定版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-stable
spec:
replicas: 9 # 90%流量
selector:
matchLabels:
app: web
track: stable
template:
metadata:
labels:
app: web
track: stable
version: v1
spec:
containers:
- name: web
image: web:v1
---
# 金丝雀版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-canary
spec:
replicas: 1 # 10%流量
selector:
matchLabels:
app: web
track: canary
template:
metadata:
labels:
app: web
track: canary
version: v2
spec:
containers:
- name: web
image: web:v2
---
# Service选择所有版本
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web # 只匹配app标签,包含stable和canary
ports:
- port: 80
targetPort: 8080
基于Istio的精细化金丝雀:
yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: web-vs
spec:
hosts:
- web-service
http:
- match:
- headers:
user-type:
exact: "beta"
route:
- destination:
host: web-service
subset: canary
- route:
- destination:
host: web-service
subset: stable
weight: 95
- destination:
host: web-service
subset: canary
weight: 5
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: web-dr
spec:
host: web-service
subsets:
- name: stable
labels:
version: v1
- name: canary
labels:
version: v2
最佳实践:
监控指标
- 错误率、延迟、吞吐量
- 自动化回滚机制
- 设置合理的观察期
健康检查
- 配置readinessProbe和livenessProbe
- 确保新版本就绪后才接收流量
自动化
- 使用CI/CD工具自动化发布流程
- 集成Flagger、Argo Rollouts等工具
回滚策略
bash
# 查看发布历史
kubectl rollout history deployment/web-app
# 快速回滚到上一版本
kubectl rollout undo deployment/web-app
# 回滚到指定版本
kubectl rollout undo deployment/web-app --to-revision=3
三、总结
本文档深入讲解了Kubernetes网络与服务发现的核心概念:
- K8S网络模型和CNI插件
- Service类型及工作原理
- Ingress高级路由配置
- NetworkPolicy网络隔离
- DNS解析机制
- 灰度发布和蓝绿部署策略
网络是K8S的核心能力之一,掌握这些知识对于架构设计和故障排查至关重要。