Kubernetes V1.17拓扑感知服务路由
还是那句话,当你觉得什么多做不了的时候,你一定比以往更渴望成功!Kubernetes 1.17 新特性K8S 更新的速度之快,至于使用感知设计不是很深,未实际环境使用。那就一起来看下吧:v1.17 新特性:拓扑感知服务路由1、名词解释:拓扑域:表示在集群中某个节点,可操作区域,也就是拓扑域名。Endpoint:IP-Port 一般来说是Node当中pod的ip+port...
还是那句话,当你觉得什么多做不了的时候,你一定比以往更渴望成功!
Kubernetes 1.17 新特性
K8S 更新的速度之快,至于使用感知设计不是很深,未实际环境使用。
那就一起来看下吧:
- v1.17 新特性:拓扑感知服务路由
1、名词解释:
- 拓扑域:表示在集群中某个节点,可操作区域,也就是拓扑域名。
- Endpoint: IP-Port 一般来说是Node当中pod的ip+port。
- Service:一组依靠labelselector的pod,起到流量均衡分发管理的作用。
2、背景:
-
当前k8s集群节点分布在不同的地方,service对应的endpoint分布在不同的节点,转发策略会对所有的endpoint做负载均衡,通常会等概率转发,访问service时,流量就负载均衡到不同的pod中,但是如果两个Node相聚较远,转发时网络延迟相对比较高,对网络要求也会相对地提升,如果可以就近感知并转发,也就减少了网络延迟,所以路由拓扑感知路由就出来了。
-
K8S存在的亲和性:
Service的就近转发实际上就是一种网络的亲和性,倾向于转发到离自己比较近的endpoint。- 节点亲和性(Node Affinity):限制pod调度到某一可用区,或者要求节点支持GPU,让Pod调度到符合一些期望条件的Node上,结果取决于节点属性。
- Pod亲和性和反亲和性(Pod Affinity/AntiAffinity):让一组pod调度到同一拓扑域,或者打散到不通过拓扑域,调度结果取决于其他pod。
- 数据卷拓扑感知调度(Volume Topology-aware Scheduling):让pod只被调度到符合其绑定的存储所在拓扑域的节点上,这算是调度与存储的亲和,调度结果取决于村粗的拓扑域。
- 本地数据卷(Local Persistent Volume):让 Pod 使用本地数据卷,比如高性能 SSD,在某些需要高 IOPS 低时延的场景很有用,它还会保证 Pod 始终被调度到同一节点,数据就不会不丢失,这也算是调度与存储的亲和,调度结果取决于存储所在节点。
- 数据卷拓扑感知动态创建(Topology-Aware Volume Dynamic Provisioning):先调度 Pod,再根据 Pod 所在节点的拓扑域来创建存储,这算是存储与调度的亲和,存储的创建取决于调度的结果。
而 k8s 目前在网络方面还没有亲和性能力,拓扑感知服务路由这个新特性恰好可以补齐这个的空缺,此特性使得 service 可以实现就近转发而不是所有 endpoint 等概率转发。
3、实现原理:
- Service转发只要是是 node 上的 kube-proxy 进程通过 watch apiserver 获取 service 对应的 endpoint,再写入 iptables 或 ipvs 规则来实现的; 对于 headless service,主要是通过 kube-dns 或 coredns 动态解析到不同 endpoint ip 来实现的。实现 service 就近转发的关键点就在于如何将流量转发到跟当前节点在同一拓扑域的 endpoint 上,也就是会进行一次 endpoint 筛选,选出一部分符合当前节点拓扑域的 endpoint 进行转发。
- 那么如何判断 endpoint 跟当前节点是否在同一拓扑域里呢?只要能获取到 endpoint 的拓扑信息,用它跟当前节点拓扑对比下就可以知道了。那又如何获取 endpoint 的拓扑信息呢?答案是通过 endpoint 所在节点的 label, 来描述拓扑域。
- 通常在节点初始化的时候,controller-manager 就会为节点打上许多 label,比如 kubernetes.io/hostname 表示节点的 hostname 来区分节点;另外,在云厂商提供的 k8s 服务,或者使用 cloud-controller-manager 的自建集群,还会给节点打上 failure-domain.beta.kubernetes.io/zone 和 failure-domain.beta.kubernetes.io/region 以区分节点所在可用区和所在地域,但自 v1.17 开始将会改名成 topology.kubernetes.io/zone 和 topology.kubernetes.io/region。如何根据 endpoint 查到它所在节点的这些 label 呢?答案是通过 Endpoint Slice,该特性在 v1.16 发布了 alpha,在 v1.17 将会进入 beta,它相当于 Endpoint API 增强版,通过将 endpoint 做数据分片来解决大规模 endpoint 的性能问题,并且可以携带更多的信息,包括 endpoint 所在节点的拓扑信息,拓扑感知服务路由特性会通过 Endpoint Slice 获取这些拓扑信息实现 endpoint 筛选 (过滤出在同一拓扑域的 endpoint),然后再转换为 iptables 或 ipvs 规则写入节点以实现拓扑感知的路由转发。
- 之前每个节点上转发 service 的 iptables/ipvs 规则基本是一样的,但启用了拓扑感知服务路由特性之后,每个节点上的转发规则就可能不一样了,因为不同节点的拓扑信息不一样,导致过滤出的 endpoint 就不一样,也正是因为这样,service 转发变得不再等概率,灵活的就近转发才得以实现。
4、前提条件:
- 集群版本在V1.17以上
- Kube-proxy 以iptables或IPVS模式运行(alpha阶段暂时只实现这两种模式)。
- Service K8S的service资源,关联一组endpoint,准发到某个endpoint。
- 启用了Endpoint Slices
- 给所有组件打开ServiceTopology和Endpointslice这两个Feature gate:
--feature-gates="ServiceTopology=true,EndpointSlice=true"
5、如何使用:
在 Service spec 里加上 topologyKeys 字段,表示该 Service 优先顺序选用的拓扑域列表,对应节点标签的 key;当访问此 Service 时,会找是否有 endpoint 有对应 topology key 的拓扑信息并且 value 跟当前节点也一样,如果是,那就选定此 topology key 作为当前转发的拓扑域,并且筛选出其余所有在这个拓扑域的 endpoint 来进行转发;如果没有找到任何 endpoint 在当前 topology key 对应拓扑域,就会尝试第二个 topology key,依此类推;如果遍历完所有 topology key 也没有匹配到 endpoint 就会拒绝转发,就像此 service 没有后端 endpoint 一样。
有一个特殊的 topology key “*“,它可以匹配所有 endpoint,如果 topologyKeys 包含了 *,它必须在列表末尾,通常是在没有匹配到合适的拓扑域来实现就近转发时,就打消就近转发的念头,可以转发到任意 endpoint 上。
当前 topology key 支持以下可能的值(未来会增加更多):
- kubernetes.io/hostname: 节点的 hostname,通常将它放列表中第一个,表示如果本机有 endpoint 就直接转发到本机的 endpoint。
- topology.kubernetes.io/zone: 节点所在的可用区,通常将它放在 kubernetes.io/hostname 后面,表示如果本机没有对应 endpoint,就转发到当前可用区其它节点上的 endpoint(部分云厂商跨可用区通信会收取额外的流量费用)。
- topology.kubernetes.io/region: 表示节点所在的地域,表示转发到当前地域的 endpoint,这个用的应该会比较少,因为通常集群所有节点都只会在同一个地域,如果节点跨地域了,节点之间通信延时将会很高。
- *: 忽略拓扑域,匹配所有 endpoint,相当于一个保底策略,避免丢包,只能放在列表末尾。
- topologyKeys 与 externalTrafficPolicy=Local 不兼容,是互斥的,如果 externalTrafficPolicy 为 Local,就不能定义 topologyKeys,反之亦然。
- topology key 必须是合法的 label 格式,并且最多定义 16 个 key。
示例:
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: ClusterIP
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
topologyKeys: ["kubernetes.io/hostname", "topology.kubernetes.io/zone", "*"]
解释: 当访问 nginx 服务时,首先看本机是否有这个服务的 endpoint,
如果有就直接本机路由过去;如果没有,就看是否有 endpoint
位于当前节点所在可用区,如果有,就转发过去,如果还是没有,就转发给任意 endpoint。
6、总结:
k8s 网络是块难啃的硬骨头,拓扑感知服务路由可以实现 service 就近转发,减少网络延时,进一步提升 k8s 的网络性能,此特性将于 k8s v1.17 发布 alpha,时间是 12 月上旬。
更多推荐
所有评论(0)