而在第二种 Service DNS 的方式下,具体还可以分为两种处理方法:
Service并不直接链接至Pod对象,它们之间还有一个中间层——Endpoints
资源对象,它是一个由IP地址和端口组成的列表,这些IP地址和端口则来自于由Service的标签选择器匹配到的Pod资源。这也是很多场景中会使用“Service的后端端点”(Endpoints)这一术语的原因。默认情况下,创建Service资源对象时,其关联的Endpoints对象会自动创建。
简单来讲,一个Service对象就是工作节点上的一些iptables或ipvs规则,用于将到达Service对象IP地址的流量调度转发至相应的Endpoints对象指向的IP地址和端口之上。工作于每个工作节点的kube-proxy
组件通过API Server持续监控着各Service及与其关联的Pod对象,并将其创建或变动实时反映至当前工作节点上相应的iptables或ipvs规则上。
Service IP事实上是用于生成iptables或ipvs规则时使用的IP地址,它仅用于实现Kubernetes集群网络的内部通信,并且仅能够将规则中定义的转发服务的请求作为目标地址予以响应,这也是它被称为虚拟IP的原因之一。kube-proxy将请求代理至相应端点的方式有三种:userspace(用户空间)、iptables和ipvs。
此处的userspace是指Linux操作系统的用户空间。这种模型中,kube-proxy负责跟踪APIServer上Service和Endpoints对象的变动(创建或移除),并据此调整Service资源的定义。对于每个Service对象,它会随机打开一个本地端口(运行于用户空间的kube-proxy进程负责监听),任何到达此代理端口的连接请求都将被代理至当前Service资源后端的各Pod对象上,至于会挑中哪个Pod对象则取决于当前Service资源的调度方式,默认的调度算法是轮询(round-robin),其工作逻辑如图6-5所示。另外,此类的Service对象还会创建iptables规则以捕获任何到达ClusterIP和端口的流量。在Kubernetes 1.1版本之前,userspace是默认的代理模型。
<aside> 💡 这种代理模型中,请求流量到达内核空间后经由套接字送往用户空间的kube-proxy,而后再由它送回内核空间,并调度至后端Pod。这种方式中,请求在内核空间和用户空间来回转发必然会导致效率不高。
</aside>
iptables代理模型中,kube-proxy负责跟踪API Server上Service和Endpoints对象的变动(创建或移除),并据此做出Service资源定义的变动。同时,对于每个Service,它都会创建iptables规则直接捕获到达ClusterIP和Port的流量,并将其重定向至当前Service的后端.
也就是说, Service资源会创建iptables规则并关联至挑选的后端一组 Endpoints,默认算法是随机调度(random ), 从而随机发送到各个Pod.
在创建Service资源时,集群中每个节点上的kube-proxy都会收到通知并将其定义为当前节点上的iptables规则,用于转发工作接口接收到的与此Service资源的ClusterIP和端口的相关流量。客户端发来的请求被相关的iptables规则进行调度和目标地址转换(DNAT)后再转发至集群内的Pod对象之上。