公司新上线的微服务系统跑在ref="/tag/2020/" style="color:#874873;font-weight:bold;">Kubernetes上,结果前端调用订单服务老是超时——查日志发现不是代码问题,是Pod之间根本连不通。这事儿在运维群里炸了锅,最后发现是CNI插件配置漏了一行,集群里跨节点的Pod压根没走对路由。
Pod之间怎么说话?别想得太复杂
K8s里每个Pod都有独立IP,同一节点上的Pod走cni0网桥直通;跨节点时,靠CNI插件(比如Calico、Flannel)在宿主机间建隧道或改路由表。比如Flannel用host-gw模式,就在每个Node上加一条静态路由:
ip route add 10.244.2.0/24 via 192.168.56.112 dev eth0这条命令的意思是:发往2号Node上所有Pod的流量,下一跳指向它的物理IP。没有它,包就卡在本地出不去。Service不是“服务”,是负载均衡入口
写个Deployment起了3个Nginx Pod,直接curl它们的Pod IP能通,但换一个Pod就失效——因为Pod IP会变。这时候Service就派上用场了:
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80集群内任何地方访问nginx-svc:80,请求就会被kube-proxy自动转到后端某个Pod。它背后要么是iptables规则链,要么是IPVS哈希表,你不用管,但得知道:Service ClusterIP只在集群内部生效,对外暴露得靠NodePort或Ingress。Ingress不是万能钥匙,得配对用
有次把Ingress资源对象写了,域名也绑了,但浏览器还是打不开。后来发现Ingress Controller根本没装——Ingress只是个YAML定义,真正干活的是Nginx Ingress Controller或者Traefik这些Pod。就像写了份快递单,没快递员接单,货永远发不出去。装好之后,再加一条规则:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-svc
port:
number: 80这时访问app.example.com,流量才真正落地到你的web-svc。网络策略(NetworkPolicy)不是摆设
测试环境没开NetworkPolicy,数据库Pod被前端Pod直接telnet通了,上线前安全团队立刻叫停。加了策略后:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-policy
spec:
podSelector:
matchLabels:
app: mysql
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api-server
ports:
- protocol: TCP
port: 3306现在只有带app: api-server标签的Pod才能连3306端口,其他一概拒绝。这不是锦上添花,是上线前必须过的关。实际跑起来才发现,K8s网络没那么玄乎——它就是一堆可配置的路由、NAT和策略组合。关键不在记住名词,而在每次连不上时,先看Pod有没有IP、再查Service endpoints有没有列表、接着确认kube-proxy是否正常、最后翻NetworkPolicy有没有拦路。一步步摸过去,比背概念管用得多。