在Kubernetes中,ClusterIP、NodePort和LoadBalancer服务类型有什么区别?

518

问题1 - 我正在阅读文档,但有些措辞让我有点困惑。它说:

ClusterIP: 在群集内部 IP 上公开服务。选择此值将使服务仅可从群集内部访问。这是默认的 ServiceType。

NodePort: 在每个节点的 IP 上公开服务,使用静态端口(NodePort)。自动创建一个 ClusterIP 服务,用于路由到 NodePort 服务。您可以通过请求 <NodeIP>:<NodePort> 来从群集外部联系 NodePort 服务。

LoadBalancer: 使用云提供商的负载均衡器在外部公开服务。自动创建 NodePort 和 ClusterIP 服务,用于路由到外部负载均衡器。

NodePort 服务类型是否仍然使用 ClusterIP,只不过在不同的端口上向外部客户端开放?因此,在这种情况下,<NodeIP>:<NodePort> 是否与 <ClusterIP>:<NodePort> 相同?

或者,NodeIP 实际上是运行 kubectl get nodes 时找到的 IP,而不是用于 ClusterIP 服务类型的虚拟 IP?

问题2 - 此外,在下面链接图片中的图表中:

enter image description here

Client 为什么在 Node 内部?我认为它需要在 ClusterIP 服务类型的情况下在 Cluster 中。

如果为 NodePort 绘制相同的图表,将客户端完全绘制在两个 NodeCluster 之外是否有效,或者我完全错了?


3
这里有一些非常好的解释 - 可惜没有人将Ingress添加为另一个比较点。 - Paul Hodges
1
解释了 Kubernetes 中 NodePort、LoadBalancer 和 Ingress 的使用场景,并提供了详细的图示,包括外部负载均衡器。文章链接:https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0 - Apurva Singh
1
解释了..包括入口和外部负载均衡,以及漂亮的图表:https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0 - undefined
11个回答

459

ClusterIP暴露了以下信息:

  • spec.clusterIp:spec.ports[*].port

只有在集群内部才能访问此服务。可通过其spec.clusterIp端口进行访问。如果设置了spec.ports[*].targetPort,则会从端口路由到目标端口。通过调用kubectl get services获取的CLUSTER-IP是分配给该服务的集群内部IP地址。

NodePort暴露了以下信息:

  • <NodeIP>:spec.ports[*].nodePort
  • spec.clusterIp:spec.ports[*].port

如果从节点的外部IP访问此服务的nodePort,则会将请求路由到spec.clusterIp:spec.ports[*].port,再将其转发到您的spec.ports[*].targetPort(如果已设置)。此服务也可以像ClusterIP一样进行访问。

您的NodeIP是节点的外部IP地址。不能从spec.clusterIp:spec.ports[*].nodePort访问您的服务。

LoadBalancer暴露了以下信息:

  • spec.loadBalancerIp:spec.ports[*].port
  • <NodeIP>:spec.ports[*].nodePort
  • spec.clusterIp:spec.ports[*].port

您可以通过负载均衡器的IP地址访问此服务,该IP地址将路由您的请求到一个nodePort,然后将请求路由到clusterIP端口。您也可以像NodePort或ClusterIP服务一样访问此服务。


242

为了解释任何想要了解三种方式之间区别的人,这里简单介绍一下。你可以使用最小的ClusterIp(在k8s集群内)或较大的NodePort(在外部到k8s集群的网络内)或LoadBalancer(外部世界或你在负载均衡器中定义的任何内容)来暴露您的服务。

ClusterIp暴露 < NodePort暴露 < LoadBalancer暴露

  • ClusterIp
    通过 ip/name:port 的方式在k8s集群中暴露服务。
  • NodePort
    通过内部网络VM,也可以是外部到k8s的网络,以 ip/name:port 的方式暴露服务。
  • LoadBalancer
    通过外部世界或者你在负载均衡器中定义的其他方式暴露服务。

117

ClusterIP:服务可由集群中的Pod/Service访问
如果我在default命名空间中创建类型为ClusterIP的服务myservice,则将创建以下可预测静态DNS地址的服务:

myservice.default.svc.cluster.local(或只是myservice.default,或在默认命名空间中的Pod上使用“myservice”也可以)

该DNS名称只能由集群内的Pod和Service解析。

NodePort:客户端可以通过LAN访问相同的网络并且可以ping到K8s主机节点(以及集群中的Pod/Service)访问服务(注意安全性,您的k8s主机节点应位于私有子网中,因此互联网上的客户端将无法访问此服务)
如果我在3个节点的Kubernetes集群上创建mynamespace命名空间中类型为NodePort的服务mynodeportservice,则将创建一个类型为ClusterIP的服务,并且可以通过以下可预测的静态DNS地址在集群内部的客户端中访问:

mynodeportservice.mynamespace.svc.cluster.local(或只是mynodeportservice.mynamespace)

对于每个mynodeportservice监听的端口,将在30000-32767范围内随机选择一个nodeport。因此,位于集群外部的外部客户端可以访问存在于集群内部的该ClusterIP服务。

假设我们的3个K8s主机节点的IP是10.10.10.1、10.10.10.2和10.10.10.3,Kubernetes服务在端口80上监听,随机选择的NodePort为31852。

集群外的客户端可以访问10.10.10.1:31852、10.10.10.2:31852或10.10.10.3:31852(因为每个Kubernetes Host Node都监听NodePort),Kubeproxy将把请求转发到mynodeportservice的端口80。

LoadBalancer: 服务可被连接到互联网的所有人使用*(常见架构是L4 LB在DMZ中公开访问互联网,或同时给其私有和公共IP,而k8s主机节点位于私有子网中)
(注意:这是唯一一种不适用于所有Kubernetes实现的服务类型,例如裸机Kubernetes,仅当Kubernetes具有云提供商的集成时才起作用。)

如果您创建了mylbservice,则会生成一个L4 LB VM(还将隐式生成一个群集IP服务和NodePort服务)。这次我们的NodePort是30222。想法是L4 LB将具有公共IP 1.2.3.4,并且它将负载平衡并转发流量到具有私有IP地址的3个K8s主机节点。(10.10.10.1:30222、10.10.10.2:30222、10.10.10.3:30222),然后Kube Proxy将其转发到存在于集群内部的ClusterIP类型的服务。


您还问道:
NodePort服务类型是否仍在使用ClusterIP?是的*

那么NodeIP实际上是在运行kubectl get nodes时找到的IP吗?回答是肯定的。

让我们来比较一下基础知识:
一个容器位于一个Pod中,一个Pod位于一个ReplicaSet中,一个ReplicaSet位于一个Deployment中。
类似地:
ClusterIP服务是NodePort服务的一部分。NodePort服务是负载均衡器服务的一部分。


在你展示的那张图中,客户端将是集群中一个Pod内的容器。


97
假设您在本地机器上创建了一个Ubuntu虚拟机。它的IP地址是192.168.1.104
您登录到虚拟机并安装了Kubernetes。然后您创建了一个运行nginx镜像的pod。
1- 如果您想在虚拟机内部访问此nginx pod,您将创建一个绑定到该pod的ClusterIP,例如:
$ kubectl expose deployment nginxapp --name=nginxclusterip --port=80 --target-port=8080

然后在浏览器中,您可以输入nginx集群IP的地址和端口80,例如:

http://10.152.183.2:80

2- 如果您想从主机访问此nginx pod,您需要使用NodePort暴露您的部署。例如:
$ kubectl expose deployment nginxapp --name=nginxnodeport --port=80 --target-port=8080 --type=NodePort

现在你可以从你的主机访问nginx,方法如下:

http://192.168.1.104:31865/

在我的仪表板上,它们显示为:

enter image description here

下面是一个图表,展示了基本的关系。

enter image description here


58
特性 ClusterIP NodePort LoadBalancer
外部暴露 在集群内部使用内部 IP 暴露服务。 将服务暴露给外部客户端 通过专用负载均衡器访问 LoadBalancer 服务,该负载均衡器由运行 Kubernetes 的云基础设施提供
集群内部 此类型使得 Service 仅从集群内部可达 NodePort 服务,在每个节点上打开一个端口,然后将接收到的流量重定向到底层服务。 LoadBalancer 服务,通过从 Kubernetes 运行的云基础设施中提供的专用负载均衡器访问
可访问性 这是默认服务,内部客户端发送请求到稳定的内部 IP 地址。
该服务可通过内部集群IP端口访问,也可以通过所有节点上的专用端口访问。 客户端通过负载均衡器的IP连接到该服务。 Yaml配置 type: ClusterIP type: NodePort type: LoadBalancer 端口范围 聚合中的任何公共IP地址 30000-32767 聚合中的任何公共IP地址 用例 用于内部通信 最适合测试公共或私有访问或提供短时间访问权限的情况。 广泛用于外部通信

来源:


23
  • 概述:

    • Service有五种类型:

      • ClusterIP(默认):内部客户端向稳定的内部IP地址发送请求。
      • NodePort:客户端通过指定Service的一个或多个nodePort值,向一个节点的IP地址发送请求。
      • LoadBalancer:客户端向网络负载均衡器的IP地址发送请求。
      • ExternalName:内部客户端使用Service的DNS名称作为外部DNS名称的别名。
      • Headless:当您需要Pod分组但不需要稳定的IP地址时,可以使用headless服务。

      NodePort类型是ClusterIP类型的扩展。因此,NodePort类型的Service具有集群IP地址。

      LoadBalancer类型是NodePort类型的扩展。因此,LoadBalancer类型的Service具有集群IP地址和一个或多个nodePort值。


这里输入图片描述


  • 详情

    • ClusterIP

      • ClusterIP是默认并且最常见的服务类型。
      • Kubernetes会为ClusterIP服务分配一个集群内部IP地址,使得该服务只能在集群内部访问。
      • 你不能从集群外部请求访问服务(Pods)。
      • 你可以选择在服务定义文件中设置Cluster IP。
      • 使用案例
        • 集群内部的服务之间通信,例如应用程序前端和后端组件之间的通信。
    • NodePort

      • NodePort服务是ClusterIP服务的扩展。它会自动创建一个ClusterIP服务,并将流量路由到该服务上。
      • 它通过在ClusterIP服务之上添加一个集群范围的端口来将服务暴露在集群外部。
      • NodePort在每个节点的IP上暴露服务的静态端口(NodePort)。每个节点都会代理该端口到你的服务上。这意味着对该端口的任何请求都会被转发到服务上。
        • 您可以通过请求以下内容来联系NodePort服务,从集群外部访问:
        • 节点端口必须在30000-32767范围内。手动分配服务端口是可选的。如果未定义,Kubernetes将自动分配一个端口。
        • 如果您要显式选择节点端口,请确保该端口尚未被另一个服务使用。
        • 用例
          • 当您想要启用对服务的外部连接时。 使用NodePort可以使您自由地设置自己的负载平衡解决方案,配置不完全支持Kubernetes的环境,甚至直接公开一个或多个节点的IP地址。 最好放置负载均衡器以避免节点故障。
      • LoadBalancer(负载均衡器)

        • LoadBalancer是NodePort服务的扩展,自动生成NodePort和ClusterIP服务,外部负载均衡器路由到这些服务。
        • 它将NodePort与基于云的负载均衡器集成。
        • 它使用云提供商的负载均衡器将服务公开给外部。
        • 每个云提供商(AWS、Azure、GCP等)都有自己的本地负载均衡器实现。云提供商将创建一个负载均衡器,然后自动将请求路由到您的Kubernetes服务。
        • 来自外部负载均衡器的流量被定向到后端Pod。云提供商决定如何进行负载平衡。
      • 负载均衡器的实际创建是异步进行的。
      • 每当您想将服务暴露给外部世界时,都必须创建一个新的负载均衡器并获取一个IP地址。
      • 使用案例
        • 当您使用云提供商来托管您的Kubernetes集群时。
    • ExternalName(外部名称)

      • 类型为ExternalName的服务将服务映射到DNS名称,而不是像“my-service”这样的典型选择器。
      • 您可以使用spec.externalName参数指定这些服务。
      • 它通过返回其值的CNAME记录将服务映射到externalName字段的内容(例如foo.bar.example.com)。
      • 不建立任何代理。
      • 使用案例
        • 这通常用于在Kubernetes内部创建一个表示外部数据存储库(如在Kubernetes之外运行的数据库)的服务。
        • 当一个命名空间中的Pod与另一个命名空间中的服务通信时,可以将该ExternalName服务(作为本地服务)用于该通信。

19
  1. clusterIP:集群内可访问的 IP(在集群内跨节点)。
nodeA : pod1 => clusterIP1, pod2 => clusterIP2
nodeB : pod3 => clusterIP3.

通过它们的clusterIP网络,pod3可以与pod1通信。

  1. nodeport:为了使pod可通过nodeIP: nodeport从集群外部访问,它将创建/保留上面的clusterIP作为其clusterIP网络。
nodeA => nodeIPA : nodeportX
nodeB => nodeIPB : nodeportX

您可以通过nodeIPA: nodeportX或者nodeIPB: nodeportX访问pod1上的服务。两种方式都可以正常工作,因为每个节点都安装了kube-proxy(它会接收您的请求并使用clusterIP网络将其[重定向(iptables术语)]跨节点分配)。

3. 负载均衡器

基本上只是将负载均衡器放在前面,这样入站流量就会分发到nodeIPA: nodeportX和nodeIPB: nodeportX,然后继续使用上面第2步的处理流程。


18

实践理解

我创建了两个服务,一个为NodePort,另一个为ClusterIP

enter image description here

如果我想从集群内(从主节点或任何工作节点)访问服务,则两个服务都可以访问。

enter image description here

现在,如果我想从集群外访问服务,则只能访问NodePort而不能访问ClusterIP

enter image description here

在这里,您可以看到localhost无法监听端口80,即使我的nginx容器正在监听端口80。


是的,这是唯一的区别。

  • ClusterIP。公开一项仅可从集群内部访问的服务。
  • NodePort。通过每个节点的IP上的静态端口公开服务。
  • LoadBalancer。通过云提供商的负载均衡器公开服务。
  • ExternalName。通过返回CNAME记录的值来将服务映射到预定义的externalName字段。

实际应用案例

假设您需要在集群中创建以下架构,我想这是相当普遍的。

进入图像描述

现在,用户只会通过某个端口与前端进行通信。后端和数据库服务始终对外隐藏。


4
Ref - ClusterIP、NodePort和LoadBalancer服务之间的区别
ClusterIP - 在Kubernetes中,ClusterIP服务帮助集群内的应用程序相互通信。 enter image description here

NodePort - Kubernetes中的NodePort服务是一种将您的应用程序暴露给外部世界或从集群外部访问它的方式。 输入图像描述 LoadBalancer - LoadBalancer服务提供一个公共IP地址和端口,作为外部流量的入口点。 输入图像描述 三种服务类型之间的区别如下所述 输入图像描述


3
以下是关于图表中第二个问题的答案,因为该问题似乎仍未得到直接回答:enter image description here 引用块: “Client为什么要在Node内部?我认为在ClusterIP服务类型的情况下,它需要在集群中的一个Cluster内部。”
在图表中,将Client放置在Node内部以突出ClusterIP只能在运行kube-proxy守护程序的机器上访问的事实。kube-proxy负责根据apiserver提供的数据配置iptables(在图表中也可见)。因此,如果您创建了一台虚拟机并将其放置在集群节点所在的网络中,并正确配置该机器上的网络,使个别集群pod可从该机器访问,则即使使用ClusterIP服务,该虚拟机也无法访问该服务,除非该虚拟机的iptables已进行了适当的配置(如果没有在该虚拟机上运行kubeproxy,则不会发生这种情况)。
引用块: “如果为NodePort绘制相同的图表,是否可以将客户端完全绘制在Node和Cluster之外,还是我完全没有理解呢?”
对于NodePort,将客户端绘制在Node和Cluster之外是有效的,因为NodePort可以从任何具有对集群节点和相应端口的访问权限的机器上访问,包括集群外部的机器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接