25、资源对象-Service【理论-回顾】

发布时间 2023-03-22 21:14:24作者: 小粉优化大师

1、基础知识

1.1、场景

通过对Pod及其管理资源RC和Deployment的实践,我们知道,我们所有的应用服务都是工作在pod资源
中,由于每个Pod都有独立的ip地址,而大量的动态创建和销毁操作后,虽然pod资源的数量是控制住了,但
是由于pod重新启动,导致他的IP很有可能发生了变化,假设我们这里有前端应用的pod和后端应用的pod,
那么再剧烈变动的场景中,两个应用该如何自由通信呢?难道是让我们以类似nginx负载均衡的方式手工定制
pod ip然后进行一一管理么?但是这是做不到的。
 Kubernetes集群就为我们提供了这样的一个对象--Service,它定义了一组Pod的逻辑集合和一个用
于访问它们的策略,它可以基于标签的方式自动找到对应的pod应用,而无需关心pod的ip地址变化与否,从而实现了类似负载均衡的效果.
 这个资源在master端的Controller组件中,由Service Controller 来进行统一管理。

1.2、简介

service是Kubernetes里最核心的资源对象之一,它是由coredns或者kube-dns组件提供的功能。每一个
Service都是一个完整的业务服务,我们之前学到的Pod、RC、Deployment等资源对象都是为Service服务的。

1.2.1、Service关系图

 

1.2.2、关系图解析

 Kubernetes 的 Service定义了一个服务的访问入口地址,前端的应用Pod通过Service访问其背后
一组有Pod副本组成的集群示例,Service通过Label Selector访问指定的后端Pod,RC保证Service的
服务能力和服务质量处于预期状态。
   Service是Kubernetes中最高一级的抽象资源对象,每个Service提供一个独立的服务,集群
Service彼此间使用TCP/IP进行通信,将不同的服务组合在一起运行起来,就行了我们所谓的"系统"

1.2.3、Service系统图

1.2.4、总结

我们知道每个Pod都有一个专用的IP地址,加上Pod内部容器的Port端口,就组成了一个访问Pod专用的
EndPoint(Pod IP+Container Port),从而实现了用户外部资源访问Pod内部应用的效果。
这个EndPoint资源在master端的Controller组件中,由EndPoint Controller 来进行统一管理。

1.3、原理解析

1.3.1、负载均衡

当多个Pod组成了一个业务集群来提供外部服务,那么外部客户端怎么才能访问业务集群服务呢?
说到外部用户来访问内部集群的场景,肯定能想到的负载均衡的案例:
nginx的upstream功能 或 LVS+keepalived功能

所有的Pod都有专用的 RIP,多个Pod副本就组成了一个Kubernetes集群的后端服务,根据对上面负载
均衡图的理解,我们需要配置一个vip。当客户端访问的请求过来后,Master结点通过VIP把客户端的请求,
负载均衡到后端的Pod副本即可。
   我们知道,Pod是工作在不同的Node节点上,而Node节点上有一个kube-proxy组件,它本身就是一个
软件负载均衡器,在内部有一套专有的负载均衡与会话保持机制,可以达到,接收到所有对Service请求,进
而转发到后端的某个具体的Pod实例上,相应该请求。

-- kube-proxy 其实就是 Service Controller位于各节点上的Agent。

1.3.2、Pod所处的Node场景分类

根据Pod所处的Node场景,有两种情况:
所有Pod副本都在同一Node节点上:
 对于这种情况,将Node节点专用的物理ip,作为负载均衡器的VIP,即可实现负载均衡后端服务的效
果。
所有Pod副本不在同一Node节点上:
 Node节点的物理ip就没有办法作为负载均衡器的VIP了,这就出现了一种常见的意外情况。
 
而Kubernetes是一个分布式的资源管理平台,所以Kubernetes集群资源对象肯定不能保证在同一台Node节
点,所以就不能使用Node节点的物理ip地址作为负载均衡器VIP地址了。

1.3.3、Node节点 VIP访问的解决方法

Kubernetes发明了一种设计,给Service分配一个全局唯一的虚拟ip地址--cluster IP,它不存在任何
网络设备上,Service通过内容的标签选择器,指定相应该Service的Pod资源,这样以来,请求发给
cluster IP,后端的Pod资源收到请求后,就会响应请求。
这种情况下,每个Service都有一个全局唯一通信地址,整个系统的内部服务间调用就变成了最基础的
TCP/IP网络通信问题。如果我们的集群内部的服务想要和外部的网络进行通信,方法很多,比如:
   NodePort类型,通过在所有结点上增加一个对外的端口,用于接入集群外部请求
   Ingress类型,通过集群附加服务功能,将外部的域名流量转交到集群内部。

1.3.4、Service vs Endpoint

1、当创建 Service资源的时候,最重要的就是为Service指定能够提供服务的标签选择器,
2、Service Controller就会根据标签选择器创建一个同名的Endpoint资源对象。
3、Endpoint Controller开始介入,使用Endpoint的标签选择器(继承自Service标签选择器),筛选符合条件的pod资源
4、Endpoint Controller 将符合要求的pod资源绑定到Endpoint上,并告知给Service资源,谁可以正常提供服务。
5、Service 根据自身的cluster IP向外提供由Endpoint提供的服务资源。

-- 所以Service 其实就是 为动态的一组pod资源对象 提供一个固定的访问入口。

2、工作模型

2.1、代理模型

2.1.1、简介

一个Service对象,对于当前集群的节点来说,就是工作节点上的一些iptables或ipvs规则,这些规
则由kube-proxy进行实时维护,kube-proxy将请求代理至相应端点的方式有三种:userspace/iptables/ipvs。

这些方法的目的是:kube-proxy如何确保service能正常工作。

2.1.2、UserSpace-代理模型

userspace模型是k8s最早的一种工作模型,从1.1版本就开始使用。他的作用就是将service的策略转换成iptables规则,这些规则仅仅做请求的拦截,而不对请求进行调度处理。
该模型中,请求流量到达内核空间后,由套接字送往用户空间的kube-proxy,再由它送回内核空间,并调度至后端Pod。因为涉及到来回转发,效率不高

2.1.3、iptables-代理模型

 

iptables模式在1.10版本开始使用。
为Service创建iptables规则,直接捕获到达ClusterIP和Port的流量,并重定向至当前Service的后
端。对每个Endpoints对象,Service资源会为其创建iptables规则并关联至挑选的后端Pod资源
优点:性能比userspace更加高效和可靠
缺点:
 不会在后端Pod无响应时自动重定向,而userspace可以
 中量级k8s集群(service有几百个)能够承受,但是大量级k8s集群(service有几千个)维护达几万条规则,难度较大

2.1.4、ipvs-代理模型

 

自1.11版本起为默认设置
请求流量的调度功能由ipvs实现,余下的其他功能仍由iptables完成
ipvs流量转发速度快,规则同步性能好,且支持众多调度算法,如rr/lc/dh/sh/sed/nq等
安装特点:echo 'KUBE_PROXY_MODE=ipvs' >> /etc/sysconfig/kubelet
优点:
 每条ipvs规则包含了两个功能:转发功能和调度功能
 
注意:
 对于我们kubeadm方式安装k8s集群来说,他会首先检测当前主机上是否已经包含了ipvs模块,如果加
载了,就直接用ipvs模式,如果没有加载ipvs模块的话,会自动使用iptables模式。

2.2、service & kube-proxy-关联关系

2.2.1、关联关系描述

1、Service作为一个资源对象,他会在在API Service服务中定义出来的。
2、Service Controller 触发每个节点上的kube-proxy,由kube-proxy实时的转换为本地的
ipvs|iptables规则。
3、默认情况下,内核中的ipvs|iptables规则,仅仅是负责本地节点用户空间pod客户端发出请求时的拦截
或者转发规则
4、如果pod客户端向Service发出请求
 pod客户端向内核发出请求,根据ipvs|iptables规则,匹配目标service
如果service匹配到的话,会返回当前service随对应的后端endpoint有哪些
 iptables|ipvs会根据情况挑选一个合适的endpoint地址
 - 如果endpoint是本机上的,则会转发给本机的endpoint
 - 如果endpoint是其他主机上的,则转发给其他主机上的endpoint

3、Service类型

对于k8s来说,内部服务的自由通信可以满足我们环境的稳定运行,但是我们作为一个平台,其核心功能还是
将平台内部的服务发布到外部环境,那么在k8s环境平台上。Service主要有四种样式来满足我们的需求。

3.1、ClusterIP 

这是service默认的服务暴露模式,主要针对的对象是集群内部。

3.2、NodePort

基于ClusterIP方式对外提供服务,端口范围 30000~32767 
NodePort是一个随机的端口,在所有节点上都会存在。

3.3、LoadBalancer

基于NodePort之上,使用运营商负载均衡器方式实现对外提供服务
底层是基于IaaS云创建一个k8s云,同时该平台也支持LBaaS产品服务

3.4、ExternalName

当前k8s集群依赖集群外部的服务,那么通过externalName将外部主机引入到k8s集群内部
外部主机名以 DNS方式解析为一个 CNAME记录给k8s集群的其他主机来使用
这种Service既不会有ClusterIP,也不会有NodePort.而且依赖于内部的CoreDNS功能