当前位置: 首页 > 知识库问答 >
问题:

kubernetes - 自建的 k8s 多节点集群,如何提供一个统一的对外 IP?

马坚白
2023-06-16

假设,我私有自建了一个 k8s 集群,集群有 10 个 node

然后我部署了一个 api 接口的 pod,我希望暴露这个 pod,让集群外的人,可以随意调用这个 api

这个时候,我有一个问题,调用者需要通过 ip+port 的方式访问,port 好说。但是 ip 填什么?

因为有 10 个 node,就有 10 个 ip,而且 pod 可以被任意调度到某个 node

这个时候,client 如何调用这个 api? 从 client 的角度,总得有一个固定 ip 吧?


这个时候,是不是要用「负载均衡」?

如果是的话,那么这个 「负载均衡」 部署在哪里?

  • 如果部署在 k8s 外面,那么问题依旧。
  • 如果部署在 k8s 集群内,作为一个 pod 存在,那么问题来了。「负载均衡」自己的 ip 就会随着部署在不同 node 上而变化,问题依旧了。

共有2个答案

冀弘厚
2023-06-16

原本没有k8s集群时,各个Node之间是独立的,组成集群后,k8s集群当作一个由多个Node组成的整体。k8s把分布在各个节点上的pod的网络合并成一个虚拟的大内网,即每个pod都在集群的内网中有一个唯一的IP地址。

如果是通过service/ingress作为流量入口,在收到请求时,最终会把请求转发给工作负载(pod),pod可能会被k8s调度到集群内的不同节点,集群内部,service就是一个负载均衡。

service有三种类型,默认的clusterIP,这个模式下,创建一个负载均衡器使用的是集群内部的IP,这种负载均衡只能在集群内部使用。

第二个是LoadBalancer,当使用公有云的集群,这种模式,正常情况下会有服务商提供一个更上层的负载均衡器,并提供一个公网IP x.x.x.x 。云服务商会将目的地址是x.x.x.x的流量转发到你的公有云的所有Node节点上。

第三个是NodePort,如果是自己建的私有集群,如果想要让服务从外部访问,只能选择这个模式。这个模式,调度器会在每个节点中都监听一个端口,每个节点都会把来自这个端口的请求负载到集群内部的pod中。

通过这个 Service 的负载机制,加上全局互通唯一的pod IP 就能够实现: 不管以哪个Node作为流量的入口,都能将请求转发到位于不同节点的POD上。


如果是自建的k8s集群,就只能选择NodePort暴露对外的服务。

这个时候可以只把一个节点暴露给外部,就可以只通过这一个节点访问集群内位于其他节点上的POD。

如果只使用一个节点,可能会有问题:

1. 这一个节点可能会有性能瓶颈,转发可能会出现问题
2. 这一个节点出现问题,会导致集群内所有的服务都不可用,就失去了“集群”冗余的作用。

为了解决上面这个问题,就是在集群上层再增加一层负载均衡,把请求转发到集群内的各个节点上。

这里如果是 LoadBalancer 类型的 service ,其实可以忽略上面这个这个集群外负载均衡的方案,因为在使用loadBalancer类型的服务时,云服务商已经帮你做了负载均衡了,云服务商会把流量转发到集群内的各个节点上,而不是单一节点。

牟稳
2023-06-16

填任意一个 Node 的 IP 即可。

如果你希望流量可以均匀的负载到每个 Node 上,那么你需要再套一层负载均衡器。那么方案无外乎三种:

  1. 你可以自己搭建一个负载均衡服务器,后面是你这 10 个 Node,把流量转发到对应的端口上。然后对外提供服务时填此负载均衡器的 IP 即可。
  2. 如果你在公有云上,也可以选择 k8s 内置的 LoadBalance 功能,此功能与云厂商提供的 LB 服务相结合。那么你对外提供服务时填的是云厂商的 LB 的地址。
  3. 如果你觉得单纯 IP 不好记,还是域名更好记,那么就是再开一个 k8s Ingress。同样地,你需要前面有一个负载均衡器,然后你把你的域名解析到此负载均衡器上,对外提供服务时填写该域名即可。

P.S. 其实你不要把 k8s 想得太复杂了,本质上就是你搭建了一个有 10 个节点的分布式集群,现在这个集群对外提供服务、需要一个所谓的统一的 Endpoint 该怎么办?没有 k8s 之前怎么办,现在依然怎么办。


【针对评论区的补充】

这里面有几个东西都起到负载均衡的作用了,所以你可能有点儿混淆。

首先先明确负载均衡的作用,它就是把一组什么玩意儿(一组里可能只有 1 个,但它也是一组),对外以一个统一入口的形式提供服务,访问这一个入口,流量会基于某种规则调度到后面的玩意儿上。这个“玩意儿”是啥,还需要具体问题具体分析,下面会讲到。

第一个是我们原本通常意义上所说的负载均衡,在有和没有 k8s 之前指的都是一回事儿。这里的负载均衡,是为了把公网流量均匀地负载到每台主机上。所以它当然是独立于你的集群存在的。这里你可以自己搭一台服务器,通过简单的反向代理来实现负载均衡。它实际就是原答案里我说的第一条。

这是“负载均衡到主机”,此时你的主机是一开始提到的那个“一组什么玩意儿”。

第二个是 k8s 的 External Load Balancer,直译过来叫外部负载均衡器。它实际就是原答案里我说的第二条。跟第一条没有什么实质性的区别,仅仅是跟公有云相结合的、所以能利用到一些公有云本身提供的能力,省得你自己搭费劲儿而已。

这是“负载均衡到 Node”,此时 Node 是一开始提到的那个“一组什么玩意儿”。但一般来说,你一台主机上只会跑一个 k8s node。除非是测试环境你没那么多真实主机可以用,只能迫不得已在一台主机上运行好几个 node 以实现伪集群。否则大部分语境下“负载均衡到主机”跟“负载均衡到 Node”是一个意思。

以上这两种,都是存在于 k8s 外部的负载均衡。只是一个是你自己搭的、你自己手动维护管理,一个是公有云提供的、你可以通过 k8s 维护管理。

第三个是 k8s 的 Service,它本身就有负载均衡的能力。你一个 Service 下可能会运行多个 Pod 对吧?那么请求实际会进到哪个 Pod 里,这是 Service 本身的负载均衡的能力。它是通过 kube-proxy 组件实现的。

这是“负载均衡到 Pod”,此时 Pod 是一开始提到的那个“一组什么玩意儿”。

第四个就是 k8s 的 Ingress 了,实质它就是个 nginx。因为是 nginx,所以它有七层负载均衡的能力。比如你可以配置 example.com/a/* 路径下的请求都转发给 Service A、 example.com/b/* 路径下的请求都转发给 Service B、 example.com/c/* 路径下的请求都转发给某一个特定的 Pod,这都可以。

这是“负载均衡到 Service/Pod”,此时 ServicePod 是一开始提到的哪个“一组什么玩意儿”。

以上这两种,都是存在于 k8s 内部的负载均衡。

这里面只有前两个你二选一即可,剩下的都是在各自范围实现的负载均衡,彼此并不重叠也不冲突。

回到原题,你需要的是第一种或第二种的负载均衡器。

 类似资料:
  • 我试图找到这个问题的答案,但在kubernetes文档或任何问答论坛中都找不到。 我有一个运行有4个节点的kubernetes集群。是否可以创建第二个集群,重用前一个集群中的一个或多个节点?或者一个节点被限制在单个kubernetes集群中? 我正在使用RKE(用于部署k8集群的牧场工具)运行实际的集群,我发现这个问题让我怀疑这种可能性。 感谢您的澄清。

  • 因为每个 Disque 节点都会将自己的配置信息储存在 disque-server 运行的文件夹里面, 而同一个文件夹只能有一份这样的配置信息, 所以如果我们打算同时运行多个节点, 那么就必须在不同的文件夹里面运行 disque-server , 并为每个节点指定不同的端口。 假设我们现在打算运行三个 Disque 节点, 那么首先要做的就是创建三个文件夹, 然后分别在这些文件夹里面运行 disq

  • null 优点: 每个网站的POD/容器级隔离 可能是骗局? null null null null

  • 问题内容: 我想为一个聊天室应用程序创建一个node.js服务器集群,以支持高并发性。我需要能够在所有节点之间共享信息。我试图找出使所有服务器保持同步的最佳方法。我希望在共享对象中具有尽可能大的灵活性,因为我计划在将来添加更多功能。 到目前为止,我想到了两种解决方案: 订阅NoSQL密钥(例如redis publish-subscribe) 节点使用套接字彼此更新。 哪个更好?还有其他想法吗? 问

  • 我正在尝试使用单个Service yaml在多个节点上设置对Pods的访问。Pods都有相同的标签(例如),但分布在多个节点上,而不是在单个节点上。 据我所知,我可以设置一个服务,通过节点端口转发对Pod的访问,比如: 其中访问节点上的端口30000会转发到pod上的端口5000。 如果我在多个节点上有pod,有没有一种方法可以让客户端访问一个endpoint,例如服务本身,从而在循环中获得任何p

  • 上节课我们和大家学习了怎样用 Promethues 来监控 Kubernetes 集群中的应用,但是对于 Kubernetes 集群本身的监控也是非常重要的,我们需要时时刻刻了解集群的运行状态。 对于集群的监控一般我们需要考虑以下几个方面: Kubernetes 节点的监控:比如节点的 cpu、load、disk、memory 等指标 内部系统组件的状态:比如 kube-scheduler、kub