容器之间的对话怎么实现
在数码世界里,越来越多的应用跑在ref="/tag/2020/" style="color:#2B406D;font-weight:bold;">Kubernetes上。你可能用着某款App,背后就是一堆容器在协作。这些容器分布在不同的节点上,却能无缝通信,靠的就是Kubernetes的网络设计。
想象一下小区里的快递系统:每个楼栋有独立门牌,但快递员不用操心路径,扔进分拣中心就能送到指定住户。Kubernetes网络也类似,它让每个Pod拥有唯一的IP地址,彼此可以直接通信,就像住在同一个局域网里。
扁平网络模型是基础
Kubernetes要求所有Pod在一个大的扁平网络空间中,不管它们在哪个Node上。这意味着Pod之间可以直接通过IP访问,不需要NAT(网络地址转换)。
举个例子,你在Node A上的Pod发请求到Node B上的另一个Pod,就像办公室A的同事直接打电话给办公室B的同事,中间没人转接。这种设计简化了服务发现和通信逻辑。
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80这个YAML定义了一个Pod,启动后会被分配一个集群内部IP。其他Pod只要知道这个IP,就能直接访问它的80端口。
网络插件挑大梁
原生Kubernetes不提供具体的网络实现,而是通过CNI(容器网络接口)标准来接入第三方插件。常见的比如Calico、Flannel、Cilium,它们负责实际的IP分配和路由规则配置。
以Calico为例,它利用BGP协议在节点间同步路由信息。当新Pod创建时,Calico会自动更新相邻节点的路由表,告诉它们“去这个IP段的数据包请发给我”。整个过程对应用完全透明。
如果你在调试网络问题,可能会发现某些Pod能ping通但服务不可用。这往往不是Kubernetes的问题,而是CNI插件配置不当或防火墙规则拦截了流量。
Service让服务更稳定
Pod是临时的,可能随时被重建。如果直接依赖Pod IP,一旦重启就会断连。Kubernetes引入了Service机制,给一组Pod提供固定的虚拟IP(ClusterIP)。
就像公司对外只有一个总机号码,内部员工换了一批,总机依然有效。Service背后的kube-proxy组件会监听Pod变化,动态更新转发规则。
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 8080这个Service会把流量转发给所有带有app=web标签的Pod。即使这些Pod不断更替,Service的IP始终保持不变。
DNS与名字解析
在集群内,你可以直接用Service名称作为域名访问。比如上面定义的web-service,在同一个命名空间下可以直接用http://web-service访问。这是由CoreDNS实现的。
CoreDNS监听Kubernetes API,每当有新的Service创建,就生成对应的DNS记录。这就像是小区物业维护一份最新的住户电话簿,谁搬进来、谁搬出去都实时更新。
外部访问的几种方式
用户不可能直接访问内网IP,所以需要入口机制。NodePort类型会把Service暴露在节点的某个端口上,比如30080,外部通过<node-ip>:30080就能访问。
Ingress则更进一步,允许你用域名和路径做精细化路由。比如blog.example.com走博客服务,api.example.com走后端接口。Ingress控制器(如Nginx Ingress)充当反向代理,把公网流量导入正确的Service。