为什么需要 Ingress:
Ingress 也是为了解决在集群之外访问集群内部的Service服务的问题。
实际上,将service的type设置为nodePort或LoadBalancer,也能实现将集群内部的服务暴露给外部访问。那Ingress是不是多余的呢?肯定不是。
先回顾下,LoadBalancer类型的Service访问流程,如下:
.————————————————————————————————————————————————
| 集群内部 .-------> Pod |
| / |
集群外部(用户) ----> LoadBalancer -----+--> node_ip:nodePort ----> Service |
| |
| '-------> Pod |
| |
'————————————————————————————————————————————————
LoadBalancer 类型的 Service 一般应用于云平台环境中,这个LoadBalancer是由云厂商提供的,位于k8s集群外部,当用户在云平台上创建一个该类型的Service时,同时会为该 Service 创建一个对应的负载均衡器,也就是说,每个 Service 都要有一个负载均衡器,这种做法实际上是成本比较高。
同样,Ingress除了能将集群内部的服务暴露给外界访问,它也是一个负载均衡器,而且专门是为集群内部的Service提供负载均衡服务。
Ingress 与 LoadBalancer 类型的 Service 有点类似,但区别在于,Ingress是一个k8s集群内部的全局的负载均衡器,作为k8s集群中的一个对象资源而存在,而LoadBalancer类型则是一个集群外部的负载均衡服务器。
Ingress 工作原理:
Ingress,是K8s的一个资源对象,定义了一系列路由转发规则(或反向代理规则),它规定了外部进来的HTTP/HTTPS请求应该被转发到哪个Service上。
简单的说,Ingress就是一段nginx服务的反向代理配置,它能根据请求中不同的Host和URL路径,将请求转发到不同的Service的Pod上。
Ingress Controller相当于是一个反向代理程序,负责解析Ingress的反向代理规则,并实时感知Ingress路由规则的变化。一旦Ingress有增删改的变动,Ingress Controller会及时更新自己相应的转发规则,当Ingress Controller收到请求后,就会根据这些规则将请求转发到对应的Service。
具体点说,Ingress Controller是通过API Server获取Ingress资源的变化,并动态地生成Load Balancer(如Nginx程序)所需的配置文件(如nginx.conf),然后重新加载Load Balancer(如执行nginx -s load重新加载Nginx。)来生成新的路由转发规则。
Ingress与手动部署反向代理服务器的思路是一样的。如果反向代理服务器使用的是Nginx程序,Ingress Controller 会将 Ingress 规则变化生成一段Nginx的配置,然后将这个配置写到Ingress Controller管理下的Nginx Pod中,然后reload。
二、Nginx Ingress部署与使用 Ingress 部署:Ingress组件需要提前部署到k8s集群中,它包括 Ingress Service 与 Ingress Controller,以及Ingress Controller管理下的两个Nginx Pod。反向代理服务器有Nginx、Apache、traefik等,这里选择用Nginx。
官网部署手册:https://github.com/kubernetes/ingress-nginx/blob/main/docs/deploy/index.md
当部署好后,查看环境信息。若成功部署,则环境中能看到有一个Ingress Service、Ingress Controller、Nginx Pod,如下:
# 查看Ingress Service(该Service用的是LoadBalancer方式对外暴露服务,也可以用nodePort方式) $ kubectl -n kube-system get svc nginx-ingress-lb NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-ingress-lb LoadBalancer 172.17.216.4 10.82.33.4 80:31366/TCP,443:30489/TCP 487d $ kubectl -n kube-system describe svc nginx-ingress-lb Name: nginx-ingress-lb Namespace: kube-system Labels: app=nginx-ingress-lb Annotations: ..... Selector: app=ingress-nginx Type: LoadBalancer IP: 172.17.216.4 LoadBalancer Ingress: 10.82.33.4 Port: http 80/TCP TargetPort: 80/TCP NodePort: http 31366/TCP Endpoints: 172.16.1.130:80,172.16.1.131:80 Port: https 443/TCP TargetPort: 443/TCP NodePort: https 30489/TCP Endpoints: 172.16.1.130:443,172.16.1.131:443 Session Affinity: None External Traffic Policy: Local HealthCheck NodePort: 30135 Events:Ingress 使用:# 查看Ingress控制器 $ kubectl -n kube-system get deploy nginx-ingress-controller NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-ingress-controller 2 2 2 2 487d # 查看Ingress控制器下的两个Nginx Pod $ kubectl -n kube-system get pods -owide -l app=ingress-nginx NAME READY STATUS RESTARTS AGE IP NODE nginx-ingress-controller-787644849b-nmsbm 1/1 Running 0 487d 172.16.1.130 node1 nginx-ingress-controller-787644849b-tn7bq 1/1 Running 0 487d 172.16.1.131 node1
Ingress能将来自于不同域名的请求转发到不同的Service上,也可以将同一个域名下的请求,根据不同URI接口转发到不同的Service上。
Ingress对象字段说明:
spec:
backend: 全局默认后端。若不匹配任何规则的请求,都会代理到默认后端
serviceName: service的名称。要将请求代理到哪个Service上
servicePort: service的端口
rules: 定义入站流量的转发规则
host: 第一条规则,检查入站流量是否匹配此处定义的域名
http:
paths:
path: 第二条规则,检查入站流量的URI路径,是否匹配此处定义的path(省略即为"/")
backend: 自定义后端。所有入站流量都会先匹配host与path规则,当两个都匹配时,才会将流量代理到下面定义的service上,否则会发送到默认backend
serviceName:
servicePort:
tls: 配置HTTPS
示例1:根据不同域名转发到不同的service上
第一步,先创建两个service,分别是my-service-1和my-service-2。
my-service-1:
apiVersion: v1
kind: Service
metadata:
name: my-service-1
namespace: default
spec:
selector:
app: my-nginx-web1
ports:
- name: nginx
port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: my-nginx-web1
template:
metadata:
labels:
app: my-nginx-web1
spec:
containers:
- name: nginx-web1
image: nginx:1.7.9
ports:
- name: http
containerPort: 80
my-service-2:
apiVersion: v1
kind: Service
metadata:
name: my-service-2
namespace: default
spec:
selector:
app: my-nginx-web2
ports:
- name: nginx
port: 8080
targetPort: 80
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-deploy-2
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: my-nginx-web2
template:
metadata:
labels:
app: my-nginx-web2
spec:
containers:
- name: nginx-web2
image: nginx:1.7.9
ports:
- name: http
containerPort: 80
第二步,创建一个Ingress规则,根据不同域名转发到不同的service上
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-demo-0915
namespace: default
spec:
rules:
- host: my.test.com #将来自于my.test.com域名的请求代理到my-service-1上
http:
paths:
- backend:
serviceName: my-service-1
servicePort: 80
- host: a.test.com #将来自于a.test.com域名的请求代理到my-service-2上
http:
paths:
- backend:
serviceName: my-service-2
servicePort: 8080
第三步,查看service与pod信息
#查看两个service $ kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR my-service-1 ClusterIP 172.17.171.280/TCP 35m app=my-nginx-web1 my-service-2 ClusterIP 172.17.101.107 8080/TCP 59m app=my-nginx-web2 $ kubectl describe svc my-service-1 Name: my-service-1 Namespace: default Labels: Annotations: ... Selector: app=my-nginx-web1 Type: ClusterIP IP: 172.17.171.2 Port: nginx 8080/TCP TargetPort: 80/TCP Endpoints: 172.16.1.150:80,172.16.2.156:80 Session Affinity: None Events: $ kubectl describe svc my-service-2 Name: my-service-2 Namespace: default Labels: Annotations: ... Selector: app=my-nginx-web2 Type: ClusterIP IP: 172.17.101.107 Port: nginx 8080/TCP TargetPort: 80/TCP Endpoints: 172.16.1.151:80 Session Affinity: None Events: #查看service的Pod $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE my-nginx-deploy-6fb9f56545-8k4mk 1/1 Running 0 87s 172.16.2.156 node1 my-nginx-deploy-6fb9f56545-c7gcx 1/1 Running 0 87s 172.16.1.150 node2 my-nginx-deploy-2-7f47d46589-mnpbl 1/1 Running 0 67m 172.16.1.151 node2
查看Ingress信息:
# 查看ingress $ kubectl get ingress ingress-demo-0915 NAME HOSTS ADDRESS PORTS AGE ingress-demo-0915 my.test.com,a.test.com 10.82.33.4 80 3h14m $ kubectl describe ingress ingress-demo-0915 Name: ingress-demo-0915 Namespace: default Address: 10.82.33.4 Default backend: default-http-backend:80 () Rules: Host Path Backends ---- ---- -------- my.test.com my-service-1:80 ( ) a.test.com my-service-2:8080 ( ) Annotations: nginx.ingress.kubernetes.io/service-weight: my-service-1: 100, my-service-2: 100 .... Events:
第四步,访问测试
$ curl a.test.com $ curl my.test.com



