Kubernetes Service
标签及标签选择器是什么,如何使用
标签是键值对类型,标签可以附加到任何资源对象上,主要用于管理对象,查询和筛选。
标签常被用于标签选择器的匹配度检查,从而完成资源筛选;一个资源可以定义一个或多个标签在其上面。
标签选择器,标签要与标签选择器结合在一起,标签选择器允许我们选择标记有特定标签的资源对象子集,如pod,并对这些特定标签的pod进行查询,删除等操作。
标签和标签选择器最重要的使用之一在于,在deployment中,在pod模板中定义pod的标签,然后在deployment定义标签选择器,这样就通过标签选择器来选择哪些pod是受其控制的,service也是通过标签选择器来关联哪些pod最后其服务后端pod。
service是如何与pod关联的
答案是通过标签选择器,每一个由deployment创建的pod都带有标签,这样,service就可以定义标签选择器来关联哪些pod是作为其后端了,就是这样,service就与pod管联在一起了。
service的域名解析格式、pod的域名解析格式
service的DNS域名表示格式为<servicename>.<namespace>.svc.<clusterdomain>
,
servicename是service的名称,namespace是service所处的命名空间,clusterdomain是k8s集群设置的域名后缀,一般默认为 cluster.local
pod的DNS域名格式为:<pod-ip>.<namespace>.pod.<clusterdomain>
,
其中,pod-ip需要使用-将ip直接的点替换掉,namespace为pod所在的命名空间,clusterdomain是k8s集群设置的域名后缀,一般默认为 cluster.local ,
演示如下:10-244-1-223.default.pod.cluster.local
对于deployment、daemonsets等创建的pod,还还可以通过<pod-ip>.<deployment-name>.<namespace>.svc.<clusterdomain>
这样的域名访问。
service的类型有哪几种
service的类型一般有4中,分别是:
-
ClusterIP:表示service仅供集群内部使用,默认值就是ClusterIP类型
-
NodePort:表示service可以对外访问应用,会在每个节点上暴露一个端口,这样外部浏览器访问地址为:任意节点的IP:NodePort就能连上service了
-
LoadBalancer:表示service对外访问应用,这种类型的service是公有云环境下的service,此模式需要外部云厂商的支持,需要有一个公网IP地址
-
ExternalName:这种类型的service会把集群外部的服务引入集群内部,这样集群内直接访问service就可以间接的使用集群外部服务了
一般情况下,service都是ClusterIP类型的,通过ingress接入的外部流量。
Pod到Service的通信
(1)k8s在创建服务时为服务分配一个虚拟IP,客户端通过该IP访问服务,服务则负责将请求转发到后端Pod上;
(2)Service是通过kube-proxy服务进程实现,该进程在每个Node上均运行可以看作一个透明代理兼负载均衡器;
(3)对每个TCP类型Service,kube-proxy都会在本地Node上建立一个SocketServer来负责接受请求,然后均匀发送到后端Pod默认采用Round Robin负载均衡算法;
(4)Service的Cluster IP与NodePort等概念是kube-proxy通过Iptables的NAT转换实现,kube-proxy进程动态创建与Service相关的Iptables规则;
(5)kube-proxy通过查询和监听API Server中Service与Endpoints的变化来实现其主要功能,包括为新创建的Service打开一个本地代理对象,接收请求针对发生变化的Service列表,kube-proxy会逐个处理;
一个应用pod是如何发现service的,或者说,pod里面的容器用于是如何连接service的
1、环境变量:
当pod被创建之后,k8s系统会自动为容器注入集群内有效的service名称和端口号等信息为环境变量的形式,
这样容器应用直接通过取环境变量值就能访问service了,
如curl http://${WEBAPP_SERVICE_HOST}:{WEBAPP_SERVICE_PORT}
2、DNS方式:
使用dns域名解析的前提是k8s集群内有DNS域名解析服务器,
默认k8s中会有一个CoreDNS作为k8s集群的默认DNS服务器提供域名解析服务器;
service的DNS域名表示格式为<servicename>.<namespace>.svc.<clusterdomain>
,
servicename是service的名称,namespace是service所处的命名空间,clusterdomain是k8s集群设置的域名后缀,一般默认为 cluster.local ,
这样容器应用直接通过service域名就能访问service了,
如wget http://svc-deployment-nginx.default.svc.cluster.local:80
,
另外,service的port端口如果定义了名称,那么port也可以通过DNS进行解析,
格式为:_<portname>._<protocol>.<servicename>.<namespace>.svc.<clusterdomain>
如何创建一个service代理外部的服务,或者换句话来说,在k8s集群内的应用如何访问外部的服务,如数据库服务,缓存服务等
可以通过创建一个没有标签选择器的service来代理集群外部的服务。
1、创建service时不指定selector标签选择器,但需要指定service的port端口、端口的name、端口协议等,这样创建出来的service因为没有指定标签选择器就不会自动创建endpoint;
2、手动创建一个与service同名的endpoint,endpoint中定义外部服务的IP和端口,endpoint的名称一定要与service的名称一样,端口协议也要一样,端口的name也要与service的端口的name一样,不然endpoint不能与service进行关联。
完成以上两步,k8s会自动将service和同名的endpoint进行关联,
这样,k8s集群内的应用服务直接访问这个service就可以相当于访问外部的服务了。
service、endpoint、kube-proxys三种的关系是什么
service:
在kubernetes中,service是一种为一组功能相同的pod提供单一不变的接入点的资源。
当service被建立时,service的IP和端口不会改变,这样外部的客户端(也可以是集群内部的客户端)通过service的IP和端口来建立链接,这些链接会被路由到提供该服务的任意一个pod上。
通过这样的方式,客户端不需要知道每个单独提供服务的pod地址,这样pod就可以在集群中随时被创建或销毁。
endpoint:
service维护一个叫endpoint的资源列表,endpoint资源对象保存着service关联的pod的ip和端口。
从表面上看,当pod消失,service会在endpoint列表中剔除pod,当有新的pod加入,service就会将pod ip加入endpoint列表;
但是正在底层的逻辑是,endpoint的这种自动剔除、添加、更新pod的地址其实底层是由endpoint controller
控制的,endpoint controller
负责监听service和对应的pod副本的变化,如果监听到service被删除,则删除和该service同名的endpoint对象,如果监听到新的service被创建或者修改,则根据该service信息获取得相关pod列表,然后创建或更新service对应的endpoint对象,如果监听到pod事件,则更新它所对应的service的endpoint对象。
kube-proxy:
kube-proxy运行在node节点上,在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作,
kube-proxy
会监听api-server
中从而获取service和endpoint的变化情况,创建并维护路由规则以提供服务IP和负载均衡功能。
简单理解此进程是Service的透明代理兼负载均衡器,其核心功能是将到某个Service的访问请求转发到后端的多个Pod实例上。
无头service和普通的service有什么区别,无头service使用场景是什么
无头service没有cluster ip,在定义service时将 service.spec.clusterIP:None
,就表示创建的是无头service。
普通的service是用于为一组后端pod提供请求连接的负载均衡,让客户端能通过固定的service ip地址来访问pod,这类的pod是没有状态的,同时service还具有负载均衡和服务发现的功能。普通service跟我们平时使用的nginx反向代理很相识。
试想这样一种情况,有6个redis pod ,它们相互之间要通信并要组成一个redis集群,
不需要所谓的service负载均衡,这时无头service就是派上用场了,
无头service由于没有cluster ip,kube-proxy就不会处理它也就不会对它生成规则负载均衡,无头service直接绑定的是pod 的ip。无头service仍会有标签选择器,有标签选择器就会有endpoint资源。
无头service使用场景:
无头service一般用于有状态的应用场景,如Kaka集群、Redis集群等,这类pod之间需要相互通信相互组成集群,不在需要所谓的service负载均衡。