Pod是非永久性资源,会动态创建和销毁,pod的ip会变化。这会导致一类Pod(业务1)访问另一类Pod(业务2)需要找出并跟踪Pod(业务2)的IP地址,再者Pod(业务2)是多个的,如何提供负载均衡呢?虽然Pod1通过轮询一组Pod的ip可以实现,但会Pod就需要增加负载均衡的逻辑,Pod就变得不纯粹了,不符合单一设计原则。于是有了Service,把一类Pods上的应用程序抽象成服务,并提供可以访问他们的策略。
有两种方式: 选择算符的Service 和 没有选择算符的Service
这是最常见的方式,指定 specselector 即通过打标签的方式,主要是针对集群内部同命名空间的Pod
创建上面的Service,会自动创建相应的 Endpoint 对象
查看自动创建的Endpoint对象
主要是针对希望服务指向另一个名字空间或者其他集群中的服务,比如外部的ES集群
此服务没有选择算符,因此不会自动创建相应的 Endpoint 对象, 需要手动动添加 Endpoint 对象,将服务手动映射到运行该服务的网络地址和端口
该模式下,节点上kube-proxy 持续监听 Service 以及 Endpoints 对象的变化,并设置进本地节点iptables,请求反向代理全部交给 iptables 来实现。每个Node节点都会配置所有Service进iptables,当捕获到Service的clusterIP和端口请求,利用注入的iptables,将请求重定向到Service的对应的Pod,v12版本之后的默认模式。
通过查看iptables规则可以看到:
kube-proxy 在 iptables 模式下随机选择一个后端Pod,利用Pod 就绪探测器验证Pod是否正常,kube-proxy只会把正常的Pod写入iptables,避免流量进入不正常的Pod。
kube-proxy 会监视 Kubernetes 控制平面对 Service 对象和 Endpoints 对象的添加和移除 *** 作。 对每个 Service,它会在本地 Node 上打开一个端口(随机选择)。请求先经过iptables规则,当捕获到达Service 的 clusterIP和 Port 的请求,并重定向到代理端口(kube-proxy),再由代理端口再代理请求到后端Pod(v12版本之前的默认模式)
IPVS模式是利用linux的IPVS模块实现,同样是由kube-proxy实时监视集群的service和endpoint,调用netlink接口相应的创建ipvs规则,由ipvs实现负载均衡访问。IPVS 专为负载平衡而设计,并基于内核内哈希表,有更高的网络流量吞吐量(iptables 模式在大规模集群 比如10000 个服务中性能下降显著),并且具有更复杂的负载均衡算法(最小连接、局部性、 加权、持久性)。(v18以后新支持的)
上面讲的Pod之间调用,采用Service进行抽象,服务之间可以通过clusterIP 进行访问调用,不用担心Pod的销毁重建带来IP变动,同时还能实现负载均衡。但是clusterIP也是有可能变动,况且采用IP访问始终不是一种好的方式。通过 DNS 和 环境变量 可以实现通过服务名现在访问。
k8s采用附加组件(CoreDNS)为集群提供DNS服务,会为每个服务创建DNS记录,CoreDNS只为Service和Pod创建DNS记录。kubernetes强烈推荐采用DNS方式
例如,如果你在 Kubernetes 命名空间 my-ns 中有一个名为 my-service 的服务, 则控制平面和 DNS 服务共同为 my-servicemy-ns 创建 DNS 记录。 my-ns 命名空间中的 Pod 应该能够通过按名检索 my-service 来找到服务,其他命名空间中的 Pod 必须将名称限定为 my-servicemy-ns 。 这些名称将解析为为服务分配的集群 IP。
Kubernetes 还支持命名端口的 DNS SRV(服务)记录。 如果 my-servicemy-ns 服务具有名为 >
headless不分配clusterIP
headless service可以通过解析service的DNS,返回所有Pod的地址和DNS(statefulSet部署的Pod才有DNS)
普通的service,只能通过解析service的DNS返回service的ClusterIP
statefulSet下的Pod有DNS地址,通过解析Pod的DNS可以返回Pod的IP
deployment下的Pod没有DNS
1另一个pod里 可以通过dns+[pod的端口]访问到该服务
Service的ClusterIP工作原理:一个service可能对应一组endpoints(所有pod的地址+端口),client访问ClusterIP,通过iptables或者ipvs转发到Real Server(Pod),具体 *** 作如下
从上面的结果能看到,虽然Service有2个endpoint,但是DNS查询时只会返回Service的ClusterIP地址,具体Client访问的是哪个real server,由iptables或者ipvs决定
据结果看到,dns查询会返回3个endpoint,也就是3个pod地址和DNS,通过解析pod的DNS也能返回Pod的IP
第一种:自主选择权,有时候client想自己决定使用哪个Real Server,可以通过查询DNS来获取Real Server的信息
第二种:headlessservice关联的每个endpoint(也就是Pod),都会有对应的DNS域名;这样Pod之间就可以互相访问
如上,eureka就是我们场景的StatefulSet,对应的pod就是eureka-demo-com-0,eureka-demo-com-1,eureka-demo-com-2,他们之间能互相访问,这样对于一些集群类型的应用就可以解决互相身份识别的问题了
1headless service会为关联的service分配一个域
<service name>$<namespace name>svcclusterlocal
2StatefulSet会为关联的Pod保持一个不变的Pod Name
statefulset中Pod的hostname格式为$(StatefulSet name)-$(pod序号)
3StatefulSet会为关联的Pod分配一个dnsName
$<Pod Name>$<service name>$<namespace name>svcclusterlocal
以上就是关于k8s的Service详解全部的内容,包括:k8s的Service详解、nacos与k8s 服务注册与发现、Service之headless和statefulSet结合等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)