一、理论
ingress解决了service的哪些问题?
service发布时,有四种模式可选,其中只有两种方式能在linux上让外部访问,是nodeport和loadbalancer模式,nodeport和loadbalancer模式原理相同,只是环境不同,nodeport在k8s中,loadbalancer在公有云环境。这两个不管是哪一个,都会让群集内所有节点变为访问入口,这样安全性太低。
所以,可以使用ingress来进行服务发布,ingress发布后,只有运行ingress的节点才会成为群集访问入口,安全性得到提高。
ingress工作原理
ingress共有两个,一个是ingress,另一个是ingress-controller。
ingress是一个API对象,通过yaml文件来配置,ingress对象的作用是定义请求如何转发到service的规则,可以理解为配置模板。
ingress-controller是具体实现反向代理和负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。
常用的ingress有treafik、nginx、haproxy、lstio等,treafik和lsito是云原生环境中使用的流量控制软件,nginx和haproxy是传统环境使用的流量控制软件。
SSL终结
网站对外提供加密服务(https),数据传输会消耗大量资源,主要是因为加密和解密消耗资源多。此时,可以将一台nginx部署到网站服务器的前方,让nginx调度网站请求给网站服务器,同时由nginx来解密客户的连接,当网站服务器返回内容给nginx后,nginx再将数据加密传输给客户端。这样,网站服务器不需要加密和解密,只需要处理网页请求,它根本不知道客户端发来的是https请求,nginx将ssl加密截断,相当于终结了SSL。
ingress只能通过域名访问,因为service可能会重建,如果在ingress上配置ip地址与端口,当service重建后,ingress就必须要更改配置,而使用域名就能很好解决这一问题,service更改后,域名并不改变。
二、实践
bash
-- 部署ingress --
1、上传镜像、资源清单及ingress-nginx,导入镜像
2、helm部署,未部署手动安装即可,这里已安装查看版本。
[root@k8s-master ~]# helm version
version.BuildInfo{Version:"v3.9.4", GitCommit:"dbc6d8e20fe1d58d50e6ed30f09a04a77e4c68db", GitTreeState:"clean", GoVersion:"go1.17.13"}
3、部署ingress-nginx(helm安装包)
[root@k8s-master ~]# cd ingress-nginx
[root@k8s-master ingress-nginx]# ls
changelog changelog.md.gotmpl ci README.md templates
CHANGELOG.md Chart.yaml OWNERS README.md.gotmpl values.yaml
4、配置
[root@k8s-master ingress-nginx]# vim values.yaml
修改这里面的镜像地址,不开启摘要值校验,这里面已经被更改过了。
指定节点1的标签,ingress会部署到这个节点上。
[root@k8s-master ingress-nginx]# ku label node k8s-node01 ingress=true
node/k8s-node01 labeled
创建所需命名空间
[root@k8s-master ingress-nginx]# ku create ns ingress-nginx
namespace/ingress-nginx created
5、部署及查看状态
[root@k8s-master ingress-nginx]# helm install ingress-nginx -n ingress-nginx .
[root@k8s-master ingress-nginx]# ku get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-controller-twhwj 1/1 Running 0 37s
[root@k8s-master ingress-nginx]# ku get pod -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-controller-twhwj 1/1 Running 0 45s 192.168.10.102 k8s-node01 <none> <none>
-- ingress简单使用 --
1、创建测试使用的命名空间
[root@k8s-master ~]# ku create ns study-ingress
namespace/study-ingress created
2、以deployment方式创建使用的pod,
[root@k8s-master ~]# ku create deployment nginx --image=nginx:1.7.9 -n study-ingressdeployment.apps/nginx created
[root@k8s-master ~]# ku get pod -n study-ingress
NAME READY STATUS RESTARTS AGE
nginx-85658cc69f-2vqh2 1/1 Running 0 16s
3、创建service
暴露名称为nginx的deployment的80端口,命名空间为study-ingress。
[root@k8s-master ~]# ku expose deployment nginx --port 80 -n study-ingress
service/nginx exposed
查看study-ingress命名空间下的service。
[root@k8s-master ~]# ku get svc -n study-ingress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP 10.105.99.181 <none> 80/TCP 21s
4、访问测试
[root@k8s-master ~]# curl -I 10.105.99.181
HTTP/1.1 200 OK
5、创建ingress
[root@k8s-master ~]# vim web-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
namespace: study-ingress
spec:
ingressClassName: nginx # ingress底层使用的代理工具
rules:
- host: nginx.test.com # nginx中基于域名的虚拟主机
http:
paths:
- backend:
service:
name: nginx # ingress通过名称找service
port:
number: 80
path: / # 访问路径,等同于nginx.test.com/
pathType: ImplementationSpecific # 路径类型
[root@k8s-master ~]# ku create -f web-ingress.yaml
ingress.networking.k8s.io/nginx-ingress created
6、访问
打开windows,修改windows/system32/drivers/etc/hosts文件,添加ingress节点的ip及对应的域名 192.168.10.102 nginx.test.com
在浏览器中输入nginx.test.com访问,能看到nginx的页面。
-- ingress重定向 --
1、编写ingress配置文件
[root@k8s-master ~]# vim redirect.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/permanent-redirect: https://www.baidu.com # 永久重定向至百度
name: nginx-redirect
namespace: study-ingress
spec:
ingressClassName: nginx
rules:
- host: nginx.redirect.com # nginx基于域名的虚拟主机
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: ImplementationSpecific
[root@k8s-master ~]# ku create -f redirect.yaml
ingress.networking.k8s.io/nginx-redirect created
2、客户端修改hosts文件
3、访问
[root@localhost ~]# curl -I nginx.redirect.com
HTTP/1.1 301 Moved Permanently
浏览器访问,确实是重定向至百度
-- ingress实现前后端分离 -- (前端是指用户能访问的页面,后端是指管理员访问的管理界面)
1、创建后端pod
[root@k8s-master ~]# ku create deployment backend-api --image=nginx:1.7.9 -n study-ingress
deployment.apps/backend-api created
[root@k8s-master ~]# ku get pod -n study-ingress
NAME READY STATUS RESTARTS AGE
backend-api-bf6cfd8-xfhq6 1/1 Running 0 24s # 后端pod,后端页面
nginx-85658cc69f-2vqh2 1/1 Running 0 57m # 前端pod,前端页面
2、发布后端页面(暴露端口)
[root@k8s-master ~]# ku expose deployment backend-api --port 80 -n study-ingress
service/backend-api exposed
[root@k8s-master ~]# ku get svc -n study-ingress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
backend-api ClusterIP 10.100.130.40 <none> 80/TCP 10s
nginx ClusterIP 10.105.99.181 <none> 80/TCP 56m
3、修改后端页面
[root@k8s-master ~]# ku -n study-ingress exec -it backend-api-bf6cfd8-xfhq6 -- bash
root@backend-api-bf6cfd8-xfhq6:/# cd /usr/share
root@backend-api-bf6cfd8-xfhq6:/usr/share# cd nginx/
root@backend-api-bf6cfd8-xfhq6:/usr/share/nginx# cd html/
root@backend-api-bf6cfd8-xfhq6:/usr/share/nginx/html# echo "backend.com" > index.html
4、内部访问测试
[root@k8s-master ~]# ku get svc -n study-ingress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
backend-api ClusterIP 10.100.130.40 <none> 80/TCP 4m3s
nginx ClusterIP 10.105.99.181 <none> 80/TCP 60m
[root@k8s-master ~]# curl 10.100.130.40
backend.com
5、编写后端重写配置文件
[root@k8s-master ~]# vim rewirte.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: backend-api
namespace: study-ingress
spec:
ingressClassName: nginx
rules:
- host: nginx.test.com
http:
paths:
- backend:
service:
name: backend-api
port:
number: 80
path: /api-a(/|$)(.*)
pathType: ImplementationSpecific
注:
$2:匹配第二个捕获组。
path:/api-a(/|$)(.*)这个路径使用正则表达式来匹配请求,这里有两个捕获组。
(/|$):第一个捕获组,表示匹配/或者以api-a结尾
(.*):第二个捕获组,匹配任意字符串,表示匹配/api-a之后的路径部分,此处表示任意路径名称。
访问nginx.test.com/ 会访问前端页面
访问nginx.test.com/api-a/ 会访问后端页面
访问nginx.test.com/api-a/XXX 会访问后端页面
[root@k8s-master ~]# ku create -f rewirte.yaml
ingress.networking.k8s.io/backend-api created
6、访问测试
前端页面在前面已经发布了
[root@localhost ~]# curl nginx.test.com 前端页面
<h1>Welcome to nginx!</h1>
[root@localhost ~]# curl nginx.test.com/api-a 后端页面
backend.com
[root@localhost ~]# curl nginx.test.com/api-a/index.html 后端页面
backend.com
[root@localhost ~]# curl nginx.test.com/api-a/a.html 第二级所写文件必须存在,否则会找不到。
<html>
<head><title>404 Not Found</title></head>
-- SSL配置 --
1、生成证书
[root@k8s-master ~]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginx.test.com"
CN是主题的意思
[root@k8s-master ~]# ls
canary-v2.yaml ingress-ssl.yaml redirect.yaml tls.key
images ingress-with-auth.yaml rewirte.yaml v1-ingress.yaml
ingress-nginx init-config.yaml tls.crt web-ingress.yaml
2、创建secret,保存证书和密钥文件,让其他节点使用
secret类型为tls 名称为ca-secret --cert指定证书文件 key指定密钥文件 -n 指定命名空间
[root@k8s-master ~]# ku create secret tls ca-secret --cert=tls.crt --key=tls.key -n study-ingress
secret/ca-secret created
3、编写ingress配置文件
[root@k8s-master ~]# vim ingress-ssl.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
creationTimestamp: null # 不创建时间戳
name: nginx-ingress-ssl
spec:
ingressClassName: nginx-ssl # ingress使用的底层代理工具
rules:
- host: nginx.test.com
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: ImplementationSpecific
tls:
- hosts:
- nginx.test.com # 访问这个站点时,会使用ssl加密。
secretName: ca-secret # 使用证书资源
4、创建
[root@k8s-master ~]# ku create -f ingress-ssl.yaml
ingress.networking.k8s.io/nginx-ingress-ssl created
5、访问
https://nginx.test.com
会报不安全(因为没有客户端证书),高级-继续访问。
-- 身份认证 --
1、安装认证工具
[root@k8s-master ~]# dnf -y install httpd-tools
2、创建认证用户
[root@k8s-master ~]# htpasswd -c auth zhangsan 用户1
New password:
Re-type new password:
Adding password for user zhangsan
(密码123)
[root@k8s-master ~]# ls
auth ingress-ssl.yaml rewirte.yaml web-ingress.yaml
canary-v2.yaml ingress-with-auth.yaml tls.crt
images init-config.yaml tls.key
ingress-nginx redirect.yaml v1-ingress.yaml
[root@k8s-master ~]# cat auth
zhangsan:$apr1$2Fsge40s$T.EB32D2JDKRjCkWtiGD3.
[root@k8s-master ~]# htpasswd auth lisi 用户2
New password:
Re-type new password:
Adding password for user lisi
(密码1234)
[root@k8s-master ~]# cat auth
zhangsan:$apr1$2Fsge40s$T.EB32D2JDKRjCkWtiGD3.
lisi:$apr1$4HA.9LOk$6TGzc4giF40L8yhUMfR2p/
3、创建secret,存储用户信息
generic是通用的,basic-auth是secret名称 -n指定命名空间
[root@k8s-master ~]# ku create secret generic basic-auth --from-file=auth -n study-ingress
secret/basic-auth created
[root@k8s-master ~]# rm -rf auth
4、编写ingress配置文件
[root@k8s-master ~]# vim ingress-with-auth.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-realm: Please Input Your Username and Password
nginx.ingress.kubernetes.io/auth-secret: basic-auth # secret名称
nginx.ingress.kubernetes.io/auth-type: basic # 认证类型
name: ingress-with-auth
namespace: study-ingress
spec:
ingressClassName: nginx
rules:
- host: auth.test.com
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: ImplementationSpecific
5、创建
[root@k8s-master ~]# ku create -f ingress-with-auth.yaml
ingress.networking.k8s.io/ingress-with-auth created
6、访问
客户端编写hosts文件
访问auth.test.com
输入zhangsan 密码123 可查看到网站内容。
清除缓存
再次访问,输入lisi 密码1234 可查看到网站内容。