service用途:
service 为后端pod提供一组负载均衡代理
-
userpace在这种模式下,kube-proxy监视Kubernetes主服务器以添加和删除Service和Endpoint对象。对于每个服务,它都会在本地节点上打开一个端口(随机选择)。与此代理端口的任何连接都代理到服务的后端Pod。SessionAffinity在决定使用哪个后端Pod时,kube-proxy会考虑服务的设置。最后,用户控件代理安装iptables规则,以获取服务clusterIP和流量port。规则将流量重定向到代理后端Pod的端口。
4ec2d5628535e5dd2498b135256bf6e9cc1b62d3.png -
iptables目前默认的方案,完全以内核iptables的nat方式实现service负载均衡。该方式在大规模情况下存在一些性能问题;首先,iptables没有增量更新的功能,更新一条规则需要整体flush,更新时间长,这段时间之内流量会有不同程度的影响;此外,iptables规则串行匹配,没有预料到Kubernetes这种在一个机器上会有很多规则的情况,流量需要经过所有规则的匹配后在进行转发,对时间和内存都是极大的小号,尤其在大规模情况下对性能的影响十分明显
f703738da9773912504833aea9b4d71e347ae2c3.png -
ipvs与iptables、userspace 模式一样,kube-proxy 依然监听Service以及Endpoints对象的变化, 不过它并不创建反向代理, 也不创建大量的 iptables 规则, 而是通过netlink 创建ipvs规则,并使用k8s Service与Endpoints信息,对所在节点的ipvs规则进行定期同步; netlink 与 iptables 底层都是基于 netfilter 钩子,但是 netlink 由于采用了 hash table 而且直接工作在内核态,在性能上比 iptables 更优
48540923dd54564e3ea2821de073cd84d0584f06.png
同时,ipvs负载均衡除了简单rr规则还有很多选择,适合在大型集群中使用,而缺点是带来了额外的配置维护操作
简单点来说Service的请求先从用户空间进入内核iptables转发到这个端口,然后再回到用户空间,由kube-proxy完成后端endpoint的选择和代理,这样流量会有从用户空间进入内核的过程,效率低,有明显的性能瓶颈
使用Service服务还会涉及到几种IP:
ClusterIP
Pod IP 地址是实际存在于某个网卡(可以是虚拟设备)上的,但clusterIP就不一样了,没有网络设备承载这个地址。它是一个虚拟地址,由kube-proxy使用iptables规则重新定向到其本地端口,再均衡到后端Pod。当kube-proxy发现一个新的service后,它会在本地节点打开一个任意端口,创建相应的iptables规则,重定向服务的clusterIP和port到这个新建的端口,开始接受到达这个服务的连接。Pod IP
Pod的IP,每个Pod启动时,会自动创建一个镜像为gcr.io/google_containers/pause的容器,Pod内部其他容器的网络模式使用container模式,并指定为pause容器的ID,即:network_mode: "container:pause容器ID",使得Pod内所有容器共享pause容器的网络,与外部的通信经由此容器代理,pause容器的IP也可以称为Pod IP。节点IP
Node-IP,service对象在Cluster IP range池中分配到的IP只能在内部访问,如果服务作为一个应用程序内部的层次,还是很合适的。如果这个service作为前端服务,准备为集群外的客户提供业务,我们就需要给这个服务提供公共IP了。指定service的spec.type=NodePort,这个类型的service,系统会给它在集群的各个代理节点上分配一个节点级别的端口,能访问到代理节点的客户端都能访问这个端口,从而访问到服务。
创建一个Service
[root@node1 svc]# vim nginx_svc.yml
apiVsersion: v1
kind: Service #资源类型
metadata:
name: myweb #名称
spec:
type: NodePort #形式,端口映射
ports:
- port: 80 #vip端口
nodePort: 30000 #映射宿主机的端口 默认30000-32767
targetPort: 80 #PodIp地址
selector:
app: myweb #选择器,为myweb设置
创建
[root@node1 svc]# kubectl create -f nginx_svc.yml
service "myweb" created
查看myweb
[root@node1 svc]# kubectl describe svc myweb
Name: myweb
Namespace: default
Labels: <none>
Selector: app=myweb
Type: NodePort
IP: 10.254.129.217
Port: <unset> 80/TCP
NodePort: <unset> 30000/TCP
Endpoints: 172.16.102.3:80,172.16.20.2:80
Session Affinity: None
No events.
使用浏览器可以访问
[http://192.168.1.103:30000/](http://192.168.1.103:30000/)
service服务自动发现
扩展Pod
[root@node1 svc]# kubectl scale rc myweb --replicas=3
replicationcontroller "myweb" scaled
[root@node1 svc]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
myweb-0x2z8 1/1 Running 0 29m 172.16.20.2 192.168.1.103
myweb-45qvj 1/1 Running 0 29m 172.16.102.3 192.168.1.114
myweb-phmvg 1/1 Running 0 7s 172.16.14.3 192.168.1.113
Pod会自动加入svc
[root@node1 svc]# kubectl describe svc myweb
Name: myweb
Namespace: default
Labels: <none>
Selector: app=myweb
Type: NodePort
IP: 10.254.129.217
Port: <unset> 80/TCP
NodePort: <unset> 30000/TCP
Endpoints: 172.16.102.3:80,172.16.14.3:80,172.16.20.2:80
Session Affinity: None
No events.
service负载均衡
编写页面放入到Pod当中
[root@node1 svc]# echo 'node1' >> index.html
[root@node1 svc]# kubectl cp index.html myweb-0x2z8:/usr/share/nginx/html/index.html
[root@node1 svc]# echo 'node2' > index.html
[root@node1 svc]# kubectl cp index.html myweb-45qvj:/usr/share/nginx/html/index.html
[root@node1 svc]# echo 'node3' > index.html
[root@node1 svc]# kubectl cp index.html myweb-phmvg:/usr/share/nginx/html/index.html
访问IP可以实现轮询
参考文章
https://baijiahao.baidu.com/s?id=1660475099516957179&wfr=spider&for=pc