Pod是临时的,IP会变。Service为一组Pod提供稳定的访问入口(固定IP + DNS名),并通过selector自动负载均衡到后端Pod。
┌─────────────────────┐
│ Client (Pod A) │
│ curl httpd-svc:80 │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Service │
│ ClusterIP: 10.96.x │
│ DNS: httpd-svc │
│ Port: 80 → 8080 │
└──────────┬──────────┘
│ 负载均衡(round-robin)
┌────────────────┼────────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ Pod-1 │ │ Pod-2 │ │ Pod-3 │
│ 10.244.1.x│ │ 10.244.2.x│ │ 10.244.1.y│
│ Ready ✓ │ │ Ready ✓ │ │ Ready ✓ │
└───────────┘ └───────────┘ └───────────┘
kube-proxy在每个节点维护iptables/IPVS规则:
ClusterIP → DNAT → PodIP (round-robin)
| 类型 | 访问范围 | 外部IP | 典型场景 |
|---|---|---|---|
ClusterIP | 集群内部 | 无 | 微服务间通信 |
NodePort | 集群内外 | NodeIP:30000-32767 | 开发测试、临时暴露 |
LoadBalancer | 公网 | 云厂商LB IP | 生产环境对外服务 |
ExternalName | DNS CNAME | 无 | 引用外部服务 |
# clusterip-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: web-svc
namespace: default
spec:
type: ClusterIP # 默认值
selector:
app: web-app # 匹配Pod标签
ports:
- name: http
port: 80 # Service端口
targetPort: 8080 # Pod容器端口
protocol: TCP
- name: https
port: 443
targetPort: 8443
sessionAffinity: ClientIP # 会话亲和性(同一客户端→同一Pod)
sessionAffinityConfig:
clientIP:
timeoutSeconds: 3600
# ✅ 验证通过
kubectl apply -f clusterip-svc.yaml
kubectl get svc web-svc
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# web-svc ClusterIP 10.96.142.58 <none> 80/TCP,443/TCP 5s
# DNS解析测试
kubectl run test --image=busybox:1.36 --rm -it --restart=Never -- \
nslookup web-svc.default.svc.cluster.local
# Server: 10.96.0.10
# Address: 10.96.0.10
# Name: web-svc.default.svc.cluster.local
# Address: 10.96.142.58
# nodeport-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: web-nodeport
spec:
type: NodePort
selector:
app: web-app
ports:
- name: http
port: 80 # ClusterIP端口
targetPort: 8080 # Pod端口
nodePort: 30080 # 节点端口(30000-32767)
# ✅ 验证通过
kubectl apply -f nodeport-svc.yaml
kubectl get svc web-nodeport
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# web-nodeport NodePort 10.96.200.1 <none> 80:30080/TCP 5s
# 从任意节点访问
curl http://<NodeIP>:30080
# loadbalancer-svc.yaml(云环境专用)
apiVersion: v1
kind: Service
metadata:
name: web-lb
annotations:
# AWS示例
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
type: LoadBalancer
selector:
app: web-app
ports:
- port: 80
targetPort: 8080
# ✅ 验证通过(云环境)
kubectl get svc web-lb
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
# web-lb LoadBalancer 10.96.50.1 a1b2c3.elb.amazonaws.com 80:31234/TCP
# external-svc.yaml - 引用集群外部服务
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: mysql.prod.example.com
# 集群内访问:external-db.default.svc.cluster.local
# 实际CNAME到 mysql.prod.example.com
# 手动管理Endpoints(对接外部服务)
apiVersion: v1
kind: Service
metadata:
name: external-api
spec:
ports:
- port: 443
targetPort: 443
# 注意:没有selector!
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-api # 必须与Service同名
subsets:
- addresses:
- ip: 192.168.1.100 # 外部服务IP
- ip: 192.168.1.101
ports:
- port: 443
┌──────────────────────────────────────────────────┐
│ K8s网络四大黄金法则 │
├──────────────────────────────────────────────────┤
│ 1️⃣ 所有Pod间可以直接通信(无需NAT) │
│ 2️⃣ 所有Node与Pod间可以直接通信(无需NAT) │
│ 3️⃣ Pod看到的自己的IP和别人看到它的IP一致 │
│ 4️⃣ 同Pod内容器共享Network Namespace(localhost) │
└──────────────────────────────────────────────────┘
网络层级:
┌────────────────── CNI ──────────────────┐
│ Flannel | Calico | Cilium | Weave Net │
└──────────────────────────────────────────┘
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│ Pod网络 │ │Service │ │ 外部流量 │
│ Pod↔Pod │ │ ClusterIP│ │ Ingress │
└─────────┘ └─────────┘ └─────────┘
# K8s DNS命名规范
# <service-name>.<namespace>.svc.<cluster-domain>
# 同命名空间
curl http://web-svc:80
# 跨命名空间
curl http://web-svc.production:80
# 完整FQDN
curl http://web-svc.default.svc.cluster.local:80
# Headless Service(无ClusterIP,直接返回Pod IP)
apiVersion: v1
kind: Service
metadata:
name: web-headless
spec:
clusterIP: None # Headless!
selector:
app: web-app
ports:
- port: 80
targetPort: 8080
# ✅ 验证通过 - DNS返回所有Pod IP
kubectl run test --image=busybox:1.36 --rm -it --restart=Never -- \
nslookup web-headless.default.svc.cluster.local
# Name: web-headless.default.svc.cluster.local
# Address: 10.244.1.5
# Address: 10.244.2.8
# Address: 10.244.1.12
# 查看kube-proxy模式
kubectl get configmap kube-proxy -n kube-system -o yaml | grep mode
# mode: "iptables" 或 "ipvs"
# iptables模式(默认)
# 规则链:KUBE-SERVICES → KUBE-SVC-xxx → KUBE-SEP-xxx
# 随机选择后端Pod
sudo iptables -t nat -L KUBE-SERVICES | head -10
# IPVS模式(高性能)
# 支持更多负载均衡算法:rr|lc|wrr|wlc|sh|dh
# 性能更好:O(1) vs O(n)
kubectl get configmap kube-proxy -n kube-system -o yaml | sed 's/mode: "".*/mode: "ipvs"/' | \
kubectl apply -f -
kubectl rollout restart daemonset kube-proxy -n kube-system
# networkpolicy-basics.yaml - 默认拒绝入站
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: default
spec:
podSelector: {} # 匹配所有Pod
policyTypes:
- Ingress # 拒绝所有入站
---
# 允许特定标签Pod访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
spec:
podSelector:
matchLabels:
app: backend # 应用到backend Pod
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend # 只允许frontend Pod访问
ports:
- port: 8080
protocol: TCP
# 现象:访问Service无响应
kubectl get endpoints web-svc
# NAME ENDPOINTS AGE
# web-svc <none> 5m ← 没有后端!
# 排查:检查selector是否匹配
kubectl get pods --show-labels | grep web-app
# web-app-xxx 1/1 Running app=web,version=v1 ← 标签不匹配!
# Service selector: app=web-app
# Pod labels: app=web ← 名称不一致!
# 修复:统一标签
kubectl edit svc web-svc
# 将selector改为 app=web
# 检查CoreDNS
kubectl get pods -n kube-system -l k8s-app=kube-dns
# NAME READY STATUS RESTARTS AGE
# coredns-5dd5756b68-xxx 1/1 Running 0 1h
# 测试DNS
kubectl run test --image=busybox:1.36 --rm -it --restart=Never -- \
nslookup kubernetes.default.svc.cluster.local
# 如果失败:
# 1. 检查CoreDNS日志
kubectl logs -n kube-system coredns-5dd5756b68-xxx
# 2. 检查resolv.conf
kubectl run test --image=busybox:1.36 --rm -it --restart=Never -- \
cat /etc/resolv.conf
# 3. 检查kubelet的cluster-dns配置
# 排查CNI
kubectl get pods -n kube-flannel
# 如果Flannel Pod异常,跨节点通信会失败
# 检查节点路由
ip route | grep flannel
# 10.244.1.0/24 via ... ← 对端节点的Pod网段路由
# 检查节点间网络连通性
ping <other-node-ip>
traceroute <other-node-pod-ip>
下一课预告:第05课深入ConfigMap与Secret——配置与密钥管理最佳实践。