ingress翻译过来是入口的意思,k8s希望ingress是整个集群流量的入口,引入ingress后整个请求如下图所示
为什么需要Ingress资源
由于K8S集群拥有强大的副本控制能力,Pod随时可能从一个节点上被驱逐到另一个节点上,或者直接销毁再来一个新的。
然而伴随着Pod的销毁和重生,Pod的IP等信息不断地在改变,此时使用K8S提供的Service机制可以解决这一问题,Service通过标签选定指定的Pod作为后端服务,并监听这些Pod的变化。
在对外暴露服务时,使用Service的NodePort是一个方法,但还会有以下几个问题
问题1 - 如何管理端口
当需要对外暴露的服务量比较多的时候,端口管理的问题便会暴露出来。并且service只支持4层代理,也就是只能根据ip+端口
此时的一个处理方案是使用一个代理服务(例如Nginx)根据请求信息将请求转发到不同的服务上去。
问题2 - 如何管理转发配置
每当有新服务加入,都需要对该服务的配置进行修改、升级,在服务数量逐渐变多后,该配置项目会变得越来越大,手工修改的风险也会逐渐增高。
那么需要一个工具来简化这一过程,希望可以通过简单的配置动态生成代理中复杂的配置,最好还可以顺手重新加载配置文件。
K8S刚好也提供了此类型资源。
安装ingress
默认k8s是不带ingress的,需要我们单独安装
下载安装文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml
执行安装操作
kubectl apply -f deploy.yaml
查看安装的结果
kubectl get pod,svc -n ingress-nginx
因为ingress要接所有的请求流量,安装完还会产生一个NodePort类型的service,http(32083)、https(32099)
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-admission-create-xjcds 0/1 Completed 0 45s
pod/ingress-nginx-admission-patch-n929x 0/1 Completed 0 45s
pod/ingress-nginx-controller-65bf56f7fc-zf7t5 0/1 Running 0 45s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller NodePort 10.1.221.227 <none> 80:32083/TCP,443:32099/TCP 45s
service/ingress-nginx-controller-admission ClusterIP 10.1.157.154 <none> 443/TCP 45s
尝试访问下32083端口
因为是NodePort,所以你可以访问你k8s集群内任意一台服务的端口
域名访问
首先我们准备一段yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-server
spec:
replicas: 2
selector:
matchLabels:
app: hello-server
template:
metadata:
labels:
app: hello-server
spec:
containers:
- name: hello-server
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-server
ports:
- containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-demo
name: nginx-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-demo
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- image: nginx
name: nginx
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-demo
name: nginx-demo
spec:
selector:
app: nginx-demo
ports:
- port: 8000
protocol: TCP
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
labels:
app: hello-server
name: hello-server
spec:
selector:
app: hello-server
ports:
- port: 8000
protocol: TCP
targetPort: 9000
配置一个ingress,当我使用hello.com交给hello-server处理,使用demo.com交给nginx处理
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-host-bar
spec:
ingressClassName: nginx
rules:
- host: "hello.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-server
port:
number: 8000
- host: "demo.com"
http:
paths:
- pathType: Prefix
path: "/nginx" # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
backend:
service:
name: nginx-demo ## java,比如使用路径重写,去掉前缀nginx
port:
number: 8000
执行上面文件
kubectl apply -f ing-rule.yaml
查看是否成功
[root@k8s-master opt]# kubectl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-host-bar nginx hello.com,demo.com 172.16.55.77 80 38s
可以看到这边匹配到了hello.com,demo.com两个域名
现在修改下我本地的host来解析这两个域名
101.37.160.113 hello.com
101.37.160.113 demo.com
这时候我们访问是需要带上之前的端口的
service/ingress-nginx-controller NodePort 10.1.221.227 <none> 80:32083/TCP,443:32099/TCP 45s
也就是可以使用hello.com32083 或者 hello.com:32099,另一个域名也是
路径重写
配置如下
在metadata里面加入了annotations(注解)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: ingress-host-bar
spec:
ingressClassName: nginx
rules:
- host: "hello.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-server
port:
number: 8000
- host: "demo.com"
http:
paths:
- pathType: Prefix
path: "/nginx(/|$)(.*)" # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
backend:
service:
name: nginx-demo ## java,比如使用路径重写,去掉前缀nginx
port:
number: 8000
流量限制
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-limit-rate
annotations:
nginx.ingress.kubernetes.io/limit-rps: "1"
spec:
ingressClassName: nginx
rules:
- host: "haha.atguigu.com"
http:
paths:
- pathType: Exact
path: "/"
backend:
service:
name: nginx-demo
port:
number: 8000