对一些应用的某些部分(如前端),可能希望将其暴露给 Kubernetes 集群外部的 IP 地址。
Kubernetes ServiceTypes 允许指定你所需要的 Service 类型。
可用的 type 值及其行为有:
1、ClusterIP
通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。 这也是你没有为服务显式指定 type 时使用的默认值。 你可以使用 Ingress 或者 Gateway API 向公众暴露服务。
2、NodePort
通过每个节点上的 IP 和静态端口(NodePort)暴露服务。 为了让节点端口可用,Kubernetes 设置了集群 IP 地址,这等同于你请求 type: ClusterIP 的服务。
3、LoadBalancer
使用云提供商的负载均衡器向外部暴露服务。 Kubernetes 不直接提供负载均衡组件;你必须提供一个,或者将你的 Kubernetes 集群与云提供商集成。
4、ExternalName
将服务映射到 externalName 字段的内容(例如,映射到主机名 api.foo.bar.example)。 该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 CNAME 记录。 无需创建任何类型代理。
服务 API 中的 type 字段被设计为层层递进的形式 - 每个级别都建立在前一个级别基础上。 并不是所有云提供商都如此严格要求的,但 Kubernetes 的 Service API 设计要求满足这一逻辑。
此默认服务类型从你的集群中有意预留的 IP 地址池中分配一个 IP 地址
其他几种服务类型在 ClusterIP 类型的基础上进行构建
如果你定义的服务将 .spec.clusterIP 设置为 “None”,则 Kubernetes 不会分配 IP 地址。有关详细信息,请参阅 headless 服务
在 Service 创建的请求中,可以通过设置 spec.clusterIP 字段来指定自己的集群 IP 地址。 比如,希望替换一个已经已存在的 DNS 条目,或者遗留系统已经配置了一个固定的 IP 且很难重新配置
用户选择的 IP 地址必须合法,并且这个 IP 地址在 service-cluster-ip-range CIDR 范围内, 这对 API 服务器来说是通过一个标识来指定的。 如果 IP 地址不合法,API 服务器会返回 HTTP 状态码 422,表示值不合法
阅读避免冲突, 了解 Kubernetes 如何协助降低两种不同服务试图使用相同 IP 地址的风险和影响
如果你将 type 字段设置为 NodePort,则 Kubernetes 控制平面将在 --service-node-port-range 标志指定的范围内分配端口(默认值:30000-32767)。 每个节点将那个端口(每个节点上的相同端口号)代理到你的服务中。 你的服务在其 .spec.ports[*].nodePort 字段中报告已分配的端口
使用 NodePort 可以让你自由设置自己的负载均衡解决方案, 配置 Kubernetes 不完全支持的环境, 甚至直接暴露一个或多个节点的 IP 地址
对于 NodePort 服务,Kubernetes 额外分配一个端口(TCP、UDP 或 SCTP 以匹配服务的协议)。 集群中的每个节点都将自己配置为监听分配的端口并将流量转发到与该服务关联的某个就绪端点。 通过使用适当的协议(例如 TCP)和适当的端口(分配给该服务)连接到所有节点, 你将能够从集群外部使用 type: NodePort 服务
如果需要特定的端口号,你可以在 nodePort 字段中指定一个值。 控制平面将为你分配该端口或报告 API 事务失败。 这意味着你需要自己注意可能发生的端口冲突。 你还必须使用有效的端口号,该端口号在配置用于 NodePort 的范围内。
以下是 type: NodePort 服务的一个示例清单,它指定了一个 NodePort 值(在本例中为 30007)
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
你可以在集群中设置节点以使用特定 IP 地址来提供 NodePort 服务。 如果每个节点都连接到多个网络(例如:一个网络用于应用程序流量,另一个网络用于节点和控制平面之间的流量), 你可能需要执行此操作。
如果你要指定特定的 IP 地址来代理端口,可以将 kube-proxy 的 --nodeport-addresses 标志或 kube-proxy 配置文件的等效 nodePortAddresses 字段设置为特定的 IP 段。
此标志采用逗号分隔的 IP 段列表(例如 10.0.0.0/8、192.0.2.0/25)来指定 kube-proxy 应视为该节点本地的 IP 地址范围。
例如,如果你使用 --nodeport-addresses=127.0.0.0/8 标志启动 kube-proxy, 则 kube-proxy 仅选择 NodePort 服务的环回接口。 --nodeport-addresses 的默认值是一个空列表。 这意味着 kube-proxy 应考虑 NodePort 的所有可用网络接口。 (这也与早期的 Kubernetes 版本兼容。)
此服务呈现为 :spec.ports[].nodePort 和 .spec.clusterIP:spec.ports[].port。 如果设置了 kube-proxy 的 --nodeport-addresses 标志或 kube-proxy 配置文件中的等效字段, 则 将是过滤的节点 IP 地址(或可能的 IP 地址
在使用支持外部负载均衡器的云提供商的服务时,设置 type 的值为 “LoadBalancer”, 将为 Service 提供负载均衡器。 负载均衡器是异步创建的,关于被提供的负载均衡器的信息将会通过 Service 的 status.loadBalancer 字段发布出去。
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app.kubernetes.io/name: nginx
ports:
- protocol: TCP
port: 80
targetPort: 8080
clusterIP: 10.10.2.5
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 192.168.122.235
来自外部负载均衡器的流量将直接重定向到后端 Pod 上,由云提供商决定如何进行负载平衡。
要实现 type: LoadBalancer 的服务,Kubernetes 通常首先进行与请求 type: NodePort 服务等效的更改。 cloud-controller-manager 组件随后配置外部负载均衡器以将流量转发到已分配的节点端口。
你可以将负载均衡服务配置为忽略分配节点端口, 前提是云提供商实现支持这点。
某些云提供商允许设置 loadBalancerIP。 在这些情况下,将根据用户设置的 loadBalancerIP 来创建负载均衡器。 如果没有设置 loadBalancerIP 字段,将会给负载均衡器指派一个临时 IP。 如果设置了 loadBalancerIP,但云提供商并不支持这种特性,那么设置的 loadBalancerIP 值将会被忽略掉。
针对 Service 的 .spec.loadBalancerIP 字段已在 Kubernetes v1.24 中被弃用。
此字段的定义模糊,其含义因实现而异。它也不支持双协议栈联网。 此字段可能会在未来的 API 版本中被移除。
如果你正在集成某云平台,该平台通过(特定于提供商的)注解为 Service 指定负载均衡器 IP 地址, 你应该切换到这样做。
如果你正在为集成到 Kubernetes 的负载均衡器编写代码,请避免使用此字段。 你可以与 Gateway 而不是 Service 集成, 或者你可以在 Service 上定义自己的(特定于提供商的)注解,以指定等效的细节。