对于 Kubernetes (K8S) 的初学者来说最早接触到的一个概念可能就是 Pod 与 Service. Pod 简单来说就是一个或者一组 container 的集合. 但是在 K8S 的世界里, Pod 的一生可能非常短暂, 稍纵即逝. 而且 Pod 在每次启动时都会分配一个新的 IP 地址. 这样的话集群中互相依赖的 Pod 之间的访问就成了一个新的问题!!
K8S 为了解决这个问题引入了 Service 资源. Service 资源的本质是为一组 Pod 提供一个相对固定的 IP 地址. 无论 Pod 的 IP 地址如何变化, Service 的 IP 地址都不会改变. K8S 集群中每个 Node 上运行的 kube-proxy 组件负责转发 Service 与 Pod 之间的流量. kube-proxy 通过 iptables DNAT 或者 ipvs 规则将一个数据包的目的IP 从 Service 的 Cluster IP 修改为其背后的 Pod 的 IP 地址并进行转发. 比如在我们的 K8S 集群中有如下 pod:
1 2 3
# kubectl get pod dvwa-6bcb999d58-hpg2j -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES dvwa-6bcb999d58-hpg2j 1/1 Running 0 29d 10.42.3.125 node2 <none> <none>
我们看到这个 Pod 的 IP 地址为 10.42.3.125, 并且运行在 node2 这个节点上. 这个 Pod 对应的 Service 为:
1 2 3
# kubectl get service dvwa -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR dvwa NodePort 10.43.18.128 <none> 80:30237/TCP 29d app=dvwa
我们看到这个 Service 的 CLUSTER-IP 为 10.43.18.128. 我们尝试访问下这个服务, 可以看到请求可以正常转发到实际通过服务的 Pod 上.
此时我们重启 node2 再对 Pod 进行观察. 由于 node2 无法提供服务, pod 漂移到了 node1 并且获得了新的 IP 10.42.2.140. 于此同时, K8S 删除了之前的 Pod dvwa-6bcb999d58-hpg2j. 与此同时 Service dvwa 的 IP 地址并没有改变, 访问此IP 仍然可以访问服务: