拓扑域:表示在集群中某个节点,可操作区域,也就是拓扑域名。
Endpoint: IP-Port 一般来说是Node当中pod的ip+port。
Service:一组依靠labelselector的pod,起到流量均衡分发管理的作用。
集群版本在V1.17以上
Kube-proxy 以iptables或IPVS模式运行(alpha阶段暂时只实现这两种模式)。
Service K8S的service资源,关联一组endpoint,准发到某个endpoint。
启用了Endpoint Slices
给所有组件打开ServiceTopology和Endpointslice这两个Feature gate:
--feature-gates=ServiceTopology=true,EndpointSlice=true
kube-apiserver 前期启动OwnerReferencesPermissionEnforcement 插件请删除不然一直提示 Warning FailedToUpdateEndpointSlices 8m24s (x7 over 11m) endpoint-slice-controller (combined from similar events): Error updating Endpoint Slices for Service kube-system/kube-DNS: Error creating EndpointSlice for Service kube-syste
m/kube-dns: endpointslices.discovery.k8s.io "kube-dns-x8qmh" is forbidden: cannot set blockOwnerDeletion if an ownerReference refers to a resource you can't set finalizers on: ,
root@Qist:/opt/kube14# kubectl get endpointslices
NAME ADDRESSTYPE PORTS ENDPOINTS AGE
kube-dns-kh6ls IPv4 53,9153,53 10.83.98.136,10.90.153.135 15m
metrics-server-gqgqm IPv4 443 10.93.92.195 15m
在 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。
# 以kube-dns 为例:
---
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
kubernetes.io/name: "CoreDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 192.66.0.2
topologyKeys: ["kubernetes.io/hostname", "topology.kubernetes.io/zone", "*"] # 添加参数
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
- name: metrics
port: 9153
protocol: TCP
# 验证ServiceTopology 是否生效
进去node 节点
无kube-dns 容器节点
root@k8s-master-01:~# ipvsadm -Ln | grep :53
TCP 10.66.0.2:53 rr
-> 10.83.98.136:53 Masq 1 0 0
-> 10.90.153.135:53 Masq 1 0 0
UDP 10.66.0.2:53 rr
-> 10.83.98.136:53 Masq 1 0 0
-> 10.90.153.135:53 Masq 1 0 0
# 有kube-dns 容器节点
[root@k8s-node-09 ~]# ipvsadm -Ln| grep :53
TCP 10.66.0.2:53 rr
-> 10.90.153.135:53 Masq 1 0 0
UDP 10.66.0.2:53 rr
-> 10.90.153.135:53 Masq 1 0 0
# 直接就是当前node 节点容器IP