前言
在 Kubernetes 集群中,管理外部服务的访问和流量路由至关重要。通过使用 Ingress 控制器,我们能够实现对外部服务的有效管理,配置灵活的路由规则,并实现负载均衡和流量控制。
目录
一、Ingress 介绍
1. Ingress 概述
2. 对外暴露几种方案(发布方式)
2.1 NodePort
2.2 LoadBalancer
2.3 externalIPs
2.4 Ingress
3. Ingress 组成
3.1 Ingress-nginx 资源规则
3.2 ingress-controller
4. Ingress 工作原理
5. ingress 暴露服务的方式
5.1 方式一:Deployment+LoadBalancer 模式的 Service
5.2 方式二:DaemonSet+HostNetwork+nodeSelector
5.3 方式三:Deployment+NodePort模式的Service
二、部署 nginx-ingress-controller
1. 方式二:DaemonSet+HostNetwork+nodeSelector
1.1 部署 ingress-controller pod 及相关资源
1.2 修改 ClusterRole 资源配置
1.3 指定 nginx-ingress-controller 运行在 node02 节点
1.4 修改 Deployment 为 DaemonSet ,指定节点运行,并开启 hostNetwork 网络
1.5 加载镜像
1.6 启动 nginx-ingress-controller
1.7 创建 ingress 规则
1.7.1 创建一个 deploy 和 svc
1.7.2 创建 ingress
1.8 测试访问
1.9 查看 nginx-ingress-controller
2. 方式三:Deployment+NodePort模式的Service
2.1 下载 nginx-ingress-controller 和 ingress-nginx 暴露端口配置文件
2.2 加载镜像
2.3 启动 nginx-ingress-controller
三、Ingress HTTP 代理访问
1. 创建 deployment、Service、Ingress Yaml 资源
2. 进入容器编辑页面内容
3. 访问页面
四、Ingress HTTP 代理访问多域名服务路由
五、Ingress HTTPS 代理访问
1. 创建ssl证书
2. 创建 secret 资源进行存储
3. 创建 deployment、Service、Ingress Yaml 资源
4. 启动资源
5. 访问资源
六、Nginx 进行 BasicAuth
1. 生成用户密码认证文件,创建 secret 资源进行存储
2. 创建一个 Secret 对象
3. 创建 ingress 资源
4. 添加宿主机域名解析www.abc.com,访问测试
七、Nginx 重写
1. metadata.annotations 配置说明
2. 示例
一、Ingress 介绍
1. Ingress 概述
service 的作用体现在两个方面:
- 对集群内部,它不断跟踪pod的变化,更新 endpoint 中对应 pod 的对象,提供了 ip 不断变化的 pod 的服务发现机制;
- 对集群外部,他类似负载均衡器,可以在集群内外部对 pod 进行访问。
Ingress 是 Kubernetes 中用于管理对集群内服务的外部访问的 API 对象。它允许您将 HTTP 和 HTTPS 路由流量到集群中的服务,通过定义规则,Ingress 可以将传入的请求路由到适当的服务。
2. 对外暴露几种方案(发布方式)
外部访问内部图示:
在 Kubernetes 中,Pod 的 IP 地址和 service 的 ClusterIP 仅可以在集群网络内部使用,对于集群外的应用是不可见的。为了使外部的应用能够访问集群内的服务,Kubernetes 目前提供了以下几种方案:
2.1 NodePort
将service暴露在节点网络上,NodePort背后就是Kube-Proxy,Kube-Proxy是沟通service网络、Pod网络和节点网络的桥梁。
测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的端口管理就是个灾难。因为每个端口只能是一种服务,端口范围只能是 30000-32767。
2.2 LoadBalancer
通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址。这种用法仅用于在公有云服务提供商的云平台上设置 Service 的场景。受限于云平台,且通常在云平台部署LoadBalancer还需要额外的费用。
在service提交后,Kubernetes就会调用CloudProvider在公有云上为你创建一个负载均衡服务,并且把被代理的Pod的IP地址配置给负载均衡服务做后端。
2.3 externalIPs
service允许为其分配外部IP,如果外部IP路由到集群中一个或多个Node上,Service会被暴露给这些externalIPs。通过外部IP进入到集群的流量,将会被路由到Service的Endpoint上。
示例:
① 创建控制器定义容器,并对外暴露端口
[root@master01 ingress]# kubectl create deployment app01 --image=nginx:1.14 --replicas=1 --port=80
deployment.apps/app01 created
[root@master01 ingress]# kubectl get pod
NAME READY STATUS RESTARTS AGE
app01-68d9b5486f-d6s4x 1/1 Running 0 3s
[root@master01 ingress]# kubectl expose deployment app01 --port=80 --target-port=80
service/app01 exposed
② 编辑 "app01" 的 Service 的配置文件
[root@master01 ingress]# kubectl edit svc app01 externalIPs:- 192.168.190.88
③ 查看 Service 列表
[root@master01 ingress]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
app01 ClusterIP 10.96.82.195 192.168.190.88 80/TCP 8m43s
④ 访问页面
2.4 Ingress
只需一个或者少量的公网IP和LB,即可同时将多个HTTP服务暴露到外网,七层反向代理。
可以简单理解为service的service,它其实就是一组基于域名和URL路径,把用户的请求转发到一个或多个service的规则。
原始架构与 Ingress 对比:
原来ens33是service端去暴露端口的,安全性低、不易管理,会面临k8s端口不够用的问题。
NodePort 和 Ingress 是 Kubernetes 中用于公开服务的两种不同方式:
NodePort:
- NodePort 允许从集群外部访问您的服务。它会在每个节点上打开一个端口,并将该端口映射到 Service 的端口上。这意味着可以通过节点的 IP 地址和 NodePort 来访问 Service。
- 通常用于需要直接暴露到外部的服务,但不适合大规模使用,因为需要管理大量的端口映射。
Ingress:
- Ingress 是一种对外暴露服务的高级方式,它允许您将 HTTP 和 HTTPS 路由流量到集群中的服务。通过定义规则,Ingress 可以将传入的请求路由到适当的服务,实现灵活的流量控制。
- Ingress 需要配合 Ingress Controller 使用,通常基于反向代理实现。它提供了更复杂的路由、负载均衡和 SSL 终止等功能。
3. Ingress 组成
3.1 Ingress-nginx 资源规则
可以理解为 nginx 的配置文件。ingress是一个API对象,通过yaml文件来配置,ingress对象的作用是定义请求如何转发到service的规则,可以理解为配置模板。
ingress通过http或https暴露集群内部service,给service提供外部URL、负载均衡、SSL/TLS以及基于域名的反向代理。ingress要依靠 ingress-controller 来具体实现以上功能。
3.2 ingress-controller
可以当做反向代理或者说是转发器。ingress-controller是具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。
实际上负责实现 Ingress 规则并处理外部流量的组件。Ingress Controller 监视 Kubernetes API 中的 Ingress 资源变化,并根据这些资源的配置来配置后端负载均衡器、反向代理或其它网络设备,以实现外部访问服务的目的。
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等等。
4. 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一下使配置生效。以此达到域名区分配置和动态更新的作用。
5. ingress 暴露服务的方式
5.1 方式一:Deployment+LoadBalancer 模式的 Service
如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个 type为 LoadBalancer 的 service 关联这组 pod。大部分公有云,都会为 LoadBalancer 的 service 自动创建一个负载均衡器,通常还绑定了公网地址。 只要把域名解析指向该地址,就实现了集群服务的对外暴露。
5.2 方式二:DaemonSet+HostNetwork+nodeSelector
用DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。 比较适合大并发的生产环境使用。
5.3 方式三:Deployment+NodePort模式的Service
同样用deployment模式部署ingress-controller,并创建对应的service,但是type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口,一般会在前面再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境ip地址不变的场景。
NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定影响。
二、部署 nginx-ingress-controller
1. 方式二:DaemonSet+HostNetwork+nodeSelector
1.1 部署 ingress-controller pod 及相关资源
[root@master01 ~]# mkdir /opt/ingress;cd /opt/ingress
[root@master01 ingress]# ls
mandatory.yaml
官方下载地址:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.25.0/deploy/static/mandatory.yaml上面可能无法下载,可用国内的 gitee
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.25.0/deploy/static/mandatory.yaml
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml
mandatory.yaml文件中包含了很多资源的创建,包括namespace、ConfigMap、role,ServiceAccount等等所有部署ingress-controller需要的资源。
1.2 修改 ClusterRole 资源配置
[root@master01 ingress]# vim mandatory.yaml84 - apiGroups:85 - "extensions"86 - "networking.k8s.io" #(0.25版本)增加networking.k8s.io Ingress资源的api 100 - apiGroups:
101 - "extensions"
102 - "networking.k8s.io" #(0.25版本)增加networking.k8s.io/v1 Ingress资源的api
1.3 指定 nginx-ingress-controller 运行在 node02 节点
采用方式二:DaemonSet+HostNetwork+nodeSelector
[root@master01 ingress]# kubectl label node node02 nj=zs[root@master01 ingress]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
master01 Ready control-plane,master 18d v1.20.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=
node01 NotReady <none> 18d v1.20.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,fql=a,kubernetes.io/arch=amd64,kubernetes.io/hostname=node01,kubernetes.io/os=linux
node02 NotReady <none> 18d v1.20.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,fql=b,kubernetes.io/arch=amd64,kubernetes.io/hostname=node02,kubernetes.io/os=linux,nj=zs
1.4 修改 Deployment 为 DaemonSet ,指定节点运行,并开启 hostNetwork 网络
[root@master01 ingress]# vim mandatory.yaml
191 kind: DaemonSet # 修改 kind
199 # replicas: 1 # 删除Replicas
212 spec:
213 hostNetwork: true # 使用主机网络
214 nodeSelector: # 选择节点运行
215 nj: zs
1.5 加载镜像
在所有 node02 节点上传 nginx-ingress-controller 镜像压缩包 ingree.contro.tar.gz 到 /opt/ingress 目录,并解压和加载镜像。
[root@node02 data]# ls
ingree.contro.tar.gz
[root@node02 data]# tar xf ingree.contro.tar.gz
[root@node02 data]# ls
ingree.contro.tar ingree.contro.tar.gz
[root@node02 data]# docker load -i ingree.contro.tar
Loaded image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0
1.6 启动 nginx-ingress-controller
[root@master01 ingress]# kubectl apply -f mandatory.yaml
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRole is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRole
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
Warning: rbac.authorization.k8s.io/v1beta1 Role is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 Role
role.rbac.authorization.k8s.io/nginx-ingress-role created
Warning: rbac.authorization.k8s.io/v1beta1 RoleBinding is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 RoleBinding
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRoleBinding is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRoleBinding
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
daemonset.apps/nginx-ingress-controller created
① nginx-ingress-controller 已经运行 node02 节点
[root@master01 ingress]# kubectl get pod -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-c5xfb 1/1 Running 0 11s 192.168.190.102 node02 <none> <none>
# 如果是0/1去node节点查看一下80端口是否有pod占用[root@node02 data]# netstat -antulp | grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 129841/nginx: mast[root@master01 ingress]# kubectl get cm,daemonset -n ingress-nginx -o wide
NAME DATA AGE
configmap/ingress-controller-leader-nginx 0 69s
configmap/nginx-configuration 0 73s
configmap/tcp-services 0 73s
configmap/udp-services 0 73sNAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
daemonset.apps/nginx-ingress-controller 1 1 1 1 1 nj=zs 72s nginx-ingress-controller quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0 app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/part-of=ingress-nginx
② 到 node02 节点查看
[root@node02 data]# netstat -lntp | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 129841/nginx: maste
tcp 0 0 0.0.0.0:8181 0.0.0.0:* LISTEN 129841/nginx: maste
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 129841/nginx: maste
tcp6 0 0 :::10254 :::* LISTEN 129805/nginx-ingre
由于配置了 hostnetwork,nginx 已经在 node 主机本地监听 80/443/8181 端口。其中 8181 是 nginx-controller 默认配置的一个 default backend(Ingress 资源没有匹配的 rule 对象时,流量就会被导向这个 default backend)。
这样,只要访问 node 主机有公网 IP,就可以直接映射域名来对外网暴露服务了。如果要 nginx 高可用的话,可以在多个 node上部署,并在前面再搭建一套 LVS+keepalived 做负载均衡。
1.7 创建 ingress 规则
1.7.1 创建一个 deploy 和 svc
[root@master01 ingress]# kubectl create deployment myapp-demo01 --image=nginx:1.14 --replicas=3 --port=80
deployment.apps/myapp-demo01 created
[root@master01 ingress]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-demo01-98f9b7bf7-kftxn 1/1 Running 0 2s
myapp-demo01-98f9b7bf7-sgzfn 1/1 Running 0 2s
myapp-demo01-98f9b7bf7-tsjvv 1/1 Running 0 2s[root@master01 ingress]# kubectl delete svc --all[root@master01 ingress]# kubectl expose deployment myapp-demo01 --port=80 --target-port=80
service/myapp-demo01 exposed
[root@master01 ingress]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
myapp-demo01 ClusterIP 10.96.227.130 <none> 80/TCP 3s[root@master01 ingress]# curl 10.96.227.130 -I
HTTP/1.1 200 OK
到这里,四层转发已经没有问题了;接下来就是要把 ingress-controller 关联 service。即七层关联四层。
1.7.2 创建 ingress
方法一:(extensions/v1beta1 Ingress 在1.22版本即将弃用)
[root@master01 ingress]# vim ingress-app.yaml
apiVersion: extensions/v1beta1
kind: Ingress # 这是一个 Ingress 资源,用于定义对集群中服务的外部访问规则
metadata: # 元数据name: nginx-app-ingress # 资源的名称
spec: # 规定了 Ingress 资源的规格,包括访问规则rules: # 定义了访问规则,指定了如何路由到后端服务- host: www.aaa.com # 指定了这条规则适用于主机 www.aaa.comhttp: # 定义了 HTTP 访问规则paths: # 指定了路径匹配规则- path: / # 表示所有以 / 开头的路径都会匹配到这个规则,这里是网站的根路径backend: # 指定了后端服务的配置serviceName: myapp-demo01 # 后端服务的名称为 myapp-demo01,这是要将流量转发到的服务的名称servicePort: 80
方法二:
[root@master01 ingress]# vim ingress-app01.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx-app-ingress
spec:rules: # 定义了访问规则,指定了如何路由到后端服务- host: www.aaa.com # 指定了这条规则适用于主机 www.aaa.comhttp: # 定义了 HTTP 访问规则paths: # 指定了路径匹配规则- path: / # 网站路径,所有以 / 开头的路径都会匹配到这个规则pathType: Prefix # 路径匹配,基于前缀;exect 完全匹配backend: # 指定了后端服务的配置service: # 定义了后端服务的名称和端口号name: myapp-demo01 # 后端服务的名称为 myapp-demo01,这是要将流量转发到的服务port:number: 80
启动 Ingress
[root@master01 ingress]# kubectl apply -f ingress-app.yaml
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/nginx-app-ingress created
[root@master01 ingress]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-demo01-98f9b7bf7-kftxn 1/1 Running 0 12m
myapp-demo01-98f9b7bf7-sgzfn 1/1 Running 0 12m
myapp-demo01-98f9b7bf7-tsjvv 1/1 Running 0 12m
[root@master01 ingress]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx-app-ingress <none> www.aaa.com 80 28s
1.8 测试访问
本地 host 添加域名解析:
[root@master01 ingress]# echo 192.168.190.102 www.aaa.com >> /etc/hosts
访问页面:
[root@master01 ingress]# curl www.aaa.com -I
HTTP/1.1 200 OK
1.9 查看 nginx-ingress-controller
[root@master01 ingress]# kubectl get pod -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-c5xfb 1/1 Running 0 32m 192.168.190.102 node02 <none> <none>[root@master01 ingress]# kubectl exec -it nginx-ingress-controller-c5xfb -n ingress-nginx /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
www-data@node02:/etc/nginx$ cat /etc/nginx/nginx.conf
2. 方式三:Deployment+NodePort模式的Service
2.1 下载 nginx-ingress-controller 和 ingress-nginx 暴露端口配置文件
[root@master01 ingress]# kubectl delete -f ingress-app.yaml
[root@master01 ingress]# kubectl delete -f mandatory.yaml [root@master01 ingress]# mkdir nodeport;cd 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 资源地址:
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[root@master01 nodeport]# rz -E
rz waiting to receive.
[root@master01 nodeport]# ls
ingress-nginx.yaml mandatory.yaml service-nodeport.yaml
2.2 加载镜像
在所有 node 节点上传镜像包 ingress-controller-0.30.0.tar 到 /opt/ingress-nodeport 目录,并加载镜像。
[root@node01 data]# rz -E
rz waiting to receive.
[root@node01 data]# ls
ingree.contro-0.30.0.tar.gz
[root@node01 data]# tar xf ingree.contro-0.30.0.tar.gz
[root@node01 data]# ls
ingree.contro-0.30.0.tar ingree.contro-0.30.0.tar.gz
[root@node01 data]# docker load -i ingree.contro-0.30.0.tar[root@node02 data]# docker load -i ingree.contro-0.30.0.tar
2.3 启动 nginx-ingress-controller
[root@master01 nodeport]# kubectl apply -f mandatory.yaml
[root@master01 nodeport]# kubectl apply -f service-nodeport.yaml[root@master01 nodeport]# kubectl get svc,pod -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx NodePort 10.96.69.94 <none> 80:32269/TCP,443:32017/TCP 69sNAME READY STATUS RESTARTS AGE
pod/nginx-ingress-controller-54b86f8f7b-2gm9j 1/1 Running 0 100s
如果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
解决方案:
① 给需要调度的node加上对应标签
# 相对上面这个Yaml文件的例子
kubectl label nodes node_name kubernetes.io/os=linux
② 删除Yaml文件中的nodeSelector,如果对节点没有要求的话,直接删除节点选择器即可
三、Ingress HTTP 代理访问
Ingress HTTP代理访问通常用于在Kubernetes集群中管理入站和出站流量。通过设置Ingress代理,可以实现对集群中部署的服务进行访问控制、负载均衡、SSL终止等功能。
1. 创建 deployment、Service、Ingress Yaml 资源
[root@master01 nodeport]# vim ingress-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-app
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.aaa.com # 指定了这条规则适用于主机 www.aaa.comhttp: # 定义了 HTTP 访问规则paths: # 指定了路径匹配规则- path: / # 表示所有以 / 开头的路径都会匹配到这个规则pathType: Prefix # 指定了路径匹配类型为前缀匹配backend: # 指定了后端服务的配置service: # 定义了后端服务的名称和端口号name: nginx-svc # 指定了后端服务的名称为 nginx-svcport:number: 80[root@master01 nodeport]# kubectl apply -f ingress-nginx.yaml
[root@master01 nodeport]# kubectl get pod,svc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-app-57dd86f5cc-2qgww 1/1 Running 0 2m29s 10.244.1.225 node01 <none> <none>
pod/nginx-app-57dd86f5cc-2rhh5 1/1 Running 0 2m29s 10.244.2.61 node02 <none> <none>NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/nginx-svc ClusterIP 10.96.206.53 <none> 80/TCP 4m26s name=nginx[root@master01 nodeport]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx-test <none> www.aaa.com 10.96.69.94 80 12m
2. 进入容器编辑页面内容
[root@master01 nodeport]# kubectl exec -it nginx-app-57dd86f5cc-2qgww sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# echo "this is web1" > /usr/share/nginx/html/index.html
# exit
[root@master01 nodeport]# kubectl exec -it nginx-app-57dd86f5cc-2rhh5 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# echo "this is web2" > /usr/share/nginx/html/index.html
3. 访问页面
[root@master01 nodeport]# kubectl get endpoints nginx-svc
NAME ENDPOINTS AGE
nginx-svc 10.244.1.225:80,10.244.2.61:80 24m任意node地址添加域名解析:
[root@master01 nodeport]# curl www.aaa.com:32269
this is web1
[root@master01 nodeport]# curl www.aaa.com:32269
this is web2
四、Ingress HTTP 代理访问多域名服务路由
测试和实践在Kubernetes集群中使用Ingress资源实现同一端口但不同域名的服务路由和负载均衡。具体来说,通过创建两个不同的Service资源,并使用Ingress资源来将不同域名的流量路由到这两个Service上。
① 创建虚拟主机1资源
[root@master01 nodeport]# mkdir vhost
[root@master01 nodeport]# cd vhost/[root@master01 vhost]# vim deployment1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: deployment1
spec:replicas: 1selector: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
② 启动主机1资源
[root@master01 vhost]# kubectl apply -f deployment1.yaml
③ 创建虚拟主机2资源
[root@master01 vhost]# vim deployment2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: deployment2
spec:replicas: 1selector: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
④ 启动主机2资源
[root@master01 vhost]# kubectl apply -f deployment2.yaml[root@master01 vhost]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment1-c8d988f6c-hrk88 1/1 Running 0 69s
deployment2-5588d5cdcd-k6cx6 1/1 Running 0 38s
⑤ 创建ingress资源
[root@master01 vhost]# vim ingress-nginx.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress1
spec: # 规定了 Ingress 资源的规格,包括访问规则rules: # 定义了访问规则,指定了如何路由到后端服务- host: www.fff.com # 指定了这条规则适用于主机 www.fff.comhttp: # 定义了 HTTP 访问规则paths: # 指定了路径匹配规则- path: / # 表示所有以 / 开头的路径都会匹配到这个规则pathType: Prefix # 指定了路径匹配类型为前缀匹配backend: # 指定了后端服务的配置service: # 定义了后端服务的名称和端口号name: svc-1 # 指定了后端服务的名称为 svc-1port:number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress2
spec:rules:- host: www.qqq.comhttp:paths:- path: /pathType: Prefixbackend:service: name: svc-2port:number: 80
⑥ 查看svc、ingress信息
[root@master01 vhost]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc ClusterIP 10.96.206.53 <none> 80/TCP 47m
svc-1 ClusterIP 10.96.43.42 <none> 80/TCP 5m35s
svc-2 ClusterIP 10.96.30.23 <none> 80/TCP 5m4s[root@master01 vhost]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.96.69.94 <none> 80:32269/TCP,443:32017/TCP 64m[root@master01 vhost]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress1 <none> www.fff.com 10.96.69.94 80 117s
ingress2 <none> www.qqq.com 10.96.69.94 80 117s
nginx-test <none> www.aaa.com 10.96.69.94 80 49m
⑦ 进入容器编辑页面内容
[root@master01 vhost]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment1-c8d988f6c-hrk88 1/1 Running 0 11m
deployment2-5588d5cdcd-k6cx6 1/1 Running 0 11m[root@master01 vhost]# kubectl exec -it deployment1-c8d988f6c-hrk88 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # echo "this is web01" > /usr/share/nginx/html/index.html
/ # exit
[root@master01 vhost]# kubectl exec -it deployment2-5588d5cdcd-k6cx6 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # echo "this is web02" > /usr/share/nginx/html/index.html
/ # exit
⑧ 测试访问
[root@master01 vhost]# vim /etc/hosts
192.168.190.102 www.aaa.com www.fff.com www.qqq.com[root@master01 vhost]# curl www.fff.com:32269
this is web01
[root@master01 vhost]# curl www.qqq.com:32269
this is web02
五、Ingress HTTPS 代理访问
在Kubernetes集群中使用Ingress资源实现通过HTTPS代理访问服务。
1. 创建ssl证书
生成一个自签名的TLS证书,用于在实验中配置HTTPS代理访问时使用
[root@master01 vhost]# cd ../
[root@master01 nodeport]# mkdir https
[root@master01 nodeport]# cd https/[root@master01 https]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
[root@master01 https]# ls
tls.crt tls.key# -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(组织)。
2. 创建 secret 资源进行存储
[root@master01 https]# kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret/tls-secret created
[root@master01 https]# kubectl get secret
NAME TYPE DATA AGE
tls-secret kubernetes.io/tls 2 7s
[root@master01 https]# kubectl describe secret tls-secret
Name: tls-secret
Namespace: default
Labels: <none>
Annotations: <none>Type: kubernetes.io/tlsData
====
tls.crt: 1143 bytes
tls.key: 1704 bytes
3. 创建 deployment、Service、Ingress Yaml 资源
[root@master01 https]# vim ingress-https.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-fql
spec:replicas: 1selector:matchLabels:name: nginxtemplate:metadata:labels:name: nginxspec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: n-svc-https
spec:ports:- port: 80targetPort: 80protocol: TCPselector:name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx-https
spec:tls: # 定义了TLS配置,用于配置HTTPS访问- hosts:- www.lll.com # 指定了使用TLS的主机名为www.lll.comsecretName: tls-secret # 存储TLS证书和私钥的 Secret 对象的名称为tls-secretrules: # 定义了访问规则,指定了如何路由到后端服务- host: www.lll.com # 这条规则适用于主机 www.lll.comhttp: # 定义了HTTP访问规则paths: # 指定了路径匹配规则- path: / # 表示所有以 / 开头的路径都会匹配到这个规则pathType: Prefix # 路径匹配类型为前缀匹配backend: # 指定了后端服务的配置service: # 定义了后端服务的名称和端口号name: n-svc-https #后端服务的名称为 n-svc-httpsport:number: 80
4. 启动资源
[root@master01 https]# kubectl apply -f ingress-https.yaml[root@master01 https]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
n-svc-https ClusterIP 10.96.7.182 <none> 80/TCP 22s[root@master01 https]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.96.69.94 <none> 80:32269/TCP,443:32017/TCP 101m[root@master01 https]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx-https <none> www.lll.com 80, 443 5s
5. 访问资源
在宿主机的 C:\Windows\System32\drivers\etc\hosts 文件中添加 192.168.190.102 www.lll.com 记录。
六、Nginx 进行 BasicAuth
Basic认证是一种简单的HTTP身份验证方法,通过用户名和密码验证用户身份。
1. 生成用户密码认证文件,创建 secret 资源进行存储
[root@master01 https]# cd ..
[root@master01 nodeport]# mkdir basic-auth
[root@master01 nodeport]# cd basic-auth/[root@master01 basic-auth]# yum -y install httpd-tools.x86_64
[root@master01 basic-auth]# htpasswd -c auth fql # 认证文件名必须为 auth
[root@master01 basic-auth]# htpasswd -c auth fql
New password: # 密码123
Re-type new password:
Adding password for user fql
[root@master01 basic-auth]# ls
auth
2. 创建一个 Secret 对象
[root@master01 basic-auth]# kubectl create secret generic basic-auth --from-file=auth
3. 创建 ingress 资源
[root@master01 basic-auth]# vim ingress-auth.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress-authannotations:nginx.ingress.kubernetes.io/auth-type: basicnginx.ingress.kubernetes.io/auth-secret: basic-authnginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - fql'
spec:rules:- host: www.abc.comhttp:paths:- path: /pathType: Prefixbackend:service: name: nginx-svcport:number: 80[root@master01 basic-auth]# kubectl apply -f ingress-auth.yaml[root@master01 basic-auth]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-auth <none> www.abc.com 10.96.69.94 80 3m4s
4. 添加宿主机域名解析www.abc.com,访问测试
七、Nginx 重写
在进行 Nginx Ingress 的 URL 重写实验中,可以配置 Nginx Ingress Controller,然后通过编辑 Ingress 资源规则,使用 Nginx 的 rewrite 指令来修改传入请求的 URL 路径,实现定制的路由和重定向功能。
1. 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上定义的路径是否使用正则表达式
2. 示例
针对主机 "www.efg.com" 的请求,在经过 Nginx Ingress Controller 处理后,会被重写为指定的目标 URL www.abc.com:32269,并最终路由到名为 "nginx-svc" 的后端服务的端口 80。
① 定义 Ingress
[root@master01 basic-auth]# vim ingress-rewrite.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx-rewriteannotations:nginx.ingress.kubernetes.io/rewrite-target: http://www.fff.com:32269
spec:rules:- host: www.efg.com #由于www.efg.com只是用于跳转不需要真实站点存在,因此svc资源名称可随意定义http:paths:- path: /pathType: Prefixbackend:service: name: nginx-svcport:number: 80
② 启动 ingress
[root@master01 basic-auth]# kubectl apply -f ingress-rewrite.yaml[root@master01 basic-auth]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx-rewrite <none> www.efg.com 80 9s
④ 添加宿主机域名解析,访问测试
192.168.190.102 www.lll.com www.abc.com www.efg.com www.fff.com