Roy学Kubernetes(8):Kubernetes之Service
Service是Kubernetes中的关键对象,Kubernetes将运行在一组pod上的应用程序公开为网络服务的抽象方法。为应用程序实现自动化的服务发现,为Pods提供了自己的IP地址和一组Pod的单个DNS名称,并且可以在它们之间进行负载均衡。
Service的由来
Kubernetes Pod是有生命周期的,如果使用Deployment来部署,Pod都是动态生成和删除的。也就是说,每个Pod的很多状态都是动态的,例如IP。这样会导致一个问题:如果某些Pod(后端)为集群内的其他Pod(前端)提供功能,前端如何找出并跟踪要连接的后端IP地址 ,以便前端可以接受请求工作并负载到后端?因此,Service诞生了。它就是来满足这类场景需求的Kubernetes对象,帮助前端和后端实现解耦。
Service虚拟IP模式
Kubernetes集群中的每个节点都运行一个kube-proxy。 kube-proxy负责为ExternalName以外的类型的Service实现虚拟IP。实现虚拟IP有以下三种模式:
- User space proxy mode:>= Kubernetes v1.0
- iptables proxy mode:>= Kubernetes v1.1 Kubernetes v1.2为默认模式
- IPVS proxy mode:>= Kubernetes v1.8
想了解实现原理,见这里
配置Service
创建一个Service示例:
my-service.yaml
1 | apiVersion: v1 |
Kubernetes为该Service分配一个IP地址(有时称为Cluster IP),由Servcie代理使用。Servcie选择器的控制器不断扫描与其selector匹配的Pod,然后对名为“my-service”的Endpoint对象进行更新。Servcie的默认协议是TCP; 你还可以使用任何其他支持的协议。由于许多Servcie需要公开多个端口,因此Kubernetes支持Service对象上的多个端口定义。 每个端口定义的协议也可不同。
配置不带selectors选择器的Service
如下场景可能会用到:
- Service配置使用外部数据库集群
- 将服务指向其他命名空间或其他群集上的服务。
- 将业务迁移至Kubernetes。 为了评估及验证,你只在Kubernetes中运行一部分后端,另一部分通过Service指向你原来的后端上。
由于此服务没有选择器,因此不会自动创建相应的Endpoint对象。 你可以手动添加Endpoint对象,手动将服务映射到运行它的网络地址和端口:
1 | apiVersion: v1 |
注意:端点IP不能是:loopback(IPv4为127.0.0.0/8,IPv6为::1/128),或本地链路(IPv4为169.254.0.0/16和224.0.0.0/24,IPv6为fe80::/64)。端点IP地址也不能是其他Kubernetes服务的群集IP,因为kube-proxy不支持虚拟IP作为目标。
ExternalName服务是Service的一个特例,它没有选择器而是使用DNS名称。 有关详细信息,请参阅ExternalName部分。
由上我们可以理解,在不配置selectors的情况下,Service类似一个负载均衡器,我们可以灵活的用它来自定义集成k8s内部或外部的后端应用服务。
配置多端口Service
某些服务,你想公开多个端口,Service支持这类配置需求。
1 | apiVersion: v1 |
注意:端口名称只能包含小写字母、数字字符和-,且以字母、数字字符开头和结尾。
可设置.spec.clusterIP字段指定自己的群集IP地址。 例如,你已经拥有要重用的现有DNS记录,或者为保留旧的特定IP地址配置。配置的IP地址必须是为API服务器配置的service-cluster-ip-range CIDR范围内的有效IPv4或IPv6地址。 如果使用无效的clusterIP地址值创建Servcie,API服务器将返回422的HTTP错误返回码。
服务发现
Kubernetes支持2种主要的服务发现模式 - 环境变量和DNS
环境变量方式
当Pod在节点上运行时,kubelet为每个活动服务添加一组环境变量。 它支持Docker链接兼容变量(请参阅makeLinkVariables)和更简单的{SVCNAME} _SERVICE_HOST和{SVCNAME} _SERVICE_PORT变量,其中服务名称为大写,短横线转换为下划线。
例如,为暴露TCP端口6379并已分配群集IP地址为10.0.0.11的名为redis-master的service生成以下环境变量:
1 | REDIS_MASTER_SERVICE_HOST=10.0.0.11 |
如果你有一个需要访问服务的Pod,并且正在使用环境变量方法将端口和Cluster IP发布到客户端Pod,则必须在客户端Pod存在之前创建Service。否则,这些客户端Pod将不会更新其环境变量。如果仅使用DNS来发现服务的Cluster IP,则无需担心此问题。
DNS方式
Kubernetes集群是通过插件方式配置DNS服务,插件详见。
DNS服务器(如CoreDNS)会监视Kubernetes API以获取新服务,并为每个服务创建一组DNS记录。 所有Pod应自动通过此DNS解析名称服务。
例如,如果在Kubernetes命名空间“my-ns”中有一个名为“my-service”的服务,则DNS服务会创建“my-service.my-ns”的DNS记录。 “my-ns”命名空间中的Pod应该能够通过简单地为my-service执行名称查找来找到它(“my-service.my-ns”也可以工作)。其他命名空间中的Pod必须将名称限定为my-service.my-ns。 这些名称将解析为Service分配的Cluster IP。
Kubernetes还支持命名端口的DNS SRV(服务)记录。 如果“my-service.my-ns”1服务具有名为“http”且协议设置为TCP的端口,则可以对_http._tcp.my-service.my-ns执行DNS SRV查询以发现端口号 “http”,及其IP地址。
Kubernetes DNS服务器是访问ExternalName服务的唯一方法。
Headless Services
Headless Services即无头服务,有时你不需要负载均衡和Cluster IP。 在这种情况下,你可以通过设置群集IP(.spec.clusterIP)为“None”来创建无头服务。
无头服务未分配Cluster IP,所以kube-proxy不会处理这些服务,且Kubernetes没有为它们分配负载平衡或代理。 如何自动配置DNS取决于服务是否已定义selector选择器。
- 配置selector:Endpoint控制器会在API中创建Endpoints记录,并且修改DNS配置对应的A记录地址,访问这个地址可直达Service后端的Pod上
- 不配置selector:Endpoint控制器不会创建Endpoints记录,但DNS系统仍会查寻和配置ExternalName类型的CNAME记录、以及与Service共享一个名称的任何Endpoints
对于配置的selector的无头服务,Servie的名称会被DNS轮循解释到后端的Pod上,且每个Pod在DNS上都有对应的记录,且每个PDd的DNS域名是有规律且不变的(pod_name-id.service_name,其中id编号是从0开始递增的数字),这种特性特别适合我们在Kubernetes中创建有状态的服务(例如rabbitmq集群)。
发布Service
Service可能发布时可选择多种类型,按场景和业务需求来选择。配置ServiceTypes来指定你想要发布的Service类型,默认是ClusterIP。ServiceTypes支持的类型如下:
- ClusterIP:通过集群的内部IP暴露服务,服务只能够在集群内部可以访问,这也是默认的ServiceType。
- NodePort:通过每个k8s节点上的IP和静态端口(NodePort)暴露服务。NodePort服务会路由到ClusterIP的服务,这个ClusterIP服务会自动创建。通过请求
: ,可以从集群的外部访问一个NodePort服务。 - LoadBalancer:使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到NodePort服务和ClusterIP服务。
- ExternalName:通过返回CNAME值,将服务映射到externalName的字段内容,例如,foo.bar.example.com。不会创建任何代理,需要Kubernetes 1.7或更高版本的kube-dns支持。
- 本文链接:http://www.whyvv.top/k8s8.html
- 版权声明:版权所有,转载请注明出处。
分享