APISIX Ingress 如何支援自定義外掛

Apache_APISIX發表於2022-12-16

摘要:本篇主要介紹了 Ingress 資源相關的語義,以及如何對 Ingress 資源進行能力的擴充套件。

作者:張晉濤,API7.ai 雲原生技術專家,Apache APISIX PMC 成員,Apache APISIX Ingress Controller 專案維護者。

Ingress 和 Ingress controller

Kubernetes 中的 Ingress 是一種資源物件,用於定義如何從 Kubernetes 叢集外訪問到 Kubernetes 叢集內的服務,其中包含了具體的訪問規則,通常情況下客戶端使用 HTTP/HTTPS 協議進行訪問。

客戶端可按照 Ingress 資源定義的規則,將客戶端請求路由到 Kubernetes 叢集中的服務或具體的 Pod中。

3df3234c-7ae7-48de-8dbb-0449226e4f2e.png

以下是一個 Ingress 資源的示例:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: apisix-gateway
spec:
  rules:
  - host: apisix.apache.org
    http:
      paths:
      - backend:
          service:
            name: apisix-gateway
            port:
              number: 80
        path: /
        pathType: Exact

上述示例中包含了以下內容:

  • metadata.name:Ingress 資源的名稱
  • spec.rules[].host:外部訪問使用的域名
  • spec.rules[].http.paths[].backend:定義了 Kubernetes 叢集中服務的相關資訊
  • spec.rules[].http.paths[].path:定義了外部服務訪問 Kubernetes 叢集中服務時使用的路徑
  • spec.rules[].http.paths[].pathType:定義了外部服務訪問 Kubernetes 叢集中服務時路徑的匹配規則
    從上述內容可以看到,Ingress 資源的語義是相對比較簡單的。

Ingress 僅僅是 Kubernetes 中的一種資源定義,它本身不具備任何流量處理能力。要讓 Ingress 資源生效,則必須要有 controller 來處理這些 Ingress 資源,通常這樣的 controller 我們稱之為 Ingress controller。

Ingress controller 會持續地監控或監聽 Kubernetes 叢集中 Ingress 資源的變化,並根據 Ingress 資源中定義的規則,轉換為其資料面中的代理規則,並由資料面來實際的承載流量。

在實際的生產環境中,客戶端訪問的需求是多種多樣的。比如最常見的認證、路由重寫等能力,透過 Ingress 資源是無法直接進行描述的。那麼這些需求要如何滿足呢?

Ingress-NGINX 如何支援擴充套件功能

首先我以 Kubernetes 社群的 Ingress-NGINX controller 為例,介紹如何在其中使用擴充套件功能。

在 Ingress-NGINX 專案中,可以為 Ingress 資源增加一些 Annotation 來描述其需要使用的擴充套件能力。比如使用如下配置便可開啟 cors 能力。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: https://foo.com,https://bar.com
    nginx.ingress.kubernetes.io/cors-allow-headers: x-foo-1,x-foo-2
    nginx.ingress.kubernetes.io/cors-allow-methods: GET,POST,PUT
  name: nginx-ingress
spec:
  rules:
  - host: kubernetes.github.io
    http:
      paths:
      - path: /ingress
        pathType: Exact
        backend:
          service:
            name: nginx
            port:
              number: 80

這種方式僅僅需要為 Ingress 資源新增 Annotations 的配置即可,相對簡單。但需要注意,使用這種模式需要 Ingress-NGINX controller 已經完成了對該 Annotations 的完整支援,否則該配置是無效的。

如果需要其他的一些 Ingress-NGINX controller 尚未實現的能力,則需要對其進行二次開發。

在 APISIX Ingress 中使用外掛

相較於 Ingress-NGINX controller,APISIX Ingress 使用 APISIX 作為資料面,APISIX 是一個高效能的全動態 API 閘道器。所有的配置變更都是動態進行的,無需重啟,所以對業務流量不會造成任何影響。

在 Apache APISIX Ingress 中可以透過使用外掛,來滿足使用者各種流量處理的需求和具體場景。當前有 80+ 外掛開箱即用,當然使用者也可以開發自定義外掛來進行能力的擴充套件。

output.png

目前,在 Apache APISIX 中支援多種方式進行自定義外掛的開發:

  • 使用 Lua 進行外掛的開發,這類外掛會在 APISIX 內部執行;
  • 使用其他語言進行外掛的開發,這種機制叫作 Plugin Runner,利用該機制開發的外掛屬於 external-plugin。
    關於 APISIX 外掛的開發,可參考官方文件:
  • 外掛開發 https://apisix.apache.org/docs/apisix/plugin-develop/
  • External Plugin 開發:https://apisix.apache.org/docs/apisix/external-plugin/
    瞭解了 APISIX 的外掛開發模式後,接下來將介紹 3 種在 APISIX Ingress 中使用 Lua 語言開發外掛的方式。

方式一:純 CRD 模式

APISIX Ingress controller 支援自己設計的一套 CRD 規範,你可以直接在路由規則中開啟外掛(無論是內建外掛還是自定義外掛),例如:

apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
 name: httpbin-route
spec:
 http:
 - name: rule1
   match:
     hosts:
     - apisix.apache.org
     paths:
       - /apisix-ingress
   backends:
   - serviceName: apisix-gateway
     servicePort: 80
   plugins:
   - name: cors
     enable: true
     config:
       allow_origins: http://foo.bar.org
       allow_methods: "GET,POST"
       max_age: 3600
       expose_headers: x-foo,x-baz
       allow_headers: x-from-ingress
       allow_credential: true

透過上述配置可以建立路由規則,並且在此路由中開啟 cors 外掛。

這是 APISIX Ingress 中最原生支援的方式,這種方式也與 APISIX 更加貼合。同時,使用者新增自定義外掛後,APISIX Ingress 也無需進行任何二次開發,可直接使用。

方式二:Ingress Annotations 模式

由於 Ingress 資源的語義有限,所以通常情況下我們可以透過 annotations 為資源物件擴充套件一些資訊,這也是最常見的對 Ingress 能力擴充套件的方式。例如:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: apisix
    k8s.apisix.apache.org/enable-cors: "true"
    k8s.apisix.apache.org/cors-allow-origin: https://foo.com,https://bar.com
    k8s.apisix.apache.org/cors-allow-headers: x-foo-1,x-foo-2
    k8s.apisix.apache.org/cors-allow-methods: GET,POST,PUT
  name: apisix-ingress
spec:
  rules:
  - host: apisix.apache.org
    http:
      paths:
      - path: /apisix-ingress
        pathType: Exact
        backend:
          service:
            name: apisix-gateway
            port:
              number: 80

上述配置在 Ingress 資源中增加了 cors 相關的一些資訊。APISIX Ingress controller 可以識別這些資訊,並將這些資訊轉換為資料面中 cors 的配置,進而完成對 Ingress 資源的擴充套件。

但是這種模式下,需要確保在 APISIX Ingress controller 中已經實現了對這些 Annotations 的處理邏輯,如果尚未實現,則需要進行一些二次開發。

如果需要進行二次開發,可參考《如何進行 APISIX Ingress controller 的開發》

方式三:CRD + Ingress Annotations 模式

除以上兩種方式外,在 APISIX Ingress 中也可以透過 CRD + Ingress Annotations 的方式進行擴充套件,例如:

apiVersion: apisix.apache.org/v2
kind: ApisixPluginConfig
metadata:
  name: cors-plugin
spec:
  plugins:
    - name: cors
      enable: true
      config:
        allow_origins: http://foo.bar.org
        allow_methods: "GET,POST"
        max_age: 3600
        expose_headers: x-foo,x-baz
        allow_headers: x-from-ingress
        allow_credential: true
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: apisix
    k8s.apisix.apache.org/plugin-config-name: cors-plugin
  name: apisix-ingress
spec:
  rules:
  - host: apisix.apache.org
    http:
      paths:
      - path: /apisix-ingress
        pathType: Exact
        backend:
          service:
            name: apisix-gateway
            port:
              number: 80

透過上方的這段配置,可以單獨建立名為 cors-plugin 的外掛配置,並透過 Ingress 資源的 k8s.apisix.apache.org/plugin-config-name: cors-plugin 對其進行引用。透過這種操作的實際效果與前兩個方式基本類似,都會在對應的路由上開啟 cors 外掛。

在這種模式下,使用者的外掛配置可以作為獨立資源,並且可以被多個 Ingress 資源共享。同時,也無需進行任何二次開發。

總結

本篇主要介紹了 Ingress 資源相關的語義,以及如何對 Ingress 資源進行能力的擴充套件。在 Ingress-NGINX 中可以透過 Annotations 的方式進行能力的擴充套件,但在 Apache APISIX Ingress 中可以透過三種模式進行配置。且其中兩種對於使用者自己開發的自定義外掛而言,是無需進行任何二次開發的,進而滿足使用者更多的場景和需求。

相關文章