Service四层代理详解
K8S在创建Service时,会根据**标签选择器(Label Selector)**来查找对应的Pod,据此创建与Service同名的endpoint对象,当Pod地址发生变化时,Endpoint也会随之发生变化,Service接收前端Client请求的时候,就会通过Endpoint,找到转发到哪个Pod进行访问的地址(至于转发到哪个节点的Pod,由负载均衡Kube-proxy决定)。
目录
Service是一个固定接入层,客户端可以通过访问 Service ip和端口访问到Service所关联的后端Pod。Service 工作依赖于在Kubernetes集群之上部署的一个附件,就是Kubernetes的Dns,服务(不同Kubernetes版本的Dns默认使用的也是不一样的,1.11之前的版本使用的是KubeDNS,较新的版本使用的是Coredns),Service的名称解析是依赖于Coredns.附件的,因此在部署完K8S之后需要部署Dns附件,Kubernetes,要想给客户端提供网络功能,需要依赖第三方的网络插件(Flannel,Calico等)。 每个K8S节点上都有一个组件叫做Kube-proxy,Kube-proxy需要跟Master之上的ApiServer交互,随时连接到ApiServer获取任何一个与Service资源相关的资源变动状态,这种是通过Kubernetes.中固有的一种请求方法 Watch(监视)来实现的,一旦有Service资源的内容发生变动(如创建,删除),Kube-proxy都会将它转化成当前节点之上的能够实现Service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是lptables,也可能是ipvs,取决于Service 的部署实现方式。
K8S在创建Service时,会根据标签选择器(Label Selector)来查找对应的Pod,据此创建与Service同名的endpoint对象,当Pod地址发生变化时,Endpoint也会随之发生变化,Service接收前端Client请求的时候,就会通过Endpoint,找到转发到哪个Pod进行访问的地址(至于转发到哪个节点的Pod,由负载均衡Kube-proxy决定)。
总结:
1、Service通过 Label Selector查找指定的Pod
2、Service通过endpoint来获取Pod地址列表;
3、Service通过CoreDNS实现名称解析;
4、Service通过 Kube-Proxy实现Pod 的代理;
5、Kube-Proxy通过IPVS或者iptables实现负载均衡
1.Service类型
有四种类型: ClusterIP ,NodePort ,ExternalName , LoadBalancer
1.1 ExternalName
适用于k8s集群内部容器访问外部资源,它没有selector,也没有定义任何的端口和Endpoint。
Service定义的是将Prod名称空间中的my-service服务映射到my.database.example.com
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
当查询主机 my-service.prod.svc.cluster.local时﹐群集DNS 将返回值为 my.database.example.com 的CNAME记录。
Service的 FQDN是:<service_name>.<namespace>.suc.cluster.local
1.2 ClusterIP
通过K8S集群内部IР暴露服务,通过该类型服务只能够集群内通信,这也是默认的ServiceType。
1.3 NodePort
通过每个Node节点上的IP和静态端口暴露K8S集群内部的服务。通过请求<NodelP>:<NodePort>可以把请求代理到内部的Pod。
访问流程:Client --> NodelP:NodePort --> Service lp:ServicePort --> PodlP:ContainerPort。
1.4、LoadBalancer
使用云提供商的负载均衡器(阿里云SLB/腾讯云ELB),可以向外部暴露服务。外部的负载均衡器可以路由到NodePort服务和ClusterlP服务。
elinks --dump 172.16.104.18
Service可以对外提供统一固定的ip地址,并将请求重定向至集群中的pod。其中“将请求重定向至集群中的pod”就是通过endpoint 与selector协同工作实现。selector是用于选择pod,由selector选择出来的pod的 ip.地址和端口号,将会被记录在endpoint中。 endpoint 便记录了所有pod 的ip.地址和端口号。当一个请求访问到service的ip.地址时,就会从endpoint中选择出一个ip地址和端口号,然后将请求重定向至pod中。具体把请求代理到哪个pod,需要的就是kube-proxy的轮询实现的。service不会直接到pod,service是直接到endpoint资源,就是地址加端口,再由endpoint再关联到pod。 service只要创建完成,我们就可以直接解析它的服务名,每一个服务创建完成后都会在集群dns.中动态添加一个资源记录,添加完成后我们就可以解析了,资源记录格式是:sVC_NAME.NS_NAME.DOMAIN.LTD. 服务名.命名空间.域名后缀
nodeport案例
apiVersion: v1
kind: Service
metadata:
name: dream-svc
labels:
run: dream-deployment
spec:
type: NodePort
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: dream-deployment
服务请求走向:Client node ip:30380 -service ip:80 -> pod ip:container port
Client >192.168.200.111:30380 →10.102.109.111:80 ->pod ip:80
Externalname案例:
vim client.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: client
spec:
replicas: 3
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","sleep 36000"]
vim clint-server.yaml
apiVersion: v1
kind: Service
metadata:
name: clint-service
spec:
type: ExternalName
externalName: nginx-dreamsrv.nginx-namedr.svc.cluster.local
ports:
- name: http
port: 80
targetPort: 80
kubectl create ns nginx-namedr
vim nginx-1212.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-1212
namespace: nginx-namedr
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21.5
imagePullPolicy: IfNotPresent
vim nginx-1212-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-dreamsrv
namespace: nginx-namedr
spec:
selector:
app: nginx
ports:
- name: hhtp
protocol: TCP
port: 80
targetPort: 80
这样配置 client里的pod 可以通过externalname这个类型进行访问到nginx-1212的pod
externalName: nginx-dreamsrv.nginx-namedr.svc.cluster.local svc.cluster.local这个格式是固定不变的
并且pod nginx-1212的service的名字是nginx-dreamsrv nginx-1212的namespace是nginx-namedr
映射外部服务案例
k8s集群引用外部的mariadb 数据库
在node1上安装mariadb数据库
在master上写service和endpoint两条yaml
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
type: ClusterIP
ports:
- port: 3306
apiVersion: v1
kind: Endpoints
metadata:
name: mysql
subsets:
- addresses:
- ip: 192.168.120.102
ports:
- port: 3306
然后在node1 节点登陆mysql mysql -uroot -h 10.97.56.178 这个ip地址用的是service里面的
然后给master授权给权限: grant all on . to root@'192.168.120.10_' identified by '123456'; flush privillges;
然后再master节点进入 mysql -uroot -p123456 -h 10.97.56.178
然后把service的类型改为nodeport
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
type: NodePort
ports:
- port: 3306
nodePort: 30388
然后就可以再windos的mysql数据库通过连接30388端口
更多推荐
所有评论(0)