一文读懂k8s的外网访问方式,Ingress/NodePort/LoadBanlancer
集群内访问
在k8s中创建的微服务,大部分都是在集群内部互相调用,这时候,使用DNS就可以很方面访问。
比如:服务名是 my-service,端口号是8080,命名空间是yifan,那么就可以通过域名+端口 “my-service.yifan.svc.cluster.local:8080” 在集群内访问。
当然,也可以直接用服务的ClusterIP+服务的端口号,只是这么使用的较少。
DNS解析到的IP也就是这个服务的ClusterIP,只是咱们不需要记住ClusterIP,记住服务名对应的域名更加容易。
如上图所示,就是k8s集群内的服务访问流程。
客户端通过DNS服务的域名解析 my-service.yifan.svc.cluster.local 返回这个服务的ClusterIP。
然后创建TCP连接到这个ClusterIP+端口号上。
网络请求经过Iptables/ipvs规则处理,经过负载均衡策略,把这个ClusterIP重定向到服务的后端实例,也就是这个服务的某一个Pod得PodIP。
这样TCP连接成功创建,客户端也就建立了与服务的后端实例的连接,也就可以进行后续的请求了。
下面是Cluster类型的service的yaml文件示例:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ClusterIP
selector:
app: my-app
ports:
- name: http
port: 80
targetPort: 8080
这个YAML文件包含以下内容:
apiVersion
: 指定Kubernetes API的版本。kind
: 指定要创建的对象类型,此处为Service。metadata.name
: 指定Service的名称,此处为“my-service”。spec.type
: 指定Service的类型,此处为“ClusterIP”。spec.selector
: 指定要为Service选择的Pod或副本集的标签选择器。在这个例子中,标签选择器是“app=my-app”。spec.ports
: 指定要公开的端口及其配置信息。在这个例子中,将公开端口80,名称为“http”,将流量转发到Pod中的端口8080。
要使用此YAML文件创建Service,请使用以下命令:
kubectl apply -f service.yaml
这是集群内访问的流程,接下来,再来看看本文的核心内容,外网如何访问。
集群外访问
k8s集群的外网访问方式有3种:
Ingress, NodePort和LoadBanlancer。
其中Ingress是k8s的一个抽象层,有很多的IngressController和服务可以来实现这个Ingress服务,然后由这个Ingress服务把外网的请求转发到集群内的服务。
NodePort和LoadBanlancer是k8s中service的类型。上面讲到的集群内访问,ClusterIP也是service的一种类型。
而LoadBanlancer类型需要各个云厂商自己来实现的CloudControllerManager,所以,采用不同的云厂商,它们的LoadBanlancer也就会有一些区别,它们的功能以及使用方法也就不一样了。
接下里,咱们就单独来看看这3种外网访问方式吧。
Ingress转发外网请求
先来看下Ingress配置的yaml文件:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: yifan-online.com
http:
paths:
- path: /app1
pathType: Prefix
backend:
service:
name: app1-service
port:
name: http
- path: /app2
pathType: Prefix
backend:
service:
name: app2-service
port:
name: http
此文件指定了一个名为“my-ingress”的Ingress,将传入的请求路由到两个不同的服务,其中一个服务名称为“app1-service”,另一个服务名称为“app2-service”。
请注意,此文件的规范部分中指定了两个规则,每个规则都包含一个主机名和一组路径规则。每个路径规则都指定了如何将传入请求路由到服务。
如要支持gRPC协议,配置的yaml文件如下:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grpc-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
spec:
rules:
- host: yifan-online.com
http:
paths:
- path: /grpc
backend:
serviceName: grpc-service
servicePort: 9000
在这个示例中,我们指定了Ingress类为nginx,并使用了nginx负载均衡器来支持gRPC协议。然后,我们定义了一个名为“grpc-service”的gRPC服务,它将运行在端口9000上。
接下来,我们定义了一个Ingress规则,它将传入的请求路由到主机“yifan-online.com”的“/grpc”路径。这个规则使用了我们先前定义的gRPC服务,并将所有请求转发到端口9000上的gRPC服务。
请注意,在此示例中,我们还使用了一个特殊的注释“nginx.ingress.kubernetes.io/backend-protocol: “GRPC””,它指定了gRPC作为后端协议。这个注释将告诉nginx负载均衡器将请求路由到gRPC服务。
上面的yaml文件,咱们知道如何通过Ingress服务来做请求转发,是通过host和path来识别请求,然后转发到backend的servieName和servicePort。
那么,外网的客户端,要怎么请求到这个Ingress呢?
这时候,还是需要有一个外网可访问LoadBanlancer来把外网请求接入进来,转发到Ingess上。
而上面的Ingress配置,只是一个配置转发的规则,还需要有一个真实存在的Ingress服务才可以实现上面的转发逻辑。
这时候,就需要例如:NginxIngress服务。
所以,还需要部署一个NginxIngress服务,当然也有很多其他类型的Ingress服务。
综上,我们再来看下Ingress方式的外网请求,是怎样的一个处理流程吧。
上面的LoadBanlancer是云厂商提供的一个服务,所以也是要单独收费的。
Ingress服务需要在集群内部署一个Nginx服务(其他的Ingress服务也是类似)。
host+path是Ingress的转发规则,所有实现了IngressController的服务都是可以支持的。
那么再来看下LoadBanlancer吧。
LoadBanlancer接入外网请求
要配置Kubernetes中的LoadBalancer,可以编写一个LoadBalancer的Service YAML文件,其中包含有关如何将Kubernetes Service公开到外部的信息。
以下是一个基本的LoadBalancer Service YAML文件示例:
apiVersion: v1
kind: Service
metadata:
name: my-loadbalancer-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
在这个示例中,我们定义了一个名为“my-loadbalancer-service”的Service,它将使用LoadBalancer来公开Kubernetes集群中的应用程序。其中的“type: LoadBalancer”声明将告诉Kubernetes将此服务配置为使用LoadBalancer。
接下来,我们定义了一个选择器,它将选择具有标签“app: my-app”的Pod作为后端。我们还指定了一个端口“80”,它将用于将传入请求路由到Pod的端口“8080”。
请注意,这个示例还包含一个名为“service.beta.kubernetes.io/aws-load-balancer-type”的注释,它指定了LoadBalancer的类型。在这个示例中,我们使用了Amazon Web Services(AWS)的Network Load Balancer(NLB)类型。如果您使用的是其他云提供商或自己的LoadBalancer,您可以根据需要更改此注释。
完成了这个配置文件并且Service已经创建时,Kubernetes将为您创建一个LoadBalancer,并为您的应用程序分配一个唯一的IP地址。您可以使用此IP地址来访问您的应用程序。请注意,不同的云提供商可能会有不同的方式来访问LoadBalancer的IP地址。
很多云厂商在实现LoadBanlancer的时候,还会用到NodePort服务类型,比如:腾讯云的CLB。
最后,再来看下LoadBanlancer的处理流程。
最后,咱们再来看下NodePort这种外网访问方式吧。
NodePort接入外网请求
要配置一个Kubernetes的NodePort,您可以编写一个NodePort的Service YAML文件,其中包含有关如何暴露Kubernetes Service的信息。
以下是一个基本的NodePort Service YAML文件示例:
apiVersion: v1
kind: Service
metadata:
name: my-nodeport-service
spec:
type: NodePort
selector:
app: my-app
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
nodePort: 30000
在这个示例中,我们定义了一个名为“my-nodeport-service”的Service,它将会使用NodePort来暴露Kubernetes集群内的应用程序。其中的“type: NodePort”声明将告诉Kubernetes将此服务配置为使用NodePort。
接下来,我们定义了一个选择器,它将选择具有标签“app: my-app”的Pod作为后端。我们还指定了一个端口“80”,它将用于将传入请求路由到Pod的端口“8080”。
此外,我们还指定了一个NodePort“30000”,这将是我们将用来从集群外访问Service的端口。Kubernetes将在集群节点上随机选择此端口。
请注意,您可以通过将“nodePort”字段留空来让Kubernetes自动选择端口。但是,为了避免端口冲突,建议指定一个特定的端口号。
当您完成了这个配置文件并且Service已经创建时,您可以使用集群节点的IP地址和NodePort来访问Service。例如,在这个示例中,您可以使用节点的IP地址和端口“30000”来访问应用程序。
K8S集群中的工作节点有外网IP,就可以通过这些外网IP+NodePort暴露的端口号来访问到K8S集群内部的服务了。
在 Kubernetes 中,NodePort 的端口号范围默认是从 30000 到 32767。这个范围可以通过 kube-apiserver 的 --service-node-port-range
参数进行配置。
在实际使用中,需要注意端口号的冲突问题,也要避免滥用NodePort暴露了外网端口引发的安全问题。
那我们再来看下NodePort的数据处理流程。
创建一个 NodePort 类型的 Service 时,Kubernetes 会在集群中的每个节点上开放一个指定的端口号,例如 30000。每个节点上的 kube-proxy 组件会监听该端口号,并将所有流量转发到后端 Pod 的相应端口上。
具体来说,kube-proxy 会在每个节点上启动一个代理服务器(即 iptables 或者 IPVS),并为每个 Service 分配一个唯一的虚拟 IP 地址(即 ClusterIP)。当有请求到达 NodePort 时,kube-proxy 会根据负载均衡策略将请求转发到某个节点上,并使用该节点上的代理服务器将请求转发到相应的后端 Pod 上。后端 Pod 的响应将通过同样的方式返回给客户端。
看到这里,大家知道如何配置和使用这些服务了吗?
现在,你能完整的把一个外网请求,从LoadBanlancer到NodePort,再到Ingress,最后到服务实例的全部过程了吗?
总结和对比
Ingress、NodePort和LoadBalancer都是Kubernetes中用于将Service公开到外部的方法,但它们之间有一些区别和适用场景。以下是一些选择的建议:
-
Ingress:如果需要在同一IP地址和端口上公开多个服务,并根据请求路径或主机名进行路由,则可以使用Ingress。 Ingress是Kubernetes中的一个抽象层,它可以将多个Service公开到同一个IP地址和端口上,并根据请求路径或主机名进行路由,非常适合用于Web应用程序。
-
NodePort:如果您需要将一个Service公开到集群外部,但又不想使用负载均衡器,则可以使用NodePort。 NodePort将Service公开到所有节点的IP地址上,并将随机端口映射到目标端口。如果您只需要将一个Service公开到外部,并且您有一个静态IP地址或DNS名称来访问它,则NodePort可能是一个不错的选择。
-
LoadBalancer:如果您需要将一个Service公开到外部,并且需要一个负载均衡器来处理流量,则可以使用LoadBalancer。 LoadBalancer可以将流量负载均衡到多个Pod之间,从而提高应用程序的可用性和可伸缩性。如果您正在运行在公共云环境中,例如AWS、Azure或GCP,那么您可以使用云提供商的负载均衡器服务,否则您可以使用Kubernetes自带的负载均衡器。
在云厂商的服务中,如果要使用Ingress暴露k8s集群内的服务到外网,实际上会用也到LoadBanlancer和NodePort类型,只是大家不必关心它的内部实现细节而已。
Ingress和网关的区别
Ingress是Kubernetes中的一个抽象层,它允许您公开多个服务到同一IP地址和端口,并根据请求路径或主机名进行路由。 Ingress通常用于HTTP/HTTPS流量,并且可以支持TLS endpoint、基于路径的路由和负载均衡等功能。可以使用Kubernetes Ingress Controller实现Ingress功能,例如Nginx Ingress Controller、Traefik Ingress Controller和Istio Ingress Gateway。
网关(Gateway)通常是一个独立的组件,用于提供对应用程序的访问控制、身份验证、安全性、流量管理和监视等功能。 网关通常可以支持多个协议和传输层,并且可以部署在Kubernetes集群之外,例如API网关、网络应用防火墙(WAF)和服务网格(Service Mesh)等。流量可以通过不同的方式路由到网关,例如DNS名、IP地址、负载均衡器和Ingress等。
简而言之,Ingress是Kubernetes中的一个抽象层,用于将多个服务公开到同一IP地址和端口,并根据请求路径或主机名进行路由,而网关则是提供对应用程序的访问控制、身份验证、安全性、流量管理和监视等功能的组件,它可以与Kubernetes集群一起使用,但也可以独立于Kubernetes集群之外部署。
不知道大家还有什么想要了解的,可以在评论区提出来,后续可以接着细聊。也请关注我的课程哟。
共同学习,写下你的评论
评论加载中...
作者其他优质文章