目录
2、下载nginx-ingress-controller的chart以及修改values.yaml文件
6、实验6—Ingress-nginx 错误代码重定向 - 默认错误后端
10、实验10—ingress-nginx 灰度或者金丝雀发布
11、实验11—ingress-nginx 代理后端https协议
13、实验13—ingress-nginx 基于UDP四层代理
一、四层负载与七层负载
四层负载均衡和七层负载均衡的主要区别在于它们工作的网络层次和功能特点。
1、工作层次
- 四层负载均衡:工作在OSI模型的第四层,即传输层,主要基于IP地址和端口号进行负载均衡。它通过修改数据包的IP地址和端口号来转发流量,不涉及应用层的内容。客户端和后端服务器是一次完整的TCP连接,负载均衡器只是起到转发作用。
- 它在接收到客户端的流量以后通过修改数据包的地址信息(目标地址和端口,以及源地址)将流量转发到应用服务器。其中目的地址即需要转发的目的服务器,源地址原本是客户端地址,但是转发中会把源地址修改为负载均衡服务器的地址。
- LVS是典型的四层负载均衡调度器,如下是基本架构。
- 七层负载均衡:工作在OSI模型的第七层,即应用层,可以根据应用层的内容(如HTTP头、URL路径、Cookie等)进行负载均衡。它能够解析应用层的数据,根据具体的请求信息进行更加精细的负载均衡。
- 它首先会与客户端建立一条完整的连接并将应用层的请求流量解析出来,再按照调度算法选择一个应用服务器,并与应用服务器建立另外一条连接将请求发送过去。所以七层负载均衡是需要建立两次连接。
- Nginx是典型的7层负载均衡调度器,如下是基本架构。
2、七层负载的应用场景
四层和七层负载均衡在实际应用中有什么区别呢?
比如,如果客户端想发起HTTPS的请求访问(安全性),假如你使用的是四层负载均衡器,因为四层负载均衡器只是转发,所以后端服务器要都是HTTPS服务才行。但如果是使用的七层负载均衡器的话, 因为是两次连接,客户端可以和Nginx走https服务,确保安全,第二次连接Nginx和后端服务器之间可以走http服务。
如下是通过Nginx七层负载均衡完成客户端和后端微服务的两次连接。
整体访问链接的过程如下:客户端首先访问的是nginx的ip+端口,以及页面地址。比如如果访问的是stu/xxx.phh页面,Nginx接收到请求后,因为Nginx是可以工作在七层负载,它可以解析数据包获取域名,得到域名后会在server区中找到访问stu的路径,反向代理指向http://stu:80地址,该地址在upstream区中是upstream stu,然后会有两台服务器,分别是14和15服务器,通过负载均衡算法,选中一台服务器进行访问建立连接。
在K8S集群中通过Nginx做七层负载均衡,整体框架可以如下。
通过创建nodeport-nginx的pod,可以让外网通过nodeport绑定的端口(10080和10443两个端口,这两个端口分别映射到nginx pod的80和443端口上),这两个端口的访问路由到由deployment控制器创建的nginx的pod,nginx因为工作在7层负载均衡,它会解析数据包,得到域名,根据配置内容,反向代理信息等,www1.xinxianghf.com的域名访问会代理到http://www1的地址,这个地址在upstream区域中,会找到server为www1svcIP:port的服务器地址,即途中名为www1的service的clusterIp地址及端口号,四层负载均衡服务器地址,这个www1的service会帮忙负载到对应下边的2台tomcat app=www1的服务器中的一台中。www2的访问路径同www1。
deployment中启动的nginx,其配置文件可以通过configmap文件进行版本管理,可以进行修改形成新的版本,不过configmap修改重新使得nginx生效需要手动重启。
以上是可以利用k8s已有的组件可以完成七层负载均衡的搭建。那为什么还需要Ingress呢,发现上面的框架中,我们还是需要手动配置Nginx的文件,设定好对应的service集群的ip和端口使之和实际的要匹配,也就是这部分需要人工手动进行配置,如果配置错了就会出现问题。
另外,每当有新服务加入,都需要对nginx相关的配置进行修改、升级,在服务数量逐渐变多后,该配置项目会变得越来越大,手工修改的风险也会逐渐增高。
那么需要一个工具来简化这一过程,希望可以通过简单的配置动态生成代理中复杂的配置,最好还可以顺手重新加载配置文件。
想想怎么实现配置的自动化生成和修改?
二、Ingress概念和应用场景
Ingress是API Server中的一个组件,Ingress 包含两大组件:Ingress Controller 和 Ingress。
Ingress并不直接处理或转发流量,它需要与Ingress Controller一起使用。Ingress Controller是一个实际处理流量的组件,它根据Ingress资源中定义的规则,将请求路由到正确的服务。这种组合使得在Kubernetes环境中能够方便地管理多个服务的访问入口。
- Ingress 资源对象:这是通过 YAML 文件配置的,它定义了请求如何转发到服务的规则。Ingress 对象可以包含多个规则,每个规则可以指定不同的域名、路径和后端服务。
- Ingress 控制器(Ingress Controller):这是一个运行在 Kubernetes 集群中的组件,它负责实现 Ingress 资源对象中定义的规则。Ingress 控制器通常是一个反向代理服务器,如 Nginx 或 Traefik,它根据 Ingress 规则来处理进入集群的流量。
一般,ingress-controller的形式都是一个pod,里面跑着daemon程序和反向代理程序。daemon负责不断监控集群的变化,根据 ingress对象生成配置并应用新配置到反向代理,比如ingress-nginx就是动态生成nginx配置,动态更新upstream,并在需要的时候reload程序应用新配置。为了方便,后面的例子都以k8s官方维护的ingress-nginx为例。
Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginx
Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/
总结来说:ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到 ingress-controller, 而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名、哪些URL要转发到哪些service等等。
Ingress 简单的理解就是你原来需要改 Nginx 配置,然后配置各种域名对应哪个 Service,现在把这个动作抽象出来,变成一个 Ingress 对象,你可以用 yaml 创建,每次不要去改 Nginx 了,直接改 yaml 然后创建/更新就行了;
Ingress Controller 通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,并按照规则模板生成一段 Nginx 配置,再写到 Nginx Pod 里,最后 reload 一下。
使用Nginx的Ingress内部工作原理图
store协程主要是监听变化事件,并根据事件情况分两条路径分发,如果是配置Nginx服务必要的信息则会直接给到Sync协程处理,如果不是,则写入缓存处理系统当中。分两条处理的思路是对于必要紧急的事件是需要实时性的处理的,而对于非实时性处理事件可以延后一段时间进行处理,因为处理结果是需要reload nginx服务的,这会有代价的。所以需要分开区别对待。
基于Ingress API的七层实现
三、Ingress安装部署
1、各节点安装2个镜像
docker pull registry.aliyuncs.com/google_containers/kube-webhook-certgen:v1.4.3
docker pull registry.aliyuncs.com/google_containers/nginx-ingress-controller:v1.10.0
在各个节点上都运行上面两条命令,拉取2个镜像到本地。
2、下载nginx-ingress-controller的chart以及修改values.yaml文件
#chart包的下载地址
wget https://github.com/kubernetes/ingress-nginx/releases/download/helm-chart-4.8.3/ingress-nginx-4.8.3.tgz
tar -xf ingress-nginx-4.8.3.tgz
cd ingress-nginx/
vim values.yaml
修改values.yaml文件内容如下:
1)hostNetwork: false =》 hostNetwork: true
#开启与宿主机共享网络,就像docker的host网络模式,不用单独建立网络命名空间了
2)dnsPolicy: ClusterFirst =》 dnsPolicy: ClusterFirstWithHostNet
3)kind: Deployment =》 kind: DaemonSet
#修改默认控制器类型,DaemonSet让nginx-ingress有高可用的这么个机制,保证每个节点都有一个pod
4)ingressClassResource.default: false => ingressClassResource.default: true
#设置默认Ingress控制器类名,Ingress控制器有很多的,这里设置为nginx的意思是只要明确指定别的控制器,默认被nginx代理
5)注释掉digest值。如果你的digest值与官方不一致就会重新下载。
6)将2个镜像的registry和image都修改为上面pull到本地的名称。如下:
3、部署nginx-ingress-controller
kubectl create ns ingress #单独建立命名空间是为了方便隔离,管理。
执行安装命令:
helm install ingress-nginx -n ingress ./ingress-nginx -f ./ingress-nginx/values.yaml
查看部署结果如下:
四、应用ingress
1、实验1—Ingress-nginx http代理
(1)创建单一服务
vim 5.ingress.yaml
####10章节,ingress-http代理
apiVersion: apps/v1
kind: Deployment
metadata:
name: ngress-httpproxy-www1
spec:
replicas: 2
selector:
matchLabels:
hostname: www1
template:
metadata:
labels:
hostname: www1
spec:
containers:
- name: nginx
image: nginx: v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: ingress-httpproxy-www1
spec:
selector:
hostname: www1 #标签选择器,匹配标签为hostname=www1的pod,也就是能够匹配到上面deployment控制器的pod。
ports:
- port: 80 #SVC暴露的端口
targetPort: 80 #讲流量转发给容器的端口,必须要和containerPort一致
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-httpproxy-www1
spec:
# 指定使用的 Ingress 控制器类,这里使用 nginx。这就是安装部分修改的默认控制器类型,如果刚才设置了可以不写,反之则必须写。推荐写上
ingressClassName: nginx
rules: # 定义路由规则
- host: www1.test.com # 第一条规则,基于域名 www1.test.com
http: # 定义 HTTP 路由规则
paths: # 定义路径规则
- path: / # 匹配根路径 /
pathType: Prefix # 路径匹配类型为前缀匹配(Prefix)
backend: # 定义后端服务
service: # 后端服务的定义
name: ingress-httpproxy-www1 # 后端服务的名称
port: # 后端服务的端口
number: 80 # 端口号为 80
执行创建命令:kubectl create -f 5.ingress.yaml
检查对应的deployment、service、pod以及ingress创建成功。
在master01节点上访问服务:
在虚拟机外的物理主机上访问IP服务: