01Service简介
Kubernetes Pod 是有生命周期的,它们可以被创建,也可以被销毁,然而一旦被销毁生命就永远结束。通过 ReplicationController 能够动态地创建和销毁 Pod(例如,需要进行扩缩容,或者执行 滚动升级)。每个 Pod 都会获取它自己的 IP 地址,即使这些 IP 地址不总是稳定可依赖的。这会导致一个问题:在 Kubernetes 集群中,如果一组 Pod(称为 backend)为其它 Pod (称为 frontend)提供服
务,那么那些 frontend 该如何发现,并连接到这组 Pod 中的哪些 backend 呢?
Kubernetes Service 定义了这样一种抽象:一个 Pod 的逻辑分组,一种可以访问它们的策略 —— 通常称为微服务。这一组 Pod 能够被 Service 访问到,通常是通过 Label Selector实现的。Service 通过标签来选取服务后端,一般配合 Replication Controller 或者 Deployment 来保证后端容器的正常运行。这些匹配标签的 Pod IP 和端口列表组成 endpoints,由 kube-proxy 负责将服务 IP 负载均衡到这些 endpoints 上。
1、Service定义服务入口:
即k8s的Service定义了一个服务的访问入口地址,前端的应用通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,来自外部的访问请求被负载均衡到后端的各个容器应用上。
2、Service与pod:
Service与其后端Pod副本集群之间则是通过Label Selector来实现对接的。而RC的作用相当于是保证
Service的服务能力和服务质量始终处于预期的标准。
通过分析、识别并建模系统中的所有服务为微服务-Kubernetes Service,最终我们的系统由多个提供不同业务能力而又彼此独立的微服务单元所组成,服务之间通过TCP/IP进行通信,从而形成了我们强大而又灵活的弹性网格,拥有了强大的分布式能力、弹性扩展能力、容错能力,与此同时,我们的程序架构也变得简单和直观许多。
3、Service的负载均衡器kube-proxy
Kubernetes也遵循了上述常规做法,运行在每个Node上的kube-proxy进程其实就是一个智能的软件负载均衡器,它负责把对Service的请求转发到后端的某个Pod实例上,并在内部实现服务的负载均衡与会话保持机制。但Kubernetes发明了一种很巧妙又影响深远的设计: Service不是共用一个负载均衡器的IP地址,而是每个Service分配了一个全局唯一的虚拟IP地址,这个虚拟IP被称为Cluster IP,这样一来,每个服务就变成了具备唯一IP地址的“通信节点”,服务调用就变成了最基础的TCP网络通信问题.
02kube-proxy
service工作的核心是kube-proxy,kube-proxy负责为Service提供cluster内部的服务发现和负载均衡,它运行在每个Node计算节点上,负责Pod网络代理, 它会定时从etcd服务获取到service信息来做相应的策略,维护网络规则和四层负载均衡工作。在K8s集群中微服务的负载均衡是由Kube-proxy实现的,它是K8s集群内部的负载均衡器,也是一个分布式代理服务器,在K8s的每个节点上都有一个,这一设计体现了它的伸缩性优势,需要访问服务的节点越多,提供负载均衡能力的Kube-proxy就越多,高可用节点也随之增多。
service是一组pod的服务抽象,相当于一组pod的LB,负责将请求分发给对应的pod。service会为这个LB提供一个IP,一般称为cluster IP。kube-proxy的作用主要是负责service的实现,具体来说,就是实现了内部从pod到service和外部的从node port向service的访问。
kube-proxy有三种代理模式:userspace、 iptables和ipvs。
1.userspace
kube-proxy 会监视 Kubernetes 控制平面对 Service 对象和 Endpoints 对象的添加和移除操作。对每个 Service,它会在本地 Node 上打开一个端口(随机选择)。请求先经过iptables规则,当捕获到达Service 的 clusterIP和 Port 的请求,并重定向到代理端口(kube-proxy),再由代理端口再代理请求到后端Pod(v1.2版本之前的默认模式)
userspace是在用户空间,通过kube-proxy来实现service的代理服务,service的请求会先从用户空间进入内核iptables,然后再回到用户空间,由kube-proxy完成后端Endpoints的选择和代理工作,这样流量从用户空间进出内核带来的性能损耗是不可接受的,因此这种方式已经不用了。
2.iptables
这种模式,kube-proxy 会监视 Kubernetes 控制节点对 Service 对象和 Endpoints 对象的添加和移除。对每个 Service,它会配置 iptables 规则,从而捕获到达该 Service 的 clusterIP和端口的请求,进而将请求重定向到 Service 的一组后端中的某个 Pod 上面。对于每个 Endpoints 对象,它也会配置iptables 规则,这个规则会选择一个后端组合。
默认的策略是,kube-proxy 在 iptables 模式下随机选择一个后端。
使用 iptables 处理流量具有较低的系统开销,因为流量由 Linux netfilter 处理,而无需在用户空间和内核空间之间切换。这种方法也可能更可靠。
如果 kube-proxy 在 iptables 模式下运行,并且所选的第一个 Pod 没有响应, 则连接失败。这与用户空间模式不同:在这种情况下,kube-proxy 将检测到与第一个 Pod 的连接已失败, 并会自动使用其他后端 Pod 重试。
可以使用 Pod 就绪探测器 验证后端 Pod 可以正常工作,以便 iptables 模式下的 kube-proxy仅看到测试正常的后端。这样做意味着你避免将流量通过 kube-proxy 发送到已知已失败的 Pod。
通过以下命令可以查看iptables规则
iptables -t nat -nvL|grep gateway-svc
kube-proxy 在 iptables 模式下随机选择一个后端Pod,利用Pod 就绪探测器验证Pod是否正常,kube-proxy只会把正常的Pod写入iptables,避免流量进入不正常的Pod。
3. ipvs
在 ipvs 模式下,kube-proxy 监视 Kubernetes 服务和端点,调用 netlink 接口相应地创建 IPVS 规则,并定期将 IPVS 规则与 Kubernetes 服务和端点同步。该控制循环可确保IPVS 状态与所需状态匹配。访问服务时,IPVS将流量定向到后端Pod之一。
IPVS代理模式基于类似于 iptables 模式的 netfilter 挂钩函数,但是使用哈希表作为基础数据结构,并且在内核空间中工作。这意味着,与 iptables 模式下的 kube-proxy 相比,IPVS模式下的 kube-proxy重定向通信的延迟要短,并且在同步代理规则时具有更好的性能。与其他代理模式相比,IPVS模式还支持更高的网络流量吞吐量。
IPVS 提供了更多选项来平衡后端 Pod 的流量。
要在 IPVS 模式下运行 kube-proxy,必须在启动 kube-proxy 之前使 IPVS 在节点上可用。
当 kube-proxy 以 IPVS 代理模式启动时,它将验证 IPVS 内核模块是否可用。如果未检测到 IPVS 内核模块,则kube-proxy 将退回到以 iptables 代理模式运行。
Service 是由 kube-proxy 组件,加上 iptables 来共同实现的.
kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相当多的 iptables规则,如果宿主机有大量的Pod,不断刷新iptables规则,会消耗大量的CPU资源。
IPVS模式的service,可以使K8s集群支持更多量级的Pod。
**开启kube-proxy的ipvs模式:**
所有节点安装:
yum install -y ipvsadm
master端修改为ipvs模式
kubectl edit cm kube-proxy -n kube-system
#将mode字段内容改为ipvs
mode: "ipvs"
master端更新kube-proxy
[root@master ~]# kubectl get pod -n kube-system |grep kube-proxy | awk
'{system("kubectl delete pod "$1" -n kube-system")}'
pod "kube-proxy-4gp79" deleted
pod "kube-proxy-jdhlk" deleted
pod "kube-proxy-twxdz" deleted
[root@master ~]# kubectl get pod -n kube-system |grep kube-proxy
kube-proxy-nrb4g 1/1 Running 0 51s
kube-proxy-p2lvh 1/1 Running 0 57s
kube-proxy-z48pl 1/1 Running 0 54s
03资源清单
Service的资源清单文件如下:
kind: Service # 资源类型
apiVersion: v1 # 资源版本
metadata: # 元数据
name: service # 资源名称
namespace: dev # 命名空间
spec: # 描述
selector: # 标签选择器,用于确定当前 service 代理哪些 pod
app: nginx
type: # Service 类型,指定 service 的访问方式
clusterIP: # 虚拟服务的 ip 地址
sessionAffinity: # session 亲和性,支持 ClientIP、None 两个选项
ports: # 端口信息
- protocol: TCP
port: 3017 # service 端口
targetPort: 5003 # pod 端口
nodePort: 31122 # 主机端口
type 的类型有下面几种
1. ClusterIP:默认值,它是 Kubernetes 系统自动分配的虚拟 IP,只能在集群内部访问;
2. NodePort:将 Service 通过指定的 Node 上的端口暴露给外部,通过此方法,就可以在集群外部访问服务;
3. LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境支持;
4. ExternalName:把集群外部的服务引入集群内部,直接使用;
下期分享k8s之service 服务类型,敬请关注!