1、service type
clusterIp: 虚拟的服务IP地址,仅仅用于kubernetes集群内部的pod访问,在node上kube-proxy通过设置的iptables规则转发
nodePort: 使用宿主机的端口,使能够访问node的外部客户端通过node的ip和端口号就可以访问pod里的服务
loadBalancer:使用外接负载均衡器完成到服务的负载分发
service通过label标签来和pod关联,这些匹配到label的pod的ip和端口组成endPoints,然后由kube-proxy负责将服务IP负载均衡到这些endpoint
2、无label的service
若想将外部的一个服务纳管到集群中,可以创建一个无标签的service,由于无label则无法找到对应的pod,即无法生成对应的endpoint,
因此需要手动创建一个和该 Service同名的Endpoint,用于指向实际的后端访问地址
3、Headless Service
若不使用kubernetes提供的负载均衡策略,而要自己来实现控制,Headless Service来实现这种功能, 即不为Service设置ClusterIP(入口IP地址),仅通过Label Selector将后 端的Pod列表返回给调用的客户端
clusterIp:None
4、外部访问集群内部
4.1 将容器里的端口号映射到物理机
通过设置容器级别的hostPort
4.2 通过设置pod级别的hostNetwork = true
此时如果不指定容器里的hostPort,则默认hostPort等于containerPort
4.3 将service的端口号映射到宿主机
指定service的type 为NodePort,同时指定ports里的节点端口号nodePort,同样,对该Service的访问也将被负载分发到后端的多个Pod上
5、service的负载均衡原理
service其实是对一组pod的抽象,它会根据访问策略来访问这组pod,在大多数情况下,service其实只是一种抽象的概念,其真正实现是运行在node上的kube-proxy进程
kube-proxy 一共经历了三次演变
第一次:客户端发起请求到service的clusterIp时,service根据iptables规则再将请求转发到本机的kube-proxy(用户态)上,然后由kube-proxy与pod建立起TCP/UDP连接,然后将请求转发到某个后端Pod上
第二次:kubernetes从1.2版本起,将iptables作为kube-proxy的默认模式,iptables模式下的kube-proxy不再起到代理的作用,其核心功能:通过API Server的WATCH机制实时监控service以及endpoint的变更信息,并更新对应的iptables规则,client的请求流量通过iptables的DNAT机制直接路由到目标pod上,此模式简单,但是有个缺陷:在集群中 的Service和Pod大量增加以后,iptables中的规则会急速膨胀,导致性能显著下降,在某些极端情况下甚至会出现规则丢失的情况,并且这种故 障难以重现与排查,由此引入第三代
第三次:将iptables升级为IPVS (实现机制同上,只是将iptables替换成了IPVS,在某些场景下还是需要与iptables搭配使用)
iptables与IPVS虽然都是基于Netfilter实现的,但因为定位不同,二 者有着本质的差别:iptables是为防火墙而设计的;IPVS则专门用于高 性能负载均衡,并使用更高效的数据结构(Hash表),允许几乎无限的 规模扩张,因此被kube-proxy采纳为第三代模式,但由于IPVS无法提供包过滤、airpin-masquerade tricks(地址伪装)、SNAT等功能,因此在某些场景(如NodePort的实现)下还要与iptables 搭配使用。在IPVS模式下,kube-proxy又做了重要的升级,即使用 iptables的扩展ipset,而不是直接调用iptables来生成规则链。