【问题标题】:Is there a way to not use GKE's standard load balancer?有没有办法不使用 GKE 的标准负载均衡器?
【发布时间】:2018-09-17 21:19:20
【问题描述】:

我正在尝试使用 Kubernetes 来明确定义配置和部署,我也喜欢 Kubernetes 的 pod 调度机制。 (目前)只有 2 个应用程序在 3 个节点上的 2 个副本上运行。但是谷歌的 Kubernetes Engine 的负载均衡器对于像我们这样的小型应用程序(至少目前如此)来说非常昂贵,同时我不愿意更改为容器上的单实例托管解决方案或在 Docker swarm 上部署应用程序等.

使用节点的 IP 似乎是一种黑客攻击,我认为它可能会暴露集群内部的一些安全问题。因此,我配置了一个 Træfik 入口和一个入口控制器,以克服 Google 昂贵的负载平衡统一费率,但结果是面向外的入口会启动标准负载平衡器,否则我会遗漏一些东西。

我希望我错过了一些东西,因为按照这个费率(每月 16 美元),我无法合理地从启动这个应用程序开始使用 kubernetes。

有没有办法在不使用 Google 的负载均衡器的情况下使用 GKE?

【问题讨论】:

标签: kubernetes google-compute-engine traefik


【解决方案1】:

Ingress 只是一组规则,告诉集群如何路由到您的服务,Service 是另一组规则,用于根据选择器在一组 Pod 之间进行访问和负载平衡.一个服务可以使用 3 种不同的路由类型:

  • ClusterIP - 这为服务提供了一个 IP,该 IP 仅在集群内部可用,该集群路由到 pod。
  • NodePort - 这会创建一个 ClusterIP,然后在集群中的每个节点上创建一个外部可访问的端口。到这些端口的流量路由到内部服务 IP,然后路由到 pod。
  • LoadBalancer - 这将创建一个 ClusterIP,然后是一个 NodePort,然后从提供程序(如果在 GKE 上可用)提供负载均衡器。流量到达负载均衡器,然后是其中一个节点上的端口,然后是内部 IP,最后是 Pod。

这些不同类型的服务不是相互排斥的,而是实际上是相互构建的,它解释了为什么任何公共服务都必须使用 NodePort。想一想 - 流量会如何到达您的集群?云负载均衡器只是将请求定向到您的节点并指向其中一个 NodePort 端口。如果您不想要 GKE 负载均衡器,那么您已经可以跳过它并直接访问这些端口。

缺点是端口限制在 30000-32767 之间。如果您需要标准 HTTP 端口 80/443,那么您无法使用 Service 完成此操作,而是必须直接在您的 Deployment 中指定端口。使用hostPort设置将容器直接绑定到节点上的80端口:

containers:
  - name: yourapp
    image: yourimage
    ports:
      - name: http
        containerPort: 80
        hostPort: 80 ### this will bind to port 80 on the actual node

这可能对您有用,并将流量直接路由到容器而无需任何负载平衡,但如果节点出现问题或应用程序停止在节点上运行,则它将不可用。

如果您仍然想要负载平衡,那么您可以运行DaemonSet(以便它在每个节点上都可用),并使用通过hostPort 公开的 Nginx(或任何其他代理),然后它将路由到您的内部服务。一个简单的运行方法是使用标准的nginx-ingress 包,但跳过为其创建 LoadBalancer 服务并使用hostPort 设置。可以为此配置 Helm 图表:

https://github.com/helm/charts/tree/master/stable/nginx-ingress

【讨论】:

  • 感谢 Mani 提供详细信息,我也相信要使用 hostPort,您需要在定义容器的规范部分启用 hostNetwork: true。
【解决方案2】:

如果将 Ingress 类指定为 Ingress 对象上的注解

kubernetes.io/ingress.class: traefik

Traefik 会拾取它,而 Google 负载均衡器会忽略它。还有a bit of Traefik documentation on this part

【讨论】:

  • 这是否完全跳过了负载平衡规则的创建?本质上 OP 不想为 Cloud Load Balancing 付费
  • 是的,它应该跳过整个 Google LB 创建过程,包括规则。从本质上讲,它的实现方式是在 GKE 集群中运行一个 Google LB 控制器(简称 glbc),用于监视具有正确 ingress.class 注释值的 Ingress。对于不满足此条件的 Ingress,glbc 将完全跳过它们,根本不访问 GCP API。
【解决方案3】:

一种选择是在您的 GKE 集群上完全禁用此功能。在 Add-ons 下创建集群(在 console.cloud.google.com)时,请禁用 HTTP 负载平衡。如果你使用gcloud,你可以使用gcloud beta container clusters create ... --disable-addons=HttpLoadBalancing

或者,您还可以通过向您的 Ingress 资源添加注释kubernetes.io/ingress.class=somerandomstring,来禁止 GCP 负载均衡器。

对于新创建的入口,你可以把这个放在yaml文档中:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: somerandomstring
...

如果您想对所有入口执行此操作,可以使用此示例 sn-p(小心!):

kubectl get ingress --all-namespaces \
  -o jsonpath='{range .items[*]}{"kubectl annotate ingress -n "}{.metadata.namespace}{" "}{.metadata.name}{" kubernetes.io/ingress.class=somerandomstring\n"}{end}' \
  | sh -x

现在在 Kubernetes 中使用 Ingress 非常有用,因此我建议您查看 nginx ingress controller 并在部署后相应地注释您的 Ingress。

【讨论】:

  • 我可以用静态ip绑定入口吗?
  • 这取决于正在使用的入口控制器。对于 GCP 负载均衡器,是的。
  • 我想这个问题并不清楚,说 GKE 的标准负载均衡器是指 GCP 负载均衡器。我正在尝试以某种方式从系统中删除 GCP 负载均衡器并绑定到静态 IP。
【解决方案4】:

您可以使用 NodePort 模式部署 nginx 入口控制器(例如,如果使用 helm chartcontroller.service.type 设置为 NodePort),然后使用 DNS 在您的实例之间进行负载平衡。只需确保您有节点的静态 IP,或者您甚至可以创建一个 DaemonSet,以某种方式使用每个节点的 IP 更新您的 DNS。

Traefik 似乎支持类似的配置(例如,通过其 helm chart 中的 serviceType)。

【讨论】:

  • NodePort 会给我一个大于 3000 的端口,我需要在该静态 ip 上绑定端口 80。
  • 嗯好吧,你可以试试hostPort——在nginx helm chart set controller.daemonset.useHostPort
猜你喜欢
  • 1970-01-01
  • 2016-07-17
  • 2019-09-14
  • 1970-01-01
  • 2019-05-27
  • 1970-01-01
  • 2019-11-28
  • 2020-07-29
  • 2021-12-07
相关资源
最近更新 更多