目录

NodePort Service

LoadBalancer Service

External IP

Ingress

Ingress资源

Ingress-controller

Ingress 工作原理

Ingress暴露服务的方式 

Deployment+LoadBalancer 模式的 Service

DaemonSet+HostNetwork+nodeSelector

Deployment+NodePort模式的Service


之前的文章写了k8s集群内部访问的service组件和基于service实现的集群内部访问方式。那关于K8s如何接入外部流量的时候,大家常常会听到NodePort,LoadBalancer和Ingress等概念,这篇文章就聊一下对外暴露集群的集中实现方式。

NodePort Service

NodePort是K8s将内部服务对外暴露的基础。

NodePort类型的service其实是基于ClusterIP类型的service做的扩展,只需把service的type设置为nodeport即可,同时需要指定nodePort值,端口范围在30000~32767之间,这个值标识主机端口

服务发布以后,K8s基于service定义中nodePort和port的值,在每个Worker节点上开启当前主机端口和service端口的映射。这个端口的背后是Kube-Proxy,当K8s外部有Client要访问K8s集群内的某个服务,它通过NodeIP:port 的方式发起调用(NodeIP可以是集群中任意一个Node节点),这个调用通过Kube-Proxy转发到内部的Servcie抽象层,然后再转发到目标Pod上。

apiVersion: v1
kind: Service 
metadata: 
  name: webapp 
spec: 
  type: NodePort		# 设置 Service 类型为 NodePort
  ports: 
  - port: 8080 			# 设置 Service 暴露的端口为 8080, 即8080(svc) <-> 80(pod)
    targetPort: 80		# 设置 Pod 的端口为 8080
    nodePort: 30081 	# 设置 NodePort 的端口为 30081,即30081(NodePort) <-> 8080(svc) <-> 80(Pod) 
  selector:
    app: webapp 

通过NodePort类型的service方式访问集群存在一些限制和缺点

  1. Kubernetes集群中主机节点是可以增加删除的,IP一般也是动态分配的,因此内部主机变更时外部访问方也需要及时变更访问IP否则就访问不到了。
  2. 没有负载均衡,这种方式暴露服务后客户端往往是通过某一个固定的主机IP访问,会造成集群中各主机之间流量不均衡,同时也存在单点故障的风险,假如一台host宕机了,客户端就无法通过该主机的nodeport访问应用了。
  3. LoadBalancer类型的Service实现其实是在主机节点的NodePort前提供了一个四层的负载均衡器。该四层负载均衡器负责将外部网络流量分发到后面的多个节点的NodePort端口上。

LoadBalancer Service

这种类型的service是在NodePort类型之上的,因此LoadBalancer一样具有NodePort和ClusterIP,同时LoadBalancer 是依赖于NodePort实现的。

但是LoadBalancer只适用于支持外部负载均衡器的云提供商(阿里云,华为云等)使用。Service中的定义只是在Kubernetes配置文件中提出了一个要求,即为该Service创建Load Balancer,至于如何创建则是由云提供商,创建的Load Balancer的过程不在Kubernetes Cluster的管理范围中。

比如要在阿里云上将K8s内部的一个服务通过LoadBalancer方式暴露出去,需要把service的type设定为LoadBalancer。在服务发布后阿里云K8s会自动帮我们申请一个SLB,有独立公网IP,并把SLB映射到后台K8s集群的对应NodePort上。这样我们就可以通过这个SLB的公网IP访问到K8s内部服务,阿里云SLB负载均衡器会在背后做负载均衡。

所以对于一个LoadBalancer类型的Service而言,它会指向关联至Kubernetes集群外部的、切实存在的某个负载均衡设备,该设备为WORK节点的NodePort提供了一个四层的负载均衡器,负责将外部网络流量分发到后面的多个节点的NodePort端口上。

下图中LoadBalancer后面接入了两个主机节点上的NodePort,后端部署了三个Pod提供服务。根据集群的规模,可以在LoadBalancer后面可以接入更多的主机节点,以进行负荷分担。

a11440bb3c804e19bd5367e687637da6.png

目前WS, Azure, CloudStack, GCE 和 OpenStack 等主流的公有云和私有云提供商都可以为Kubernetes提供Load Balancer。

External IP

一般来说,公有云提供商还会为Load Balancer提供一个External IP,以提供Internet接入,这就是基于LoadBalancer实现的最终可以暴露出去的访问地址。

需要注意的是,在非公有云的裸机场景下,如果去创建一个LoadBalancer类型的service,那么它的External IP一直是pending状态,因为裸机没办法像公有云一样创建提供公网IP。

Ingress

有了前面的NodePort + LoadBalancer组合,为啥还要Ingress ?由于公网LB+IP是需要花钱买的,LoadBalancer实现的是基于IP和端口号的四层负载均衡,这就意味着暴露一个服务就需要购买一个独立的LB+IP,那如果要暴露十个服务就需要购买十个LB+IP,显然成本会很高。

所以Ingress出现了,它本质上就是K8s集群中的一个比较特殊的Service,这个Service可以和上面LoadBalancer对接起来,然后把自身通过80或443端口暴露出去,对k8s内部提供7层反向代理的功能。可以实现基于Path或者域名转发,这样就不需要购买一堆LB和IP了。

需要注意的是,Ingress是一个7层反向代理,如果你要暴露的是4层服务,还是需要走独立LB+IP方式。

在这里插入图片描述

下面聊一下Ingress到底是一个什么东西。

Ingress一般包括ingress资源对象和ingress-controller两部分组成。 

Ingress资源

Ingress 是 Kubernetes 中的一个抽象资源,它提供了一种定义应用暴露入口的方法,可以帮助管理员在 Kubernetes 集群中管理多个服务的访问入口,方便用户访问。Ingress资源对象只是一个规范化的API对象,用于定义流量路由规则和 TLS 设置等信息。它本身不会直接处理或转发流量,而是需要配合一个 Ingress 控制器来实现。

Ingress-controller

Ingress-controller其实有多种实现的,下面列举6中主流的实现版本:

  1. Nginx Ingress Controller:基于Nginx的Ingress控制器,提供了广泛的功能和配置选项。
  2. Traefik Ingress Controller:Traefik是一个流行的反向代理和负载均衡器,Traefik Ingress Controller提供了灵活的配置选项和自动发现服务的功能。
  3. Istio Ingress Gateway:Istio是一种服务网格,它提供了基于Envoy代理的Ingress Gateway来管理入站和出站流量。
  4. Contour Ingress Controller:基于Envoy代理的Ingress控制器,具有高度可扩展性和灵活的路由规则。
  5. Kong Ingress Controller:Kong是一个API网关,提供了可扩展的路由和服务管理功能。
  6. Ambassador API Gateway:Ambassador是一个Kubernetes-native API Gateway,提供了自动化的服务发现和路由管理功能。

其中社区原生的是ingress-nginx,在这个版本的ingress-controller实现中,Ingress借助Nginx解决了NodePort方式引发的端口管理及其他弊端。

一方面,在集群内创建一个具有N个副本的nginx service并通过nodeport的方式来暴露,在nginx服务内配置各个业务服务的域名与集群内部的服务的ip转发规则。这样一来外部服务可以通过Nginx服务主机NodeIP:port端口来访问nginx,nignx在通过域名反向代理到真实的服务,这样就通过nginx代理转发解决了NodePort产生的复杂的端口管理。

另一方面,基于这种方式的实现还需要考虑到有新服务加入时应该如何修改Nginx的配置和转发IP规则信息,因此需要实现动态感知和更新。

了解了Ingress的原理后,仔细想一想其实现代的微服务网关Zuul/SpringCloudGateway/Kong/Envoy/Traefik等都可以定制开发编程Ingress,把这些服务在K8S上以普通Service部署,将type设定为LoadBalancer即可实现。

Ingress 工作原理

Ingress-controller和 kubernetes APIServer 交互,动态的监听感知集群中Ingress 资源变化,按照自定义的规则(就是写明了哪个域名对应哪个service)动态变更nginx配置,保存到Nginx组件的 /etc/nginx.conf文件中,通过reload使配置生效。以此达到域名区分配置和动态更新的作用

Ingress暴露服务的方式 
Deployment+LoadBalancer 模式的 Service

如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个 type为 LoadBalancer 的 service 关联这组 pod。大部分公有云,都会为 LoadBalancer 的 service 自动创建一个负载均衡器,通常还绑定了公网地址。 只要把域名解析指向该地址,就实现了集群服务的对外暴露

DaemonSet+HostNetwork+nodeSelector

用DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。 比较适合大并发的生产环境使用

Deployment+NodePort模式的Service

同样用deployment模式部署ingress-controller,并创建对应的service,但是type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口,一般会在前面再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境ip地址不变的场景。
NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定影响。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐