一,Service介绍
-
四层代理是基于传输层(第四层)工作的代理,主要在传输层(如TCP、UDP协议)上转发和管理数据流
-
七层代理是基于应用层(第七层)工作的代理,能够对应用层协议(如HTTP、SMTP)进行解析和处理。
Service是四层代理网络,基于IP和端口对数据进行转发和负载均衡
1,概述
因为Pod重启,重建时,它的IP很有可能会发生变化。因此在kubernetes中定义了service资源对象,Service 定义了一个服务访问的入口,客户端通过这个入口即可访问服务背后的应用集群实例。
Service是一个固定接入层,客户端可以通过访问service的ip和端口,访问到service关联的后端pod,这个service工作依赖于在kubernetes集群之上部署的一个附件,就是kubernetes的dns服务
(不同kubernetes版本的dns默认使用的也是不一样的,1.11之前的版本使用的是kubeDNs,较新的版本使用的是coredns),
service的名称解析是依赖于dns附件的,因此在部署完k8s之后,需要再部署dns附件,kubernetes要想给客户端提供网络功能,需要依赖第三方的网络插件(flannel,calico等)。
每个K8s节点上都有一个组件叫做kube-proxy,kube-proxy这个组件将始终监视着apiserver中有关service资源的变动信息,需要跟master之上的apiserver交互,随时连接到apiserver上获取任何一个与service资源相关的资源变动状态,这种是通过kubernetes中固有的一种请求方法watch(监视)来实现的,一旦有service资源的内容发生变动(如创建,删除),kube-proxy都会将它转化成当前节点之上的能够实现service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是iptables,也可能是ipvs,取决于service的实现方式。
2,工作原理
k8s在创建Service时,会根据标签选择器selector(lable selector)来查找Pod,据此创建与Service同名的endpoint对象,当Pod 地址发生变化时,endpoint也会随之发生变化,service接收前端client请求的时候,就会通过endpoint,找到转发到哪个Pod进行访问的地址。(至于转发到哪个节点的Pod,由负载均衡kube-proxy决定)
3,k8s中有三类IP地址
- 1、Node Network(节点网络):物理节点或者虚拟节点的网络,如ens33接口上的网路地址。
- 2、Pod network(pod 网络),创建的Pod具有的IP地址。
- 3、Cluster Network(集群地址,也称为service network),这个地址是虚拟的地址(virtual ip),没有配置在某个接口上,只是出现在service的规则当中。
4,常用字段介绍
kubectl explain Service[svc]
# kubectl explain serviceapiVersion <string> #service资源使用的api组[版本]
kind <string> #创建的资源类型
metadata <Object> #定义元数据
spec <Object>
# kubectl explain service.specclusterIP <string> # 动态分配的地址,也可以自己在创建的时候指定,创建之后就改不了了
ports <[]Object> # 定义service端口,用来和后端pod建立联系
selector <map[string]string> # 通过标签选择器选择关联的pod有哪些
sessionAffinityConfig <Object>
# service在实现负载均衡的时候还支持sessionAffinity,
# sessionAffinity什么意思?会话联系,默认是none,随机调度的(基于iptables规则调度的)。如果我们定义sessionAffinity的client ip,那就表示把来自同一客户端的IP请求调度到同一个pod上。
type <string> # 定义service的类型 ExternalName, ClusterIP(默认), NodePort, LoadBalancer.
# kubectl explain service.spec.typeExternalName
ClusterIP
NodePort
LoadBalancer # 下面详细介绍
# kubectl explain service.spec.portsname <string> # 定义端口的名字
nodePort <integer> # service在物理机映射的端口,默认在 30000-32767 之间
port <integer> -required- #service的端口,这个是k8s集群内部服务可访问的端口
targetPort <string> # targetPort是pod上的端口,从port和nodePort上来的流量,经过kube-proxy流入到后端pod的targetPort上,最后进入容器。
二,Service四种类型
1,ClusterIP类型
通过集群的内部 IP 公开 Service,选择该值时 Service 只能够在集群内部访问。 这也是你没有为 Service 指定 type 时使用的默认值。
你可以使用 Ingress 或者 Gateway API 向公共互联网公开服务。
创建的pod生成的ip地址,被关联的service生成的endpoints资源管理。
说明:
- k8s集群内的机器或pod,都能访问此service代理的ip或域名;机器外部是不能访问的。
- 域名格式:
[service名.命名空间名.svc.cluster.local]
2,NodePort类型
通过每个节点上的 IP 和静态端口(NodePort)公开 Service。 为了让 Service 可通过节点端口访问,Kubernetes 会为 Service 配置集群 IP 地址, 相当于你请求了 type: ClusterIP 的 Service。
宿主机(物理机)的ip+ 映射端口(30380) 可以直接访问到集群内部pod内容。
客户端请求http://192.168.40.180:30380 - > docker0虚拟网卡:172.17.0.1:30380 -> 10.244.186.236:80,10.244.140.90:80
3,ExternalName类型
将服务映射到 externalName 字段的内容(例如,映射到主机名 api.foo.bar.example)。 该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 CNAME 记录。 集群不会为之创建任何类型代理。
应用场景:**跨名称空间访问**。 例如:default名称空间下的client 服务,去访问nginx-ns名称空间下的nginx-svc服务。
4,LoadBalancer类型
使用云平台的负载均衡器向外部公开 Service。Kubernetes 不直接提供负载均衡组件; 你必须提供一个,或者将你的 Kubernetes 集群与某个云平台集成。
三,Service案例参考
场景:k8s集群引用外部的mysql数据库
【理解】:
Service 在创建时,通过定义“spec.selector”选择器,选择指定标签的pod,从而生成对应的Endpoints资源,来管理选择的pod的ip地址。
现在,我们生成service的时候,不定义“spec.selector”选择器,而是通过定义Endpoints的yaml资源,指定名称和Service名称相同,即可实现关联。与此同时,定义“subsets.addresses.ip和ports”为外部机器的ip和端口,即可实现k8s集群引用外部的服务(如:mysql数据库等)
【操作】
第一步:在node02上安装mysql数据库:
yum install mariadb-server.x86_64 -y
systemctl start mariadb
# 安装完后,直接输入 mysql 进入终端
第二步:在master上,创建service:
因为没定义“spec.selector”选择器,没有选择pod,所以Endpoint 值为none
#cat mysql_service.yaml apiVersion: v1
kind: Service
metadata:name: mysql
spec:type: ClusterIPports:- port: 3306
通过命令,再次验证没有创建对应的Endpoints资源:
kubectl get ep[Endpoints]
第三步:在master上,直接创建Endpoint资源:
metadata.name的名字,必须对应特定关联的Service的名称相同。
# cat endpoint.yaml apiVersion: v1
kind: Endpoints
metadata:name: mysql # 必须对应特定关联的Service的名称
subsets:
- addresses:- ip: 192.168.40.182 # 注册的ip地址ports:- port: 3306 # 注册的端口
此时,集群可以直接访问外部node02的集群外部服务。
四,CoreDNS
DNS全称是Domain Name System:域名系统,是整个互联网的电话簿。
其实就是一个 DNS 服务,“ 可被人理解的域名 ”翻译成“ 可被机器理解IP地址 ”。
在k8s中创建service之后,service默认的FQDN是:
<service name>.<name space>.svc.cluster.local
。