k8s中ingress-nginx介绍
1. 介绍
Ingress是一种Kubernetes资源,用于将外部流量路由到Kubernetes集群内的服务。与NodePort相比,它提供了更高级别的路由功能和负载平衡,可以根据HTTP请求的路径、主机名、HTTP方法等来路由流量。可以说Ingress是为了弥补NodePort在流量路由方面的不足而生的。使用NodePort,只能将流量路由到一个具体的Service,并且必须使用Service的端口号来访问该服务。但是,使用Ingress,就可以使用自定义域名、路径和其他HTTP头来定义路由规则,以便将流量路由到不同的Service。
# kubectl api-resources | grep ingress
ingressclasses networking.k8s.io/v1 false IngressClass
ingresses ing networking.k8s.io/v1 true Ingress
Ingress还可以与负载均衡器配合使用,以提供高可用性和水平扩展。这些功能使得Ingress比NodePort更适合在生产环境中使用。
工作机制大致如下图表示:
2. Ingress和Ingress Controller
Ingress 是 Kubernetes 中的一个抽象资源,它提供了一种定义应用暴露入口的方法,可以帮助管理员在 Kubernetes 集群中管理多个服务的访问入口,方便用户访问。Ingress资源对象只是一个规范化的API对象,用于定义流量路由规则和 TLS 设置等信息。它本身不会直接处理或转发流量,而是需要配合一个 Ingress 控制器来实现。
Ingress Controller控制器是一个独立的组件,它会监听 Kubernetes API 中的 Ingress 资源变化,并根据定义的路由规则配置负载均衡器、反向代理或其他网络代理,从而实现外部流量的转发。因此,可以将 Ingress 控制器视为 Ingress 资源的实际执行者。
实际上,Ingress相当于一个7层的负载均衡器,是kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx,可以理解成在Ingress里建立诸多映射规则,Ingress Controller通过监听这些配置规则并转化成Nginx的反向代理配置 , 然后对外部提供服务。在这里有两个概念:
- ingress:kubernetes中的一个对象,作用是定义请求如何转发到service的规则
- ingress controller:具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发,实现方式有很多,比如Nginx, Contour, Haproxy等等
Ingress(以Nginx为例)的工作原理如下:
- 用户编写Ingress规则,说明哪个域名对应kubernetes集群中的哪个Service
- Ingress控制器动态感知Ingress服务规则的变化,然后生成一段对应的Nginx反向代理配置
- Ingress控制器会将生成的Nginx配置写入到一个运行着的Nginx服务中,并动态更新
- 其实真正在工作的就是一个Nginx了,内部配置了用户定义的请求转发规则
3. 主流的Ingress Controller
在 Kubernetes 中,有很多不同的 Ingress 控制器可以选择,例如 Nginx、Traefik、HAProxy等。不同的控制器可能会提供不同的功能、性能和可靠性,可以根据实际需求来选择合适的控制器。Kubernetes生态系统中有许多不同的Ingress控制器可供选择,其中比较主流的有:
- Nginx Ingress Controller:基于Nginx的Ingress控制器,提供了广泛的功能和配置选项。
- Traefik Ingress Controller:Traefik是一个流行的反向代理和负载均衡器,Traefik Ingress Controller提供了灵活的配置选项和自动发现服务的功能。
- Istio Ingress Gateway:Istio是一种服务网格,它提供了基于Envoy代理的Ingress Gateway来管理入站和出站流量。
- Contour Ingress Controller:基于Envoy代理的Ingress控制器,具有高度可扩展性和灵活的路由规则。
- Kong Ingress Controller:Kong是一个API网关,提供了可扩展的路由和服务管理功能。
- Ambassador API Gateway:Ambassador是一个Kubernetes-native API Gateway,提供了自动化的服务发现和路由管理功能。
4. 控制器的部署方案
Ingress控制器通常建议部署在 Kubernetes 集群内部。这样可以确保 Ingress 控制器与 Kubernetes API Server 之间的网络延迟较低,并且可以通过 Kubernetes Service 来管理 Ingress 控制器的负载均衡和高可用性。在 Kubernetes 集群内部部署 Ingress 控制器通常有两种方式:
- 部署一个独立的 Ingress 控制器 Pod:可以通过将 Ingress 控制器部署为一个独立的 Pod,使用 Kubernetes Service 对其进行负载均衡和暴露服务。
- 部署一个 DaemonSet 类型的 Ingress 控制器:可以通过部署一个 DaemonSet 类型的 Ingress 控制器,使每个节点上都运行一个 Ingress 控制器 Pod,并通过 Kubernetes Service 对其进行负载均衡和暴露服务。
5. 版本兼容性
https://github.com/kubernetes/ingress-nginx
6. 安装部署
giuhub 地址:https://github.com/kubernetes/ingress-nginx
官网:https://kubernetes.github.io/
6.1 安装
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0/deploy/static/provider/cloud/deploy.yaml
6.2 查看pod
# kubectl get pod -n ingress-nginxNAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-pcm78 0/1 Completed 0 166m
ingress-nginx-admission-patch-m45zs 0/1 Completed 1 166m
ingress-nginx-controller-7cd76cdb86-hhtdq 1/1 Running 0 166m
- ingress-nginx-controller是Ingress-nginx的控制器组件,它负责监视Kubernetes API server上的Ingress对象,并根据配置动态地更新Nginx配置文件,实现HTTP(S)的负载均衡和路由。
- ingress-nginx-admission-create和ingress-nginx-admission-patch都是Kubernetes Admission Controller,它们不是一直处于运行状态的容器,而是根据需要动态地生成和销毁。这些Admission Controller在Kubernetes中以Deployment的方式进行部署,因此,它们的Pod将根据副本数创建多个副本,并根据负载和需要动态地生成和销毁。
- ingress-nginx-admission-create是一个Kubernetes Admission Controller,它可以拦截Kubernetes集群内的Ingress对象的创建操作,并在Ingress对象创建之前,对其进行一些额外的验证和处理。
- ingress-nginx-admission-patch也是一个Kubernetes Admission Controller,它可以在Ingress对象更新之前,对其进行额外的验证和处理,类似于ingress-nginx-admission-create。
为什么nginx-admission-create和ingress-nginx-admission-patch这两个pod的状态是Completed
当这两个Pod被创建时,它将开始运行容器,执行必要的初始化和验证操作,然后尝试处理Kubernetes API server发送的请求。如果请求已经被处理完毕,容器将正常终止,并将Pod的状态设置为Completed。因此,Pod处于Completed状态并不表示有任何问题或错误,而是表示容器已经完成了它需要完成的任务并终止了运行。需要注意的是,如果在Pod终止之前出现错误或异常,Pod的状态将会被设置为Failed,这可能需要进行进一步的故障排除和修复。
6.3 查看service
# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.107.38.193 <none> 8800:30399/TCP,8843:32081/TCP 170m
ingress-nginx-controller-admission ClusterIP 10.96.213.87 <none> 443/TCP 170m
ingress-nginx-controller Service:这个Service负责将请求转发到ingress-nginx-controller Pods。它通常会将流量分发到ingress-nginx-controller的多个副本中,并确保副本集的负载平衡。这个Service可以被配置为使用NodePort、LoadBalancer或ClusterIP类型,根据需要进行暴露。
ingress-nginx-controller-admission Service:这个Service是用于 Kubernetes Admission Webhooks 的,允许在创建、更新或删除资源时,对其进行校验或修改。它提供了一个API Endpoint,用于与 Kubernetes API Server 进行通信,以便进行这些校验或修改。该Service也可以被配置为使用NodePort、LoadBalancer或ClusterIP类型,根据需要进行暴露。
通常情况下,ingress-nginx-controller和ingress-nginx-controller-admission都是在同一个Deployment中运行的,以确保它们始终具有相同的标签。这些标签允许其他Kubernetes对象(例如Ingress)可以识别哪些Pods是由ingress-nginx-controller和ingress-nginx-controller-admission负责的,并将请求路由到正确的Pods中。
6.4 查看ingressclasses
参考:Ingress | Kubernetes
Ingress 可以由不同的控制器实现,通常使用不同的配置。 每个 Ingress 应当指定一个类,也就是一个对 IngressClass 资源的引用。 IngressClass 资源包含额外的配置,其中包括应当实现该类的控制器名称。
[root@master ~]# kubectl get ingressclasses -A
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 5h45m
6.5 安装过程中遇到的问题
1、port 80 is already in use. Please check the flag --http-port
securityContext:allowPrivilegeEscalation: true # 默认falsecapabilities:add:- NET_BIND_SERVICEdrop:- ALL
7. 实验
7.1 准备service和pod
创建 app-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deploymentnamespace: pro
spec:replicas: 3selector:matchLabels:app: nginx-podtemplate:metadata:labels:app: nginx-podspec:containers:- name: nginximage: nginx:1.21ports:- containerPort: 80---apiVersion: v1
kind: Service
metadata:name: nginx-servicenamespace: pro
spec:selector:app: nginx-podtype: ClusterIPports:- port: 80targetPort: 80
# 创建
[root@master ~]# kubectl apply -f app-nginx.yaml
deployment.apps/nginx-deployment created
service/nginx-service created# 查看
[root@master ~]# kubectl get svc -n pro -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-service ClusterIP 10.102.150.45 <none> 80/TCP 72s app=nginx-pod
7.2 Http代理
创建ingress-http.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress-httpnamespace: pro
spec:ingressClassName: nginxrules:- host: nginx.circle.viphttp:paths:- path: /pathType: Prefixbackend:service:name: nginx-serviceport: number: 80
# 创建
[root@master ~]# kubectl apply -f ingress-http.yaml
ingress.networking.k8s.io/ingress-http created# 查看
[root@master ~]# kubectl get ingress ingress-http -n pro
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-http nginx nginx.circle.vip 10.102.48.190 80 132m# 查看详情
[root@master ~]# kubectl -n pro describe ingress ingress-http
Name: ingress-http
Labels: <none>
Namespace: pro
Address: 10.102.48.190
Ingress Class: nginx
Default backend: <default>
Rules:Host Path Backends---- ---- --------nginx.circle.vip / nginx-service:80 (10.244.196.159:80,10.244.196.161:80,10.244.219.90:80)Annotations: <none>
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Sync 51m (x2 over 52m) nginx-ingress-controller Scheduled for sync# 接下来,在本地电脑上配置host文件,解析上面的域名到192.168.100.10(master)上
# 然后,就可以分别访问 nginx.circle.vip:31196 查看效果了
7.3 Https代理
1、创建 tls 类型 secret
[root@master ~]# kubectl create secret tls circle-vip-secret --namespace=pro --cert=/root/circle.vip.cer --key=/root/circle.vip.key
secret/circle-vip-secret created[root@master ~]# kubectl get secrets -n pro
NAME TYPE DATA AGE
circle-vip-secret kubernetes.io/tls 2 47s[root@master ~]# kubectl describe secrets circle-vip-secret -n pro
Name: circle-vip-secret
Namespace: pro
Labels: <none>
Annotations: <none>Type: kubernetes.io/tlsData
====
tls.crt: 1493 bytes
tls.key: 1708 bytes
2、创建ingress-https.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress-httpsnamespace: pro
spec:ingressClassName: nginxtls:- hosts:- nginx.circle.vipsecretName: circle-vip-secret # 指定秘钥rules:- host: nginx.circle.viphttp:paths:- path: /pathType: Prefixbackend:service:name: nginx-serviceport: number: 80
# 创建
[root@master ~]# kubectl apply -f ingress-https.yaml
ingress.networking.k8s.io/ingress-https created# 查看
[root@master ~]# kubectl -n pro get ingress ingress-https
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-https nginx nginx.circle.vip 80, 443 24s# 查看详情
[root@master ~]# kubectl -n pro describe ingress ingress-https
Name: ingress-https
Labels: <none>
Namespace: pro
Address:
Ingress Class: nginx
Default backend: <default>
TLS:circle-vip-secret terminates nginx.circle.vip,tomcat.circle.vip
Rules:Host Path Backends---- ---- --------nginx.circle.vip / nginx-service:80 (10.244.196.159:80,10.244.196.161:80,10.244.219.90:80)
Annotations: <none>
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Sync 47s nginx-ingress-controller Scheduled for sync# 下面可以通过浏览器访问https://nginx.circle.vip:30763
8. Annotations对Ingress个性化配置
参考文档 :https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md
8.1 HTTP:配置Nginx常用参数
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: example-ingressannotations:kubernetes.io/ingress.class: "nginx“nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"nginx.ingress.kubernetes.io/proxy-send-timeout: "600"nginx.ingress.kubernetes.io/proxy-read-timeout: "600"nginx.ingress.kubernetes.io/proxy-body-size: "10m"
spec:
8.2 HTTPS:禁止访问HTTP强制跳转到HTTPS(默认开启)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: tls-example-ingressannotations:kubernetes.io/ingress.class: "nginx“nginx.ingress.kubernetes.io/ssl-redirect: 'false'
spec:
9. Ingress Controller高可用方案
如果域名只解析到一台Ingress controller,是存在单点的,挂了就不能提供服务了。这就需要具备高可用,有两种常见方案:
左边:双机热备,选择两台Node专门跑Ingress controller,然后通过keepalived对其做主备。用户通过VIP访问。
右边:高可用集群(推荐),前面加一个负载均衡器,转发请求到后端多台Ingress controller。