Kubernetes基础(五)-Service

1 引言

Service 主要用于提供网络服务,通过Servicel的定义,能够 为客户端应用提供稳定的访问地址(域名或IP地址)和负载均衡功能,以及屏蔽后端Endpoint的变化,是Kubernetes实现微服务的核心资源。

本文详细讲解下Service的相关概念及原理。

2 Service介绍

2.1 Service的概念

下面演示在没有Service之前,是如何访问一个多副本的应用容器组提供的服务。

以Tomcat容器为例,其Deployment资源文件定义如下:

apiVersion: apps/v1
kind: Deployment
metadata:name: webapp
spec:replicas: 2selector:matchLabels:app: webapptemplate:metadata:labels:app: webappspec:containers:- name: webappimage: kubeguide/tomcat-app:v1 ports:- containerPort: 8080

创建完成后,查看每个pod的ip地址:

客户端应用可以直接通过这两个Pod的IP地址和端口号8080访问Web服务,例如:curl 10.0.95.22:8080

但是,提供服务的容器应用通常是分布式的,通过多个Pod副本共同提供服务(还需要考虑扩缩容的问题),要实现动态感知服务后端实例的变化,会大大增加客户端系统实现的复杂度,为了解决这个问题,Kubernetes引入 Service资源类型 。

2.2 概念

Service实现的是微服务架构中的几个核心功能:全自动的服务注册、服务发现、 服务负载均衡等。

2.2.1 创建Service的方式

2.2.1.1 使用kubectl expose命令创建

命令如下:

$ kubectl expose deployment webapp 
service/webapp exposed

查看新创建的Service,可以看到系统为它分配了一个虚拟​​IP​​​地址(​​ClusterIP​​ 地址),Service的端口号则从Pod中的containerPort复制而来:

通过curl 169.169.140.242:8080 也是可以访问的。访问时,会被自动负载分发到了后端两个Pod之一:10.0.95.22:8080或10.0.95.23:8080。 

2.2.1.2 资源文件创建
除了使用命令,还可以使用yaml资源文件的方式来创建:
apiVersion: v1
kind: Service
metadata:name: webapp
spec:ports:- protocol: TCPport: 8080targetPort: 8080selector:app: webapp

Service定义中的关键字段是ports和selector:

  • ports:定义部分指定了Service本身的端口号为8080;
  • targetPort:指定后端Pod的容器端口号;
  • selector:定义部分设置的是后端Pod所拥有的 ​​label:app=webapp​​。

使用​​kubectl create​​​命令创建后,能看到和使用​​kubectl expose​​命令创建Service的效果一样。

2.2.2 Endpoint

一个Service对应的 “后端” 由Pod的IP和容器端口号组成,这在k8s系统中称为Endpoint。

可以通过​​kubectl descirbe svc ​​命令查看Endpoint列表,如:

Kubernetes自动创建了与Service关联的Endpoint资源对象,这可以通过查询Endpoint对象讲行查看:

3 负载均衡机制

当一个 Service 对象在 Kubernetes 集群中被定义出来时,集群内的客户端应用就可以通过服务IP访问到具体的Pod容器提供的服务了。

从服务IP到后端Pod的负载均衡机制,则是由每个Node上的kube-proxy负责实现的。通过Service的负载均衡机制,Kubernetes实现了一种分布式应用的统一入口,免去了客户端应用获知后端服务实例列表和变化的复杂度。。

3.1 kube-proxy的代理模式

kube-proxy代理模式参考:Kubernetes基础(四)-Kube-proxy_kubectl proxy-CSDN博客

3.2 会话保持模式

Service支持通过设置sessionAffinity实现基于客户端IP的会话保持机制,即:首次将某个客户端来源IP发起的请求转发到后端的某个Pod上,之后从相同的客户端 IP发起的请求都将被转发到相同的后端Pod上。

配置参数为 ​​service.spec.sessionAffinity​​​,也可以设置会话保持的最长时间(​​service.spec.sessionAffinityConfig.clientIP.timeoutSeconds​​),例如下面的服务将会话保持时间设置为10800s(3h):

apiVersion: v1
kind: Service
metadata:name: webapp
spec:sessionAffinity: ClientIP sessionAffinityConfig:clientIP:timeoutSecondes: 10080ports:- protocol: TCPport: 8080targetPort: 8080selector:app: webapp

4 Service的多端口设置

一个容器应用可以提供多个端口的服务,在Service的定义中也可以相应地设置多个端口号。

在下面的例子中,Service设置了两个端口号来分别提供不同的服务,如web服务和management服务(下面为每个端口号都进行了命名,以便区分):

apiversion: v1
kind: Service
metadata:name: webapp
spec:
ports:
- port: 8080targetPort: 8080name: web
- port: 8005targetPort: 8005 name: management
selector:
app: webapp

另一个例子是同一个端口号使用的协议不同,如TCP和UDP,也需要设置为多个端口号来提供不同的服务:

apiVersion: v1
kind: Service
metadata:name: kube-dnsnamespace: kube-system labels:k8s-app: kube-dnskubernetes.io/cluster-service: "true" kubernetes.io/name: "KubeDNS"
spec:selector:k8s-app: kube-dnsclusterIP: 169.169.0.100ports:- name: dns port: 53protocol: UDP- name: dns-tcpport: 53protocol: TCP

5 将外部服务定义为Service

普通的Service通过Label Selector对后端Endpoint列表进行了一次抽象,如果后端的Endpoint不是由Pod副本集提供的,则Service还可以抽象定义任意其他服务,将一个Kubernetes集群外部的已知服务定义为Kubernetes内的一个Service, 供集群内的其他应用访问。

5.1 场景

常见的应用场景包括:

  • 已部署的一个集群外服务:例如数据库服务、缓存服务等;
  • 其他Kubernetes集群的某个服务;
  • 迁移过程中对某个服务进行Kubernetes内的服务名访问机制的验证。

Service指向外部服务如下图所示:

5.2 定义

对于这种应用场景,用户在创建​​Service​​资源对象时不设置​​Label Selector​​(后端​​Pod​​也不存在),同时再定义一个与​​Service​​关联的​​Endpoint​​资源对象,在​​Endpoint​​中设置外部服务的​​IP​​地址和端口号,例如:

apiVersion: v1
kind: Service
metadata:name: my-service
spec:ports:- protocol: TCPport: 80targetPort: 80-----------
apiversion: v1
kind: Endpoints
metadata:name: my-service
subsets:
- addresses:- IP: 1.2.3.4ports:- port: 80

6 Service类型

Kubernetes为Service创建的ClusterIP地址是对后端Pod列表的一层抽象,对于集群外部来说并没有意义,但有许多Service是需要对集群外部提供服务的,Kubernetes提供了多种机制将Service暴露出去,供集群外部的客户端访问。

这可以通过Service资源对象的类型字段“type”进行设置。

Kubernetes 服务有四种类型——ClusterIP、NodePort、LoadBalancer 和 ExternalName。 服务spec中的 type 属性决定了服务如何暴露给网络。

6.1 ClusterIP(集群IP)

  • ClusterIP 是默认和最常见的服务类型。
  • Kubernetes 会为 ClusterIP 服务分配一个集群内部 IP 地址。 这使得服务只能在集群内访问。
  • 不能从集群外部向服务(pods)发出请求。
  • 可以选择在服务定义文件中设置集群 IP。

6.1.1 使用场景

集群内的服务间通信。 例如应用程序的前端(front-end)和后端(back-end)组件之间的通信。

举例

apiVersion: v1
kind: Service
metadata:name: my-backend-service
spec:type: ClusterIP # Optional field (default)clusterIP: 10.10.0.1 # within service cluster ip rangeports:- name: httpprotocol: TCPport: 80targetPort: 8080

6.2 NodePort(节点端口)

  • NodePort 服务是 ClusterIP 服务的扩展。 NodePort服务路由到的 ClusterIP 服务会自动创建。
  • 它通过在 ClusterIP 之上添加一个集群范围的端口来公开集群外部的服务。
  • NodePort 在静态端口(NodePort)上公开每个节点 IP 上的服务。每个节点将该端口代理到后端服务中。因此,外部流量可以访问每个节点上的固定端口。这意味着对该端口上的集群的任何请求都会转发到该服务。
  • 用户可以通过请求 <NodeIP>:<NodePort> 从集群外部联系 NodePort 服务。
  • 节点端口必须在 30000-32767 范围内。手动为服务分配端口是可选的。如果未定义,Kubernetes 会自动分配一个。
  • 如果用户要明确选择节点端口,请确保该端口尚未被其他服务使用。

6.2.1 使用场景

  • 当用户想要启用与后端服务的外部连接时。
  • 使用 NodePort 可以让用户自由地设置自己的负载平衡解决方案,配置 Kubernetes 不完全支持的环境,甚至直接公开一个或多个节点的 IP。
  • 最好在节点上方放置负载均衡器以避免节点故障。

举例

apiVersion: v1
kind: Service
metadata:name: my-frontend-service
spec:type: NodePortselector:app: webports:- name: httpprotocol: TCPport: 80targetPort: 8080nodePort: 30000 # 30000-32767, Optional field

6.3 LoadBalancer(负载均衡器)

  • LoadBalancer 服务是 NodePort 服务的扩展。 外部负载均衡器路由到的 NodePort 和 ClusterIP 服务是自动创建的。
  • 它将 NodePort 与基于云的负载均衡器集成在一起。
  • 它使用云厂商的负载均衡器在外部公开服务。
  • 每个云厂商(AWS、Azure、GCP 、阿里云、腾讯云等)都有自己的原生负载均衡器实现。 云厂商将创建一个负载均衡器,然后它会自动将请求路由到您的 Kubernetes 服务。
  • 来自外部负载均衡器的流量被定向到后端 Pod。 云厂商决定如何进行负载平衡。
  • 负载均衡器的实际创建是异步发生的。
  • 每次要向外界公开服务时,都必须创建一个新的 LoadBalancer 并获取 IP 地址。

6.3.1 使用场景

当用户使用云厂商来托管Kubernetes 集群时。

举例

apiVersion: v1
kind: Service
metadata:name: my-frontend-service
spec:type: LoadBalancerclusterIP: 10.0.171.123loadBalancerIP: 123.123.123.123selector:app: webports:- name: httpprotocol: TCPport: 80targetPort: 8080

6.4 ExternalName(外部名称)

  • ExternalName 类型的服务将 Service 映射到 DNS 名称,而不是典型的选择器,例如 my-service。
  • 用户可以使用 `spec.externalName` 参数指定这些服务。
  • 它通过返回带有其值的 CNAME 记录,将服务映射到 externalName 字段(例如 foo.bar.example.com)的内容。
  • 没有建立任何类型的代理。

6.4.1 使用场景

  • 这通常用于在 Kubernetes 内创建服务来表示外部数据存储,例如在 Kubernetes 外部运行的数据库。
  • 当来自一个命名空间的 Pod 与另一个命名空间中的服务通信时,用户可以使用该 ExternalName 服务(作为本地服务)。

举例

apiVersion: v1
kind: Service
metadata:name: my-service
spec:type: ExternalNameexternalName: my.database.example.com

7 将Service暴露给外部集群

Kubernetes为Service创建的ClusterIP地址是对后端Pod列表的一层抽象,对于集群外部来说并没有意义,但有许多Service是需要对集群外部提供服务的,Kubernetes提供了多种机制将Service暴露出去,供集群外部的客户端访问。 

外部访问方式参考:Kubernetes基础(三)-Service外部网络访问方式-CSDN博客

8 Service支持的网络协议

目前Service支持的网络协议如下.

协议描述
TCPService的默认网络协议,可用于所有类型的Service。
UDP可用于大多数类型的Service,LoadBalancer类型取决于云服务商对UDP的支持。
HTTP取决于云服务商是否支持HTTP和实现机制。
PROXY取决于云服务商是否支持HTTP和实现机制。
SCTP从Kubernetes1.12版本引入,到1.19版本时达到Beta阶段,默认启用,如需关闭该特性,则需要设置kube-apiserver的启动参数–feature- gates=-SCTPSupport=-false进行关闭。

Kubernetes从1.17版本开始,可以为Service和Endpoint资源对象设置一个新的段"AppProtocol",用于标识后端服务在某个端口号上提供的应用层协议类型,例如HTTP、HTTPS、SSL、DNS等。

要使用AppProtocol,需要设置kube-apiserver的启动参数​​--feature-gates=ServiceAppProtocol=true​​进行开启,然后在Service或Endpoint的定义中设置AppProtocol字段指定应用层协议的类型,例如: 

apiVersion: v1
kind: Service
metadata: name: webapp 
spec:ports:- port: 8080targetPort: 8080AppProtocol: HTTPselector:app: webapp

8 Kubernetes的服务发现机制

服务发现机制指客户端应用在一个Kubernetes集群中如何获知后端服务的访问地址,一共有两种方式。

8.1 环境变量方式

在一个Pod运行起来的时候,系统会自动为其容器运行环境注入所有集群中有效Service的信息。

Service的相关信息包括服务IP、服务端口号、各端口号相关的协议等,通过​{SVCNAME_SERVICE_HOST}​​​和​​{SVCNAME_SERVICE_PORT}​​格式进行设置。

其中SVCNAME的命名规则为:将Service的name字符串转换为全大写字母,将中横线“”替换为下画线 “_”,以webapp服务为例:

apiVersion: v1
kind: Service
metadata:name: webapp
spec: ports:- protocol: TCPport: 8080targetPort: 8080selector:app: webapp

在一个新创建的Pod(客户端应用)中,可以看到系统自动设置的环境变量如下:

WEBAPP_SERVICE_HOST=169.169.81.175
WEBAPP_SERVICE_PORT=8080
WEBAPP_P0RT=tcp://169.169.81.175:8080
WEBAPP_P0RT_8080_TCP=tcp://169.169.81.175:8080
WEBAPP_PORT_8080_TCP_PROTO=tcp
WEBAPP_PORT_8080_TCP_PORT=8080
WEBAPP_PORT_8080_TCP_ADDR=169.169.81.175

然后客户端应用就能够根据​​Service​​相关环境变量的命名规则,从环境变量中获取需要访问的目标服务的地址了,例如:

curl http://{WEBAPP_SERVICE_HOST}:${WEBAPP_SERVICE_HOST}

8.2 DNS方式

Service在Kubernetes系统中遵循DNS命名规范,Service的DNS域名表示方法 为​​<servicename>.<namespace>.svc.<clusterdomain>​​,其中:

  • servicename:为服务的名称;
  • namespace:为其所在namespace的名称;
  • clusterdomain:为Kubernetes集群设置的域名后缀(例如cluster.local),服务名称的命名规则遵循RFC 1123规范的要求。

另外,Service定义中的端口号如果设置了名称(name),则该端口号也会拥有一个DNS域名,在DNS服务器中以SRV记录的格式保存:​​​_<portname>._<protocol>.<servicename>.<namespace>.svc. <clusterdomain>​​,其值为端口号的数值。

当​​Service​​​以​​DNS​​​域名形式进行访问时,就需要在​​Kubernetes​​​集群中存在一个​​DNS​​​服务器来完成域名到​​ClusterIP​​​地址的解析工作了,经过多年的发展,目前由CoreDNS作为Kubernetes集群的默认DNS服务器提供域名解析服务。

以​​webapp​​服务为例,将其端口号命名为“​​http​​”:

apiversion: v1
kind: Service
metadata:name: webapp
spec:ports:- protocol: TCPport: 8080targetPort: 8080name: httpselector:app: webapp

解析名为 “http” 端口的​​DNS SRV​​记录“​​_http._tcp.webapp.default.svc.cluster.local'​​​”,可以查询到其端口号的值为​​8080​​。

9 Headless Service的概念和应用 

在某些应用场景中,客户端应用不需要通过Kubernetes内置Service实现的负载均衡功能,或者需要自行完成对服务后端各实例的服务发现机制,或者需要自行实现负载均衡功能,此时可以通过创建一种特殊的名为 “Headless‘”的服务来实现。headless介绍参考: Kubernetes基础(二)-Headless Service_alden_ygq的博客-CSDN博客​​​​​​

10 端点分片和服务拓扑

Service的后端是一组Endpoint列表,为客户端应用提供了极大的便利。但随着集群规模的扩大及Service数量的增加,特别是Service后端Endpoint数量的增加,kube-proxy需要维护的负载分发规则(例如iptables规则侧或 ipvs规则)的数量也会急剧增加,导致后续对Service后端Endpoint的添加、删除 等更新操作的成本急剧上升。

假设在​​Kubernetes​​​集群中有10000个​​Endpoint​​​运行在大约5000个​​Node​​​上,则对单个​​Pod​​​的更新将需要总计约​​5GB​​​的数据传输,这不仅对集群内的网络带宽浪费巨大,而且对​​Master​​​的冲击非常大,会影响​​Kubernetes​​​集群的整体性能,在​​Deployment​​不断进行滚动升级操作的情况下尤为突出。这种情况下K8s设计了一种端点分片(​​Endpoint Slices​​)机制来解决。

EndpointSlice通过对Endpoint进行分片管理来实现降低Master和各Node之间的网络传输数据量及提高整体性能的目标。对于Deployment的滚动升级,可以实现仅更新部分Node上的Endpoint信息,Master与Node之间的数据传输量可以减少100倍左右,能够大大提高管理效率。

​​Endpoint Slices​​要实现的第2个目标是为基于Node拓扑的服务路由提供支持,这需要与服务拓扑(Service Topology)机制共同实现。

10.1 端点分片

kubernetes从1.19版本开始,EndpointSplice机制以及​​EndpointSliceProxying​​是默认开启的:

  • 通过设置​​kube-apiserver​​​和​​kube-proxy​​​服务的启动参数​​--feature-gates=“EndpointSlice=true“​​​进行启用。kube-proxy默认仍然使用Endpoint对象,为了提高性能,可以设置 kube-proxy启动参数​​--feature-gates-=“EndpointSliceProxying=true“​​让kube-proxy 使用EndpointSlice,这样可以减少kube-proxy与master之间的网络通信并提高性能。

以一个3副本的webapp服务为例,Pod列表如下:

服务和Endpoint的信息如下:

查看EndpointSlice,可以看到系统自动创建了一个名称前缀为“​​webapp-​​”的EndpointSlice:

查看其详情信息,可以看到3个Endpoint的IP地址和端口信息,同时为Endpoint设置了Topology相关信息:

 10.1.1 参数

默认情况下,在由EndpointSlice控制器创建的EndpointSlice中最多包含100个Endpoint,如需修改,则可以通过kube-controller-manager服务的启动参数​​-- max-endpoints-per-slice​​设置,但上限不能超过1000。

EndpointSlice的关键信息如下:

配置项描述
关联的服务名称将EndpointSlice与Service的关联信息设置为一个标签​​kubernetes.io/service-name=webapp​​,该标签标明了服务名称
地址类型AddressType

包括以下3种取值类型:

  • IPv4:IPv4格式的IP地址
  • IPv6:Pv6格式的IP地址
  • FQDN:全限定域名.
每个Endpoint的信息

在Endpoints列表中列出的每个Endpoint的信息:

  • Addresses:Endpoint的IP地址;
  • Conditions:Endpoint状态信息,作为EndpointSlice的查询条件;
  • Hostname:在Endpoint中设置的主机名nostname;
  • TargetRef:Endpoint对应的Pod名称;
  • Topology:拓扑信息,为基于拓扑感知的服务路由提供数据。

目前EndpointSlice控制器自动设置的拓扑信息如下:

  • -- kubernetes.io/hostname:Endpoint所在Node的名称;
  • -- topology.kubernetes.io/zone:Endpoint所在的Zone信息,使用Node标签topology.kubernetes.io/zone的值,例如上例中的Node拥有 topology.kubernetes.io/zone:north"标签。
  • -- topology.kubernetes.io/region:Endpoint所在的Region信息,使用Node标签topology.kubernetes.io/region的值。

在大规模集群中,管理员应对不同地域或不同区域的Node设置相关的 topology标签,用于为Node设置拓扑信息.

EndpointSlice的管理控制器通过​​endpointslice.kubernetes.io/managed-by​​​标签进行设置,用于存在多个管理控制器的应用场景中,例如某个​​Service Mesh​​​管理工具也可以对​​EndpointSlice​​​进行管理。为了支持多个管理工具对​​EndpointSlice​​​同时进行管理并且互不干扰,可以通过​​endpointslice.kubernetes.io/managed--by​​​标签设置管理控制器的名称,Kubernetes内置的EndpointSlice控制器自动设置该标签的值为​​endpointslice-controller.k8s.io​​,其他管理控制器应设置唯一名称用于标识.

10.1.2 复制功能

EndpointSlice复制(Mirroring)功能:应用程序有时可能会创建自定义的Endpoint资源,为了避免应用程序在创建Endpoint资源时再去创建EndpointSlice资源,Kubernetes控制平面会 自动完成 将Endpoint资源复制为EndpointSlice资源的操作。

以下几种情况下,不会执行自动复制操作:

  • Endpoint资源设置了Label:endpointslice.kubernetes.io/skip-mirror=true;
  • Endpoint资源设置了Annotation:control-plane.alpha.kubernetes.io/leader;
  • Endpoint资源对应的Service资源不存在;
  • Endpoint:资源对应的Service资源设置了非空的Selector;

一个Endpoint资源同时存在IPv4和IPv6地址类型时,会被复制为多个EndpointSlice资源,每种地址类型最多会被复制为1000个EndpointSlice资源。

10.1.3 数据分布管理机制

如上例所示,可以看到每个EndpointSlice资源都包含一组作用于全部Endpoint的端口号(Ports)。如果Service定义中的端口号使用了字符串名称,则对于相同name的端口号,目标Pod 的targetPort可能是不同的,结果是EndpointSlice资源将会不同。这与Endpoint 资源设置子集(subset)的逻辑是相同的。

Kubernetes控制平面对于EndpointSlice中数据的管理机制是尽可能填满,但不会在多个EndpointSlice数据不均衡衡的情况下主动执行重新平衡(rebalance)操作,其背后的逻辑也很简单,步骤如下:

  1. 遍历当前所有EndpointSlice资源,删除其中不再需要的Endpoint,更新已更改的匹配Endpoint;
  2. 遍历第1步中已更新的EndpointSlice资源,将需要添加的新Endpoint填充进去;
  3. 如果还有新的待添加Endpoint,则尝试将其放入之前未更新的EndpointSlice中,或者尝试创建新的EndpointSlicez并添加。

重要的是,第3步优先考虑创建新的EndpointSlice而不是更新原EndpointSlice。例如,如果要添加l0个新的Endpoint,则当前有两个EndpointSlice各有5个剩余空间可用于填充,系统也会创建一个新的EndpointSlice用来填充这10个新Endpoint。换句话说,单个EndpointSlice的创建优于对多个EndpointSlice的更新。

以上主要是由于在每个节点上运行的kube-proxy都会持续监控EndpointSlice的变化,对EndpointSlice每次更新成本都很高,因为每次更新都需要​​Master​​​将更新数据发送到每个​​kube-proxy​​。

上述管理机制旨在限制需要发送到每个节点的更新数据量,即使可能导致最终有许多EndpointSlice资源未能填满。实际上,这种不太理想的数据分布情况应该是罕见的。

Master的EndpointSlice控制器处理的大多数更新所带来的数据量都足够小,使得对已存在 (仍有空余空间)EndpointSlice的数据填充都没有问题,如果实在无法填充,则无论如何都需要创建新的EndpointSlice资源。

此外,对Deployment执行滚动升级操作时,由于后端Pod列表和相关Endpoint列表全部会发生变化,所以也会很自然地对EndpointSlice资源的内容全部进行更新。

10.2 服务拓扑

在默认情况下,发送到一个Service的流量会被均匀转发到每个后端Endpoint,但无法根据更复杂的拓扑信息设置复杂的路由策略。服务拓扑机制的引入就是为了实现基于Node拓扑的服务路由,允许Service创建者根据来源Node和目标Node的标签来定义流量路由策略。

通过对来源Node和目标Node标签的匹配,用户可以根据业务需求对Node进行分组,设置有意义的指标值来标识 “较近” 或者 “较远” 的属性:

例如对于公有云环境来说,通常有区域(Zone或Region)的划分,云平台倾向于把服务流量限制在同一个区域内,这通常是因为跨区域网络流量会收取额外的费用。另一个例子是把流量路由到由DaemonSet管理的当前Node的Pod 上。又如希望把流量保持在相同机架内的Node上,以获得更低的网络延时。

10.2.1 配置

服务拓扑机制需要通过设置​​kube-apiserver​​​和​​kube-proxy​​​服务的启动参数​​--feature-gates-=“ServiceTopology=true,EndpointSlice=true“​​​进行启用(需要同时启用​​EndpointSlice​​​功能),然后就可以在​​Service​​​资源对象上通过定义 ​​topologyKeys​​字段来控制到Service的流量路由了。

对于需要使用服务拓扑机制的集群,管理员需要为Node设置相应的拓扑标签,包括​​kubernetes.io/hostname​​​、​​topology.kubernetes.io/zone​​​ 和​​topology.kubernetes.io/region​​。

然后为Service设置topologyKeys的值,就可以实现如下流量路由策略:

  • 配置为[“kubernetes.io/hostname“]:流量只会被路由到相同Node的
  • Endpoint上,如果Node的Endpoint不存在,则将请求丢弃。
  • 配置为[“kubernetes.io/hostname" "topology.kubernetes.io/zone“ “topology.kubernetes.io/region“]:流量优先被路由到相同Node的Endpoint上, 如果Node没有Endpoint,流量则被路由到同zone的Endpoint,如果在zone中没有Endpoint,流量则被路由到通region中的Endpoint上。
  • 配置为[“topology.kubernetes.io/zone“,“​​*​​​“]:流量优先被路由到同zone 的Endpoint上,如果在zone中没有可用的Endpoint,流量则被路由到任意可用的
  • Endpoint上。

目前使用服务拓扑有以下几个约束条件:

  • 服务拓扑和externalTrafficPolicy=Local是不兼容的,所以一个Service不能同时使用这两种特性。在同一个Kubernetes集群中,启用服务拓扑的Service和设置externalTrafficPolicy=Local特性的Service:是可以同时存在的。
  • topologyKeys目前可以设置的标签只有3个:kubernetes.io/hostname、topology.kubernetes.io/zone和topology.kubernetes.io/region,未来会增加更多 的标签。
  • topologyKeys必须是有效的标签格式,并且最多定义16个。
  • 如需使用通配符“*”,则它必须是最后一个值。

10.2.2 案例

下面通过Service的YAML文件对几种常见的服务拓扑应用实例进行说明。

1)只将流量路由到相同Node的Endpoint上,如果Node没有可用的Endpoint,则将请求丢弃:

apiVersion: v1
kind: Service
metadata:name: webapp
spec:selector:app: webappports:- port: 8080topologykeys:- "kubernetes.io/hostname"

2)优先将流量路由到相同Node的Endpoint上,如果Node没有可用的Endpoint,则将请求路由到任意可用的Endpoint:

apiVersion: v1
kind: Service
metadata:name: webapp
spec:selector:app: webappports:- port:8080topologyKeys:- "kubernetes.io/hostname"- "*"

3)只将流量路由到相同zone或同region的Endpoint上,如果没有可用的Endpoint,则将请求丢弃:

apiVersion: v1
kind: Service
metadata:name: webapp
spec:selector:app: webappports:- port:8080topologyKeys:- "topology.kubernetes.io/zone" - "topology.kubernetes.io/region"

4)按同Node、同zone、同region的优先级顺序路由流量,如果Node、 zone、region都没有可用的Endpoint,则将请求路由到集群内任意可用的Endpoint.上:

apiVersion: v1
kind: Service
metadata: name: webapp
spec:selector:app: webappports:- port:8080topologyKeys:- "kubernetes.io/hostname"- "topology.kubernetes.io/zone" - "topology.kubernetes.io/region"- "*"

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/91301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

博弈论中静态博弈经典场景案例

博弈论中静态博弈经典场景案例 1、齐威王田忌赛马 田忌赛马是中国家喻户晓的故事&#xff0c;故事讲述的是齐国大将田忌的谋士孙膑如何运用计谋帮助田忌在与齐威王赛马时以弱胜强的故事&#xff0c;这个故事其实本质也是一个博弈的过程。     齐威王要和田忌赛马&#xff…

二叉树MFC实现

设有一颗二叉树如下&#xff1b; 这似乎是一颗经常用作示例的二叉树&#xff1b; 对树进行遍历的结果是&#xff0c; 先序为&#xff1a;3、2、2、3、8、6、5、4&#xff0c; 中序为&#xff1a;2、2、3、3、4、5、6、8&#xff0c; 后序为2、3、2、4、5、6、8、3&#xff1b…

MySQL学习笔记25

逻辑备份 物理备份 在线热备&#xff1a; 真实案例&#xff1a; 数据库架构是一主两从&#xff0c;但是两台从数据库和主数据不同步。但是每天会全库备份主服务器上的数据到从服务器上。需要解决主从不同步的问题。 案例背后的核心技术&#xff1a; 1、熟悉MySQL数据库常见…

【计算机视觉|人脸建模】PanoHead:360度几何感知的3D全头合成

本系列博文为深度学习/计算机视觉论文笔记&#xff0c;转载请注明出处 标题&#xff1a;PanoHead: Geometry-Aware 3D Full-Head Synthesis in 360 ∘ ^{\circ} ∘ 链接&#xff1a;[2303.13071] PanoHead: Geometry-Aware 3D Full-Head Synthesis in 360 ∘ ^{\circ} ∘ (arx…

大数据Doris(三):Doris编译部署篇

文章目录 Doris编译部署篇 一、Doris编译

学信息系统项目管理师第4版系列13_立项管理

1. 项目立项管理包括 1.1. 项目建议与立项申请 1.2. 项目可行性研究 1.2.1. 初步可行性研究 1.2.2. 详细可行性研究 1.2.2.1. 不可缺少 1.2.2.1.1. 【高21上选21】 1.2.3. 可以依据项目的规模和繁简程度合二为一 1.3. 项目评估与决策 2. 立项申请 2.1. 项目建议书 2…

Lua语法之简单变量

--nil有点类似空null a nil print(a) --type函数得到类型 返回值是string print(type(a)) print("*****")--number是数值 int float这些 --lua的变量可以随便赋值 自动识别类型 a 1 print(a) print(type(a)) print("*****")--siting可以用单引号双引号 a…

华为云HECS云服务器docker环境下安装nginx

前提&#xff1a;有一台华为云服务器。 华为云HECS云服务器&#xff0c;安装docker环境&#xff0c;查看如下文章。 华为云HECS安装docker-CSDN博客 一、拉取镜像 下载最新版Nginx镜像 (其实此命令就等同于 : docker pull nginx:latest ) docker pull nginx查看镜像 dock…

实体行业数字化转型怎么做?线上线下相结合的新零售体系怎么做?

如今&#xff0c;实体行业想要取得收入增长&#xff0c;只做线下业务或者只做线上业务&#xff0c;在当前的市场环境中是难以长久生存的&#xff0c;因此一定要线上线下相结合&#xff0c;将流量运作与线下转化进行充分结合&#xff0c;才能更好地发挥实体优势&#xff0c;带来…

Linux学习记录——삼십일 socket编程---TCP套接字

文章目录 TCP套接字简单通信1、服务端1、基本框架2、获取连接 2、客户端3、多进程4、多线程5、线程池6、简单的日志系统7、守护进程8、其它 TCP套接字简单通信 本篇gitee 学习完udp套接字通信后&#xff0c;再来看TCP套接字。 四个文件tcp_server.hpp&#xff0c; tcp_serve…

什么是Local Storage和Session Storage?它们之间有什么区别?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是 Local Storage 和 Session Storage&#xff1f;Local Storage&#xff08;本地存储&#xff09;Session Storage&#xff08;会话存储&#xff09; ⭐ 区别⭐ 示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的…

程序员的浪漫:如何用java代码画❤️表白呢?

有位小伙伴说&#xff0c;看到一个帖子&#xff0c;一个计算机博士接亲时&#xff0c;要求现场写代码&#xff0c;5分钟做出一个爱心。我们就看看如何用java设计出心形的代码。 我找了一下&#xff0c;发现方法竟然很多&#xff0c;我们就来见识一下&#xff0c;最后我们看一下…

TouchGFX之字体缓存

使用二进制字体需要将整个字体加载到存储器。 在某些情况下&#xff0c;如果字体很大&#xff0c;如大字号中文字体&#xff0c;则这样做可能不可取。 字体缓存使应用能够从外部存储器只能加载显示字符串所需的字母。 这意味着整个字体无需保存到在可寻址闪存或RAM上&#xff…

Java自学(三)面向对象编程

目录 什么是面向对象 举例 this关键字和构造器 实体类 电影小案例 什么是面向对象 我们日常生活中谈到一个事物&#xff0c;总会描述它的性质与行为&#xff0c;这个事物也就是 ”对象”。比如一个学生对象&#xff0c;他的属性有姓名、学号、成绩......他的行为有上课、…

装饰器模式详解和实现(设计模式 二)

装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你动态地将对象添加到现有对象中&#xff0c;以提供额外的功能&#xff0c;同时又不影响其他对象。 实现示例 1.定义一个接口或抽象类&#xff0c;表示被装饰对象的公共接口 //抽…

关于 自定义的RabbitMQ的RabbitMessageContainer注解-实现原理

概述 RabbitMessageContainer注解 的主要作用就是 替换掉Configuration配置类中的各种Bean配置&#xff1b; 采用注解的方式可以让我们 固化配置&#xff0c;降低代码编写复杂度、减少配置错误情况的发生&#xff0c;提升编码调试的效率、提高业务的可用性。 为什么说“降低…

QT编译报错stdlib.h:No such file or directory

如图&#xff0c;需要将第19行&#xff0c;INCLUDEPATH /usr/include 注释掉 原因分析&#xff1a; 在Ubuntu的CSTDLIB中&#xff0c;使用的是#include_next下“stdlib.h” &#xff0c;自行增加/usr/include 把include_next的顺序打乱&#xff0c;造成编译错误。但是在cento…

Ubuntu 20.04编译GPMP2过程记录

前言 GPMP2是董靖博士等人在16-17年提出的结合GTSAM因子图框架与Gaussian Processes完成motion planning的一项工作。前身源于Barfoot教授的课题组提出的STEAM(Simultaneous Trajectory Estimation and Mapping)问题及其相关工作。在提出董靖博士提出GPMP2后&#xff0c;borgl…

同步、异步

何为同步、异步&#xff1f; 同步任务&#xff08;synchronous&#xff09; 同步任务指的是&#xff0c;在主线程上排队执行的任务&#xff0c;只有前一个任务执行完毕&#xff0c;才能执行后一个任务&#xff1b;同步任务进栈顺序&#xff1a;先进后出&#xff0c;后进先出&…

网页采集工具-免费的网页采集工具

在当今数字化时代&#xff0c;网页采集已经成为了众多领域的必备工具。无论是市场研究、竞争情报、学术研究还是内容创作&#xff0c;网页采集工具都扮演着不可或缺的角色。对于许多用户来说&#xff0c;寻找一个高效、免费且易于使用的网页采集工具太不容易了。 147SEO工具的强…