目录
一、Ingress 简介
1.1service的作用
1.2外部访问方案 (四种)🌹🌹🌹
部署externalIPs
1.3Ingress 是什么
二、Ingress 组成🌹🌹🌹
三、Ingress 工作原理🐱🐱🐱
四、ingress 暴露服务的方式🐱🐱🐱
4.1方式一:Deployment+LoadBalancer 模式的 Service
4.2方式二:DaemonSet+HostNetwork+nodeSelector
4.3方式三:Deployment+NodePort模式的Service
五、部署 nginx-ingress-controller
5.1部署ingress-controller pod及相关资源
5.2修改 ClusterRole 资源配置
🤔🤔🤔采用DaemonSet+HostNetwork+nodeSelector暴露服务
5.3修改 Deployment 为 DaemonSet ,指定节点运行,并开启 hostNetwork 网络
5.4指定 nginx-ingress-controller 运行在 node02 节点
5.5在所有 node 节点上传 nginx-ingress-controller 镜像压缩包 ingree.contro.tar.gz 到 /opt/ingress 目录,并解压和加载镜像
5.6启动 nginx-ingress-controller
5.7创建 ingress 规则
创建 ingress
5.8测试访问
5.9查看 nginx-ingress-controller
5.10数据流向
🤔🤔🤔采用Deployment+NodePort模式的Service暴露服务
1.下载 nginx-ingress-controller 和 ingress-nginx 暴露端口配置文件
2.在所有 node 节点上传镜像包 ingress-controller-0.30.0.tar 到 /opt/ingress-nodeport 目录,并加载镜像
3.启动 nginx-ingress-controller
七、Ingress HTTP 代理访问
7.1创建 deployment、Service、Ingress Yaml 资源
7.2进入容器编辑页面内容
7.3测试访问
7.4数据流向
八、Ingress HTTP 代理访问虚拟主机
8.1创建虚拟主机1资源
8.2创建虚拟主机2资源
8.3创建ingress资源
8.4测试访问
九、Ingress HTTPS 代理访问
9.1创建ssl证书
9.2创建 secret 资源进行存储
9.2.1创建Secret资源:
9.2.2获取Secret资源信息:
9.2.3查看Secret资源:
9.3创建 deployment、Service、Ingress Yaml 资源
9.4访问测试
十、Nginx 进行 BasicAuth
10.1生成用户密码认证文件,创建 secret 资源进行存储
10.2创建Secret资源
10.3创建Ingress资源
10.4浏览器检测
十一、Nginx重写
11.1 metadata.annotations 配置说明
11.2创建重写Ingress资源
11.3浏览器访问
十二、温故而知新
12.1Ingress数据流向
12.2K8S集群外部的客户端访问K8S集群内部的方案?
12.3基于主机名的虚拟主机
12.4Ingress的组成
12.5创建Ingress资源
12.6Ingress资源配置
12.7基于不同域名或者不同URL路径做转发
12.8基于https代理转发
12.9Rewrite重定向
基于rewrite实现重写访问路径
12.10基于basic-auth实现访问认证
一、Ingress 简介
1.1service的作用
service的作用体现在两个方面:
- 对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制;
- 对集群外部,他类似负载均衡器,可以在集群内外部对pod进行访问。
在Kubernetes中,Pod的IP地址和service的ClusterIP仅可以在集群网络内部使用,对于集群外的应用是不可见的。
1.2外部访问方案 (四种)🌹🌹🌹
为了使外部的应用能够访问集群内的服务,Kubernetes目前提供了以下几种方案:
- NodePort:将service暴露在节点网络上,NodePort背后就是Kube-Proxy,Kube-Proxy是沟通service网络、Pod网络和节点网络的桥梁。测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的端口管理就是个灾难。因为每个端口只能是一种服务,端口范围只能是 30000-32767。
- LoadBalancer:通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址。这种用法仅用于在公有云服务提供商的云平台上设置 Service 的场景。受限于云平台,且通常在云平台部署LoadBalancer还需要额外的费用。在service提交后,Kubernetes就会调用CloudProvider在公有云上为你创建一个负载均衡服务,并且把被代理的Pod的IP地址配置给负载均衡服务做后端。
- externalIPs:service允许为其分配外部IP,如果外部IP路由到集群中一个或多个Node上,Service会被暴露给这些externalIPs。通过外部IP进入到集群的流量,将会被路由到Service的Endpoint上。
- Ingress:只需一个或者少量的公网IP和LB,即可同时将多个HTTP服务暴露到外网,七层反向代理。可以简单理解为service的service,它其实就是一组基于域名和URL路径,把用户的请求转发到一个或多个service的规则。
部署externalIPs
kubectl create deployment zzz-demo01 --image=soscscs/myapp:v1 --port=80kubectl expose deployment zzz-demo01 --type=NodePort --port=80 --target-port=80kubectl get pod,svc -owide
kubectl edit svc zzz-demo01
浏览器也可以访问哦
测试,添加了ip地址,就可以访问了哦
1.3Ingress 是什么
官方文档:Ingress | Kubernetes
Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。
Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。
Ingress 提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源所定义的规则来控制。
下面是 Ingress 的一个简单示例,可将所有流量都发送到同一 Service:
通过配置,Ingress 可为 Service 提供外部可访问的 URL、对其流量作负载均衡、 终止 SSL/TLS,以及基于名称的虚拟托管等能力。 Ingress 控制器 负责完成 Ingress 的工作,具体实现上通常会使用某个负载均衡器, 不过也可以配置边缘路由器或其他前端来帮助处理流量。
Ingress 不会随意公开端口或协议。 将 HTTP 和 HTTPS 以外的服务开放到 Internet 时,通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的 Service
二、Ingress 组成🌹🌹🌹
- ingress是一个API对象,通过yaml文件来配置,ingress对象的作用是定义请求如何转发到service的规则,可以理解为配置模板。
ingress通过http或https暴露集群内部service,给service提供外部URL、负载均衡、SSL/TLS以及基于域名的反向代理。ingress要依靠 ingress-controller 来具体实现以上功能。
- ingress-controller: 当做反向代理或者说是转发器
ingress-controller是具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。
ingress-controller并不是k8s自带的组件,实际上ingress-controller只是一个统称,用户可以选择不同的ingress-controller实现,目前,由k8s维护的ingress-controller只有google云的GCE与ingress-nginx两个,其他还有很多第三方维护的ingress-controller,具体可以参考官方文档。但是不管哪一种ingress-controller,实现的机制都大同小异,只是在具体配置上有差异。
一般来说,ingress-controller的形式都是一个pod,里面跑着daemon程序和反向代理程序。daemon负责不断监控集群的变化,根据 ingress对象生成配置并应用新配置到反向代理,比如ingress-nginx就是动态生成nginx配置,动态更新upstream,并在需要的时候reload程序应用新配置。为了方便,后面的例子都以k8s官方维护的ingress-nginx为例。
总结:
ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到 ingress-controller, 而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名、哪些URL要转发到哪些service等等。
官方文档
Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginxIngress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/
三、Ingress 工作原理🐱🐱🐱
(1)ingress-controller通过和 kubernetes APIServer 交互,动态的去感知集群中ingress规则变化,
(2)然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置,
(3)再写到nginx-ingress-controller的pod里,这个ingress-controller的pod里运行着一个Nginx服务,控制器会把生成的 nginx配置写入 /etc/nginx.conf文件中,
(4)然后reload一下使配置生效。以此达到域名区分配置和动态更新的作用。
Ingress-Nginx 工作原理
1、ingress-controller通过和apiserver交互,动态感知集群中ingress规则的变化,并读取配置
2、ingress规则中配置了基于域名或者url路径对应的service,ingress-controller读取后自动生成nginx配置信息
3、ingress-controller会将自动生成的nginx配置信息写入pod中,这个ingress-controller实际是运行一个nginx,控制器将配置信息更新到/etc/nginx.conf文件中
4、然后reload重载一下让配置生效。
这就是能够实现ingress通过ingress-controller实现对k8s集群内部的pod访问的原理
后续客户端访问指定域名和指定url路径的时候,请求会转发到nginx-controller控制器的service 然后转发到ingress控制器的pod,pod会将根据ingress的规则转发给相应的service,然后再根据标签选择器转发给业务pod
四、ingress 暴露服务的方式🐱🐱🐱
4.1方式一:Deployment+LoadBalancer 模式的 Service
如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个 type为 LoadBalancer 的 service 关联这组 pod。大部分公有云,都会为 LoadBalancer 的 service 自动创建一个负载均衡器,通常还绑定了公网地址。 只要把域名解析指向该地址,就实现了集群服务的对外暴露
4.2方式二:DaemonSet+HostNetwork+nodeSelector
用DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。 比较适合大并发的生产环境使用。
4.3方式三:Deployment+NodePort模式的Service
同样用deployment模式部署ingress-controller,并创建对应的service,但是type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口,一般会在前面再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境ip地址不变的场景。
NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定影响。
五、部署 nginx-ingress-controller
Nginx Ingress Controller通过API Server获取Ingress资源的变化,动态地生成Load Balancer(例如Nginx)所需的配置文件(例如nginx.conf),然后重新加载Load Balancer(例如执行
nginx -s reload
重新加载Nginx)来生成新的路由转发规则。
Nginx Ingress Controller可通过配置LoadBalancer类型的Service来创建SLB,因此可以从外部通过SLB访问到Kubernetes集群的内部服务。根据Nginx Ingress配置的不同规则来访问不同的服务
官方文档:
Installation Guide - Ingress-Nginx Controller (kubernetes.github.io)
5.1部署ingress-controller pod及相关资源
创建目录
mkdir /opt/ingress
cd /opt/ingress
下载配置文件
官方下载地址:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.25.0/deploy/static/mandatory.yaml#可能会下载不下来
由于官方下载地址可能无法下载,可以使用国内的Gitee镜像来下载所需的YAML配置文件。这里有两个版本的配置文件,一个是nginx-0.25.0
,另一个是nginx-0.30.0
。可以选择一个版本进行下载
#上面可能无法下载,可用国内的 gitee#对于nginx-0.25.0版本:
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.25.0/deploy/static/mandatory.yaml#对于nginx-0.30.0版本:
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml
确保下载的是最新版本的配置文件,因为新版本可能包含了安全更新和功能改进。如果不确定哪个版本更适合你,可以查看官方文档或者社区讨论来决定。
- mandatory.yaml文件中包含了很多资源的创建,包括namespace、ConfigMap、role,ServiceAccount等等所有部署ingress-controller需要的资源
5.2修改 ClusterRole 资源配置
clusterRole用于定义集群中资源的权限
vim mandatory.yaml
......
apiVersion: rbac.authorization.k8s.io/v1beta1
#RBAC相关资源从1.17版本开始改用rbac.authorization.k8s.io/v1,rbac.authorization.k8s.io/v1beta1在1.22版本即将弃用
kind: ClusterRole
metadata:name: nginx-ingress-clusterrolelabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx
rules:- apiGroups:- ""resources:- configmaps- endpoints- nodes- pods- secretsverbs:- list- watch- apiGroups:- ""resources:- nodesverbs:- get- apiGroups:- ""resources:- servicesverbs:- get- list- watch- apiGroups:- "extensions"- "networking.k8s.io" # (0.25版本)增加 networking.k8s.io Ingress 资源的 api resources:- ingressesverbs:- get- list- watch- apiGroups:- ""resources:- eventsverbs:- create- patch- apiGroups:- "extensions"- "networking.k8s.io" # (0.25版本)增加 networking.k8s.io/v1 Ingress 资源的 api resources:- ingresses/statusverbs:- update
这份 YAML 文件是对 Kubernetes 中的 ClusterRole 资源进行配置的,ClusterRole 用于定义对集群中资源的权限。下面是对该文件中各部分的详细解析:
- apiVersion:指定 Kubernetes API 的版本,此处使用的是 rbac.authorization.k8s.io/v1beta1 版本,但注释中提到从 1.17 版本开始应改用 rbac.authorization.k8s.io/v1,而 v1beta1 版本将在 1.22 版本后弃用。
- kind:指定资源的类型,这里是 ClusterRole,表示集群级别的角色。
- metadata:指定资源的元数据,包括名称和标签等信息。
- rules:定义了针对不同资源的访问规则。在这里,包含了多个规则,每个规则指定了对一类资源的访问权限。
-
第一个规则指定了对 ConfigMaps、Endpoints、Nodes、Pods 和 Secrets 等资源的 list 和 watch 权限。
-
第二个规则指定了对 Nodes 资源的 get 权限。
-
第三个规则指定了对 Services 资源的 get、list 和 watch 权限。
-
第四个规则指定了对 Ingress 资源的 get、list 和 watch 权限,其中包括了对 "extensions" 和 "networking.k8s.io" API 组的 Ingress 资源的权限。
-
第五个规则指定了对 Events 资源的 create 和 patch 权限。
-
最后一个规则指定了对 Ingress 资源状态的 update 权限,同样包括了 "extensions" 和 "networking.k8s.io" API 组的 Ingress 资源
这些规则定义了该 ClusterRole 在集群中对各种资源的访问权限,以及允许的操作。这样配置的 ClusterRole 可以被绑定到用户、服务账户或者其他身份上,以控制它们对集群资源的访问权限。
此处采用ingress暴露方式方法二:
🤔🤔🤔采用DaemonSet+HostNetwork+nodeSelector暴露服务
5.3修改 Deployment 为 DaemonSet ,指定节点运行,并开启 hostNetwork 网络
vim mandatory.yaml...
apiVersion: apps/v1
# 修改 kind
# kind: Deployment
kind: DaemonSet
metadata:name: nginx-ingress-controllernamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx
spec:
# 删除Replicas
# replicas: 1selector:matchLabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxtemplate:metadata:labels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxannotations:prometheus.io/port: "10254"prometheus.io/scrape: "true"spec:# 使用主机网络hostNetwork: true# 选择节点运行nodeSelector:ingress: "true"serviceAccountName: nginx-ingress-serviceaccount
......
要将 nginx-ingress-controller 的部署方式从 Deployment 修改为 DaemonSet,并且指定它在具有特定标签的节点上运行,同时开启 hostNetwork 模式,你需要对 mandatory.yaml 文件进行以下修改:
- 修改 kind 为 DaemonSet: 将 kind: Deployment 更改为 kind: DaemonSet。
- 删除 replicas 字段: DaemonSet 不需要 replicas 字段,因为它会确保 Pod 在每个选定的节点上运行一个实例。
- 添加 hostNetwork: true: 在 spec.template.spec 下添加 hostNetwork: true,这将使 Pod 使用宿主机的网络命名空间。
- 添加 nodeSelector: 在 spec.template.spec 下添加 nodeSelector 字段,并设置 ingress: "true",以便 Pod 只在带有 ingress=true 标签的节点上运行。
5.4指定 nginx-ingress-controller 运行在 node02 节点
kubectl label nodes node02 nanjing=dataiyang #这里选择在node02设置标签kubectl get node --show-labels #查看标签
5.5在所有 node 节点上传 nginx-ingress-controller 镜像压缩包 ingree.contro.tar.gz 到 /opt/ingress 目录,并解压和加载镜像
cd /opt/ingress
tar zxvf ingree.contro.tar.gz
scp ingree.contro.tar node02:/opt
cd /opt
docker load -i ingree.contro.tar
5.6启动 nginx-ingress-controller
kubectl apply -f mandatory.yaml
kubectl get pods -n ingress-nginx
如果此处是running但是,不是1/1,排错可能是端口占用,去node查看80端口,或者可以查看日志、或详细信息哦
查看详细信息 kubectl describe pod -n ingress-nginx pod名 进行排错
或者查看日志 kubectl logs -n ingress-nginx pod名字 进行排错
nginx-ingress-controller 已经运行 node02 节点
nginx-ingress-controller 已经在 node02 节点上成功运行,并且配置了 hostNetwork,这意味着 nginx 直接在宿主机上监听了 80、443 和 8181 端口。这样,任何对这些端口的请求都会被转发到 nginx-ingress-controller
kubectl get pod -n ingress-nginx -o widekubectl get cm,daemonset -n ingress-nginx -o wide
确保所有相关的 ConfigMaps 和 DaemonSet 都已经创建,并且状态正常
确保 nginx-ingress-controller
Pod 的状态是 Running
,并且 READY
列显示为 1/1
,这表示 Pod 已经准备好接收流量。
到 node02 节点查看
在 node02
节点上运行 netstat
命令来验证 nginx
是否在预期的端口上监听。 netstat
的输出,显示了 nginx
在 80、443 和 8181 端口上的监听。
netstat -lntp|grep nginx
由于配置了 hostnetwork,nginx 已经在 node 主机本地监听 80/443/8181 端口。其中 8181 是 nginx-controller 默认配置的一个 default backend(Ingress 资源没有匹配的 rule 对象时,流量就会被导向这个 default backend)。
这样,只要访问 node 主机有公网 IP,就可以直接映射域名来对外网暴露服务了。如果要 nginx 高可用的话,可以在多个 node上部署,并在前面再搭建一套 LVS+keepalived 做负载均衡。
5.7创建 ingress 规则
创建一个deploy的业务pod和svc
vim service-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-app
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: nginx-app-svc
spec:type: ClusterIPports:- protocol: TCPport: 80targetPort: 80selector:app: nginx
本文此处用的yaml文件
kubectl apply -f service-nginx.yaml
如果不写yaml文件,用下图的创建也可以哦
创建 ingress
#方法一:(extensions/v1beta1 Ingress 在1.22版本即将弃用)
vim ingress-app.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:name: nginx-app-ingress
spec:rules:- host: www.kgc.comhttp:paths:- path: /backend:serviceName: nginx-app-svcservicePort: 80#方法二:
vim ingress-app.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx-app-ingress
spec:rules:- host: www.kgc.comhttp:paths:- path: /pathType: Prefix backend:service:name: nginx-app-svcport:number: 80
使用方法二:
kubectl apply -f ingress-app.yaml
现在,已经准备好应用 Ingress 规则。在应用 Ingress 规则之前,请确保域名 www.zzz.com 已经正确解析到了运行 nginx-ingress-controller 的节点的公网 IP 地址。如果域名解析还没有设置好,Ingress 规则将无法正常工作,因为外部请求无法正确路由到你的服务。
kubectl apply -f service-nginx.yaml
kubectl apply -f ingress-app.yamlkubectl get pods,svc -owidekubectl get ingress
5.8测试访问
本地 host 添加域名解析
curl www.zzz.com
5.9查看 nginx-ingress-controller
kubectl get pod -n ingress-nginx -o wide
kubectl exec -it nginx-ingress-controller-brdtd -n ingress-nginx /bin/bash
more /etc/nginx/nginx.conf
在 Pod 的 Bash shell 中,可以使用 more
或 cat
命令来查看 Nginx 的配置文件。你应该能够看到 www.zzz.com
的配置,这表明 Ingress 规则已经被正确地应用到了 Nginx 的配置中。
如果看到了 www.zzz.com 的配置,这意味着 nginx-ingress-controller 已经根据你创建的 Ingress 规则更新了 Nginx 的配置。现在,当外部请求到达 node02 节点的 80 端口时,它们将被正确地路由到 nginx-app-svc 服务。
回车键可以查看
再添加一个域名:www.nanjing.com
5.10数据流向
DaemonSet+HostNetwork+nodeSelector部署 ingress-controller的数据流向
客户端---->ingress-controller(pod和host共享ip和端口---> 业务应用service----> 业务的应用 pod)
🤔🤔🤔采用Deployment+NodePort模式的Service暴露服务
为了不影响,我们先把上面的删除了,方便我们进行模拟
1.下载 nginx-ingress-controller 和 ingress-nginx 暴露端口配置文件
mkdir /opt/ingress-nodeport
cd /opt/ingress-nodeport
官方下载地址:
官方下载地址:wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
国内 gitee 资源地址:
国内 gitee 资源地址:wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
2.在所有 node 节点上传镜像包 ingress-controller-0.30.0.tar 到 /opt/ingress-nodeport 目录,并加载镜像
docker load -i ingree.contro-0.30.0.tar
3.启动 nginx-ingress-controller
kubectl apply -f mandatory.yaml
kubectl apply -f service-nodeport.yaml
#如果K8S Pod 调度失败,在 kubectl describe pod资源时显示:
Warning FailedScheduling 18s (x2 over 18s) default-scheduler 0/2 nodes are available: 2 node(s) didn't match node selector解决方案:
1. 给需要调度的node加上对应标签
# 相对上面这个Yaml文件的例子 (去配置文件查看标签,对应的去添加哦)
kubectl label nodes node_name kubernetes.io/os=linux2. 删除Yaml文件中的nodeSelector,如果对节点没有要求的话,直接删除节点选择器即可
kubectl get svc,pod -n ingress-nginx
kubectl describe svc -n ingress-nginx
从输出来看,nginx-ingress-controller Pod 正在 ingress-nginx 命名空间中正常运行,状态为 Running。同时,ingress-nginx 服务是 NodePort 类型,这意味着它在集群的每个节点上都开放了特定的端口(80 端口映射到 32383 端口,443 端口映射到 32133 端口)以供外部访问。
七、Ingress HTTP 代理访问
Ingress HTTP代理访问通常用于在Kubernetes集群中管理入站和出站流量。通过设置Ingress代理,可以实现对集群中部署的服务进行访问控制、负载均衡、SSL终止等功能。
进入Kubernetes集群中的Ingress相关的目录:/opt/ingress-nodeport
。
cd /opt/ingress-nodeport
7.1创建 deployment、Service、Ingress Yaml 资源
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-app-zzz #跟之前重复了,修改下名字
spec:replicas: 2selector:matchLabels:name: nginxtemplate:metadata:labels:name: nginxspec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: nginx-svc
spec:ports:- port: 80targetPort: 80protocol: TCPselector:name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx-test
spec: #规定了Ingress资源的规格,包括访问规则rules: #定义了访问规则,指定了如何路由到后端服务- host: www.a.com #指定了这条规则适用于主机 www.a.comhttp: #定义了 HTTP 访问规则paths: # 指定了路径匹配规则- path: / # 表示所有以 / 开头的路径都会匹配到这个规则pathType: Prefix #指定了路径匹配类型为前缀匹配backend: #指定了后端服务的配置service: #定义了后端服务的名称和端口号name: nginx-svc #指定了后端服务的名称为 nginx-svcport:number: 80
使用vim编辑器创建一个名为ingress-nginx.yaml的YAML文件,该文件包含以下资源的定义:
- kind: Deployment:名为nginx-app,包含两个Nginx容器副本,监听容器端口80。
- kind: Service:名为nginx-svc,类型为ClusterIP,端口80,选择器为name=nginx。
- kind: Ingress:名为nginx-test,配置了一个规则,将访问www.a.com域名的流量转发到nginx-svc服务的端口80。
kubectl apply -f ingress-nginx.yaml
#查看服务和Pod的状态。输出显示nginx-svc服务已创建,但没有外部IP,两个Nginx Pod正在运行。kubectl get svc,pod -owide
为了使外部流量能够访问到这个服务,需要确保:
- Ingress Controller已正确安装并运行。
- 域名
www.a.com
已正确解析到Ingress Controller的外部IP地址。 - 如果在云服务提供商上部署,可能需要配置负载均衡器或网络策略。
7.2进入容器编辑页面内容
7.3测试访问
#获取Service信息
kubectl get svc -n ingress-nginx
#使用kubectl get svc -n ingress-nginx命令获取名为ingress-nginx的Service信息。该Service配置了NodePort类型,监听端口80和443,并且有对应的NodePort(例如,80端口对应的NodePort为30864)
任意node地址添加域名解析:
[root@master01 ingress-nodeport]#vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.246.10 master01
192.168.246.11 node01
192.168.246.12 node02
192.168.246.12 www.zzz.com www.a.com
7.4数据流向
八、Ingress HTTP 代理访问虚拟主机
测试和实践在Kubernetes集群中使用Ingress资源实现同一端口但不同域名的服务路由和负载均衡。具体来说,通过创建两个不同的Service资源,并使用Ingress资源来将不同域名的流量路由到这两个Service上。
mkdir /opt/ingress-nodeport/vhost
cd /opt/ingress-nodeport/vhost
-
使用
mkdir
命令创建一个新的目录/opt/ingress-nodeport/vhost
。这个目录用于存放虚拟主机的配置文件,如SSL证书、密钥、以及其他与虚拟主机相关的文件。
使用Ingress来配置HTTP代理以访问虚拟主机。通过Ingress资源,您可以定义不同的虚拟主机(host)与后端服务之间的映射关系,从而实现基于虚拟主机的访问控制和路由。
8.1创建虚拟主机1资源
在Kubernetes集群中创建一个名为deployment1
的Deployment和一个名为svc-1
的Service。
vim deployment1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: deployment1
spec:replicas: 2selector:matchLabels:name: nginx1template:metadata:labels:name: nginx1spec:containers:- name: nginx1image: soscscs/myapp:v1imagePullPolicy: IfNotPresentports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: svc-1
spec:ports:- port: 80targetPort: 80protocol: TCPselector:name: nginx1
-
在该文件中定义了一个Deployment,名为
deployment1
,它包含两个Nginx容器的副本,这些容器使用标签name: nginx1
进行选择。 -
容器使用的镜像是
soscscs/myapp:v1
,并且监听容器端口80。
创建Service资源:
在同一个YAML文件中定义了一个Service,名为svc-1。
- 该Service配置了一个端口80,用于将外部流量转发到选择器name: nginx1匹配的Pod的80端口。
- Service类型默认为ClusterIP,这意味着它只能在集群内部访问。
kubectl apply -f deployment1.yaml
-
使用
kubectl apply -f deployment1.yaml
命令将这些配置应用到Kubernetes集群中。 -
这些资源的创建将允许在集群内部通过
svc-1
服务访问名为nginx1
的Deployment中的Nginx容器
8.2创建虚拟主机2资源
在Kubernetes集群中创建第二个虚拟主机资源,包括一个名为deployment2
的Deployment和一个名为svc-2
的Service
vim deployment2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: deployment2
spec:replicas: 2selector:matchLabels:name: nginx2template:metadata:labels:name: nginx2spec:containers:- name: nginx2image: soscscs/myapp:v2imagePullPolicy: IfNotPresentports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: svc-2
spec:ports:- port: 80targetPort: 80protocol: TCPselector:name: nginx2
kubectl apply -f deployment2.yaml #启动主机2资源
8.3创建ingress资源
vim ingress-nginx.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress1
spec:rules:- host: www01.zzz.comhttp:paths:- path: /pathType: Prefixbackend:service:name: svc-1port:number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress2
spec:rules:- host: www02.zzz.comhttp:paths:- path: /pathType: Prefixbackend:service:name: svc-2port:number: 80
- 在该文件中定义了两个Ingress资源,ingress1和ingress2。
- ingress1配置了一个规则,当访问www01.zzz.com时,流量将被路由到名为svc-1的服务的端口80。
- ingress2配置了一个规则,当访问www02.zzz.com时,流量将被路由到名为svc-2的服务的端口80。
kubectl apply -f ingress-nginx.yamlkubectl get svc -n ingress-nginx
8.4测试访问
(๑•̀ㅂ•́)و✧ 🤔修改页面的效果,有没有更清晰
九、Ingress HTTPS 代理访问
在Kubernetes集群中配置HTTPS代理访问通常涉及以下步骤:
- 获取或生成SSL/TLS证书和私钥。
- 将证书和私钥文件放置在集群节点可以访问的位置,例如您刚刚创建的https目录。
- 创建Ingress资源的YAML配置文件,指定SSL/TLS证书和私钥的位置,以及需要启用HTTPS的虚拟主机规则。
一旦这些步骤完成,就可以使用kubectl apply命令应用Ingress配置,从而启用HTTPS代理访问。这将允许外部用户通过安全的HTTPS连接访问您的服务。
mkdir /opt/ingress-nodeport/https
cd /opt/ingress-nodeport/https
使用mkdir
命令在/opt/ingress-nodeport
路径下创建一个新的目录,命名为https
。这个目录将用于存放与HTTPS相关的配置文件,如SSL/TLS证书和密钥
9.1创建ssl证书
生成一个自签名的TLS证书,用于在实验中配置HTTPS代理访问时使用
一般的话去你买域名的网站,下载
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/0=nginxsvc"# -x509:表示生成自签名的证书。
# -sha256:表示使用SHA-256算法进行证书签名。
# -nodes:表示生成的私钥不加密。
# -days 365:表示证书的有效期为365天。
# -newkey rsa:2048:表示生成一个2048位的RSA私钥。
# -keyout tls.key:表示将生成的私钥保存到名为tls.key的文件中。
# -out tls.crt:表示将生成的证书保存到名为tls.crt的文件中。
# -subj "/CN=nginxsvc/O=nginxsvc":表示指定证书的主题信息,其中/CN表示Common Name(通用名称),/O表示Organization(组织)。
9.2创建 secret 资源进行存储
9.2.1创建Secret资源:
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
-
使用
kubectl create secret tls
命令创建一个新的Kubernetes Secret资源,名为tls-secret
。 -
该Secret资源包含您之前创建的
tls.key
(私钥)和tls.crt
(证书)文件。
9.2.2获取Secret资源信息:
kubectl get secrets
-
查看当前命名空间(默认为
default
)中的Secret资源列表。 -
可以看到了名为
tls-secret
的Secret资源,它包含TLS类型的数据
9.2.3查看Secret资源:
-
使用
kubectl describe secret tls-secret
命令获取tls-secret
的详细信息。 -
可以看到了Secret资源的类型为
kubernetes.io/tls
,并且包含了证书和私钥的数据。
kubectl describe secret tls-secret
现在,可以在创建Ingress资源时引用这个Secret,以便为Ingress Controller配置HTTPS支持。这将允许Ingress Controller使用这个SSL证书来终止外部HTTPS请求。
9.3创建 deployment、Service、Ingress Yaml 资源
vim ingress-https.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-app-https #修改名字,防止重复
spec:replicas: 2selector:matchLabels:name: nginxtemplate:metadata:labels:name: nginxspec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: nginx-svc-https #后端服务的名称为nginx-svc-https
spec:ports:- port: 80targetPort: 80protocol: TCPselector:name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx-https
spec:tls:- hosts:- www3.zzz.comsecretName: tls-secret # 存储TLS证书和私钥的 Secret 对象的名称为tls-secretrules:- host: www3.zzz.comhttp:paths:- path: /pathType: Prefixbackend:service:name: nginx-svc-https #后端服务的名称为nginx-svc-httpsport:number: 80
YAML配置文件解读:
- 在该文件中定义一个Deployment(nginx-app-https),它包含两个Nginx容器的副本。
- 定义一个Service(nginx-svc-https),它将端口80的流量转发到标签为name: nginx的Pod。
- 定义一个Ingress资源(nginx-https),它配置了HTTPS支持,使用之前创建的tls-secret证书和私钥。
- Ingress资源中定义了一个规则,当访问www03.zzz.com时,流量将被路由到nginx-svc服务的端口80。
kubectl apply -f ingress-https.yaml
使用kubectl apply -f ingress-https.yaml
命令将这些配置应用到Kubernetes集群中。
kubectl get svc -n ingress-nginx
- 使用
kubectl get svc -n ingress-nginx
命令获取Ingress Controller的Service信息。会看到了ingress-nginx
服务,它是一个NodePort类型的服务,监听端口80和443,但没有外部IP地址(192.168段的)
9.4访问测试
在宿主机的 C:\Windows\System32\drivers\etc\hosts 文件中添加映射
浏览器访问测试:
www3.zzz.com:30907
请注意,由于使用的是NodePort而不是外部IP地址,这种访问方式通常只适用于集群内部或者在知道NodePort端口号的情况下。对于外部用户,他们需要通过域名解析到Ingress Controller的外部IP地址,并且Ingress Controller需要配置为使用您创建的TLS证书来处理HTTPS请求。
十、Nginx 进行 BasicAuth
在Kubernetes集群中配置Nginx Ingress Controller以实现基本的HTTP身份验证(BasicAuth)
mkdir /opt/ingress-nodeport/basic-auth
cd /opt/ingress-nodeport/basic-auth
10.1生成用户密码认证文件,创建 secret 资源进行存储
yum -y install httpd
htpasswd -c auth zhaoz #认证文件名必须为 auth
kubectl create secret generic basic-auth --from-file=auth
#认证文件名必须为 auth
10.2创建Secret资源
kubectl create secret generic basic-auth --from-file=auth
- 使用
kubectl create secret generic basic-auth --from-file=auth
命令创建一个新的Kubernetes Secret资源,名为basic-auth
,并将之前生成的auth
文件作为数据。
10.3创建Ingress资源
vim ingress-auth.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress-authannotations:#设置认证类型basicnginx.ingress.kubernetes.io/auth-type: basic#设置secret资源名称basic-authnginx.ingress.kubernetes.io/auth-secret: basic-auth#设置认证窗口提示信息nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - zhaoz'
spec:rules:- host: auth.zzz.comhttp:paths:- path: /pathType: Prefixbackend:service: name: nginx-svcport:number: 80
使用vim编辑器创建一个名为ingress-auth.yaml的YAML文件。(如上代码)
- 在该文件中定义了一个Ingress资源,名为ingress-auth,它包含了基本认证的配置。
- 使用注解设置了认证类型(basic)、认证使用的Secret资源名称(basic-auth)以及认证窗口提示信息。
- 定义了一个规则,当访问auth.zzz.com时,流量将被路由到nginx-svc服务的端口80。
具体详细设置方法可参考官网
https://kubernetes.github.io/ingress-nginx/examples/auth/basic/
kubectl apply -f ingress-auth.yamlkubectl get svc -n ingress-nginx
echo '192.168.246.11 auth.zzz.com' >> /etc/hosts
这边使用真机win进行检测,添加主机映射在本机C盘中
10.4浏览器检测
浏览器访问:http://auth.zzz.com:30864
这里,30864
是Ingress Controller的NodePort端口号。
进入查看页面
十一、Nginx重写
在Kubernetes集群中配置Nginx Ingress Controller以实现URL重写,可以配置 Nginx Ingress Controller,然后通过编辑 Ingress 资源规则,使用 Nginx 的 rewrite 指令来修改传入请求的 URL 路径,实现定制的路由和重定向功能。
11.1 metadata.annotations 配置说明
Nginx 进行重写#metadata.annotations 配置说明
●nginx.ingress.kubernetes.io/rewrite-target: <字符串> #必须重定向流量的目标URI
●nginx.ingress.kubernetes.io/ssl-redirect: <布尔值> #指示位置部分是否仅可访问SSL(当Ingress包含证书时,默认为true)
●nginx.ingress.kubernetes.io/force-ssl-redirect: <布尔值> #即使Ingress未启用TLS,也强制重定向到HTTPS
●nginx.ingress.kubernetes.io/app-root: <字符串> #定义Controller必须重定向的应用程序根,如果它在'/'上下文中
●nginx.ingress.kubernetes.io/use-regex: <布尔值> #指示Ingress上定义的路径是否使用正则表达式
11.2创建重写Ingress资源
mkdir rewrite
cd rewrite
vim ingress-rewrite.yaml
-
apiVersion: networking.k8s.io/v1 kind: Ingress metadata:name: nginx-rewriteannotations:nginx.ingress.kubernetes.io/rewrite-target: http://www02.zzz.com:30864 spec:rules:- host: re.kgc.com #由于re.kgc.com只是用于跳转不需要真实站点存在,因此svc资源名称可随意定义http:paths:- path: /pathType: Prefixbackend:service:name: nginx-svcport:number: 80
- 使用vim编辑器创建一个名为ingress-rewrite.yaml的YAML文件。
- 在该文件中定义了一个Ingress资源,名为nginx-rewrite,它包含了URL重写的注解配置。
- 注解nginx.ingress.kubernetes.io/rewrite-target设置为http://www3.zzz.com:30907,这意味着所有发送到re.gzb.com的流量都将被重定向到这个目标URI。
kubectl apply -f ingress-rewrite.yamlecho '192.168.246.11 re.kgc.com' >> /etc/hosts #任意node的ip地址
11.3浏览器访问
http://re.kgc.com:30864
浏览器访问:http://re.kgc.com:30864就会跳转到http://www02.zzz.com:30864
十二、温故而知新
- ingress是k8s集群的请求入口,可以理解为对多个service的再次抽象
- 通常说的ingress一般包括ingress资源对象及ingress-controller两部分组成
- ingress-controller有多种实现,社区原生的是ingress-nginx,根据具体需求选择
- ingress自身的暴露有多种方式,需要根据基础环境及业务类型选择合适的方式
- Ingress Controller 可以理解为控制器,它通过不断的跟 Kubernetes APl交互,实时获取后端Service、Pod的变化,比如新增、删除等,结合Ingress 定义的规则生成配置,然后动态更新上边的Nginx 或者 trafik负载均衡器,并刷新使配置生效,来达到服务自动发现的作用。
Ingress是定义规则,通过它定义某个域名的请求过来之后转发到集群中指定的 Service。它可以通过Yaml 文件定义,可以给一个或多个 Service 定义一个或多个 Ingress 规则。
12.1Ingress数据流向
- DaemonSet + Hostwork + NodeSelector Ingress-Controller 部署的ingress控制器
数据流向:客户端 -> 通过node节点的80/433端口进入ingress控制器 -> 根据ingress对象的转发规则 -> 业务Pod的Service -> 通过标签选择器 -> 业务Pod
- Deployment + NodePort
客户端------>域名访问------> ingress控制器的Service------>Ingress-Controller(Pod)---->根据ingress对象的转发规则 ------>业务应用Service------>业务的应用Pod,域名可以解析成NodePortIP或者负载均衡VIP
12.2K8S集群外部的客户端访问K8S集群内部的方案?
- 基于Service实现:NodePort LoadBalancer externalIPs 只能支持四层反向代理,如果K8S集群规模较大运行的业务较多时NodePort端口/externalIPs管理成本会很高
- 基于Ingress实现:支持七层反向代理,可自定义规则根据用户请求的域名或URL路径转发给指定Service进行代理访问
12.3基于主机名的虚拟主机
rules:
- host: hostname1
......
- host: hostname2
12.4Ingress的组成
- ingress控制器(ingress controller):根据在ingress资源对象配置的规则转发用户请求的组件,以Pod形式运行的
- ingress资源对象:设置转发规则,告诉ingress控制器应该根据什么域名或URL路径转发请求给相应的Service资源的endpoints端点(podIP:容器Port)
12.5创建Ingress资源
创建Ingress资源
kubectl create ingress <ingress资源名称> -n <命名空间> --class=<ingressclass名称> --rule=<域名>/<URL路径>=<service资源名称>:<service的port端口>
12.6Ingress资源配置
Ingress资源配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress资源名称namespace: 命名空间
spec:ingressClassName: ingressclass名称rules:- host: 域名http:paths:- path: URL路径pathType: Prefix(前缀匹配)|Exact(精准匹配)backend:service:name: Service资源名称port:number: Service资源的port端口
12.7基于不同域名或者不同URL路径做转发
#基于不同域名的代理转发- host: 域名2http:paths:- path: URL路径1pathType:backend: ....#基于不同URL路径的代理转发- path: URL路径2pathType:backend: ....
12.8基于https代理转发
要生成TLS证书和私钥文件
(在企业需要到域名中的网站下载,有免费正常购买的时候,其次收费的大概在3000/年)
创建Secret资源TLS类型,把证书信息保存到K8S集群内
#基于https代理转发tls: #与roles字段在同一层级- hosts:- 指定使用https访问的域名....secretName: 指定tls类型的secret资源名称
12.9Rewrite重定向
简约版
metadataLannotations:nginx.ingress.kubernets.io/rewrite-target#指定重定向的URL路径(http://域名:ingress-controller的端口)
spec:rules:- host: 源主机名backend#这里源主机名仅用于跳转所有不需要实际站点存在,因此后端绑定的Service资源可以随意定义
细致版
基于rewrite实现重写访问路径
#基于rewrite实现重写访问路径
在metadata.annotations字段添加相关配置
metadata:annotations:nginx.ingress.kubernetes.io/rewrite-target: https://www.bbb.com:30443
spec:rules:- host: www.aaa.com将任何访问 http://www.aaa.com:30080/XXXX 的请求,都重写成 https://www.bbb.com:30443metadata:annotations:nginx.ingress.kubernetes.io/rewrite-target: https://www.XXX.com:30443/$2nginx.ingress.kubernetes.io/use-regex: "true"
spec:rules:- host: www.aaa.comhttp:paths:- path: /(.*)backend:....将任何访问 http://www.aaa.com:30080/XXXX 的请求,都重写成 https://www.bbb.com:30443/XXXX
12.10基于basic-auth实现访问认证
#基于basic-auth实现访问认证
1)使用htpasswd创建用户数据文件,文件名为auth
2)基于auth文件创建secret资源 kubectl create secret generic <secret资源名称> --from-file=auth
3)创建ingress资源,在metadata.annotations字段添加相关配置
metadata:annotations:nginx.ingress.kubernetes.io/auth-type: basicnginx.ingress.kubernetes.io/auth-secret: secret资源名称nginx.ingress.kubernetes.io/auth-realm: '认证窗口提示信息'
GitHub - kubernetes/ingress-nginx: Ingress-NGINX Controller for Kuberneteshttps://github.com/kubernetes/ingress-nginx