1. Ingress概述
1.1 Ingress的简介
service的作用体现在两个方面:
- 对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制;
- 对集群外部,他类似负载均衡器,可以在集群内外部对pod进行访问。
在Kubernetes中,Pod的IP地址和service的ClusterIP仅可以在集群网络内部做用,对于集群外的应用是不可见的。为了使外部的应用能够访问集群内的服务,Kubernetes目前提供了以下几种方案:
- NodePort:将service暴露在节点网络上,NodePort背后就是Kube-Proxy,Kube-Proxy是沟通service网络、Pod网络和节点网络的桥梁。测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的瑞口管理就是个灾难。因为每个端口只能是一种服务,端口范围只能是 30000-32767。
- LoadBalancer:通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址。这种用法仅用于在公有云服务提供商的云平台上设置Servic的场景。受限于云平台,且通常在云平台部署LoadBalancer还需要额外的费用。
- Ingress:只需一个或者少量的公网IP和LB,即可同时将多个HTTP服务暴露到外网,七层反向代理。 可以简单理解为service的service,它其实就是一组基于域名和URL路径,把用户的请求转发到一个或多个service的规则。
Ingress解决的是新的服务加入后,域名和服务的对应问题,基本上是一个ingress的对象,通过yaml进行创建和更新进行加载。工作机制大致可以用下图表示:
实际上,ingress相当于一个7层的负载均衡器,是k8s对反向代理的一个抽象。大概的工作原理也确实类似于Nginx,可以理解成在 Ingress 里建立一个个映射规则 , ingress Controller 通过监听 Ingress这个api对象里的配置规则并转化成 Nginx 的配置(kubernetes声明式API和控制循环) , 然后对外部提供服务。
1.2 Ingress的组成
Ingress包含了两大组件Ingress Controller和Ingress。
1.2.1 Ingress组件
ingress是一个API对象,通过yaml文件来配置,ingress对象的作用是定义请求如何转发到service的规则,可以理解为配置模板。 ingress通过http或https暴露集群内部service,给service提供外部URI、负载均衡、SSL/TLS能力以及基于域名的反向代理。ingress要依靠ingress-controiler来具体实现以上功能。
简单来说,ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到ingress-controller,而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名哪些path要转发到哪些服务等等。
Ingress 格式示例:
代码语言:javascript复制apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
rules:
- http:
paths:
- path: /testpath
backend:
serviceName: test
servicePort: 80
每个 Ingress 都需要配置 rules,目前 Kubernetes 仅支持 http 规则。上面的示例表示请求 /testpath 时转发到服务 test 的 80 端口。
1.2.2 ingress-controller组件
ingress-controller是具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。 ingress-controller并不是k8s自带的组件,实际上ingess-controller只是一个统称,用户可以选择不同的ingress-controller实现,目前,由k8s维护的ingress-controller只有google云的GCE与ingress-nginx两个,其他还有很多第三方维护的ingress-controller,比如Contour, Haproxy, trafik, Istio,具体可以参考官方文档。 但是不管哪一种ingress-controller,实现的机制都大同小异,只是在具体配置上有差异,ingress controller核心是一个deployment,需要编写的yaml有:Deployment, Service, ConfigMap, ServiceAccount(Auth),其中service的类型可以是NodePort或者LoadBalancer。 一般来说,ingress-controller的形式都是一个pod,里面跑着demon程序和反向代理程序。daemon负责不断监控集群的变化,根据ingress对象生成配置并应用新配置到反向代理,比如ingress-nginx就是动态生成nginx配置,动态更新upstreanm,并在需要的时候reload程序应用新配置。为了方便,后面的例子都以k8s官方维护的ingress-nginx为例。 Ingress-Nginx github 地址: GitHub - kubernetes/ingress-nginx: Ingress-NGINX Controller for Kubernetes
Ingress-Nginx 官方网站: Welcome - NGINX Ingress Controller
1.3 Ingress的工作原理
Ingress Controller是将Ingress这种变化生成一段Nginx的配置,然后将这个配置通过Kubernetes API写到Nginx的Pod中,然后reload.(注意:写入 nginx.conf 的不是service的地址,而是service backend 的 pod 的地址,避免在 service 在增加一层负载均衡转发)。
从上图中可以很清晰的看到,实际上请求进来还是被负载均衡器拦截,比如 nginx,然后 Ingress Controller 通过跟 Ingress 交互得知某个域名对应哪个 service,再通过跟 kubernetes API 交互得知 service 地址等信息;综合以后生成配置文件,实时写入负载均衡器,然后负载均衡器 reload 该规则便可实现服务发现,即动态映射:
- ingress-controller通过和 kubernetes APIServer交互,动态的去感知集群中ingress规则变化;
- 然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置;
- 再写到nginx-ingress-controller的pod里,这个ingres-controller的pod里运行着一个Nginx服务,控制器会把生成的nginx置写入/etc/nginx.conf文件中;
- 最后reload一下使配置生效。以此达到域名区分配置和动态更新的作用。
客户端一般会把请求发送到负载均衡器上由负载均衡器转发到ingress控制所在的node节点上目的减小Node节点的负载压力。ingress控制器会根据ingress资源对象的配置转发请求到对应的service;service会根据端点,把请求转发到关联的Pod。
在使用普通的Service时,集群中每个节点的kube-proxy在监听到Service和Endpoints的变化时,会动态的修改相关的iptables的转发规则。 客户端在访问时通过iptables设置的规则进行路由转发达到访问服务的目的。
而Ingress则跳过了kube-proxy这一层,通过Ingress Controller中的代理配置进行路由转发达到访问目标服务的目的。实际上可以把IngressController看做一个拥有默认处理后端的代理,根据Ingress资源的配置动态修改代理的配置文件,以实现按照规则转发请求的功能。
参考链接
Ingress · Kubernetes指南
Ingress | Kubernetes
K8S-ingress - 不会跳舞的胖子 - 博客园
k8s ingress原理及ingress-nginx部署测试_个人文章 - SegmentFault 思否
k8s之ingress使用
k8s——ingress - 落寞1111 - 博客园
K8S对外服务之Ingress_51CTO博客_k8s ingress
K8S中的ingress_84岁带头冲锋的博客-CSDN博客_k8s的ingress
k8s之ingress
k8s 对外服务之ingress_新是一切的根源的博客-CSDN博客_ingress k8s
一文讲透K8s的Service概念