Kubernetes 文档 / 概念 / 服务、负载均衡和联网 / 服务(Service)

Kubernetes 文档 / 概念 / 服务、负载均衡和联网 / 服务(Service)

此文档从 Kubernetes 官网摘录
中文地址
英文地址

Kubernetes 中的 Service

Service API 是 Kubernetes 的组成部分,它是一种抽象,帮助你将 Pod 集合在网络上公开出去。 每个 Service 对象定义端点的一个逻辑集合(通常这些端点就是 Pod)以及如何访问到这些 Pod 的策略。

Service 抽象使这种解耦成为可能。

Service 所对应的 Pod 集合通常由你定义的选择算符来确定。 若想了解定义 Service 端点的其他方式,可以查阅不带选择算符的 Service。

如果你的工作负载使用 HTTP 通信,你可能会选择使用 Ingress 来控制 Web 流量如何到达该工作负载。Ingress 不是一种 Service,但它可用作集群的入口点。 Ingress 能让你将路由规则整合到同一个资源内,这样你就能将工作负载的多个组件公开出去, 这些组件使用同一个侦听器,但各自独立地运行在集群中。

用于 Kubernetes 的 Gateway API 能够提供 Ingress 和 Service 所不具备的一些额外能力。 Gateway 是使用 CustomResourceDefinitions 实现的一系列扩展 API。 你可以添加 Gateway 到你的集群中,之后就可以使用它们配置如何访问集群中运行的网络服务。

云原生服务发现

如果你想要在自己的应用中使用 Kubernetes API 进行服务发现,可以查询 API 服务器, 寻找匹配的 EndpointSlice 对象。 只要 Service 中的 Pod 集合发生变化,Kubernetes 就会为其更新 EndpointSlice。

对于非本地应用,Kubernetes 提供了在应用和后端 Pod 之间放置网络端口或负载均衡器的方法。

无论采用那种方式,你的负载都可以使用这里的服务发现机制找到希望连接的目标。

定义 Service

Kubernetes 中的 Service 是一个对象 (与 Pod 或 ConfigMap 类似)。你可以使用 Kubernetes API 创建、查看或修改 Service 定义。 通常你会使用 kubectl 这类工具来替你发起这些 API 调用。

例如,假定有一组 Pod,每个 Pod 都在侦听 TCP 端口 9376,并且它们还被打上 app.kubernetes.io/name=MyApp 标签。你可以定义一个 Service 来发布该 TCP 侦听器

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9376

应用上述清单时,系统将创建一个名为 "my-service" 的、 服务类型默认为 ClusterIP 的 Service。 该 Service 指向带有标签 app.kubernetes.io/name: MyApp 的所有 Pod 的 TCP 端口 9376。

Kubernetes 为该服务分配一个 IP 地址(称为 "集群 IP"),供虚拟 IP 地址机制使用。 有关该机制的更多详情,请阅读虚拟 IP 和服务代理。

此 Service 的控制器不断扫描与其选择算符匹配的 Pod 集合,然后对 Service 的 EndpointSlice 集合执行必要的更新。

说明:
Service 能够将任意入站 port 映射到某个 targetPort。 默认情况下,出于方便考虑,targetPort 会被设置为与 port 字段相同的值。

端口定义

Pod 中的端口定义是有名字的,你可以在 Service 的 targetPort 属性中引用这些名字。

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app.kubernetes.io/name: proxy
spec:
  containers:
  - name: nginx
    image: nginx:stable
    ports:
      - containerPort: 80
        name: http-web-svc

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app.kubernetes.io/name: proxy
  ports:
  - name: name-of-service-port
    protocol: TCP
    port: 80
    targetPort: http-web-svc

Service 的默认协议是 TCP; 你还可以使用其他受支持的任何协议。

由于许多 Service 需要公开多个端口,所以 Kubernetes 为同一服务定义多个端口。 每个端口定义可以具有相同的 protocol,也可以具有不同协议。

没有选择算符的 Service

由于选择算符的存在,Service 的最常见用法是为 Kubernetes Pod 集合提供访问抽象, 但是当与相应的 EndpointSlice 对象一起使用且没有设置选择算符时,Service 也可以为其他类型的后端提供抽象, 包括在集群外运行的后端。

例如:

  • 你希望在生产环境中使用外部数据库集群,但在测试环境中使用自己的数据库。
  • 你希望让你的 Service 指向另一个名字空间(Namespace)中或其它集群中的服务。
  • 你正在将工作负载迁移到 Kubernetes 上来。在评估所采用的方法时,你仅在 Kubernetes 中运行一部分后端。
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

由于此 Service 没有选择算符,因此不会自动创建对应的 EndpointSlice(和旧版的 Endpoints)对象。 你可以通过手动添加 EndpointSlice 对象,将 Service 映射到该服务运行位置的网络地址和端口:

yaml 复制代码
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
  name: my-service-1 # 按惯例将服务的名称用作 EndpointSlice 名称的前缀
  labels:
    # 你应设置 "kubernetes.io/service-name" 标签。
    # 设置其值以匹配服务的名称
    kubernetes.io/service-name: my-service
addressType: IPv4
ports:
  - name: '' # 应与上面定义的服务端口的名称匹配
    appProtocol: http
    protocol: TCP
    port: 9376
endpoints:  # 此列表中的 IP 地址可以按任何顺序显示
  - addresses:
      - "10.4.5.6"
  - addresses:
      - "10.1.2.3"
访问没有选择算符的 Service

访问没有选择算符的 Service 与有选择算符的 Service 的原理相同。 在没有选择算符的 Service 示例中, 流量被路由到 EndpointSlice 清单中定义的两个端点之一: 通过 TCP 协议连接到 10.1.2.3 或 10.4.5.6 的端口 9376。

ExternalName Service 是 Service 的特例,它没有选择算符,而是使用 DNS 名称。 更多的相关信息,请参阅 ExternalName 一节。

EndpointSlices

EndpointSlice 对象表示某个服务的后端网络端点的子集(切片)。

你的 Kubernetes 集群会跟踪每个 EndpointSlice 所表示的端点数量。 如果 Service 的端点太多以至于达到阈值,Kubernetes 会添加另一个空的 EndpointSlice 并在其中存储新的端点信息。 默认情况下,一旦现有 EndpointSlice 都包含至少 100 个端点,Kubernetes 就会创建一个新的 EndpointSlice。 在需要添加额外的端点之前,Kubernetes 不会创建新的 EndpointSlice。

Endpoints

在 Kubernetes API 中,Endpoints (该资源类别为复数形式)定义的是网络端点的列表,通常由 Service 引用, 以定义可以将流量发送到哪些 Pod。

推荐使用 EndpointSlice API 替换 Endpoints。

超出容量的端点

Kubernetes 限制单个 Endpoints 对象中可以容纳的端点数量。 当一个 Service 拥有 1000 个以上支撑端点时,Kubernetes 会截断 Endpoints 对象中的数据。 由于一个 Service 可以链接到多个 EndpointSlice 之上,所以 1000 个支撑端点的限制仅影响旧版的 Endpoints API。

如出现端点过多的情况,Kubernetes 选择最多 1000 个可能的后端端点存储到 Endpoints 对象中, 并在 Endpoints 上设置注解 endpoints.kubernetes.io/over-capacity: truncated。 如果后端 Pod 的数量降至 1000 以下,控制平面也会移除该注解。

请求流量仍会被发送到后端,但任何依赖旧版 Endpoints API 的负载均衡机制最多只能将流量发送到 1000 个可用的支撑端点。

这一 API 限制也意味着你不能手动将 Endpoints 更新为拥有超过 1000 个端点。

应用协议

appProtocol 字段提供了一种为每个 Service 端口设置应用协议的方式。 此字段被实现代码用作一种提示信息,以便针对实现能够理解的协议提供更为丰富的行为。 此字段的取值会被映射到对应的 Endpoints 和 EndpointSlice 对象中。

多端口 Service

对于某些 Service,你需要公开多个端口。Kubernetes 允许你为 Service 对象配置多个端口定义。 为 Service 使用多个端口时,必须为所有端口提供名称,以使它们无歧义。 例如:

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9376
    - name: https
      protocol: TCP
      port: 443
      targetPort: 9377

如 yarnrm service

bash 复制代码
kubectl describe service yarnrm -n bigdata
yaml 复制代码
Name:              yarnrm
Namespace:         bigdata
Labels:            app=yarnrm
                   svctype=internal
Annotations:       <none>
Selector:          app=yarnrm
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                None
IPs:               None
Port:              yarnrm-http-web  8088/TCP
TargetPort:        8088/TCP
Endpoints:         10.148.1.35:8088,10.148.1.36:8088
Port:              yarnrm-https-web  8090/TCP
TargetPort:        8090/TCP
Endpoints:         10.148.1.35:8090,10.148.1.36:8090
Port:              yarnrm-rpc  8032/TCP
TargetPort:        8032/TCP
Endpoints:         10.148.1.35:8032,10.148.1.36:8032
Port:              yarnrm-scheduler-rpc  8030/TCP
TargetPort:        8030/TCP
Endpoints:         10.148.1.35:8030,10.148.1.36:8030
Port:              yarnrm-trakcer  8031/TCP
TargetPort:        8031/TCP
Endpoints:         10.148.1.35:8031,10.148.1.36:8031
Port:              yarnrm-admin  8033/TCP
TargetPort:        8033/TCP
Endpoints:         10.148.1.35:8033,10.148.1.36:8033
Port:              yarnrm-monitor  15401/TCP
TargetPort:        15401/TCP
Endpoints:         10.148.1.35:15401,10.148.1.36:15401
Session Affinity:  None
Events:            <none>

服务类型

对一些应用的某些部分(如前端),你可能希望将其公开于某外部 IP 地址, 也就是可以从集群外部访问的某个地址。

Kubernetes Service 类型允许指定你所需要的 Service 类型。

可用的 type 值及其行为有

  • ClusterIP

    通过集群的内部 IP 公开 Service,选择该值时 Service 只能够在集群内部访问。 这也是你没有为服务显式指定 type 时使用的默认值。 你可以使用 Ingress 或者 Gateway API 向公共互联网公开服务。

  • NodePort

    通过每个节点上的 IP 和静态端口(NodePort)公开 Service。 为了让 Service 可通过节点端口访问,Kubernetes 会为 Service 配置集群 IP 地址, 相当于你请求了 type: ClusterIP 的服务。

  • LoadBalancer

    使用云平台的负载均衡器向外部公开 Service。Kubernetes 不直接提供负载均衡组件; 你必须提供一个,或者将你的 Kubernetes 集群与某个云平台集成。

  • ExternalName

    将服务映射到 externalName 字段的内容(例如,映射到主机名 api.foo.bar.example)。 该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 CNAME 记录。 集群不会为之创建任何类型代理。

type: ClusterIP

此默认 Service 类型从你的集群中为此预留的 IP 地址池中分配一个 IP 地址。

其他几种 Service 类型在 ClusterIP 类型的基础上进行构建。

如果你定义的 Service 将 .spec.clusterIP 设置为 "None",则 Kubernetes 不会为其分配 IP 地址。有关详细信息,请参阅无头服务。

选择自己的 IP 地址

在创建 Service 的请求中,你可以通过设置 spec.clusterIP 字段来指定自己的集群 IP 地址。 比如,希望复用一个已存在的 DNS 条目,或者遗留系统已经配置了一个固定的 IP 且很难重新配置。

你所选择的 IP 地址必须是合法的 IPv4 或者 IPv6 地址,并且这个 IP 地址在 API 服务器上所配置的 service-cluster-ip-range CIDR 范围内。 如果你尝试创建一个带有非法 clusterIP 地址值的 Service,API 服务器会返回 HTTP 状态码 422, 表示值不合法。

请阅读避免冲突节, 以了解 Kubernetes 如何协助降低两个不同的 Service 试图使用相同 IP 地址的风险和影响

type: NodePort

如果你将 type 字段设置为 NodePort,则 Kubernetes 控制平面将在 --service-node-port-range 标志所指定的范围内分配端口(默认值:30000-32767)。 每个节点将该端口(每个节点上的相同端口号)上的流量代理到你的 Service。 你的 Service 在其 .spec.ports[*].nodePort 字段中报告已分配的端口。

使用 NodePort 可以让你自由设置自己的负载均衡解决方案, 配置 Kubernetes 不完全支持的环境, 甚至直接公开一个或多个节点的 IP 地址。

对于 NodePort 服务,Kubernetes 额外分配一个端口(TCP、UDP 或 SCTP 以匹配 Service 的协议)。 集群中的每个节点都将自己配置为监听所分配的端口,并将流量转发到与该 Service 关联的某个就绪端点。 通过使用合适的协议(例如 TCP)和适当的端口(分配给该 Service)连接到任何一个节点, 你就能够从集群外部访问 type: NodePort 服务。

选择你自己的端口

如果需要特定的端口号,你可以在 nodePort 字段中指定一个值。 控制平面将或者为你分配该端口,或者报告 API 事务失败。 这意味着你需要自行注意可能发生的端口冲突。 你还必须使用有效的端口号,该端口号在配置用于 NodePort 的范围内。

以下是 type: NodePort 服务的一个清单示例,其中指定了 NodePort 值(在本例中为 30007):

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    # 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。
    - port: 80
      targetPort: 80
      # 可选字段
      # 默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号
      #(默认:30000-32767)
      nodePort: 30007
预留 NodePort 端口范围以避免发生冲突

为 NodePort 服务分配端口的策略既适用于自动分配的情况,也适用于手动分配的场景。 当某个用于希望创建一个使用特定端口的 NodePort 服务时,该目标端口可能与另一个已经被分配的端口冲突。

为了避免这个问题,用于 NodePort 服务的端口范围被分为两段。 动态端口分配默认使用较高的端口段,并且在较高的端口段耗尽时也可以使用较低的端口段。 用户可以从较低端口段中分配端口,降低端口冲突的风险。

为 type: NodePort 服务自定义 IP 地址配置

你可以配置集群中的节点使用特定 IP 地址来支持 NodePort 服务。 如果每个节点都连接到多个网络(例如:一个网络用于应用流量,另一网络用于节点和控制平面之间的流量), 你可能想要这样做。

如果你要指定特定的 IP 地址来为端口提供代理,可以将 kube-proxy 的 --nodeport-addresses 标志或 kube-proxy 配置文件中的等效字段 nodePortAddresses 设置为特定的 IP 段。

此标志接受逗号分隔的 IP 段列表(例如 10.0.0.0/8、192.0.2.0/25),用来设置 IP 地址范围。 kube-proxy 应视将其视为所在节点的本机地址。

例如,如果你使用 --nodeport-addresses=127.0.0.0/8 标志启动 kube-proxy, 则 kube-proxy 仅选择 NodePort 服务的本地回路接口。 --nodeport-addresses 的默认值是一个空的列表。 这意味着 kube-proxy 将认为所有可用网络接口都可用于 NodePort 服务 (这也与早期的 Kubernetes 版本兼容。)

type: LoadBalancer

在使用支持外部负载均衡器的云平台时,如果将 type 设置为 "LoadBalancer", 则平台会为 Service 提供负载均衡器。 负载均衡器的实际创建过程是异步进行的,关于所制备的负载均衡器的信息将会通过 Service 的 status.loadBalancer 字段公开出来。 例如:

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
  clusterIP: 10.0.171.239
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 192.0.2.127

来自外部负载均衡器的流量将被直接重定向到后端各个 Pod 上,云平台决定如何进行负载平衡。

要实现 type: LoadBalancer 的服务,Kubernetes 通常首先进行与请求 type: NodePort 服务类似的更改。cloud-controller-manager 组件随后配置外部负载均衡器, 以将流量转发到所分配的节点端口。

你可以将负载均衡 Service 配置为忽略分配节点端口, 前提是云平台实现支持这点。

某些云平台允许你设置 loadBalancerIP。这时,平台将使用用户指定的 loadBalancerIP 来创建负载均衡器。如果没有设置 loadBalancerIP 字段,平台将会给负载均衡器分配一个临时 IP。 如果设置了 loadBalancerIP,但云平台并不支持这一特性,所设置的 loadBalancerIP 值将会被忽略。

混合协议类型的负载均衡器

默认情况下,对于 LoadBalancer 类型的 Service,当其中定义了多个端口时, 所有端口必须使用相同的协议,并且该协议必须是被云平台支持的。

当服务中定义了多个端口时,特性门控 MixedProtocolLBService(从 kube-apiserver 1.24 版本起默认为启用)允许 LoadBalancer 类型的服务使用不同的协议。

设置负载均衡器实现的类别

对于 type 设置为 LoadBalancer 的 Service,spec.loadBalancerClass 字段允许你使用有别于云平台的默认负载均衡器的实现。

默认情况下,.spec.loadBalancerClass 是未设置的,如果集群使用 --cloud-provider 件标志配置了云平台,LoadBalancer 类型 Service 会使用云平台的默认负载均衡器实现。

如果你设置了 .spec.loadBalancerClass,则假定存在某个与所指定的类相匹配的负载均衡器实现在监视 Service 变更。所有默认的负载均衡器实现(例如,由云平台所提供的)都会忽略设置了此字段的 Service。 .spec.loadBalancerClass 只能设置到类型为 LoadBalancer 的 Service 之上, 而且一旦设置之后不可变更。

.spec.loadBalancerClass 的值必须是一个标签风格的标识符, 可以有选择地带有类似 "internal-vip" 或 "example.com/internal-vip" 这类前缀。 没有前缀的名字是保留给最终用户的。

禁用负载均衡服务的节点端口分配

在混合环境中,有时有必要在同一(虚拟)网络地址段内路由来自 Service 的流量。

在水平分割(Split-Horizon)DNS 环境中,你需要两个 Service 才能将内部和外部流量都路由到你的端点。

如要设置内部负载均衡器,请根据你所使用的云平台,为 Service 添加注解.

ExternalName 类型

类型为 ExternalName 的 Service 将 Service 映射到 DNS 名称,而不是典型的选择算符, 例如 my-service 或者 cassandra。你可以使用 spec.externalName 参数指定这些服务。

例如,以下 Service 定义将 prod 名字空间中的 my-service 服务映射到 my.database.example.com

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

无头服务(Headless Services)

有时你并不需要负载均衡,也不需要单独的 Service IP。遇到这种情况,可以通过显式设置 集群 IP(spec.clusterIP)的值为 "None" 来创建无头服务(Headless Service)。

你可以使用无头 Service 与其他服务发现机制交互,而不必绑定到 Kubernetes 的实现。

无头 Service 不会获得集群 IP,kube-proxy 不会处理这类 Service, 而且平台也不会为它们提供负载均衡或路由支持。

无头 Service 允许客户端直接连接到它所偏好的任一 Pod。 无头 Service 不使用虚拟 IP 地址和代理 配置路由和数据包转发;相反,无头 Service 通过内部 DNS 记录报告各个 Pod 的端点 IP 地址,这些 DNS 记录是由集群的 DNS 服务所提供的。 这些 DNS 记录是由集群内部 DNS 服务所提供的 要定义无头 Service,你需要将 .spec.type 设置为 ClusterIP(这也是 type 的默认值),并进一步将 .spec.clusterIP 设置为 None。

字符串值 None 是一种特殊情况,与未设置 .spec.clusterIP 字段不同。

DNS 如何自动配置取决于 Service 是否定义了选择器:

带选择算符的服务

对定义了选择算符的无头 Service,Kubernetes 控制平面在 Kubernetes API 中创建 EndpointSlice 对象,并且修改 DNS 配置返回 A 或 AAAA 记录(IPv4 或 IPv6 地址), 这些记录直接指向 Service 的后端 Pod 集合。

无选择算符的服务

对没有定义选择算符的无头 Service,控制平面不会创建 EndpointSlice 对象。 然而 DNS 系统会执行以下操作之一:

  • 对于 type: ExternalName Service,查找和配置其 CNAME 记录;
  • 对所有其他类型的 Service,针对 Service 的就绪端点的所有 IP 地址,查找和配置 DNS A / AAAA 记录:
    • 对于 IPv4 端点,DNS 系统创建 A 记录。
    • 对于 IPv6 端点,DNS 系统创建 AAAA 记录。

服务发现

对于在集群内运行的客户端,Kubernetes 支持两种主要的服务发现模式:环境变量和 DNS。

环境变量

当 Pod 运行在某 Node 上时,kubelet 会在其中为每个活跃的 Service 添加一组环境变量。 kubelet 会添加环境变量 {SVCNAME}_SERVICE_HOST 和 {SVCNAME}_SERVICE_PORT。 这里 Service 的名称被转为大写字母,横线被转换成下划线。

例如,一个 Service redis-primary 公开了 TCP 端口 6379, 同时被分配了集群 IP 地址 10.0.0.11,这个 Service 生成的环境变量如下:

bash 复制代码
REDIS_PRIMARY_SERVICE_HOST=10.0.0.11
REDIS_PRIMARY_SERVICE_PORT=6379
REDIS_PRIMARY_PORT=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP_PROTO=tcp
REDIS_PRIMARY_PORT_6379_TCP_PORT=6379
REDIS_PRIMARY_PORT_6379_TCP_ADDR=10.0.0.11
说明:
当你的 Pod 需要访问某 Service,并且你在使用环境变量方法将端口和集群 IP 发布到客户端 Pod 
时,必须在客户端 Pod 出现之前创建该 Service。 否则,这些客户端 Pod 
中将不会出现对应的环境变量。

如果仅使用 DNS 来发现 Service 的集群 IP,则无需担心此顺序问题。

DNS

你可以(并且几乎总是应该)使用插件(add-on) 来为 Kubernetes 集群安装 DNS 服务。

能够感知集群的 DNS 服务器(例如 CoreDNS)会监视 Kubernetes API 中的新 Service, 并为每个 Service 创建一组 DNS 记录。如果在整个集群中都启用了 DNS,则所有 Pod 都应该能够通过 DNS 名称自动解析 Service。

例如,如果你在 Kubernetes 命名空间 my-ns 中有一个名为 my-service 的 Service, 则控制平面和 DNS 服务共同为 my-service.my-ns 生成 DNS 记录。 名字空间 my-ns 中的 Pod 应该能够通过按名检索 my-service 来找到服务 (my-service.my-ns 也可以)。

其他名字空间中的 Pod 必须将名称限定为 my-service.my-ns。 这些名称将解析为分配给 Service 的集群 IP。

Kubernetes 还支持命名端口的 DNS SRV(Service)记录。 如果 Service my-service.my-ns 具有名为 http 的端口,且协议设置为 TCP, 则可以用 _http._tcp.my-service.my-ns 执行 DNS SRV 查询以发现 http 的端口号以及 IP 地址。

Kubernetes DNS 服务器是唯一的一种能够访问 ExternalName 类型的 Service 的方式。 关于 ExternalName 解析的更多信息可以查看 Service 与 Pod 的 DNS。

虚拟 IP 寻址机制

阅读虚拟 IP 和 Service 代理以了解 Kubernetes 提供的使用虚拟 IP 地址公开服务的机制。

流量分发

.spec.trafficDistribution 字段提供了另一种影响 Kubernetes Service 内流量路由的方法。 虽然流量策略侧重于严格的语义保证,但流量分发允许你表达一定的偏好(例如路由到拓扑上更接近的端点)。 这一机制有助于优化性能、成本或可靠性。 如果你为集群及其所有节点启用了 ServiceTrafficDistribution 特性门控, 则可以使用此可选字段。 Kubernetes 1.30 支持以下字段值:

  • PreferClose
    表示优先将流量路由到拓扑上最接近客户端的端点。 "拓扑上邻近"的解释可能因实现而异,并且可能涵盖同一节点、机架、区域甚至区域内的端点。 设置此值允许实现进行不同的权衡,例如按距离优化而不是平均分配负载。 如果这种权衡不可接受,用户不应设置此值。

如果未设置该字段,实现将应用其默认路由策略, 详见流量分发。

流量策略

你可以设置 .spec.internalTrafficPolicy 和 .spec.externalTrafficPolicy 字段来控制 Kubernetes 如何将流量路由到健康("就绪")的后端。

会话的黏性

如果你想确保来自特定客户端的连接每次都传递到同一个 Pod,你可以配置基于客户端 IP 地址的会话亲和性。可阅读会话亲和性 来进一步学习。

外部 IP

如果有外部 IP 能够路由到一个或多个集群节点上,则 Kubernetes Service 可以在这些 externalIPs 上公开出去。当网络流量进入集群时,如果外部 IP(作为目的 IP 地址)和端口都与该 Service 匹配, Kubernetes 所配置的规则和路由会确保流量被路由到该 Service 的端点之一.

定义 Service 时,你可以为任何服务类型指定 externalIPs。

在下面的例子中,名为 my-service 的服务可以在 "198.51.100.32:80" (根据 .spec.externalIPs[] 和 .spec.ports[].port 得出)上被客户端使用 TCP 协议访问。

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 49152
  externalIPs:
    - 198.51.100.32
相关推荐
陌北v17 分钟前
Docker Compose 配置指南
运维·docker·容器·docker-compose
catoop36 分钟前
K8s 无头服务(Headless Service)
云原生·容器·kubernetes
阿里嘎多学长1 小时前
docker怎么部署高斯数据库
运维·数据库·docker·容器
liuxuzxx2 小时前
1.24.1-Istio安装
kubernetes·istio·service mesh
G_whang2 小时前
windos 安装docker
运维·docker·容器
道一云黑板报2 小时前
Flink集群批作业实践:七析BI批作业执行
大数据·分布式·数据分析·flink·kubernetes
运维小文3 小时前
K8S中的PV、PVC介绍和使用
docker·云原生·容器·kubernetes·存储
ζั͡山 ั͡有扶苏 ั͡✾4 小时前
Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版)
云原生·容器·kubernetes
Hadoop_Liang4 小时前
Kubernetes ConfigMap的创建与使用
云原生·容器·kubernetes
ljh5746491194 小时前
负载均衡的原理
运维·负载均衡