一、K8S对外服务–ingress
1、Ingress和Service之间的关系
service的作用体现在两个方面:
- 对集群内部,不断跟踪Pod的变化,更新endpoint对应Pod的对象,提供了IP不断变化的Pod的服务发现机制
- 对集群外部,它类似负载均衡器,可以在集群内外部对Pod进行访问
ingress的作用:可以通过不同的域名或url路径与指定的service进行绑定,实现K8S集群外部访问内部Pod。可同时将多个http服务暴露在外网,七层反向代理
可以简单理解为:service的service,它其实就是一组基于域名或URL路径,把用户的请求转发到一个或多个service的规则
2、外部的应用能够访问集群内的服务有哪些方案?
- NodePort:将service暴露在节点网络上,
NodePort背后就是kube-proxy,kube-proxy是沟通service网络、Pod网络和节点网络的桥梁
- 缺点:测试环境使用还可以,当有上百的服务在集群中运行时,NodePort的端口管理就是灾难级别。因为每个端口只能是一种服务,默认端口范围只能是30000~32767
- LoadBalancer:通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址。这种用法仅用于在公有云服务提供商的云平台上设置Service的场景。受限于云平台,且通常在云平台部署,LoadBalancer还需要
额外的费用,而且底层还是NodePort
- 在Service提交后,kubernetes就会调用CloudProvider在公有云上为你创建一个负载均衡服务,并且被代理的Pod的IP地址配置给负载均衡服务做后端
- Ingress:只需一个或少量的公网IP和LB,即可以同时将多个HTTP服务暴露到外网,七层反向代理。
- 简单理解:ingress就是service的service,它其实就是一组基于域名或URL路径,把用户的请求转发到一个或多个service的规则
3、Ingress组成
ingress
:ingress是一个API对象,通过yaml文件来配置- ingress对象的作用:定义请求如何转发到service的规则,可以理解为配置模板
- ingress是通
过http/https暴露集群内部service,给service提供外部URL、负载均衡、ssl/tls能力以及域名的反向代理
ingress要通过ingress-controller来具体实现以上功能
ingress-controller
:- ingress-controller是具体实现反向代理及负载均衡的程序,对Ingress定义的规则进行解析,根据配置的规则来实现请求转发
- ingress-controller并不是K8s自带的组件,实际上ingress-controller只是一个统称,用户可以选择不同的ingress-controller实现,目前
由k8s维护的ingress-controller只是Google云的GCE与ingress-nginx两个
ingress-controller的形式都是一个Pod,里面跑着daemon程序和反向代理程序
- daemon负责不断监控集群的变化,根据ingress对象生成配置并应用新配置到反向代理,比如:ingress-nginx就是动态生成nginx配置,动态更新upstream,并在需要的时候reload程序应用新配置。
总结:
ingress-controller才是负责具体转发到组件,通过各种方式将它暴露在集群入口,外部对集群流量会先到ingress-controller,而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名、URL要转发到那些service等
4、Ingress-Nginx工作原理
ingress-controller通过和apiserver交互,动态感知集群中的ingress规则的变化,并读取配置
ingress规则中配置了基于域名或URL路径对应的Service,ingress-controller读取后自动生成nginx配置信息
ingress-controller会将自动生成的nginx配置信息写入Pod中,这个ingress-controller实际是运行一个nginx,控制器将配置信息更新到/etc/nginx.conf文件中
然后reload重载一下让配置生效
总结:
后续客户端访问指定域名和指定url路径的时候,请求会转发到nginx-controller控制器的service然后转发到ingress控制器的Pod,Pod会将根据ingress的规则转发给相应的Service,然后再根据标签选择器转发给业务Pod
5、Ingress暴露服务的方式:
方式一:DaemonSet+HostNetwork+nodeSelector
思维:用DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该Pod与宿主机的node的网络打通
,直接使用宿主机的80/443端口就能访问服务。
缺点:由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller Pod。比较适合大并发的生产环境使用。相对来说,安全性不高
方式二:Deployment+NodePort模式的Service
同样用Deployment模式部署ingress-controller,并创建对应的service,但是type为NodePort,这样,ingress就会暴露在集群节点IP的特定端口上
。由于NodePort暴露的端口是随机端口,一般会在前面再搭建一套负载均衡器来转发请求。
总结:
该方式一般用于宿主机是相对固定的环境IP地址不变的场景。NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能有一定影响
方式三:Deployment+LoadBalancer模式的Service
如果要把ingress部署在公有云,那用这种方式最合适。用Deployment部署ingress-controller,创建一个Type为LoadBalancer的Service关联这组Pod
。大部分公有云,都会为LoadBalancer的Service自动创建一个负载均衡器,通常还绑定了公网地址。只要把域名解析指向改地址,就实现了集群服务的对外暴露(底层还是Node
)