外部接入网络
- K8s网络的4层抽象
# NodePort
先看架构图,可以看出NodePort是K8s将内部服务对外暴露的基础,后面的LoadBalancer底层有赖于NodePort。
Kube-Proxy是K8s内部服务发现的一个关键组件,事实上,它还是K8s将内部服务暴露出去的关键组件。Kube-Proxy在K8s集群中所有Worker节点上都部署有一个,它掌握Service网络的所有信息,知道怎么和Service网络以及Pod网络互通互联。如果要将Kube-Proxy和节点网络打通(从而将某个服务通过Kube-Proxy暴露出去),只需要让Kube-Proxy在节点上暴露一个监听端口即可。这种通过Kube-Proxy在节点上暴露一个监听端口,将K8s内部服务通过Kube-Proxy暴露出去的方式,术语就叫NodePort(顾名思义,端口暴露在节点上)。下图是通过NodePort暴露服务的简化概念模型。
# LoadBalancer
LoadBalancer 类型的service 是可以实现集群外部访问服务的另外一种解决方案。不过并不是所有的k8s集群都会支持,大多是在公有云托管集群中会支持该类型。负载均衡器是异步创建的,关于被提供的负载均衡器的信息将会通过
Service
的status.loadBalancer
字段被发布出去。
将K8s内部的服务通过NodePort方式暴露出去,K8s会在每个Worker节点上都开启对应的NodePort端口。逻辑上看,K8s集群中的所有节点都会暴露这个服务,或者说这个服务是以集群方式暴露的(实际支持这个服务的Pod可能就分布在其中有限几个节点上,但是因为所有节点上都有Kube-Proxy,所以所有节点都知道该如何转发)。既然是集群,就会涉及负载均衡问题,谁负责对这个服务的负载均衡访问?答案是需要引入负载均衡器(Load Balancer)。下图是通过LoadBalancer,将服务对外暴露的概念模型。
假设我们有一套阿里云K8s环境,要将K8s内部的一个服务通过LoadBalancer方式暴露出去,可以将服务发布(Kind: Service)的type设定为LoadBalancer。服务发布后,阿里云K8s不仅会自动创建服务的NodePort端口转发,同时会自动帮我们申请一个SLB,有独立公网IP,并且阿里云K8s会帮我们自动把SLB映射到后台K8s集群的对应NodePort上。这样,通过SLB的公网IP,我们就可以访问到K8s内部服务,阿里云SLB负载均衡器会在背后做负载均衡。
如果是在本地开发测试环境里头搭建的K8s,一般不支持Load Balancer也没必要,因为通过NodePort做测试访问就够了。但是在生产环境或者公有云上的K8s,例如GCP或者阿里云K8s,基本都支持自动创建Load Balancer。
# Ingress
k8s 的服务(service)暴露service的三种方式ClusterIP、NodePort与LoadBalance,这 几种方式都是在service的维度提供的,单独用service暴露服务的方式,在实际生产 环境中不太合适:
ClusterIP的方式只能在集群内部访问。
NodePort方式的话,测试环境使用还行,当有几十上百的服务在集群中运行时NodePort的端口管理是灾难。
LoadBalance方式受限于云平台,且通常在云平台部署ELB还需要额外的费用。
k8s还提供了一种集群维度暴露服务的方式,也就是ingress。ingress可以简单理解为service的service,他通过独立的ingress对象来制定请求转发的规则,把请求路由到一个或多个service中。这样就把服务与请求规则解耦了,可以从业务维度统一考虑业务的暴露,而不用为每个service单独考虑。ingress规则是很灵活的,可以根据不同域名、不同path转发请求到不同的service,并且支持https/http。
Ingress本质上就是K8s集群中的一个比较特殊的Service(发布Kind: Ingress)。
这个Service提供的功能主要就是7层反向代理(也可以提供安全认证,监控,限流和SSL证书等高级功能),功能类似Nginx。
这个Service对外暴露出去是通过HostPort(80/443),可以和上面LoadBalancer对接起来。有了这个Ingress Service,我们可以做到只需购买一个LB+IP,就可以通过Ingress将内部多个(甚至全部)服务暴露出去,Ingress会帮忙做代理转发。
Ingress可以简单理解为service的service,他通过独立的ingress对象来制定请求转发的规则,把请求路由到一个或多个service中。这样就把服务与请求规则解耦了,可以从业务维度统一考虑业务的暴露,而不用为每个service单独考虑。ingress规则是很灵活的,可以根据不同域名、不同path转发请求到不同的service,并且支持https/http。
Ingress(入口): Service 的统一网关入口
- 底层是nginx 做的反向代理
- 官网地址:https://kubernetes.github.io/ingress-nginx/
有了前面的NodePort + LoadBalancer,将K8s内部服务暴露到外网甚至公网的需求就已经实现了,那么为啥还要引入Ingress这样一个概念呢?它起什么作用?
在公有云(阿里云/AWS/GCP)上,公网LB+IP是需要花钱买的。我们回看上图的通过LoadBalancer(简称LB)暴露服务的方式,发现要暴露一个服务就需要购买一个独立的LB+IP,如果要暴露十个服务就需要购买十个LB+IP,显然,从成本考虑这是不划算也不可扩展的。那么,有没有办法只需购买一个(或者少量)的LB+IP,但是却可以按需暴露更多服务出去呢?答案其实不复杂,就是想办法在K8内部部署一个独立的反向代理服务,让它做代理转发。谷歌给这个内部独立部署的反向代理服务起了一个奇怪的名字,就叫Ingress,它的简化概念模型如下图所示:
那么哪些软件可以做这个Ingress?
- 传统的Nginx/Haproxy可以,现代的微服务网关Zuul/SpringCloudGateway/Kong/Envoy/Traefik等等都可以。当然,谷歌别出心裁给这个东东起名叫Ingress,它还是做了一些包装,以简化对Ingress的操作。如果你理解了原理,那么完全可以用Zuul或者SpringCloudGateway,或者自己定制开发一个反向代理,来替代这个Ingress。部署的时候以普通Service部署,将type设定为LoadBalancer即可
特点总结
- Ingress(入口): Service 的统一网关入口
- Ingress 本质上就是K8s集群中的一个比较特殊的Service(发布Kind: Ingress)。
- 这个Service提供的功能主要就是7层反向代理(也可以提供安全认证,监控,限流和SSL证书等高级功能),功能类似Nginx。
- Ingress是一个7层反向代理,如果你要暴露的是4层服务,还是需要走独立LB+IP方式。
# 总结
- NodePort是K8s内部服务对外暴露的基础,LoadBalancer底层有赖于NodePort。NodePort背后是Kube-Proxy,Kube-Proxy是沟通Service网络、Pod网络和节点网络的桥梁。
- 将K8s服务通过NodePort对外暴露是以集群方式暴露的,每个节点上都会暴露相应的NodePort,通过LoadBalancer可以实现负载均衡访问。公有云(如阿里云/AWS/GCP)提供的K8s,都支持自动部署LB,且提供公网可访问IP,LB背后对接NodePort。
- Ingress扮演的角色是对K8s内部服务进行集中反向代理,通过Ingress,我们可以同时对外暴露K8s内部的多个服务,但是只需要购买1个(或者少量)LB。Ingress本质也是一种K8s的特殊Service,它也通过HostPort(80/443)对外暴露。
- K8s的Service发布主要有3种type
- type=ClusterIP,表示仅内部可访问服务
- type=NodePort,表示通过NodePort对外暴露服务
- type=LoadBalancer,表示通过LoadBalancer对外暴露服务(底层对接NodePort,一般公有云才支持)。