9 ingress 实现 7 层代理
Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。
下面是一个将所有流量都发送到同一 Service 的简单 Ingress 示例:
可以将 Ingress 配置为服务提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及提供基于名称的虚拟主机等能力。 Ingress 控制器 通常负责通过负载均衡器来实现 Ingress,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。
Ingress 不会公开任意端口或协议。 将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的服务。
9.1 ingress 到底是什么
你可以理解为它是 ingress 给我们提供了一个 api 接口暴露的方式,那也就意味着 ingress 实现的方案有很多。那我们在这里讲的是 ingress nginx 的解决方案。当然还有 ingress HAproxy 和很多解决方案,因为 nginx 是我们非常熟悉的这么一个软件,所以我们拿 ingress nginx 的方案来给大家讲解以及演示。
Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。
internet
|
[ Ingress ]
--|-----|--
[ Services ]
ingress-nginx github 地址:https://github.com/kubernetes/ingress-nginx
ingress-nginx 官方地址:https://kubernetes.github.io/ingress-nginx/
大概的访问流程
- 用户所有访问请求转发给 ingress-nodepord
- ingress-nodeport 在转发给 ingress-controller
- ingress-controller 在做判断,判断域名或者判断 location
- ingress-controller 判断完之后再转发给后面对应的 svc
- svc 通过 label 匹配在转给对应的 pod
但是 ingress 在访问量一大的时候就会出现性能问题,因为我们可以在流程访问的这个地方看到其实 ingress 这里多了一层,先通过 ingress 在转发给 svc
本来用户的访问可以直接通过 nodeport ,在有 nodeport 转给对应的 svc 在转发给对应的 pod
9.2 ingress 的访问方案:
ingress 原理:
首先我们的客户端先访问至我们的域名,也就是对于 ingress 来说需要绑定一个域名毕竟是一个 7 层代理(访问多个域名都可以)。那不同的域名都可以访问至我们 ingress-nginx ,ingress-nginx 会反向代理或叫做负载均很选择到后端的一些 service ,那这些 service 会有对应的一些容器的出现。这样的话我们就实现了从访问域名接入进 kubernetes 集群内部,然后再由 ingress-nginx 接入至不同的一些容器。
那这里有以下问题我们需要注意一下:
ingress-nginx 到底是以何种的方法去进行所谓的跟后端的 svc 进行链接,其实对于 ingress-nginx 的暴露方案来说它依然是一个 nodeport ,也就是 ingress-nginx 最常见的部署方案依然是以 nodeport 的部署方案。那这样的话 ingress-nginx 就会以内部的服务暴露给外部用户,暴露给外部用户以后我们访问到 ingress-nginx 以后, ingress-nginx 再去链接至不同的 SVC 。也就意味着我们在 SVC 中进行容器部署的话需要先创建一个 SVC 与 ingress-nginx 关联,然后这个 SVC 在被我们的 ingress-nginx 所链接进去。在进行如上图的这么一个步骤之后呢,我们会看见 ingress-nginx 里面有 server 这么一个代理配置文件的生成,是一个反向代理的区域。所以可以理解为 ingress 就是帮我们去部署了一个 nginx ,只不过进行这种访问的时候我们不需要进入到 nginx 内部去写文件了,这个反向代理的配置文件会自动的添加。
9.3 ingress-nginx 内部协程工作方案:
当然上图这个 nginx 已经被我们的 ingress 进行了修改,这个结构并不是 nginx 默认的进程之间的协程关系。
首先图中有一个 kubernetes APIserver 它需要和我们的 store 的协程进行监听状态,这里的监听方式是以一个协程的 pod 的形式向我们的 api server 发起连接的这么一种方案进行监听的,那如果发生一些新的数据写入呢会被写入到我们的这么一个 updatechannel 循环队列中去,然后我们这边有一个 nginx controller 的主进程回去监听 updatechannel 中的资源和事件,在 updatechannel 中发生一个循环之后会更新一个事件,并把该事件写入到同步队列中去等待被 sync queue 协程去更改配置文件,这个 sync queue 这个协程会定期的从队列里拉取它需要去执行添加的一些任务。
当然如果有一些直接需要去修改的不需要等待这么一些事件,会直接由 store 协程发送至 syncqueue 协程,两个协程之间会直接沟通,syncqueue 协程收取到所有要更新的数据以后呢会去判断是否要去进行一个 reload(重载)写入数据的这么一个方案,还是等等再去进行添加。如果有的话就会写入我们 nginx 的一个主配置文件,然后重新载入我们 nginx 的一些数据、那如果不需要的话就在等待后面去执行直接发送构建 post 即可。最后呢会以nginx 模块去运行。
以上就是 ingress 它自己的进程以及协程之间的沟通方案
9.4 构建 ingress-nginx 0.33.0
官方地址:https://github.com/kubernetes/ingress-nginx/tags
1.下载源码包
[12:03:20 root@k8s-master Ingress]#wget https://github.com/kubernetes/ingress-nginx/archive/refs/tags/controller-0.33.0.tar.gz
2.解压
[12:03:30 root@k8s-master Ingress]#tar xf controller-0.33.0.tar.gz
3.拷贝部署文件
[12:03:38 root@k8s-master Ingress]#cp ingress-nginx-controller-0.33.0/deploy/static/provider/baremetal/deploy.yaml .
4.修改配置文件中的 nodeport
[15:35:44 root@k8s-master Ingress]#vim deploy.yaml
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
nodePort: 40080 # 添加该参数,如果访问 http 就直接访问 40080
- name: https
port: 443
protocol: TCP
targetPort: https
nodePort: 40443 # 添加该参数,如果访问 https 就直接访问 40443
# 因为该文件默认是没有指定 nodeport 端口的所以为了不想让他随机,这里通过认为手段指定
5、通过kubectl apply
创建,这个过程需要一段时间,因为我们不是国外节点,并且镜像有 300M 这么大。所以等待几分钟,要是实在不行我们可以通过 阿里云镜像仓库进行下载。
[11:56:22 root@k8s-master Ingress]#kubectl apply -f deploy.yaml
6.pod 运行成功
[12:07:02 root@k8s-master Ingress]#kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-g7njk 0/1 Completed 0 131m
ingress-nginx-admission-patch-srdtt 0/1 Completed 0 131m
ingress-nginx-controller-7566fdb978-mvb9g 1/1 Running 0 132m
7.svc 生效
[15:42:17 root@k8s-master Ingress]#kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 172.30.201.103 <none> 80:40080/TCP,443:40443/TCP 3h35m
ingress-nginx-controller-admission ClusterIP 172.30.139.148 <none> 443/TCP 3h35m
8.浏览器访问 ingress 暴露的 nodeport 端口,因为当前没有 index 文件所以 404
如果是直接访问不了这个页面就说明我们的访问压根就没有过去
9.5 实现单个域名的 ingress
与所有其他 Kubernetes 资源一样,Ingress 需要使用 apiVersion
、kind
和 metadata
字段。 Ingress 对象的命名必须是合法的 DNS 子域名名称。 有关使用配置文件的一般信息,请参见部署应用、 配置容器、 管理资源。 Ingress 经常使用注解(annotations)来配置一些选项,具体取决于 Ingress 控制器,例如 重写目标注解。 不同的 Ingress 控制器 支持不同的注解。查看文档以供你选择 Ingress 控制器,以了解支持哪些注解。
Ingress 规约 提供了配置负载均衡器或者代理服务器所需的所有信息。 最重要的是,其中包含与所有传入请求匹配的规则列表。 Ingress 资源仅支持用于转发 HTTP 流量的规则。
路径类型
Ingress 中的每个路径都需要有对应的路径类型(Path Type)。未明确设置 pathType
的路径无法通过合法性检查。当前支持的路径类型有三种:
ImplementationSpecific
:对于这种路径类型,匹配方法取决于 IngressClass。 具体实现可以将其作为单独的pathType
处理或者与Prefix
或Exact
类型作相同处理。-
Exact
:精确匹配 URL 路径,且区分大小写。 -
Prefix
:基于以/
分隔的 URL 路径前缀匹配。匹配区分大小写,并且对路径中的元素逐个完成。 路径元素指的是由/
分隔符分隔的路径中的标签列表。 如果每个 p 都是请求路径 p 的元素前缀,则请求与路径 p 匹配。说明: 如果路径的最后一个元素是请求路径中最后一个元素的子字符串,则不会匹配 (例如:
/foo/bar
匹配/foo/bar/baz
, 但不匹配/foo/barbaz
)。
这里我跑一个 tomcat 然后通过 ingress 来实现对这个 tomcat 的 pod 实现代理
创建 ns
[16:28:42 root@k8s-master Ingress]#vim web-ns.yaml
apiVersion: v1
kind: Namespace
metadata:
name: web
[16:29:03 root@k8s-master Ingress]#kubectl apply -f web-ns.yaml
1.编写创建 pod 和 svc
[17:10:58 root@k8s-master ingress]#vim nginx-app1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app1
namespace: web
spec:
replicas: 2
selector:
matchLabels:
name: nginx-app1
template:
metadata:
labels:
name: nginx-app1
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
# 这里的 svc 我用的 custer ip ,K8S 集群外的服务是无法访问的
---
apiVersion: v1
kind: Service
metadata:
name: nginx-app1-svc
namespace: web
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx-app1
2.创建 pod
[15:54:23 root@k8s-master Ingress]#kubectl apply -f tomcat-app1.yaml
# pod 创建成功
[15:56:13 root@k8s-master Ingress]#kubectl get pod -n web
NAME READY STATUS RESTARTS AGE
tomcat-app1-58b466b4c5-6rnlf 1/1 Running 0 3m4s
3、通过 master 节点直接访问当然是没有问题
那现在我们想去通过 nginx 的 ingress 方案,将该 svc 暴露出去,实现一个根据域名访问的这么一个结构
4.编写 ingress 单个主机访问 yaml
也可以从该 ingress yaml 文件中看出来也就意味这里的 ingress 链接的其实是我们的 nginx-svc ,所以这个 svc 是要提前创建的
[16:53:52 root@k8s-master Ingress]#vim ingress1.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-web
namespace: web
annotations:
# 指定Ingress Controller的类型
kubernetes.io/ingress.class: "nginx"
# 指定后面rules定义的path可以使用正则表达式
nginx.ingress.kubernetes.io/use-regex: "true"
# 连接超时时间,默认为5s
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
# 后端服务器回转数据超时时间,默认为60s
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
# 后端服务器响应超时时间,默认为60s
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
# 客户端上传文件,最大大小,默认为20m
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
#nginx.ingress.kubernetes.io/rewrite-target: / ##URL重写
# 当用户访问的 rul 不存在就自定跳转至 /index.html
nginx.ingress.kubernetes.io/app-root: /index.html
spec:
rules: # 规则
- host: www.zgy.com # 使用的规则是 host,也就是主机域名是什么
http: # 使用 http 的详细信息
paths: # 访问的路径
- path: / # 访问 / URL ,就会调用下面的 nginx-svc
pathType: Exact # 精确匹配 URL 路径,且区分大小写。
backend: # 后端 svc 匹配
service:
name: svc-ingress # service name = nginx-svc 匹配 SVC
port:
number: 80 # 暴露的端口是 80
5.创建
[17:13:40 root@k8s-master ingress]#kubectl apply -f ingress1.yaml
6、通过域名访问。淡然现在在我们的 windos 系统上没有做 DNS 解析,所以需要修改 hosts 文件。
C:\Windows\System32\drivers\etc
7、kubectl get svc
查看我们的 SVC 服务,并且指定名称空间是在 ingress-nginx 下
[21:15:51 root@master-1 ~]#kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 172.30.233.1 <none> 80:32188/TCP,443:30216/TCP 3h39m
8、通过浏览器访问,这时候一定要注意端口不是 80,而是我们 ingress 的随机端口 32188
这就是一个根据我们域名的 ingress 代理
9.6 基于 ingress 实现虚拟主机
接下来我给大家演示一下基于 ingress 实现虚拟主机的方案,如上图。首先我们要新建两个我们的 deployment ,一个叫做 www1 的 deployment 一个叫做 www2 的 deployment ,这两个 deployment 会创建出一些对应的pod 。接着我们要去创建一个 svc 与这个 deployment 和 pod 相关联,然后我们在去创建一个 ingress ,这个 ingress 里面的配置方式与这两个 SVC 进行相关联左边我们就叫它 www1.zgy.com ,右边就是我们的 www2.zgy.com 。也就意味着我们需要干这么多事情才能建立两个不同的基于我们虚拟域名主机的访问。
9.6.1 创建第一个 deployment
1、首先我们创建一个 ingress-vh 的目录
[21:24:47 root@master-1 ~]#mkdir ingress-vh
[21:44:24 root@master-1 ~]#cd ingress-vh/
2、接着创建的我们的 deployment
[21:44:27 root@master-1 ingress-vh]#vim deployment1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment1
spec:
replicas: 2
selector:
matchLabels:
name: nginx
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: svc-1
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx
3、通过 kubectl apply
创建
[21:46:43 root@master-1 ingress-vh]#kubectl apply -f deployment1.yaml
4、kubectl get svc
查看该 SVC 是否创建
[21:46:54 root@master-1 ingress-vh]#kubectl get svc
svc-1 ClusterIP 172.30.181.106 <none> 80/TCP 35s
5、通过culr
访问该 SVC
[21:47:29 root@master-1 ingress-vh]#curl 172.30.181.106
9.6.2 创建第二个 deployment
第一个 deployment 创建成功了,接着创建我们的第二个 deployment
1、将 deployment1 的 yaml 文件拷贝成为 deployment2
[21:47:53 root@master-1 ingress-vh]#cp deployment1.yaml deployment2.yaml
2、修改 deployment2 的 yaml 文件
[21:49:47 root@master-1 ingress-vh]#vim deployment2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment2 #修改为 deployment2
spec:
replicas: 2
selector:
matchLabels:
name: apache #标签也要修改为 nginx1
template:
metadata:
labels:
name: apache #改为 apache
spec:
containers:
- name: apache #容器名改为 apache
image: httpd #镜像使用 httpd 等会为了和 nginx 区分
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: svc-2 #svc 名称改为 2
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: apache #标签使用 apache
3、通过kubectl apply
创建
[21:55:09 root@master-1 ingress-vh]#kubectl apply -f deployment2.yaml
4、kubectl get svc
查看该 SVC2 是否创建
[21:55:10 root@master-1 ingress-vh]#kubectl get svc
svc-1 ClusterIP 172.30.181.106 <none> 80/TCP 8m50s
svc-2 ClusterIP 172.30.208.160 <none> 80/TCP 5s
5、通过curl
访问
[21:58:31 root@master-1 ingress-vh]#curl 172.30.208.160
<html><body><h1>It works!</h1></body></html>
现在我们的 SVC 就建立了,接下来需要写我们的 ingress 规则
9.6.3 创建 ingress
1、编写 ingress 的 yaml 文件
[21:59:50 root@master-1 ingress-vh]#vim ingressrule.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-1
spec:
rules:
- host: www1.zgy.com
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: svc-1
port:
number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-2
spec:
rules:
- host: www2.zgy.com
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: svc-2
port:
number: 80
2、通过kubectl apply -f
声明式创建
[22:07:00 root@master-1 ingress-vh]#kubectl apply -f ingressrule.yaml
3、查看运行在 ingress-nginx 名称空间下的 ingress 控制器 pod
[22:07:34 root@master-1 ingress-vh]#kubectl get pod -n ingress-nginx
ingress-nginx-controller-f8d756996-24jjc 1/1 Running 0 4h25m
4、进入该 pod ,查看 nginx 的配置文件中会发现多个 proxy 代理规则。所以其实就是将刚才我们写的 ingress 规则,它会将这些 ingress 的规则转会为 nginx 的代理配置文件,注入到 nginx 的配置之中达到被访问代理的这么一个目的。
#进入该 pod
[22:10:26 root@master-1 ingress-vh]#kubectl exec -it ingress-nginx-controller-f8d756996-24jjc -n ingress-nginx -- /bin/bash
kubectl exec -i: #使用交互的方式访问 pod
ingress-nginx-controller-f8d756996-24jjc: #被访问 pod 的名称
-n ingress-nginx: #该 pod 运行在那个名称空间下
-- /bin/bash: #进入 pod 使用 bahs 命令
#在 pod 中查看 nginx 的配置文件
bash-5.0$ cat /etc/nginx/nginx.conf
9.6.4 测试是否实现了多虚拟主机代理
1、在 windows 主机中的 hosts 文件中添加我们的主机头。
2、通过kubectl get svc -n ingress-nginx
查看 ingress nginx 暴露的 IP 和随机端口
[22:18:06 root@master-1 ingress-vh]#kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 172.30.233.1 <none> 80:32188/TCP,443:30216/TCP 4h36m
3、通过浏览器访问 ingress-nginx 暴露出来的 32188 随机端口。
访问地址:http://www1.zgy.com:32188/
这是 nginx
访问地址:http://www2.zgy.com:32188/
这是 apache
这就是根据我们的虚拟主机去实现的,根据不同的域名区实现我们的虚拟主机
4、通过kubectl get ingresses
查看 ingress 的规则
[22:22:52 root@master-1 ~]#kubectl get ingresses
NAME HOSTS ADDRESS PORTS AGE
ingress1 www1.zgy.com 172.16.18.104 80 16m
ingress2 www2.zgy.com 172.16.18.104 80 15m
9.7 通过 ingress 实现 https 代理
也就意味着和我们之前说的会话卸载层一样,后端的 pod 暴露的端口都是 80 ,然后我们的 ingress 会暴露一个 443 的访问。这样的话我们的 client 访问之我们的 ingress 443 端口,然后再由 ingress 调度后端的 pod 80 即可。相当于是一个 https 的会话卸载层。
9.7.1 创建证书 以及 cert 存储方式
因为是 https 的访问方式所以我们需要提前将证书创建出来。
1、创建一个 https 目录
[10:27:45 root@master-1 ~]#mkdir https
[10:28:08 root@master-1 ~]#cd https/
2、创建证书
[10:28:10 root@master-1 https]#openssl req -x509 -sha256 -nodes -days 3650 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
openssl: #使用 openssl
req: #证书请求
-x509: #x509格式
-sha256: #我们使用的是 sha256 加密方式
-days 3650: #有效期为 3650 天
-newkey : #一个新 key
rsa:2048: #用这个 key 去新建
-keyout tls.key: #这个新 key 输出的结果是 tls.key
-out tls.crt : #输出的是 tls.crt 证书
-subj "/CN=nginxsvc/O=nginxsvc": #标识,CN 中国 nginxsvc 、O nginxsvc
#通过查看证书私钥都有了
[10:28:19 root@master-1 https]#ls
tls.crt tls.key
3、通过kubectl create
创建将它封装进去
[10:28:30 root@master-1 https]#kubectl create secret tls tls-secret --key tls.key --cert tls.crt
kubectl create secret tls tls-secret: #创建了一个 secret 加密的 tls 文件,或叫做数据存储结构
--key tls.key --cert tls.crt: #通过指定我们的 tls key 文件和 tls证书文件
9.7.2 创建 deployment、service
我们对 deployment 和 service 进行创建,因为创建资源需要有先后顺序
YAML 文件详解:
apiVersion: apps/v1 # api 接口使用的是 apps/v1 版
kind: Deployment # 类型是 deployment
metadata: # deployment 元数据详细信息
name: deployment3 # 该 deployment 名为 deployment 3
spec: # deployment 详细信息描述
replicas: 2 # pod 副本数目为 2
selector: # 标签选择器
matchLabels: # 匹配标签
name: nginx3 # 匹配 name=nginx3 的标签
template: # pod 模板数据
metadata: # pod 元数据信息
labels: # pod 使用标签匹配
name: nginx3 # 该 pod 标签 name=nginx3
spec: # pod 详细信息描述
containers: # 容器信息
- name: nginx3 # 容器名为 nginx3
image: nginx # 使用的镜像是 nginx
imagePullPolicy: IfNotPresent # 镜像下载策略,如果有该镜像就不用下载,没有该镜像就需要下载
ports: # 暴露端口策略
- containerPort: 80 # 容器使用端口为 80
--- # svc yaml 创建模板
apiVersion: v1 # api 使用版本为 v1
kind: Service # kind 类型是 svc
metadata: # svc 元数据信息
name: svc-3 # 该 SVC 名为 SVC-3
spec: # svc 的详细描述
ports: # 端口暴露策略
- port: 80 # 暴露容器 80 端口
targetPort: 80 # 目标端口 80
protocol: TCP # 使用的是 TCP 链接方式
selector: # 标签选择器
name: nginx3 # 匹配的是 name=nginx3 的标签
1、编写 yaml
文件
[11:30:22 root@master-1 https]#vim deployment3.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment3
spec:
replicas: 2
selector:
matchLabels:
name: nginx3
template:
metadata:
labels:
name: nginx3
spec:
containers:
- name: nginx3
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: svc-3
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx3
2、通过kubectl apply
创建
[11:32:12 root@master-1 https]#kubectl apply -f deployment3.yaml
kubectl apply -f: # 通过声明式创建
deployment3.yaml: # 使用该 yaml 文件
3、通过kubectl get svc
查看当前的 svc 信息,我们的 svc 3 已经创建
[11:32:14 root@master-1 https]#kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 172.30.0.1 <none> 443/TCP 2d12h
nginx-svc ClusterIP 172.30.236.134 <none> 80/TCP 38h
svc-1 ClusterIP 172.30.181.106 <none> 80/TCP 37h
svc-2 ClusterIP 172.30.208.160 <none> 80/TCP 37h
svc-3 ClusterIP 172.30.93.149 <none> 80/TCP 4m55s
4、我们通过curl
去访问这个 svc-3 的 svc 验证已经没有问题
[11:33:17 root@master-1 https]#curl 172.30.93.149
接下来我们进行一个 https ingress 的创建
9.7.3 创建 https ingress
yaml 文件详解:
apiVersion: networking.k8s.io/v1beta1 # api 使用的是 networking.k8s.io/v1beta1
kind: Ingress # kind 类型为 ingress
metadata: # ingress 元数据信息
name: https # 这个 ingress 叫做 https
spec: # 详细描述
tls: # tls 详细信息
- hosts: # hosts 信息
- www3.zgy.com # 主机名或域名
secretName: tls-secret # 也就是我们刚才创建的 secret 保存的名称叫什么,也和刚才创建的对应上
rules: # 规则
- host: www3.zgy.com # 访问的主机名
http: # 使用 http 详细信息
paths: # 访问的路径详细信息
- path: / # 访问的路径是 / 根
backend: # 后端匹配信息
serviceName: svc-3 # 后端使用的 svc 是我的 svc-3
servicePort: 80 # 后端 svc 暴露的端口为 80
1、编写 yaml
文件
[11:34:17 root@master-1 https]#vim ingress-https.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: https
spec:
rules:
- host: www3.zgy.com
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: https
port:
number: 80
tls:
- hosts:
- www3.zgy.com
secretName: tls-secret
2、通过kubectl apply
声明式创建
[11:49:51 root@master-1 https]#kubectl apply -f ingress-https.yaml
3、因为他是一个 https 的访问所以我们需要提前看一下他的 ip 地址
[14:14:42 root@master-1 https]#kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 172.30.233.1 <none> 80:32188/TCP,443:30216/TCP 44h
4、在自己的 windows 主机上添加www3.zgy.com
的主机头
9.6.4 浏览器访问测试
访问我们 ingress-nginx 这个名称空间下的 SVC 的 443 映射的随机端口 30216.
https://www3.zgy.com:30216/
已经实现了访问
以上就是整个在 ingress 里面去配置我们的 https 的会话卸载层
9.8 nginx 进行 BasicAuth(nginx 的基础登录认证)
对 nginx 的认证方法来说是采用的 apache 的这么一个 httpd-tools 模块,所以我们在进行 nginx 配置的时候需要提前安装 apache 的模块,其实因为 ingress 实现的方案采用的是 nginx 的软件,所以 nginx 相关的特性都支持比如我们的 nginx 登录认证方案。我们先安装以下 httpd 这个服务,因为我们需要 httpd-tools 这个模块。
9.8.1 安装 httpd 生成 htpasswd 命令
我们先安装以下 apache 因为我们需要 htpasswd 这个命令进行所谓的密码文件的创建。
1、安装 apache
#注意由于我使用的是 ubuntu 系统,如是 centos 需要安装 httpd 服务
[14:36:06 root@master-1 ~]#apt install apache2 -y
2、安装完成以后创建用给存放加密文件的目录。比如就叫做 basic-auth
[14:37:22 root@master-1 ~]#mkdir basic-auth
[14:38:50 root@master-1 ~]#cd basic-auth/
3、进入 basic-auth 文件之后我们进行创建我们的密钥文件
[14:38:58 root@master-1 basic-auth]#htpasswd -c auth foo
New password: #使用的密码为 12345
Re-type new password: #重复密码 12345
htpasswd -c: #创建
auth foo: #用户名为 foo
#通过查看 auth 文件已经创建
[14:40:13 root@master-1 basic-auth]#ls
auth
4、创建 auth 保存文件
[15:19:31 root@master-1 basic-auth]#kubectl create secret generic basic-auth --from-file=auth
kubectl create: #通过 create 命令式创建
secrete: #以我们 create 的方式进行保存
generic: #类型为 generic 的 create 格式
basic-auth: #基础认证
--from-file=auth: #需要使用到的 auth 文件路径
9.8.2 通过 ingress 确定 基础登录认证
yaml 文件详解:
apiVersion: networking.k8s.io/v1beta1 # api 接口为 networking.k8s.io/v1beta1
kind: Ingress # kind 类型为 ingress
metadata: # ingress 元数据信息
name: ingress-with-auth # 名称为 ingress
annotations: # 解释描述信息
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kunernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
#使用 foo 用户认证
spec: # 描述信息
rules: # 规则
- host: auth.zgy.com # 绑定在 auth.zgy.com 这个主机上
http: # http 描述信息
paths:
- path: / # 路径为 / 根路径
backend: # 后端信息
serviceName: svc-1 # 后端 SVC 名为 SVC-1
servicePort: 80 # 后端服务器暴露端口为 80
1、编写 yaml 文件
[14:44:32 root@master-1 basic-auth]#vim ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auth
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kunernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
spec:
rules:
- host: auth.zgy.com
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: svc-1
port:
number: 80
2、通过kubectl apply
声明式创建
[14:58:28 root@master-1 basic-auth]#kubectl apply -f ingress.yaml
9.8.3 浏览器访问验证
1、到 windows 主机上添加主机头
2、通过浏览器访问
9.9 nginx 进行重定向
ingress-nginx 中比较常用的就是我们的重写模块,重写模块需要在我们的 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 上定义的路径是否使用正则表达式 | 布尔 |
9.9.1 ingress-nginx 重定向演示
上图讲解:
我们这里已经运行了一个 ingress 3 了,而且是一个 https 的访问,这个 ingress-3 连接的是我们的 SVC-3 这个 service ,SVC-3 下面连接是我们的 deployment ,这个 deployment 是我们的 V3 版。
现在我在给她创建一个 ingress ,比如这个叫做 ingress-re,这个 ingress-re 绑定的地址是我们的 re.zgy.com ,如果有客户端一旦访问我们这个 re.zgy.com 就会被跳转到我们的 www3.zgy.com 这个网站上,然后间接的访问到我的 svc-3 这个 svc。从而实现了一个地址跳转。下面我们就来实现
1、创建一个 re 的文件
[16:15:06 root@master-1 ~]#mkdir re
[17:01:24 root@master-1 ~]#cd re/
接下来我们对 ingress-nginx 的 yaml 文件进行详解
yaml 文件详解:
apiVersion: networking.k8s.io/v1beta1 # api 版本使用的是 networking.k8s.io/v1beta1
kind: Ingress # kind 类型为 ingress
metadata: # ingress 元数据信息
name: nginx #
annotations:
nginx.ingress.kubernetes.io/rewrite-target: https://www3.zgy.com:30216
#这里使用的是 rewrite-target ,也就是重定向到目标的 url 最后访问的其实是我们的 www3.zgy.com 这个地址
spec: # 详细信息描述
rules: # 规则
- host: re.zgy.com # 访问的主机头地址是 re.zgy.com
http: # http 链接信息
paths:
- path: / # 访问的是我的 / 文件
backend: # 匹配后端 SVC 信息
serviceName: svc-1 # 使用的是 svc-1 这个 服务
servicePort: 80 # 使用的端口是 80
2、创建 yaml 文件
[16:47:33 root@master-1 ~]#vim ingress-rewrite.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: https://www3.zgy.com:31909
spec:
rules:
- host: re.zgy.com
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: svc-3
port:
number: 80
3、通过kubectl apply
声明式创建该 ingress
[17:08:23 root@master-1 re]#kubectl apply -f ingress-rewrite.yaml
4、在我们的 windows 系统上添加我们的主机头
5、通过查看 svc
并且名称空间是ingress-nginx
下的
[17:08:30 root@master-1 re]#kubectl get svc -n ingress-nginx
9.9.2 通过浏览器访问检测
我们访问 re.zgy.com 然后加上 ingress 的 SVC 暴露出来的随机端口(因为在 ingress 的配置文件中暴露的是 80端口,所以需要使用 80 的随机端口进行访问)
就会自动跳转到我们的https
这个链接上,并且端口由 32188
变为了 30216
说明已经实现了跳转。
总结:
这以上就是我们 ingress
的实现方案,因为 ingress 里面的配置非常的多,比如还有haroxy
等等,但是相对来说 nginx
是比较合理,而且 ingress-nginx 的方案还有其他很多功能。我们可以通过它的官方文档进行查看相关帮助:https://kubernetes.github.io/ingress-nginx/