"本文将为你介绍Service在Kubernetes集群中的价值和做用"
Service是Kubernetes接入层的一种抽象资源,它为咱们提供了一种固定的、统一的访问接口地址和负载均衡能力,这时可能会想到,当时使用docker-compose的时候,不存在Service概念,不也运行起来了吗?是的,在Kubernetes集群内部Pod ip也是互通的,可是Pod的ip会常常由于扩容、重建而致使客户端访问错误,pod访问没法提供负载均衡的能力,而Service经过选择一组Pod的label就直接能够访问到Pod,并且可使用万年不变的域名,因此就选择Service了。
一、Service是怎么产生的,在集群内部是如何存在的呢?
在kubernetes当中所谓的Service是kube-proxy生成iptables或ipvs规则,它会产生一组虚拟地址,在集群环境下有效。Service不能直接到达Pod内部,中间会间隔EndPoints,这是一组ip和port的组合。默认类型是ClusterIP它仅能接收集群中pod客户端程序的访问请求。这也是最经常使用的一种类型,另外还有NodePort、LoadBalancer、ExternalName。
二、iptables或ipvs,究竟是iptables仍是ipvs呢?
一个Service对象就是工做节点上的一些iptables或ipvs规则,用于将到达Service对象IP地址的流量调度转发至相应的Endpoints对象指向的IP地址和端口之上。
Kubernetes1.1以前是基于userspace实现,这种模型之下,每次请求流量要先到达内核空间,经有套接字转发到kube-proxy,而后再由它送回到内核空间,以后调度到后端pod之上,能够看出请求在用户空间和内核空间来回转发,效率必然不高。可是当pod无响应时,可以自动重定向到其它pod。
在Kubernetes1.1版本开始引入iptables规则,Kubernetes1.2开始成为默认类型。即在建立Service资源时,集群上每一个节点的kube-proxy都会收到通知,而且建立iptables规则,用于转发到此Service ClusterIP的流量。工做TCP/IP的传输层,高效稳定。
可是这种方式有以下缺点:
一、iptables代理模型挑中的pod无响应时,不能自动重定向到集群内部其它pod资源对象之上。
二、kube-proxy经过iptables处理Service和pod的交互,每产生一个计算节点或者产生大量的pod就须要产生相应大量的iptables规则,不难想象,这些iptables规则每次须要刷新匹配保证正确性,就须要占用大量的CPU资源,因此基于iptables的Service实现就成了制约Kubernetes承载更多pod的瓶颈。
在Kubernetes1.11开始默认使用ipvs模型,在这种模型下kube-proxy会跟踪APIServer上Service和endpoints对象变化,调用netlink建立ipvs规则,请求调度流量功能由ipvs实现,运行于netfilter之上的钩子函数,具备流量转发速度快,规则性能同步好的特色,支持众多调度算法,剩下仍然由iptables完成。说到这里咱们就大概明白了iptables和ipvs的做用和关系了。
三、Kubernetes的服务发现是经过dns实现,那么为何会出现四种类型的服务暴露方式呢?
说到Service不得不介绍kubernetes网络模型和通讯方式
一个完整的Kubernetes集群应该包含三层网络,首先第一层是mater和node节点之间的网络,这个网络须要在部署kubernetes集群以前配置完成;
第二层网络是pod的网络经过kubelet或者cni插件实现,用于pod之间或者内部的通讯,集群中的全部pod均处在同一个网络平面空间内,能够直接通讯;
第三层网络是Service资源的网络,是一个虚拟网络,用于为Kubernetes集群配置IP地址,但此地址并不配置于任何主机或者容器的网络接口之上,而是经过kubeproxy配置为iptables规则,将发往该地址的全部流量调度至后端的pod之上。
同一个pod的内部通讯;
java
各个pod彼此通讯;
node
pod和service的通讯;
web
集群外部流向service的通讯。算法
因此Service为了知足这些通讯方式就出现了以下类型:
ClusterIP:为集群内部ip地址暴露服务,仅在集群内可达,外部ip没法访问,默认Service类型;
NodePort:这种类型创建在clusterIp之上,为节点的IP地址暴NodePort服务,外部节点能够经过NodeIP:NodePort直接访问;
LoadBalancer:这种类型构建在NodePort之上,它能够关联到集群外部的某个负载均衡设备。Kubernetes没有为私有化集群提供LoadBalancer的支持。若是在私有化集群使用须要自建负载均衡器;
ExternalName:其经过将Service映射至由externalName字段的内容指定的主机名来暴露服务,此主机名须要被DNS服务解析至CNAME类型的记录。这句话怎么理解呢?
举个例子,你全部的服务都在集群内部,可是你有个数据库是mongodb,没有实现容器化,更没有部署在Kubernetes内部,固然你能够经过在ConfigMap中添加配置访问这个外部服务,可是当你的环境发生变化,好比从开发环境和生产环境的数据地址不一样,这个时候你须要修改和重建ConfigMap。
这个时候可使用Kubernetes ExternalName内置服务发现机制运用于集群外部运行的服务,像使用集群内的服务同样使用外部服务!经过这种方式,您能够在开发环境和生产环境中实现相同的功能,若是您最终将服务移入集群内,则不须要更改任何代码和配置。
kind: ServiceapiVersion: v1metadata: name: mongospec: type: ExternalName externalName: mango123456.com
你只须要访问:mongodb://<dbuser>:<dbpassword>@mongo:<port>就能够自动访问外部服务。
四、Service自己有端口、Pod也有端口、容器也有端口,之间有什么关系呢?
containerPort:一个信息性数据,为集群提供一个能够快速了解相关pod能够访问端口的途径,并且显式指定容器端口,不管你是否指定都不影响其余节点上的客户端pod对其进行访问;
port:服务提供端口,用于kubernetes集群内部服务访问;
targetPort:pod目标端口,若是不设置使用默认port端口,port和nodePort的数据经过这个端口进入到Pod内部,Pod里面的containers的端口映射到这个端口,提供服务;
nodePort:Kubernetes集群外部用户访问端口;
五、总结
本文主要总结了Service的工做原理和机制。只有明白Service这些概念,才能灵活使用Service,当咱们服务出现故障的时候,根据它的原理去分析问题到底出在什么地方,进而快速解决问题。
推荐阅读
Kubernetes排障指南mongodb
从零搭建Kubernetes下的nignx和tomcat
docker
Kubernetes中如何使用ClusterDNS进行服务发现?数据库
Kubernetes入门培训(内含PPT)
后端
从Ice到Kubernetes容器技术,微服务架构经历了什么?
api
原创不易,随手关注或者”在看“,诚挚感谢!
tomcat