Service介绍
Kubernetes 之所以需要 Service,一方面是因为 Pod的IP不是固定的,另一方面则是因为一组 Pod 实例之间总会有负载均衡的需求
Service是由Kube-proxy组件加上iptables来共同实现的
Service vip(vip 是k8s自动为Service分配的)到Pod的转发
iptables 对流入的IP包还设置了一个“标志”(–set-xmark)
只有处于Running状态,且readinessProbe检查通过的Pod,才会出现在Service的Endpoints 列表里.并且,当某一个 Pod 出现问题时,Kubernetes会自动把它从Service里摘除掉
Service基本原理
当用户把一个service yaml文件提交给k8s后,kube-proxy组件通过Service的Informer感知到一个Service对象的添加,作为对这个事件的响应它就会在宿主机上创建一条iptables规则 可以通过iptables-save命令来查看
Service的VIP地址只是一条iptables规则上的配置 并没有真正的网络设备 所以ping这个地址 是不会有任何响应的
DNAT的作用,就是在PREROUTING检查点之前,也就是在路由之前,将流入IP包的目的地址和端口,改成–to-destination指定的新目的地址和端口
访问Service VIP的IP包经过上述 iptables 处理之后,就已经变成了访问具体某一个后端Pod的IP包了.
不难理解,这些 Endpoints 对应的iptables规则,正是kube-proxy通过监听Pod的变化事件,在宿主机上生成并维护的
iptables模式和ipvs模式
kube-proxy通过iptables处理Service 的过程,其实需要在宿主机上设置相当多的 iptables 规则 当你的宿主机上有大量Pod的时候,成百上千条iptables规则不断地被刷新,会大量占用该宿主机的CPU资源 IPVS 模式 IPVS 模式的工作原理,其实跟iptables模式类似.当我们创建了前面的 Service 之后,kube-proxy首先会在宿主机上创建一个虚拟网卡(叫作:kube-ipvs0)并为它分配 Service VIP作为 IP 地址kube-proxy就会通过Linux的IPVS 模块,为这个IP地址设置三个IPVS 虚拟主机,并设置这三个虚拟主机之间使用轮询模式 (rr) 来作为负载均衡策略
而相比于 iptables,IPVS 在内核中的实现其实也是基于 Netfilter的NAT模式,所以在转发这一层上,理论上 IPVS 并没有显著的性能提升.但是IPVS 并不需要在宿主机上为每个Pod设置 iptables 规则,而是把对这些“规则”的处理放到了内核态,极大地降低了维护这些规则的代价 不过需要注意的是,IPVS 模块只负责上述的负载均衡和代理功能.而一个完整的 Service 流程正常工作所需要的包过滤,SNAT等操作,还是要靠iptables来实现.只不过,这些辅助性的 iptables 规则数量有限,也不会随着Pod数量的增加而增加
Service和DNS的关系
在kubernetes中,所有的Service和Pod都会被分配一条对应的DNS A记录( 通过域名解析到IP地址的记录 )
clusterIP Service的分配方式
ClusterIP模式的Service 来说,它的 A 记录的格式是:myservicename.mynamespace.svc.cluster.local 当你访问这条 A 记录的时候,它解析到的就是该Service的VIP 地址Headliness Service的分配方式
ClusterIP=None 的 Headless Service 来说,它的 A 记录的格式也是:myservicename.mynamespace.svc.cluster.local 当你访问这条A记录的时候,它返回的是所有被代理的Pod的IP地址的集合.当然,如果你的客户端没办法解析这个集合的话,它可能会只会拿到第一个Pod的IP地址
clusterIP Service被代理Pod的分配方式
对于ClusterIP模式的Service来说,它代理的Pod被自动分配的A记录的格式是:PodIP.mynamespace.pod.cluster.local 这条记录指向Pod的IP地址
Headliness Service被代理Pod的分配方式
1.对Headless Service 来说,它代理的Pod被自动分配的A记录的格式是:mypodname.myservicename.mynamespace.svc.cluster.local 这条记录也指向Pod的IP地址 2. 如果Pod本身声明了hostname和subdomain字段,那么这时候Pod的A记录就会变成: podhostname.mysubdomain.mynamespace.svc.cluster.local
在上面这个Service和Pod被创建之后,你就可以通过busybox-1.default-subdomain.default.svc.cluster.local 解析到这个Pod的IP地址了
在 Kubernetes 里,/etc/hosts 文件是单独挂载的,这也是为什么kubelet能够对hostname进行修改并且Pod 重建后依然有效的原因这跟 Docke的Init层是一个原理
用途
ClusterIP模式的Service为你提供的,就是一个Pod的稳定的IP地址,即 VIP. 并且,这里Pod和Service 的关系是可以通过 Label 确定的 Headless Service 为你提供的,则是一个 Pod 的稳定的 DNS 名字,并且,这个名字是可以通过Pod名字和Service名字拼接出来 服务发现: 即当我的一个服务(Pod)的IP地址是不固定的且没办法提前获知时,该如何通过一个固定的方式访问到这个Pod