Kubernetes服務發現之Ingress

2020-08-14 01:04:38

通過Service可以實現存取Kubernetes叢集中的一組Pod及實現負載均衡 ,但Service中的負載均衡都是基於IP和埠的四層負載均衡。而要想實現七層負載均衡,則需要引入IngressIngress 是對叢集中服務的外部存取進行管理的API物件,典型的存取方式是HTTP。Ingress可以提供負載均衡、SSL和基於主機名的存取。

本文主要參考官方文件對Kubernetes的Ingress進行一個簡單總結。

一、環境資訊

本文所使用的環境如下:

  • 操作系統:CentOS Linux release 8.2.2004
  • Docker:19.03.12
  • kubernetes:v1.18.5

二、Ingress相關概念

1.相關術語

  • 節點(Node):Kubernetes叢集中其中一臺工作機器,是叢集的一部分。
  • 叢集(Cluster):一組執行由Kubernetes管理的容器化應用程式的節點。 在此範例和在大多數常見的Kubernetes部署環境中,叢集中的節點都不在公共網路中。
  • 邊緣路由器(Edge router):在叢集中強制執行防火牆策略的路由器(router)。可以是由雲提供商管理的閘道器,也可以是物理硬體。
  • 叢集網路(Cluster network):一組邏輯的或物理的連線,根據Kubernetes網路模型在叢集內實現通訊。
  • 服務(Service):Kubernetes服務是使用標籤選擇器(selector)標識的一組Pod。 除非另有說明,否則假定服務僅具有在叢集網路中可路由的虛擬IP。

2.什麼是Ingress

Ingress公開了從叢集外部到叢集內的HTTP和HTTPS路由。流量路由由Ingress資源上定義的規則控制。

    internet
        |
   [ Ingress ]
   --|-----|--
   [ Services ]

可以給Ingress設定爲服務提供外部可存取的URL、負載均衡流量、SSL/TLS以及提供基於名稱的虛擬主機等。Ingress控制器(Ingress Controller)通常負責通過負載均衡器來實現Ingress,儘管它也可以設定邊緣路由器或其他前端來幫助處理流量。Ingress不會公開任意埠或協定。將HTTP和HTTPS以外的服務公開到Internet時,通常使用Service.Type=NodePortService.Type=LoadBalancer型別的服務。

3.Ingress控制器

Ingress資源自身並不能進行「流量穿透」,它僅是一組路由規則的集合,這些規則要想真正發揮作用還需要其他功能的輔助,如監聽某通訊端,然後根據這些規則的匹配機制 機製路由請求流量。這種能夠爲Ingress資源監聽通訊端並轉發流量的元件稱爲Ingress控制器(Ingress Controller)。

爲了讓Ingress資源工作,叢集必須有一個正在執行的Ingress控制器。與作爲kube-controller-manager可執行檔案的一部分執行的其他型別的控制器不同,Ingress控制器不是隨叢集自動啓動的,需要在叢集上單獨部署。Kubernetes專案目前支援和維護GCE和nginx控制器。至於其他控制器可以參考Ingress控制器官方文件

可以在叢集中部署任意數量的ingress控制器,建立ingress時,應該使用適當的ingress.class註解每個Ingress以表明在叢集中如果有多個Ingress控制器時,應該使用哪個Ingress控制器。如果不定義ingress.class,雲提供商可能使用預設的Ingress控制器。

4.先決條件

必須具有Ingress控制器才能 纔能滿足Ingress的要求。僅建立Ingress資源本身沒有任何效果。使用Ingress可能需要部署一個例如ingress-nginx的Ingress控制器。至於使用哪個Ingress控制器,可以從許多Ingress控制器中進行選擇。理想情況下,所有Ingress控制器都應符合參考規範。但實際上,不同的Ingress控制器操作略有不同。

5.Ingress工作流程

如下圖所示,流量首先到達外部負載均衡器,這個負載均衡器是由我們自己部署的,然後轉發到Ingress控制器的Service上,然後再轉發到Ingress控制器的Pod上,通過Ingress控制器基於Ingress資源定義的規則將用戶端請求流量直接轉發至與Service對應的後端Pod上。這種轉發機制 機製會繞過Service,從而省去了由kube-proxy實現的埠代理開銷,Ingress規則需要由一個Service資源物件輔助識別相關的所有Pod資源。
1

三、部署Ingress控制器

Ingress控制器自身是執行於Pod中的容器應用,一般是例如Nginx這種具有代理及負載均衡功能的守護行程,它監視着來自API ServerIngress物件狀態,並根據規則生成相應的應用程式專有格式的組態檔並通過過載或重新啓動守護行程而使新設定生效。Ingress控制器其實就是託管於Kubernetes系統之上的用於實現在應用層發佈服務的Pod資源,跟蹤Ingress資源並實時生成設定規則。

1.部署方式

Ingress控制器可以通過兩種方式部署以接入外部請求流量。第一種方式是通過Deployment控制器管理Ingress控制器的Pod資源,通過NodePortLoadBalancer型別的Service物件爲其接入叢集外部的請求流量,所有這種方式在定義一個Ingress控制器時必須在其前端定義一個專用的Service資源。如下圖所示:
2
第二種方式是通過DaemonSet控制器確保叢集的所有或部分工作節點中每個節點上只執行Ingress控制器的一個Pod資源,並設定這類Pod物件以HostPortHostNetwork的方式在當前節點接入外部流量。如下圖所示:
3

2.部署Nginx Ingress控制器

進入用於存放k8s相關檔案的目錄,這裏是/usr/local/k8s/,建立一個用於ingress-nginx的目錄並進入:

cd /usr/local/k8s/
mkdir -p ingress-controller/ingress-nginx
cd ingress-controller/ingress-nginx/

下面 下麪就開始安裝ingress-nginx,可以參考ingress-nginx官方文件進行安裝,官方提供了多種平臺的安裝方式。由於這裏用的是自己使用kubeadm搭建的k8s環境,所以選擇Bare-metal的安裝組態檔進行安裝。下載v0.34.1版的ingress-nginx的設定清單檔案並建立ingress-nginx:

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/baremetal/deploy.yaml
kubectl apply -f deploy.yaml

4
ingress-nginx控制器的所有資源都在ingress-nginx名稱空間下,檢視ingress-nginx名稱空間中的Pod及ingress-nginx控制器的Pod的詳細資訊,這裏只擷取了部分資訊:
5
檢視ingress-nginx名稱空間中的Serviceingress-nginx-controller的詳細資訊:
6
可知建立了一個NodePort型別的Service,名爲ingress-nginx-controller,並隨機分配httpNodePort31681httpsNodePort的爲31620,對外暴露服務。

四、Ingress資源

一個最小的Ingress資源範例:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        pathType: Prefix
        backend:
          serviceName: test
          servicePort: 80

與所有其他Kubernetes資源一樣,Ingress也需要使用apiVersionkindmetadata欄位。Ingress提供了設定負載均衡器或者代理伺服器所需的所有資訊,其中包含與所有傳入請求匹配的規則列表。Ingress資源僅支援用於轉發HTTP流量的規則。

1.Ingress規則

IngressSpec下的rules用於設定Ingress的主機規則列表,如果未指定規則或未匹配到任何規則,則所有流量都會被轉發到預設後端。每個HTTP規則都包含以下資訊:

  • 可選主機(host):在此範例中,未指定主機,因此該規則適用於通過指定IP地址的所有入站HTTP通訊。如果提供了主機,例如 foo.bar.com,則規則適用於該主機。
  • 路徑列表(path):例如/testpath,每個路徑都有一個由serviceNameservicePort定義的關聯後端。在負載均衡器將流量定向到參照的服務之前,主機和路徑都必須匹配傳入的請求。
  • 後端(backend):是服務和伺服器端口的組合。與規則的主機和路徑匹配的對Ingress的HTTP(和HTTPS )請求將發送到列出的後端。

2.預設後端

沒有定義規則的Ingress將所有流量發送到同一個預設後端。預設後端通常是Ingress控制器的設定選項,並且未在Ingress資源中指定。如果主機或路徑都沒有與Ingress物件中的HTTP請求匹配,則流量將路由到預設後端。

3.路徑型別

Ingress中的每個路徑都有對應的路徑型別。當前支援以下三種路徑型別:

  • ImplementationSpecific (預設):對於這種型別,匹配取決於IngressClass。具體實現可以將其作爲單獨的pathType處理或者與PrefixExact型別作相同處理。
  • Exact:精確匹配URL路徑,且對大小寫敏感。
  • Prefix:基於以/分隔的URL路徑字首匹配。匹配對大小寫敏感,並且對路徑中的元素逐個完成。路徑元素指的是由/分隔符分隔的路徑中的標籤列表。

注意:

  • 如果路徑的最後一個元素是請求路徑中最後一個元素的子字串,則不會匹配 (例如:/foo/bar匹配/foo/bar/baz,但不匹配/foo/barbaz)。
  • 如果Ingress中的多條路徑匹配同一個請求。這種情況下最長的匹配路徑優先。 如果仍然有兩條同等的匹配路徑,則Exact路徑型別優先於Prefix路徑型別。

五、Ingress型別

1.單服務Ingress

Kubernetes允許暴露單個Service,本文使用ingress-nginx控制器暴露服務,示意圖如下:
7
先建立一個名爲ingress-test1的名稱空間,方便管理。建立namespace-ingress-test1.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-test1
  labels:
    env: ingress-test1

建立名稱空間ingress-test1

kubectl apply -f namespace-ingress-test1.yaml

檢視ingress-test1名稱空間:

kubectl get namespace ingress-test1

8
部署nginx範例,通過Deployment控制器在ingress-test1名稱空間中部署nginxPod,通過名爲mynginx-serviceservice資源的88埠暴露容器的80埠。先建立deploy-svc-test1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mynginx-deployment
  namespace: ingress-test1
  labels:
    app: MyNginx
    version: v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: MyNginx
      version: v1
  template:
    metadata:
      labels:
        app: MyNginx
        version: v1
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: mynginx-service
  namespace: ingress-test1
spec:
  type: ClusterIP
  selector:
    app: MyNginx
    version: v1
  ports:
    - name: http
      port: 88
      targetPort: 80

建立DeploymentService

kubectl apply -f deploy-svc-test1.yaml

檢視名稱空間ingress-test1中的DeploymentServicePod資訊:

kubectl get deployment -n ingress-test1
kubectl get pod -n ingress-test1 -o wide
kubectl get svc -n ingress-test1
kubectl describe svc mynginx-service -n ingress-test1

9
下面 下麪建立Ingress資源,匹配mynginx-service並將該Service88埠暴露,這個Ingress的規則將域名myapp.nginx.com的根目錄對映到mynginx-service。先建立single-svc-ingress.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: single-svc-ingress
  namespace: ingress-test1
spec:
  rules:
    - host: myapp.nginx.com
      http:
        paths:
          - path: /
            backend:
              serviceName: mynginx-service
              servicePort: 88

建立名爲single-svc-ingressIngress資源:

kubectl apply -f single-svc-ingress.yaml

檢視名稱空間ingress-test1中的Ingresssingle-svc-ingress詳細資訊:

kubectl get ingress -n ingress-test1
kubectl describe ingress single-svc-ingress -n ingress-test1

10
檢視ingress-nginx控制器Pod中生成的nginx組態檔:

kubectl exec ingress-nginx-controller- -n ingress-nginx -it -- /bin/sh
cat /etc/nginx/nginx.conf

這裏擷取了部分內容:
11
在本地和虛擬機器hosts檔案中新增域名解析列表,新增叢集任意一個節點IP與域名對應即可:

192.168.1.16 myapp.nginx.com
192.168.1.17 myapp.nginx.com
192.168.1.18 myapp.nginx.com

存取myapp.nginx.com:3168131681爲服務ingress-nginx-controller對外暴露的http存取的NodePort
12
13
驗證是否排程到後端的Pod資源,檢視日誌:
14

2.基於名稱的虛擬主機

基於名稱的虛擬主機支援將針對多個主機名的HTTP流量路由到同一IP地址上,即將不同的host名對映到不同的Service。如下圖所示:
15
先建立一個名爲ingress-test2的名稱空間,方便管理。建立namespace-ingress-test2.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-test2
  labels:
    env: ingress-test2

建立並檢視名稱空間ingress-test2
16
然後建立一組NginxTomcat範例,先建立資源清單檔案deploy-svc-test2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mynginx-deployment
  namespace: ingress-test2
  labels:
    app: MyNginx
    version: v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: MyNginx
      version: v1
  template:
    metadata:
      labels:
        app: MyNginx
        version: v1
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: mynginx-service
  namespace: ingress-test2
spec:
  type: ClusterIP
  selector:
    app: MyNginx
    version: v1
  ports:
    - name: http
      port: 88
      targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mytomcat-deployment
  namespace: ingress-test2
  labels:
    app: MyTomcat
    version: v1  
spec:
  replicas: 3
  selector:
    matchLabels:
      app: MyTomcat
      version: v1
  template:
    metadata:
      labels: 
        app: MyTomcat
        version: v1
    spec:
      containers:
      - name: tomcat
        image: tomcat:8.0.53
        imagePullPolicy: IfNotPresent
        ports:
        - name: http 
          containerPort: 8080
        - name: ajp
          containerPort: 8009
---
apiVersion: v1
kind: Service
metadata:
  name: mytomcat-service
  namespace: ingress-test2
spec:
  selector:
    app: MyTomcat
    version: v1    
  ports:
  - name: http
    port: 8080
    targetPort: 8080
  - name: ajp
    port: 8009
    targetPort: 8009

Tomcat映象用的較老的8.0.53版本,因爲較新版本的Tomcat沒有index頁面,爲了方便測試,選擇了低版本。建立資源清單中定義的資源物件並檢視:
17
18
建立Ingress資源,先建立name-virtual-host-ingress.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
  namespace: ingress-test2  
spec:
  rules:
  - host: mynginx.test.com
    http:
      paths:
      - path: /      
        backend:
          serviceName: mynginx-service
          servicePort: 88
  - host: mytomcat.test.com
    http:
      paths:
      - path: /      
        backend:
          serviceName: mytomcat-service
          servicePort: 8080

建立Ingress資源物件並檢視:
19
在本地和虛擬機器hosts檔案中新增域名解析列表,新增叢集任意一個節點IP與域名對應即可:

192.168.1.16 mynginx.test.com mytomcat.test.com
192.168.1.17 mynginx.test.com mytomcat.test.com
192.168.1.18 mynginx.test.com mytomcat.test.com

存取mynginx.test.com:31681
20
存取mytomcat.test.com:31681
21

3.簡單分列

根據請求的HTTP URI可以將流量從單個IP地址路由到多個服務。即根據請求URL的路徑將不同路徑的請求發送到不同的服務,用戶端可以通過一個Ingress控制器的IP地址存取到多個服務。如下圖所示:
22

注意:Ingresspath的要與後端Service提供的Path一致,否則將被轉發到一個不存在的path上,引起錯誤。

一個將不同的路徑發送到不同服務的Ingress資源如下:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: simple-fanout-ingress
  namespace: ingress-test2  
spec:
  rules:
  - host: myapp.test.com
    http:
      paths:
      - path: /nginx
        backend:
          serviceName: mynginx-service
          servicePort: 88
      - path: /tomcat
        backend:
          serviceName: mytomcat-service
          servicePort: 8080

4.TLS

可以通過設定包含TLS私鑰和證書的Secret來保護Ingress。目前,Ingress只支援單個TLS埠443。這裏使用openssl生成自簽名證書:

#生成mynginx.test.com域名的證書
openssl genrsa -out mynginx.test.com.key 4096
openssl req -x509 -new -key mynginx.test.com.key -days 3650 -out mynginx.test.com.crt -subj /C=CN/ST=ChongQing/L=ChongQing/O=RtxTitanV/CN=mynginx.test.com
#生成mytomcat.test.com域名的證書
openssl genrsa -out mytomcat.test.com.key 4096
openssl req -x509 -new -key mytomcat.test.com.key -days 3650 -out mytomcat.test.com.crt -subj /C=CN/ST=ChongQing/L=ChongQing/O=RtxTitanV/CN=mytomcat.test.com

建立Secret

#建立mynginx.test.com域名的secret
kubectl create secret tls mynginx-ingress-secret --cert=mynginx.test.com.crt --key=mynginx.test.com.key -n ingress-test2
#建立mytomcat.test.com域名的secret
kubectl create secret tls mytomcat-ingress-secret --cert=mytomcat.test.com.crt --key=mytomcat.test.com.key -n ingress-test2

檢視Secret

kubectl get secret -n ingress-test2

23
建立帶TLS的Ingress資源,先建立tls-ingress.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: tls-ingress
  namespace: ingress-test2  
spec:
  tls:
  - hosts:
    - mynginx.test.com
    secretName: mynginx-ingress-secret
  - hosts:
    - mytomcat.test.com
    secretName: mytomcat-ingress-secret    
  rules:
  - host: mynginx.test.com
    http:
      paths:
      - path: /      
        backend:
          serviceName: mynginx-service
          servicePort: 88
  - host: mytomcat.test.com
    http:
      paths:
      - path: /      
        backend:
          serviceName: mytomcat-service
          servicePort: 8080

建立ingress資源並檢視:
24
進行https存取測試,通過ingress-nginx控制器的前端的Service資源的對外暴露的NodePort來存取此服務,而ingress-nginx控制器的Service443埠對應的NodePort31620,下面 下麪存取https://mynginx.test.com:31620/
25
存取https://mytomcat.test.com:31620/
26
提示不安全是因爲證書是自簽名證書,不用管它。

六、Nginx Ingress進行BasicAuth和重寫

1.BasicAuth

首先安裝httpd:

yum install -y httpd

建立認證檔案auth,並根據auth檔案儲存到k8s的secret中:

htpasswd -c auth rtxtitanv
kubectl create secret generic basic-auth --from-file=auth -n ingress-test1

27
建立basicauth-ingress.yaml以新增需要認證的主機名:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: basicauth-ingress
  namespace: ingress-test1
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - rtxtitanv'  
spec:
  rules:
    - host: bashauth.nginx.com
      http:
        paths:
          - path: /
            backend:
              serviceName: mynginx-service
              servicePort: 88

建立ingress資源並檢視:
28
下面 下麪進行存取測試,先在hosts檔案新增域名解析,使bashauth.nginx.com對映到k8s任意節點IP,然後存取bashauth.nginx.com:31681,需要先輸入剛纔設定的使用者名稱和密碼:
29
30

2.重寫

Nginx重寫主要有以下幾種,都在annotations下宣告:

名稱 描述
nginx.ingress.kubernetes.io/rewrite-target 必須重定向流量的目標URL 字串
nginx.ingress.kubernetes.io/ssl-redirect 指示位置部分是否僅可存取SSL(當Ingress包含證書時預設爲True)布爾 布爾
nginx.ingress.kubernetes.io/force-ssl-redirect 即使lngress未啓用TLS,也強制重定向到HTTPS 布爾
nginx.ingress.kubernetes.io/app-root 定義Controller必須重定向的應用程式根,如果它在‘/’上下文中 字串
nginx.ingress.kubernetes.io/use-regex 指示lngress上定義的路徑是否使用正則表達式 布爾

建立Ingress資源,使存取re.mynginx.com的請求都將被重定向到myapp.nginx.com。先建立rewrite-ingress.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: rewrite-ingress
  namespace: ingress-test1
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: http://myapp.nginx.com:31681
spec:
  rules:
    - host: re.mynginx.com
      http:
        paths:
          - path: /
            backend:
              serviceName: mynginx-service
              servicePort: 88

建立ingress資源並檢視:
31
下面 下麪進行存取測試,先在hosts檔案新增域名解析,使re.mynginx.com對映到k8s任意節點IP,然後存取re.mynginx.com:31681,會跳轉到myapp.nginx.com:31681
32

七、更新Ingress

如果要更新現有的Ingress以新增新的Host,可以通過編輯Ingress資源來對其進行更新。先檢視名稱空間ingress-test1single-svc-ingress的詳細資訊:

kubectl describe ingress single-svc-ingress -n ingress-test1

33
在更新之前先在ingress-test1名稱空間中建立TomcatDeploymentService,建立過程參考上文,這裏就省略了。然後執行以下命令修改設定以更新Ingress

kubectl edit ingress single-svc-ingress -n ingress-test1

這一命令將開啓編輯器,如下修改設定來增加新的主機:

spec:
  rules:
  - host: myapp.nginx.com
    http:
      paths:
      - backend:
          serviceName: mynginx-service
          servicePort: 88
        path: /
        pathType: ImplementationSpecific
  - host: myapp.tomcat.com
    http:
      paths:
      - backend:      
          serviceName: mytomcat-service
          servicePort: 8080
        path: /  
        pathType: ImplementationSpecific

儲存更改後,kubectl 將更新API伺服器中的資源,該資源將告訴Ingress控制器重新設定負載均衡器。驗證:

kubectl describe ingress single-svc-ingress -n ingress-test1

34
single-svc-ingress的詳細資訊可知已經新增了一條Ingress規則。下面 下麪進行存取測試,先在hosts檔案新增域名解析,使myapp.tomcat.com對映到k8s任意節點IP,然後存取myapp.tomcat.com:31681,成功存取到Tomcat歡迎頁面,說明Ingress更新成功:
35

八、IngressClass

Ingress可以由不同的控制器實現,通常使用不同的設定。每個Ingress應當指定一個Class,也就是一個對IngressClass資源的參照。 IngressClass資源包含額外的設定,其中包括應當實現該類的控制器名稱。例如:

apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
  name: external-lb
spec:
  controller: example.com/ingress-controller
  parameters:
    apiGroup: k8s.example.com/v1alpha
    kind: IngressParameters
    name: external-lb

IngressClass資源包含一個可選的參數欄位parameters,可用於爲該Class參照額外設定。

1.棄用的Annotation

在Kubernetes 1.18版本引入IngressClass資源和ingressClassName欄位之前,IngressClass是通過Ingress中的一個kubernetes.io/ingress.class註解來指定的。這個註解從未被正式定義過,但是得到了Ingress控制器的廣泛支援。Ingress中新的 ingressClassName欄位用來替代該註解,但並非完全等價。該註解通常用於參照實現該Ingress的控制器的名稱,而這個新的欄位則是對一個包含額外Ingress設定的IngressClass資源的參照,包括Ingress控制器的名稱。

2.預設IngressClass

可以將一個特定的IngressClass標記爲叢集預設選項。將一個IngressClass資源的ingressclass.kubernetes.io/is-default-class註解設定爲true將確保新的未指定ingressClassName欄位的Ingress能夠分配爲這個預設的IngressClass。注意,如果叢集中有多個IngressClass被標記爲預設,則準入控制器將阻止建立新的未指定ingressClassName的Ingress物件。解決這個問題只需確保叢集中最多隻能有一個IngressClass被標記爲預設。