Kubernetes学习笔记整理之Ingress Controller
一、概念理解
1. 简介
Ingress 是反向代理规则,用来规定 HTTP/S 请求应该被转发到哪个 Service 上,比如根据请求中不同的 Host 和 url 路径让请求落到不同的 Service 上
2. 两大组件
简单来说,Ingress 只有两大组件:Ingress Controller 和 Ingress
Ingress
其中,Ingress资源通过yaml文件申明规则配置
Ingress Controller
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如何被集群外访问
有以下几种暴露内部流量的方式:
- Ingress Controller 用 Deployment 方式部署,给它添加一个 Service,类型为 LoadBalancer,这样会自动生成一个 IP 地址,通过这个 IP 就能访问到了,并且一般这个 IP 是高可用的(前提是集群支持 LoadBalancer,通常云服务提供商才支持,自建集群一般没有,这也是最简单的方式)
- 使用集群内部的某个或某些节点作为边缘节点,它们才是真正监听端口,让外界流量进入集群内部的节点,给这些边缘节点 node 添加 label 来标识(比如说设置ingress-controller=true),Ingress Controller 用 DaemonSet 方式部署(Deployment也可以),使用 nodeSelector 绑定到边缘节点,保证每个边缘节点启动一个 Ingress Controller 实例,用 hostPort 直接在这些边缘节点宿主机暴露端口,然后我们可以访问边缘节点中 Ingress Controller 暴露的端口,这样外部就可以访问到 Ingress Controller 了,多个边缘节点前面可以自己再搭一个负载均衡器,比如用Nginx或者有条件直接挂F5。
- Ingress Controller 用 Deployment 方式部署,给它添加一个 Service,类型为 NodePort,部署完成后查看会给出一个端口,通过
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 不再起作用。
二、部署方案
1. 部署default.backend
为了让Ingress Controller 能够正常启动,还需要为它配置一个默认的backend,用于在客户端访问的URL地址不存在时,能够返回一个正确的404应答。这个backend服务用任何应用实现都可以,只要满足默认对路径的访问返回404应答,并且提供/healthz完成对它的健康检查。如下,default-backend.yaml 文件可以在 官方 Ingress 仓库 找到:kubectl create-f default-backend.yaml
2.部署Ingress Controller
部署文件也可以在 官方仓库找到,注意会需要拉取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使用
3. 部署ingress
直接编写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的设置。