k8s中ingress-nginx介绍

1. 介绍

Ingress是一种Kubernetes资源,用于将外部流量路由到Kubernetes集群内的服务。与NodePort相比,它提供了更高级别的路由功能和负载平衡,可以根据HTTP请求的路径、主机名、HTTP方法等来路由流量。可以说Ingress是为了弥补NodePort在流量路由方面的不足而生的。使用NodePort,只能将流量路由到一个具体的Service,并且必须使用Service的端口号来访问该服务。但是,使用Ingress,就可以使用自定义域名、路径和其他HTTP头来定义路由规则,以便将流量路由到不同的Service。

bash 复制代码
# 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为例)的工作原理如下:

  1. 用户编写Ingress规则,说明哪个域名对应kubernetes集群中的哪个Service
  2. Ingress控制器动态感知Ingress服务规则的变化,然后生成一段对应的Nginx反向代理配置
  3. Ingress控制器会将生成的Nginx配置写入到一个运行着的Nginx服务中,并动态更新
  4. 其实真正在工作的就是一个Nginx了,内部配置了用户定义的请求转发规则

3. 主流的Ingress Controller

在 Kubernetes 中,有很多不同的 Ingress 控制器可以选择,例如 Nginx、Traefik、HAProxy等。不同的控制器可能会提供不同的功能、性能和可靠性,可以根据实际需求来选择合适的控制器。Kubernetes生态系统中有许多不同的Ingress控制器可供选择,其中比较主流的有:

  1. Nginx Ingress Controller:基于Nginx的Ingress控制器,提供了广泛的功能和配置选项。
  2. Traefik Ingress Controller:Traefik是一个流行的反向代理和负载均衡器,Traefik Ingress Controller提供了灵活的配置选项和自动发现服务的功能。
  3. Istio Ingress Gateway:Istio是一种服务网格,它提供了基于Envoy代理的Ingress Gateway来管理入站和出站流量。
  4. Contour Ingress Controller:基于Envoy代理的Ingress控制器,具有高度可扩展性和灵活的路由规则。
  5. Kong Ingress Controller:Kong是一个API网关,提供了可扩展的路由和服务管理功能。
  6. Ambassador API Gateway:Ambassador是一个Kubernetes-native API Gateway,提供了自动化的服务发现和路由管理功能。

4. 控制器的部署方案

Ingress控制器通常建议部署在 Kubernetes 集群内部。这样可以确保 Ingress 控制器与 Kubernetes API Server 之间的网络延迟较低,并且可以通过 Kubernetes Service 来管理 Ingress 控制器的负载均衡和高可用性。在 Kubernetes 集群内部部署 Ingress 控制器通常有两种方式:

  1. 部署一个独立的 Ingress 控制器 Pod:可以通过将 Ingress 控制器部署为一个独立的 Pod,使用 Kubernetes Service 对其进行负载均衡和暴露服务。
  2. 部署一个 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 安装

bash 复制代码
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0/deploy/static/provider/cloud/deploy.yaml

6.2 查看pod

bash 复制代码
# kubectl get pod -n ingress-nginx

NAME                                        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

bash 复制代码
# 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 资源包含额外的配置,其中包括应当实现该类的控制器名称。

bash 复制代码
[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

bash 复制代码
        securityContext:
          allowPrivilegeEscalation: true  # 默认false
          capabilities:
            add:
            - NET_BIND_SERVICE
            drop:
            - ALL

7. 实验

7.1 准备service和pod

创建 app-nginx.yaml

bash 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: pro
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: pro
spec:
  selector:
    app: nginx-pod
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
bash 复制代码
# 创建
[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

bash 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-http
  namespace: pro
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.circle.vip
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port: 
              number: 80
bash 复制代码
# 创建
[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

bash 复制代码
[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/tls

Data
====
tls.crt:  1493 bytes
tls.key:  1708 bytes

2、创建ingress-https.yaml

bash 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-https
  namespace: pro
spec:
  ingressClassName: nginx
  tls:
    - hosts:
      - nginx.circle.vip
      secretName: circle-vip-secret # 指定秘钥
  rules:
  - host: nginx.circle.vip
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port: 
              number: 80
bash 复制代码
# 创建
[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常用参数

bash 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
     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(默认开启)

bash 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-example-ingress
  annotations:
    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。

相关推荐
终端行者7 小时前
k8s之Ingress服务接入控制器
云原生·容器·kubernetes
学Linux的语莫12 小时前
k8s的nodeport和ingress
网络·rpc·kubernetes
aashuii18 小时前
k8s通过NUMA亲和分配GPU和VF接口
云原生·容器·kubernetes
Most661 天前
kubesphere安装使用
kubernetes
Kentos(acoustic ver.)1 天前
云原生 —— K8s 容器编排系统
云原生·容器·kubernetes·云计算·k8s
哈里谢顿1 天前
Kubernetes 简介
kubernetes
__Smile°1 天前
k8s-MongoDB 副本集部署
云原生·容器·kubernetes
Jy_06221 天前
k8s 中的 deployment,statefulset,daemonset 控制器的区别
云原生·容器·kubernetes
果子⌂2 天前
Kubernetes 服务发布进阶
linux·运维·服务器·云原生·容器·kubernetes·云计算
Gold Steps.2 天前
K8s WebUI 选型:国外 Rancher vs 国内 KubeSphere vs 原生 Dashboard,从部署到使用心得谁更适合企业级场景?
云原生·容器·kubernetes