选择正确的 Kubernetes 服务类型:ClusterIP、NodePort 与 LoadBalancer

比较 ClusterIP、NodePort 和 LoadBalancer,以便使用正确的服务类型暴露 Kubernetes 应用。

选择合适的 Kubernetes 服务类型:ClusterIP vs NodePort vs LoadBalancer

选择合适的 Kubernetes 服务类型决定了谁能访问你的应用以及流量如何到达。选错了,你的应用可能无法访问、过度暴露,或者绑定了你并不需要的云资源。

本指南对三种基本的 Kubernetes 服务类型:ClusterIPNodePortLoadBalancer 进行了全面比较。通过理解每种类型的用例、实现机制和相关权衡,你可以做出明智的决策,使其与应用的网络需求完美匹配,确保内部通信和外部访问都得到有效管理。

理解 Kubernetes 服务

在深入探讨具体类型之前,记住 Kubernetes 服务的作用至关重要。Pod 是短暂的;它们的 IP 地址会随着创建、销毁或重新调度而改变。服务为一组动态变化的 Pod 提供了一个稳定的端点(固定的 IP 地址和 DNS 名称),实现了集群内的可靠通信。

服务使用 Service 对象清单定义,通常指定一个 selector 来查找相关的 Pod,以及一个 type 来定义服务的暴露方式。

ClusterIP:内部通信

ClusterIP 是默认且最基本的服务类型。它在集群内部的一个内部 IP 地址上暴露服务。此服务仅能从集群内部访问。

ClusterIP 的用例

  • 后端服务: 适用于数据库、内部 API、缓存层或微服务,这些服务只需要与同一 Kubernetes 集群内运行的其他服务或前端应用通信。
  • 内部发现: 它利用 Kubernetes 的内部 DNS 提供稳定的服务发现名称(例如 my-database.namespace.svc.cluster.local)。

实现细节

当创建 ClusterIP 服务时,Kubernetes 会为其分配一个仅在集群网络结构内部可路由的虚拟 IP 地址。外部流量无法直接访问此 IP。

示例清单 (ClusterIP):

apiVersion: v1
kind: Service
metadata:
  name: internal-api
spec:
  selector:
    app: backend-service
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: ClusterIP

提示: 如果你只是在构建一个所有组件都位于集群内部的分布式系统,ClusterIP 是最安全、最高效的选择,因为它避免了不必要的对外暴露。

NodePort:通过集群节点暴露服务

NodePort 是从外部暴露服务的最简单方式。它在集群中的每个节点(虚拟机或物理机)上打开一个特定端口,并将到达该端口的外部流量路由到服务。

NodePort 的用例

  • 开发和测试: 在开发过程中,当完整的云负载均衡器设置过于繁琐时,可用于快速测试可从外部访问的服务。
  • 非云环境: 在裸机或本地 Kubernetes 安装中必不可少,因为在这些环境中无法使用原生的云负载均衡集成。

实现细节

当创建 NodePort 服务时,Kubernetes 会在每个节点上选择一个配置范围内的静态端口(默认是 30000–32767)。该服务通过以下方式暴露应用:

http://<NodeIP>:<NodePort>

如果你有三个节点,IP 分别为 10.0.0.110.0.0.210.0.0.3,并且 NodePort 是 30080,你可以通过这三个 IP 中的任何一个在端口 30080 上访问该服务。

示例清单 (NodePort):

apiVersion: v1
kind: Service
metadata:
  name: test-web-app
spec:
  selector:
    app: frontend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30080 # 可选:指定外部端口,否则 Kubernetes 会选择一个
  type: NodePort

警告: 由于服务在每个节点上都暴露,你的外部路由层仍然需要避免不健康的节点。默认的 NodePort 范围是 30000-32767,但集群管理员可以配置不同的范围。

LoadBalancer:云原生外部暴露

LoadBalancer 通过一个外部负载均衡器暴露服务,前提是你的集群具有可以配置该负载均衡器的集成。这在托管云 Kubernetes 平台上很常见。在许多生产环境中,你也可以在几个内部服务前面放置一个 Ingress 或 Gateway,而不是为每个应用创建一个负载均衡器。

LoadBalancer 的用例

  • 生产部署: 提供稳健、高可用的外部访问,并与云提供商的基础设施无缝集成。
  • 自动 IP 管理: 它抽象了了解单个节点 IP 或管理端口冲突的需要。

实现细节

在支持的环境中创建类型为 LoadBalancer 的服务时,云控制器管理器或负载均衡控制器会配置一个外部负载均衡器,并将其配置为将流量路由到该服务。

外部地址由提供商分配。它可能在服务的生命周期内保持稳定,但除非你通过特定于提供商的设置进行配置,否则它不总是保留的静态 IP。

示例清单 (LoadBalancer):

apiVersion: v1
kind: Service
metadata:
  name: public-web-service
spec:
  selector:
    app: public-facing
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer

创建后,输出(使用 kubectl get svc)将显示分配的外部 IP:

NAME                  TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)        AGE
public-web-service    LoadBalancer   10.96.45.11   34.120.200.55    80:30021/TCP   1m

现在可以通过 http://34.120.200.55 访问该应用。

最佳实践: 对于 HTTPS,使用你的平台支持的最佳模式:云负载均衡器注解、Ingress 控制器或 Kubernetes Gateway API。将 TLS 配置保留在一个管理良好的层中,而不是分散到每个 Pod。

总结比较表

特性 ClusterIP NodePort LoadBalancer
主要用途 内部服务通信 简单的外部访问(测试/裸机) 生产环境、云原生外部访问
可达性 仅在集群内部 每个节点上的静态端口 (30000-32767) 由云提供商管理的外部 IP
IP 稳定性 稳定的内部 IP 稳定的节点 IP,但需要知道端口 稳定的外部 IP(取决于提供商)
云依赖 需要负载均衡器集成
成本 无外部负载均衡器 使用节点资源 通常按外部负载均衡器资源计费
配置复杂度 最低 中等(需要云配置)

要点

选择正确的服务类型是 Kubernetes 网络中的一个基本步骤:

  1. 从内部开始 (ClusterIP): 如果你的服务永远不需要从集群外部访问,始终使用 ClusterIP。这最大限度地减少了攻击面和开销。
  2. 测试/裸机 (NodePort): 如果你需要基本的外部测试,或者是在主要云环境之外运行 Kubernetes,NodePort 提供了即时但不太稳健的外部访问。
  3. 生产云 (LoadBalancer): 对于托管在 AWS、GCP 或 Azure 上且需要持久、稳定和专用外部入口点的任何生产应用,LoadBalancer 是正确的选择,它利用云基础设施实现弹性。

通过将服务类型与所需的可访问性和部署环境对齐,你可以确保在容器编排架构中获得最佳性能、安全性和集成。