一、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其实便是办理service的拜访进口,包括集群内Pod到Service的拜访和集群外拜访service。
- kube-proxy办理sevice的Endpoints,该service对外露出一个Virtual IP,也成为Cluster IP, 集群内经过拜访这个Cluster IP:Port就能拜访到集群内对应的serivce下的Pod。
- service是经过Selector选择的一组Pods的服务笼统,其实便是一个微服务,供给了服务的LB和反向署理的才能,而kube-proxy的主要作用便是担任service的完结。
- service另外一个重要作用是,一个服务后端的Pods或许会跟着生存灭亡而产生IP的改动,service的呈现,给服务供给了一个固定的IP,而无视后端Endpoint的变化。
二、Service 简介
Kubernetes Service界说了这样一种笼统: Service是一种能够拜访 Pod逻辑分组的战略, Service通常是经过 Label Selector拜访 Pod组。
Service能够供给负载均衡的才能,可是在运用上有以下限制:只供给 4 层负载均衡才能,而没有 7 层功用,但有时我们或许需求更多的匹配规矩来转发恳求,这点上 4 层负载均衡是不支撑的。
三、Service 类型
Service在 K8s中有以下四种类型:
1)ClusterIp(集群内部运用)
默许类型,主动分配一个仅Cluster内部能够拜访的虚拟IP(VIP)。
2)NodePort(对外露出运用)
在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就能够经过NodeIP:NodePort拜访来拜访该服务。 端口规模:30000~32767
3)LoadBalancer(对外露出运用,适用于公有云)
在NodePort的基础上,借助Cloud Provider创立一个外部负载均衡器,并将恳求转发到NodePort。
4)ExternalName
创立一个dns别名指到service name上,主要是防止service name产生变化,要配合dns插件运用。经过回来 CNAME 和它的值,能够将服务映射到 externalName 字段的内容。这只有 Kubernetes 1.7或更高版别的kube-dns才支撑(我这儿是Kubernetes 1.22.1版别)。
四、Service 作业流程
- 客户端拜访节点时经过 iptables完结的
- iptables规矩是经过 kube-proxy写入的
- apiserver经过监控 kube-proxy去进行对服务和端点的监控
- kube-proxy经过 pod的标签( lables)去判断这个断点信息是否写入到 Endpoints里
五、Endpoints简介
endpoint是k8s集群中的一个资源目标,存储在etcd中,用来记录一个service对应的一切pod的拜访地址。service装备selector,endpoint controller才会主动创立对应的endpoint目标;否则,不会生成endpoint目标。
【例如】k8s集群中创立一个名为hello的service,就会生成一个同名的endpoint目标,ENDPOINTS便是service关联的pod的ip地址和端口。
1)作业流程
一个 Service 由一组 backend Pod 组成。这些 Pod 经过 endpoints 露出出来。 Service Selector 将继续评估,成果被 POST 到一个名称为 Service-hello 的 Endpoint 目标上。 当 Pod 停止后,它会主动从 Endpoint 中移除,新的能够匹配上 Service Selector 的 Pod 将主动地被添加到 Endpoint 中。 检查该 Endpoint,留意到 IP 地址与创立的 Pod 是相同的。现在,能够从集群中恣意节点上运用 curl 命令恳求 hello Service <CLUSTER-IP>:<PORT> 。
2)示例
1、deployment-hello.yaml
$ cat << EOF > deployment-hello.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
spec:
replicas: 3
selector:
matchLabels:
run: hello
template:
metadata:
labels:
run: hello
spec:
containers:
- name: nginx
image: nginx:1.17.1
EOF
2、service-hello.yaml
$ cat << EOF > service-hello.yaml
apiVersion: v1
kind: Service
metadata:
name: service-hello
labels:
name: service-hello
spec:
type: NodePort #这儿代表是NodePort类型的,另外还有ingress,LoadBalancer
ports:
- port: 80
targetPort: 8080
protocol: TCP
nodePort: 31111 # 一切的节点都会开放此端口30000--32767,此端口供外部调用。
selector:
run: hello
EOF
3、检查验证
$ kubectl apply -f deployment-hello.yaml
$ kubectl apply -f service-hello.yaml
# 检查pod,假如本地没有镜像,或许等候的时分比较长,必定要比及一切pod都在运转中才行。
$ kubectl get pod -o wide|grep hello-*
# 检查service
$ kubectl get service service-hello -o wide
# 检查service详情
$ kubectl describe service service-hello
# 检查pointer
$ kubectl get endpoints service-hello
六、Service, Endpoints与Pod的联系
Kube-proxy进程获取每个Service的Endpoints,完结Service的负载均衡功用。
Service的负载均衡转发规矩
拜访Service的恳求,不论是Cluster IP+TargetPort的方法;仍是用Node节点IP+NodePort的方法,都被Node节点的Iptables规矩重定向到Kube-proxy监听Service服务署理端口。kube-proxy接收到Service的拜访恳求后,根据负载战略,转发到后端的Pod。
七、Service的资源清单文件详解
apiVersion: v1
kind: Service
metadata:
#元数据
name: string
#Service名称
namespace: string
#命名空间,不指定时默许为default命名空间
labels:
#自界说标签属性列表
- name: string
annotations:
#自界说注解属性列表
- name: string
spec:
#具体描述
selector: []
#这儿选择器必定要选择容器的标签,也便是pod的标签
#selector:
# app: web
#Label Selector装备,选择具有指定label标签的pod作为办理规模
type: string
#service的类型,指定service的拜访方法,默许ClusterIP
#ClusterIP:虚拟的服务ip地址,用于k8s集群内部的pod拜访,在Node上kube-porxy经过设置的iptables规矩进行转发
#NodePort:运用宿主机端口,能够拜访各Node的外部客户端经过Node的IP和端口就能拜访服务器
#LoadBalancer:运用外部负载均衡器完结到服务器的负载分发,
#需求在spec.status.loadBalancer字段指定外部负载均衡服务器的IP,并同时界说nodePort和clusterIP用于公有云环境。
clusterIP: string
#虚拟服务IP地址,当type=ClusterIP时,如不指定,则系统会主动进行分配,也能够手动指定。当type=loadBalancer,需求指定
sessionAffinity: string
#是否支撑session,可选值为ClietIP,默许值为空
#ClientIP表示将同一个客户端(根据客户端IP地址决定)的拜访恳求都转发到同一个后端Pod
ports:
#service需求露出的端口列表
- name: string
#端口名称
protocol: string
#端口协议,支撑TCP或UDP,默许TCP
port: int
#服务监听的端口号
targetPort: int
#需求转发到后端的端口号
nodePort: int
#当type=NodePort时,指定映射到物理机的端口号
status:
#当type=LoadBalancer时,设置外部负载均衡的地址,用于公有云环境
loadBalancer:
#外部负载均衡器
ingress:
#外部负载均衡器
ip: string
#外部负载均衡器的IP地址
hostname: string
#外部负载均衡器的机主机
八、kubernetes中的四种port
1)nodePort
nodePort是外部拜访k8s集群中service的端口,经过nodeIP: nodePort能够从外部拜访到某个service。
2)port
port是k8s集群内部拜访service的端口,即经过clusterIP: port能够拜访到某个service。
3)targetPort
targetPort是pod的端口,从port和nodePort来的流量经过kube-proxy流入到后端pod的targetPort上,最终进入容器。
4)containerPort
containerPort是pod内部容器的端口,targetPort映射到containerPort。
九、kubernetes服务发现
Kubernetes供给了两种方法进行服务发现, 即环境变量和DNS, 简单说明如下:
1)环境变量
当你创立一个Pod的时分,kubelet会在该Pod中注入集群内一切Service的相关环境变量。
【留意】要想一个Pod中注入某个Service的环境变量,则必须Service要比该Pod先创立。这一点,几乎使得这种方法进行服务发现不行用。比方,一个ServiceName为redis-master的Service,对应的ClusterIP:Port为172.16.50.11:6379,则其对应的环境变量为:
REDIS_MASTER_SERVICE_HOST=172.16.50.11 REDIS_MASTER_SERVICE_PORT=6379 REDIS_MASTER_PORT=tcp://172.16.50.11:6379 REDIS_MASTER_PORT_6379_TCP=tcp://172.16.50.11:6379 REDIS_MASTER_PORT_6379_TCP_PROTO=tcp REDIS_MASTER_PORT_6379_TCP_PORT=6379 REDIS_MASTER_PORT_6379_TCP_ADDR=172.16.50.11
2) DNS
这是k8s官方强烈推荐的方法!!! 能够经过cluster add-on方法轻松的创立KubeDNS来对集群内的Service进行服务发现。
十、Service署理形式
k8s群会集的每个节点都运转一个kube-proxy的组件,kube-proxy其实是一个署理层担任完结service。
Kubernetes v1.2之前默许是userspace,v1.2之后默许是iptables形式,iptables形式功能和可靠性更好,可是iptables形式依靠健康检查,在没有健康检查的情况下假如一个pod不响应,iptables形式不会切换另一个pod上。
1)userspace形式
客户端拜访ServiceIP(clusterIP)恳求会先从用户空间到内核中的iptables,然后回到用户空间kube-proxy,kube-proxy担任署理作业。
缺陷:
可见,userspace这种mode最大的问题是,service的恳求会先从用户空间进入内核iptables,然后再回到用户空间,由kube-proxy完结后端Endpoints的选择和署理作业,这样流量从用户空间进出内核带来的功能损耗是不行承受的。这也是k8s v1.0及之前版别中对kube-proxy质疑最大的一点,因而社区就开始研讨iptables mode。
具体作业流程:
userspace这种形式下,kube-proxy 继续监听 Service 以及 Endpoints 目标的变化;对每个 Service,它都为其在本地节点开放一个端口,作为其服务署理端口;发往该端口的恳求会采用必定的战略转发给与该服务对应的后端 Pod 实体。kube-proxy 同时会在本地节点设置 iptables 规矩,装备一个 Virtual IP,把发往 Virtual IP 的恳求重定向到与该 Virtual IP 对应的服务署理端口上。其作业流程大体如下:
【剖析】该形式恳求在抵达 iptables 进行处理时就会进入内核,而 kube-proxy 监听则是在用户态, 恳求就形成了从用户态到内核态再回来到用户态的传递进程, 必定程度降低了服务功能。
2)iptables形式(默许形式)
该形式彻底利用内核iptables来完结service的署理和LB, 这是K8s在v1.2及之后版别默许形式. 作业原理如下:
iptables mode因为运用iptable NAT来完结转发,也存在不行忽视的功能损耗。另外,假如集群中存在上万的Service/Endpoint,那么Node上的iptables rules将会非常巨大,功能还会再打扣头。这也导致现在大部分企业用k8s上出产时,都不会直接用kube-proxy作为服务署理,而是经过自己开发或许经过Ingress Controller来集成HAProxy, Nginx来替代kube-proxy。
具体作业流程:
iptables 形式与 userspace 相同,kube-proxy 继续监听 Service 以及 Endpoints 目标的变化;但它并不在本地节点敞开反向署理服务,而是把反向署理悉数交给 iptables 来完结;即 iptables 直接将对 VIP 的恳求转发给后端 Pod,经过 iptables 设置转发战略。其作业流程大体如下:
【剖析】 该形式比较 userspace 形式,克服了恳求在用户态-内核态反复传递的问题,功能上有所提升,但运用 iptables NAT 来完结转发,存在不行忽视的功能损耗,并且在大规模场景下,iptables 规矩的条目会非常巨大,功能上还要再打扣头。
示例:
cat << EOF > mysql-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
name: mysql
role: service
name: mysql-service
spec:
ports:
- port: 3306
targetPort: 3306
nodePort: 30964
type: NodePort
selector:
mysql-service: "true"
name: mysql
EOF
$ kubectl apply -f mysql-service.yaml
$ kubectl get svc
3)ipvs模型
在kubernetes 1.8以上的版别中,关于kube-proxy组件增加了除iptables形式和用户形式之外还支撑ipvs形式。kube-proxy ipvs 是根据 NAT 完结的,经过ipvs的NAT形式,对拜访k8s service的恳求进行虚IP到POD IP的转发。当创立一个 service 后,kubernetes 会在每个节点上创立一个网卡,同时帮你将 Service IP(VIP) 绑定上,此时相当于每个 Node 都是一个 ds,而其他任何 Node 上的 Pod,甚至是宿主机服务(比方 kube-apiserver 的 6443)都或许成为 rs;
具体作业流程:
与iptables、userspace 形式相同,kube-proxy 依然监听Service以及Endpoints目标的变化, 不过它并不创立反向署理, 也不创立很多的 iptables 规矩, 而是经过netlink 创立ipvs规矩,并运用k8s Service与Endpoints信息,对地点节点的ipvs规矩进行定期同步; netlink 与 iptables 底层都是根据 netfilter 钩子,可是 netlink 由于采用了 hash table 并且直接作业在内核态,在功能上比 iptables 更优。其作业流程大体如下:
【剖析】ipvs 是现在 kube-proxy 所支撑的最新署理形式,比较运用 iptables,运用 ipvs 具有更高的功能。
4)kube-proxy装备 ipvs形式(一切节点)
1、加载ip_vs相关内核模块
$ modprobe -- ip_vs
$ modprobe -- ip_vs_sh
$ modprobe -- ip_vs_rr
$ modprobe -- ip_vs_wrr
$ modprobe -- nf_conntrack_ipv4
一切节点验证敞开了ipvs:
$ lsmod |grep ip_vs
2、装置ipvsadm工具
$ yum install ipset ipvsadm -y
3、编辑kube-proxy装备文件,mode修改成ipvs
$ kubectl edit configmap -n kube-system kube-proxy
4、重启kube-proxy 先检查之前的kube-proxy
$ kubectl get pod -n kube-system | grep kube-proxy
删掉上面三个kube-proxy,重新拉起新的服务
$ kubectl get pod -n kube-system | grep kube-proxy |awk '{system("kubectl delete pod "$1" -n kube-system")}'
再检查
$ kubectl get pod -n kube-system | grep kube-proxy
5、检查
$ ipvsadm -Ln
关于Kubernetes(k8s)kube-proxy、Service的介绍,就先到这儿了,有疑问的小伙伴,欢迎给我留言哦~