背景
下面我将以这个思维导图来总结一下service。
简介
由于pod会重建,所以通过pod的ip来访问服务是不可靠的,这时就需要通过service来访问服务。
k get svc wordpress -n wordpress -o yaml
可以看到service的spec中重要的组成部分是:
- selector
k8s 允许将 pod 对象通过标签 (Label)进行标记,并通过 selector 定义基于 pod 标签的过滤规则,选择带这个label的一组pod。
- ports
Ports 属性中定义了负载均衡规则,包括服务的端口、协议,目标端口等。service在4层提供服务。
endpoint对象
endpoint关联了svc和pod。
- 当 Service 的 selector 不为空时,Kubernetes Endpoint Controller 会侦听服务创建事件,创建与Service 同名的 Endpoint 对象。
可以看到svc和ep的name都是wordpress。ep的ip是pod的ip,port是svc的port。
- Selector 能够选取的所有 pod-ip 都会被配置到addresses 属性中.
- 如果此时 selector 所对应的 filter 查询不到对应的pod,则 addresses 列表为空。
- 默认配置下,如果此时对应的pod为not ready状态,则对应的 PodiP 只会出现在subsets的notReadyAddresses 属性中,这意味着对应的pod还没准备好提供服务,不能作为流量转发的目标。
- 如果设置了 PublishNotReadyAdddress 为 true,则无论 pod 是否就绪都会被加入 readyAddress list。
endpointSlice对象
endpointSlice对象的出现是为了性能优化。
- 当某个service对应的backend pod较多时,endpoint对象就会因保存的地址信息过多而变得异常庞大。
- pod状态的变更会引起endpoint的变更,endpoint的变更会被推送至所有节点,从而导致持续占用大量网络带宽。
- 用于对pod较多的endpoint进行切片,切片大小可以自定义。这样当pod的ip发生变化时,只需要变动这个ip的endpointSlice,就不用推送全部了。
不定义selector的svc
用户创建svc但不定义selector:
- Endpoint Controller 不会为该service自动创建endpoint。
- 用户可以手动创建endpoint对象,并设置任意ip地址到 Address 属性。
- 访问该服务的请求会被转发至目标地址。
比如需要访问集群外部的机器,可以创建一个不带selector的svc,然后再手动创建一个endpoint,配置外部机器的ip地址到address中,这样访问外部机器的请求就会通过kube-proxy转发出去。
Service、 Endpoint 和 Pod 的对应关系
- service通过endpoint实现一对多pod。
- endpoint中subsets的addresses,notReadyAddresses属性把pod的ip和endpoint关联起来。
- service的port就是endpoint中的port。
- service启动的时候,apiserver通过- –service-cluster-ip-range=10.96.0.0/16配置给svc分配一个clusterip。
- 通过svc的clusterip实现负载均衡。就是把clusterip当成虚ip。
- 通过负载均衡器,把请求转发到pod中,port就是service中的targetport。
service的类型
clusterlp
- Service 的默认类型,服务被发布至仅集群内部可见的虚拟1P 地址上。
- 在API Server 启动时,需要通过 service-cluster-ip-range 参数配置虚拟IP地址段,API Server 中有用于分配IP地址和端口的组件,当该组件捕获 Service 对象并创建事件时,会从配置的虚拟 IP 地址段中取一个有效的 IP 地址,分配给该 Service 对象。
nodePort
- 在 API Server 启动时,需要通过 node-port-range 参数配置 nodePort 的范围,同样的,API Server 组件会捕获Service 对象并创建事件,即从配置好的 nodePort 范围取一个有效端口,分配给该 Service。这个可以修改,默认是30000-32768。
- 每个节点的 kube-proxy 会监听这个端口,并转发给服务对应的后端 Pod 实例。
LoadBalancer
- 企业数据中心一般会采购一些负载均衡器,作为外网请求进入数据中心内部的统一流量入口。
- 针对不同的基础架构云平台,Kubernertes Cloud Manager 提供支持不同供应商 API 的 Service Controller。 如果需要在 Openstack 云平台上搭建 Kubernetes 集群,那么只需提供一份openstack.rc, Openstack ServiceController 即可通过调用 LBaaS API完成负载均衡配置。
Headless Service
- Headless 服务是用户将 clusteriP 显示定义为 None 的服务。
- 无头的服务意味着 Kubernetes 不会为该服务分配统一入口,包括 clusteriP, nodePort 等。服务发现是基于dns。
ExternalName Service
为一个服务创建别名。dns中就是cname。比如要访问谷歌,把集群内部的一个service设置成ExternalName,指定谷歌地址即可。
Service Topology
- 一个网络调用的延迟受客户端和服务器所处位置的影响,两者是否在同一节点、同一机架、同一可用区、同一数据中心,都会影响参与数据传输的设备数量。a服务访问b服务,肯定是本地调用效率最高的。
- 在分布式系统中,为保证系统的高可用,往往需要控制应用的错误域(Failure Domain),比如通过反亲和性配置,将一个应用的多个副本部署在不同机架,甚至不同的数据中心。
- Kubernetes 提供通用标签来标记节点所处的物理位置。比如:
topology.kubernetes.io/zone: hanzghou-west2-a failure-domain.beta.kubernetes.io/region: hangzhou-west failure-domain.tess.io/network-device: hangzhou-west05-ra053 failure-domain.tess.io/rack: hangzhou_west02_02-314_19_12 kubernetes.io/hostname: node-1
- Service 引入了 topologykeys 属性,可以通过如下设置来控制流量:
- 当 topologykKeys 设置为 ["kubernetes.io/hostname"]时,调用服务的客户端所在节点上如果有pod正在运行,则该实例处理请求,否则,调用失败。
- 当 topologykeys 设置为[ “kubernetes.io/hostname", "topology.kubernetes.io/zone","topology. kubernetes.io/region〞」时,若同一节点有对应的pod,则请求会优先转发至该pod。否则,顺序查找当前zone及当前region是否有pod,并将请求按顺序转发。
- 当 topologyKeys 设置为[ “topology.kubernetes.io/ zone",*"]时,请求会被优先转发至当前zone的pod。如果当前zone不存在pod,则请求会被转发至任意pod。
- 当 topologykKeys 设置为 ["kubernetes.io/hostname"]时,调用服务的客户端所在节点上如果有pod正在运行,则该实例处理请求,否则,调用失败。