Ingress 是反向代理规则,用来规定 HTTP/S 请求应该被转发到哪个 Service 上,比如根据请求中不同的 Host 和 url 路径让请求落到不同的 Service 上
简单来说,Ingress 只有两大组件:Ingress Controller 和 Ingress
其中,Ingress资源通过yaml文件申明规则配置
Ingress Controller 就是一个反向代理程序,它负责解析 Ingress 的反向代理规则,以Pod的形式运行,监控apiserver的/ingress端口后的backend services,如果 Ingress 有增删改的变动,所有的 Ingress Controller 都会及时更新自己相应的转发规则,当 Ingress Controller 收到请求后就会根据这些规则将请求转发到对应的 Service。
核心是一个deployment,实现方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,需要编写的yaml有:Deployment, Service, ConfigMap, ServiceAccount(Auth),其中service的类型可以是NodePort或者LoadBalancer。
QA1:Ingress Controller具体怎么工作的呢?
实际上,Ingress Controller通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取它,按照自定义的规则(规则就是写明了哪个域名对应哪个service),生成一段 Nginx 配置,再写到 Nginx-ingress-control的 Pod 里,这个 Ingress Contronler 的pod里面运行着一个nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中,然后 reload 一下 使用配置生效。以此来达到域名分配置及动态更新的问题。
QA2:Ingress Controller如何被集群外访问
有以下几种暴露内部流量的方式:
kubectl get svc
我们可以查看到这个端口,这个端口在集群的每个节点都可以访问,通过访问集群节点的这个端口就可以访问 Ingress Controller 了。但是集群节点这么多,而且端口又不是 80和443,太不爽了,一般我们会在前面自己搭个负载均衡器,比如用 Nginx,将请求转发到集群各个节点的那个端口上,这样我们访问 Nginx 就相当于访问到 Ingress Controller 了通常用的是前两种方式。
QA3:外部流量进集群POD是怎么被转发的
我们这里以上文中第二种方案(自建集群)画图说明,用到了3个边缘节点,流量从F5/LB进来,然后被转发到其中一个ingress controller的pod里面,并根据svc规则转发到svc对应的后端endpoint上(对应app pod),其中ingress controller是运行在某个ingress controller pod里面,直接watch API SERVER里面ingress规则的变更,这里就已经不需要ingress-nginx的svc了(不过一般还需要配置下,否则集群会一直提示err services "ingress-nginx" not found
图中可以看出,不需要Ingress Controller的SVC了,而且也跳过kube-proxy的转发功能,kube-proxy 不再起作用。
为了让Ingress Controller 能够正常启动,还需要为它配置一个默认的backend,用于在客户端访问的URL地址不存在时,能够返回一个正确的404应答。这个backend服务用任何应用实现都可以,只要满足默认对路径的访问返回404应答,并且提供/healthz完成对它的健康检查。如下,default-backend.yaml 文件可以在 官方 Ingress 仓库 找到:kubectl create-f default-backend.yaml
部署文件也可以在 官方仓库找到,注意会需要拉取ingress-controller镜像,如果离线环境提前下载好。另外不同环境下载不同的部署yaml文件,这里只是示例,我们采用Helm方式来部署:
$ kubectl label node sysops00001 ingress-controller=true
node "sysops00001" labeled
helm install stable/nginx-ingress \
--namespace ingress-nginx \
--name nginx-ingress \
--version=0.23.0 \
--set controller.kind=DaemonSet \
--set controller.daemonset.useHostPort=true \
--set controller.nodeSelector.node=edge \
--set controller.service.type=ClusterIP
查看状态
# kubectl get pods -n ingress-nginx -o wide
nginx-ingress-controller-b47h9 1/1 Running 0 1h
nginx-ingress-default-backend-9c5d6df7d-7dwll 1/1 Running 0 1h
注意,ingress-controller 会监听node节点上的80和443端口,因此尽量在使用端口时保留80和443给ingress-controller使用
直接编写ingress yaml文件并通过kubectl apply即可
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cafe-ingress
spec:
rules:
# 配置七层域名
- host: foo.bar.com
http:
paths:
# 配置Context Path
- path: /tea
backend:
serviceName: tea-svc
servicePort: 80
# 配置Context Path
- path: /coffee
backend:
serviceName: coffee-svc
servicePort: 80
注意,使用无域名的Ingress转发规则时,将默认禁用非安全HTTP,强制启用HTTPS. 可以在Ingress的定义中设置一个 annotation “ingress.kubernetes.io/ssl-redirect=false” 来关闭强制启用HTTPS的设置。