Ingress
Ingress是Kubernetes的用于管理外部访问的一个工具,允许定义路由规则,将外部流量引导到集群内的服务,并支持TLS、虚拟主机和负载均衡等功能。
Ingress 是什么?
Ingress提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。
下面是 Ingress 的一个简单示例,将所有流量都发送到同一个Service:
工作原理
ingress-contronler通过与k8s的api进行交互,动态的去感知k8s集群中ingress服务规则的变化,然后读取它,并按照定义的ingress规则,转发到k8s集群中对应的service。
这个ingress规则写明了哪个域名对应k8s集群中的哪个service,然后再根据ingress-controller中的nginx配置模板,生成一段对应的nginx配置
。
然后把该配置动态的写到ingress-controller的pod里,该ingress-controller的pod里面运行着一个nginx服务,控制器会把生成的nginx配置写入到nginx的配置文件中,然后reload一下,使其配置生效。以此来达到域名分配置及动态更新的效果。
使用Ingress的好处:
端口管理。减少不必要端口暴露,便于管理。
所有的请求,通过Ingress对应的
IP:PORT
进入,过滤/转发/负载均衡到相应的service/pod
。NodePort
会在每个node上暴露对应的port,不便管理。
环境准备
你必须安装 Ingress 控制器 才能使用 Ingress。
你需要先安装 Ingress 控制器,例如 ingress-nginx。 你可以从许多 Ingress 控制器 中进行选择。
安装ingress 控制器
本例使用谷歌提供的 nginx-ingress-controller 镜像创建 ingress-controller
,并以 Pod + Service 方式运行,其中 Service 使用 nodePort 方式将80
,443
端口映射至物理机上。
部署过程中使用到的文档参考:https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md#bare-metal
下载各所需的yaml文件
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.41.2/deploy/static/provider/cloud/deploy.yaml >deploy.yaml
启动上述yaml文件
kubectl create -f deploy.yaml
上述yaml文件中可以不用修改,直接运行。
注意:国内下载:需要将 k8s.gcr.io/ingress-nginx/controller:v0.41.2 替换成 kubebiz/ingress-nginx:controller-v0.41.2
也可到这里下载:https://www.kubebiz.com/orchome/ingress-nginx (镜像已替换为国内的)
Ingress
Ingress由两部分组成:Ingress Controller 和 Ingress 服务。
核心逻辑:Ingress Contronler 通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段 Nginx 配置,再写到 Nginx-ingress-control的 Pod 里,这个 Ingress Contronler 的pod里面运行着一个nginx服务,控制器会把生成的nginx配置写入
/etc/nginx.conf
文件中,然后 reload 一下 使用配置生效。以此来达到域名分配置及动态更新。
- 对
https://mywebsite.com/api
的访问将被路由到后端名为"api"的 Service。 - 对
https://mywebsite.com/web
的访问将被路由到后端名为"web"的 Service。 - 对
https:/mywebsite.com/doc
的访问将被路由到后端名为"doc"的 Service。
下面通过一个例子分三步说明Ingress Controller
和Ingress 策略
和客户端
如何访问 Ingress 提供的服务。
ingress规则编写
下面是一个简单的例子:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
ingress.kubernetes.io/ssl-redirect: "false" ##关闭强制使用HTTPS的设置
spec:
rules:
## 根据URL路径实现转发,域名为 *
- https:
paths:
- path: /demo
backend:
serviceName: mydemo
servicePort: 8080
- path: /test
backend:
serviceName: mytest
servicePort: 8080
根据域名实现转发:
$ cat mytest.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: pand-ingress
annotations:
ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
## 根据域名实现转发
- host: www.mywebsite1.com
https:
paths:
- backend:
serviceName: mydemo
servicePort: 8080
- host: www.mywebsite2.com
https:
paths:
- backend:
serviceName: mytest
servicePort: 8080
创建上述ingress,在客户端配置好域名解析,实现访问。
也可以通过curl指定解析访问:
curl --resolve www.mywebsite1.com:80:172.10.18.3 www.mywebsite1.com/mydemo
总结
优点:Ingress支持L7负载均衡;Ingress基于Pod部署,并将Pod网络设置成external network;Ingress controller支持Nginx、Haproxy,能够满足企业内部使用。
缺点:因为pod是临时的,由于Ingress Controller也是基于Pod部署,这样Ingress对外的IP会发生变化。在企业内部都会在防火墙上给Service的访问IP设定规则,而IP变动对这一机制是致命的,因为企业不可能经常手动修改防火墙规则。
更多详情,请参考官方:https://kubernetes.io/zh/docs/concepts/services-networking/ingress/
有一点疑惑的地方,ingress是如何做到负载均衡的?
请求从ingress controller进来到service似乎只有路由的功能,
我个人理解,如果有负载均衡效果,需要直接路由到对应的pod
service就是负载呀。
粗暴的理解是 ingress 相当于 nginx,比nginx多了一点,就是可以识别service。
我理解的负载均衡应该是多个同等服务之间均衡处理,
所以到service只是类似于寻址一样的转发,一对一,看不到类似应用负载均衡算法(或者说多个选一个)的地方
没懂,kubernetes service默认的算法是轮询额。
ingress做统一入口,主要用在域名解析到service。
从service到pod的负载均衡我明白,但这部分是kube-proxy负责的,不使用ingress,这部分还是存在。
如果把ingress当作一个域名解析到service,那不就只是一个路由效果吗,真正的均衡还是由kube-proxy来做
主要就是做统一入口,域名解析和对kubernetes service的识别支持,配置的是
NodePort
类型,所有的node都可以作为入口。非常感谢耐心解答。
不过我后续在找一些资料过程中,也发现了一个说法,就是ingress controller是可以直接到pods完成负载均衡和更高效的转发
相关链接
更早的的外文出处
这里的servicePort:8080有什么用吗,我感觉好像没用上
只是为了易读,原理可查看:
为什么ingress servicePort设置service的"port" 和 "targetPort"都可以?
使用域名加prefix的方式转发的话,外部通过域名访问,域名是怎么解析过来的。直接解析到master上吗?还是怎么弄
对,准确的说,是解析任意node上就可以了,node之间都识别的。