1 概述
NodePort、LoadBalancer 和 Ingress 都是将集群外部流量导入到集群内的方式,只是实现方式不同。以下是三种方式的工作原理
注意:这里说的每一点都基于Google Kubernetes Engine。如果用 minikube 或其它工具,以预置型模式(om prem)运行在其它云上,对应的操作可能有点区别。
2 ClusterIP
ClusterIP 服务是 Kubernetes 的默认服务。它提供一个集群内的服务,集群内的其它应用都可以访问该服务。集群外部无法访问ClusterIP。
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 的 proxy 模式来访问该服务,其链路如下:
proxy设置方式:
kubectl proxy --port=8080
2.1 访问方式
- 启动 Kubernetes proxy后就可以使用http://localhost:8080/api/v1/proxy/namespaces//services/:/通过 Kubernetes API 访问 service。
- 也可以使用http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/这个地址,访问上面定义的 service。
2.2 使用场景
- 调试service,或直接从笔记本电脑连接到 service;
- 允许内部流量访问,显示内部 dashboards
由于此方法要求将 kubectl 作为认证用户运行,因此不能使用这个方法将service 暴露在公网上或将其用于生产环境下。
3 NodePort
NodePort 类型的 service 是让外部流量可以访问集群内部服务最基本的方式。NodePort是在所有 Node(VM)上打开一个特定的 port,任何发送到此 port 的流量都将转发到 service 上。
从技术上看,这也许不是最准确的图表,但它表明了 NodePort 的工作方式。
NodePort 类型的 service 的 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
3.1 与clusterip的区别
NodePort 类型的 service 与普通的 “ClusterIP” 类型的 service 有两点区别:
- 类型是 “NodePort”;
- 它有一个被称为 nodePort 的附加 port,可以在 node 上指定打开哪个 port 。如果不指定一个 port,NodePort 类型的 service 就会随机选择一个。大多数时候应该让 Kubernetes 来选择 port;
3.2 使用场景
- 运行的服务不用保持始终可用;
- 适用于一个演示应用程序或其他临时的东西
3.3 缺点
- 每个端口只能绑定一个 service;
- 可使用端口号只能是 30000 到 32767;
- 如果节点/VM 的 IP 地址发生变化,需要做处理。
4 LoadBalancer
LoadBalancer (负载均衡器)类型的 service 是在公网上暴露服务的标准方式。在 GKE 上将启动一个网络LoadBalancer,该网络LoadBalancer将为svc提供一个 IP 地址,用来将所有流量转发到kubernetes service 上。
在云提供商上运行的Kubernetes集群通常支持从云基础架构自动提供负载平衡器。 所有需要做的就是设置服务的类型为Load Badancer而不是NodePort。 负载均衡器拥有自己独一无二的可公开访问的 IP 地址, 并将所有连接重定向到服务。可以通过负载均衡器的 IP 地址访问服务。如果Kubemetes在不支持Load Badancer服务的环境中运行, 则不会调配负载平衡器, 但该服务仍将表现得像 一 个NodePort服 务。 这是因为LoadBadancer服务是NodePort服务的扩展。
Yaml文件:
apiVersion: v1
kind: Service
metadata:
name: kubia-loadbalancer
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
可以路由到 NodePort 服务和 ClusterIP 服务,这个需要结合具体的云厂商进行操作。
4.1 使用场景
- 需要直接暴露service到外部的应用。
4.2 缺点
- 没有过滤条件,没有路由等。这意味着几乎可以发送任何种类的流量到该服务,像
HTTP,TCP,UDP,Websocket,gRPC
或其它任意种类。 - 每一个用
LoadBalancer
暴露的服务都会有它自己的 IP 地址,每个用的LoadBalancer
都需要付费,成本高;
5 Ingress
Ingress 实际上不是 service 的一个类型。其架构侧位于多个 service 之前,充当集群中的“智能路由器”或入口点。用户可以使用 Ingress 做很多不同的事情。现在市面上有许多不同类型的 Ingress 控制器,不同类型的ingress具有不同的功能。
默认的 GKE ingress 控制器将为k8s集群启动一个 HTTP(S)LoadBalancer。帮助用户用来执行基于路径和子域的路由到后端服务。例如:用户可以将http://a.baidu.com上的所有内容发送到 对应 service 上,将http://b.baiud.com/test 路径下所有内容发送到对应service 上。
GKE 上 Ingress 对象的 YAML 如下所示(带有 L7 HTTPLoadBalancer):
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
5.1 使用场景
Ingress 是暴露 service 最强大的方式,但也是最复杂的。其实,Ingress 控制器有很多类型,像来自 Google Cloud 的LoadBalancer,Nginx,Contour,Istio 等。还有用于 Ingress 控制器的插件,如 cert-manager,均可以为用户的 service 自动提供 SSL 证书。
如果业务需要在相同的 IP 地址下暴露多个 service,并且这些 service 都使用相同的 L7 协议(通常是 HTTP),此刻Ingress 是最适用的。如果业务需要使用GCP 集成,那么只需使用一台负载均衡器。由于 Ingress 是“智能的”,用户可以获得许多“开箱即用”的功能,如 SSL,Auth,路由等。