Kubernetes NodePort vs LoadBalancer vs Ingress? 我们应该什么时候使用?

Kubernetes NodePort vs LoadBalancer vs Ingress? 我们应该什么时候使用?

作者:Sandeep Dinesh

翻译:狄卫华

原文:Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?

原文链接:https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0

最近有人向我了解 NodePorts ,LoadBalancers 和 Ingress 之间的区别是怎么样的。 它们都是将外部流量引入群集的方式,适用的场景却各不相同。 本文接下来我们将介绍它们的工作原理以及适用的相关场景。

注意:文中所述内容适用于 GKE [Google Kubernetes Engine]。 如果你在其他云平台上运行使用步骤略有不同,比如 minikube 或其他相关软件。 我本人也不打算过多深入技术细节, 如果您有兴趣了解更多,Kubernetes 官方文档 会提供更多的有用资源!

ClusterIP

ClusterIP 服务是 Kubernetes 默认的服务类型。 如果你在集群内部创建一个服务,则在集群内部的其他应用程序可以进行访问,但是不具备集群外部访问的能力。

ClusterIP 服务的 YAML 文件看起来像这样:

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

如果不能从互联网访问 ClusterIP 服务,我为什么要谈论它呢?事实上,你可以通过 Kubernetes 代理进行访问。

img

感谢 Ahmet Alp Balkan 提供的图表

启动 Kubernetes 代理:

$ kubectl proxy --port=8080

现在,可以通过 Kubernetes API 通过以下的模式来访问这个服务:

http://localhost:8080/api/v1/proxy/namespaces//services/:/,

通过这种方式可以使用以下的地址来访问我们上述定义的服务:

http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/

何时使用这种访问方式?

有以下几种场景,你可以使用 Kubernetes 代理的方式来访问服务:

  1. 调试服务或者某些情况下通过笔记本电脑直接连接服务
  2. 允许内部的通信,显示内部的仪表盘(dashboards)等

因为此种方式需要作为一个授权用户运行 kubectl,因此不应该用来暴露服务至互联网访问或者用于生产环境。

NodePort

NodePort 服务通过外部访问服务的最基本的方式。顾名思义,NodePort 就是在所有的节点或者虚拟机上开放特定的端口,该端口的流量将被转发到对应的服务。

img

从技术上层面,这不能算是最准确的图表,但我认为它能够直观展示了 NodePort 的工作方式。

NodePort 服务的 YAML 文件看起来像这样:

apiVersion: v1
kind: Service
metadata:  
  name: my-nodeport-service
selector:    
  app: my-app
spec:
  type: NodePort
  ports:  
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30036
    protocol: TCP

从根本上讲,NodePort 方式的服务与 ClusterIP 方式的服务有两个区别。第一,类型是 NodePort,这需要指定一个称作 nodePort 的附加端口,并在所有节点上打开对应的端口。如果我们不具体指定端口,集群会选择一个随机的端口。大多数的情况下,我们都可以让 Kubernetes 帮我们选择合适的端口。正如 thockin 所描述的那样,有许多相关的注意事项(caveats)关于那些端口可供我们使用。

何时使用这种访问方式?

NodePort 方式有许多缺点:

  1. 每个服务占用一个端口

  2. 可以使用的 30000-32767 范围端口 (译者注:可以通过api-server启动参数service-node-port-range

    指定限制范围,默认为30000-32767)

  3. 如果节点/虚拟机IP地址发生更改,需要进行相关处理

由于上述原因,我不建议在生产环境中使用直接暴露服务。 如果运行的服务不要求高可用或者非常关注成本,这种方法则比较适合。 很好的例子就是用于演示或临时使用的程序。

LoadBalancer

LoadBalancer 服务是暴露服务至互联网最标准的方式。在 GKE 上,这将启动一个网络负载均衡器(Network Load Balancer),它会提供一个 IP 地址,以将所有流量转发到服务。

img

感谢 Ahmet Alp Balkan 提供图表

何时使用这种访问方式?

这是公开服务的默认的方法。指定的端口上流量都将被转发到对应的服务,不经过过滤和其他路由等操作。这种方式意味着转发几乎任何类型的流量,如HTTP,TCP,UDP,Websockets,gRPC或其他。

这种方式最大的缺点是,负载均衡器公开的每个服务都将获取独立 IP 地址,而我们则必须为每个暴露的服务对应的负载均衡器支付相关费用,这可能会变得非常昂贵!

Ingress

和上述讨论的服务方式不同,Ingress 实际上并不是服务类型中的一种。相反,它位于多个服务的前端充当一个智能路由或者集群的入口点。

你可以使用 Ingress 做很多不同的事情,并且不同类型的 Ingress 控制也具备不同的能力。

GKE 默认的 Ingress 控制器将启动一个 HTTP(S) 的负载均衡器。则将使我们可以基于访问路径和子域名将流量路由到后端服务。例如,你可以将 foo.yourdomain.com 下的流量转发到 foo 服务,将 yourdomain.com/bar/ 路径下的流量转发到 bar 服务。

img

感谢 Ahmet Alp Balkan 提供图表

在 GKE 上定义 L7层 HTTP 负载均衡器的 Ingress 对象定义的 YAML 看起来像这样:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: other
    servicePort: 8080
  rules:
  - host: foo.mydomain.com
    http:
      paths:
      - backend:
          serviceName: foo
          servicePort: 8080
  - host: mydomain.com
    http:
      paths:
      - path: /bar/*
        backend:
          serviceName: bar
          servicePort: 8080

何时使用这种方式?

Ingress 方式可能是暴露服务的最强大的方式,但也最复杂。现在有不同类型的 Ingress 控制器,包括 Google 云 负载均衡器, Nginx, Contour, Istio 等。此外,还有 Ingress 控制器的许多插件,比如 cert-manager 可以用来自动为服务提供 SSL 证书。

如果希望在同一个IP地址下暴露多个服务,并且它们都使用相同的 L7 协议(通常是HTTP),则 Ingress 方式最有用。 如果使用本地 GCP 集成,则只需支付一台负载平衡器费用,并且是“智能”性 Ingress ,可以获得许多开箱即用的功能(如SSL,Auth,路由等)。

发表评论

电子邮件地址不会被公开。 必填项已用*标注