KubeSphere 網關的設計與實現(解讀)

語言: CN / TW / HK

作者:泓舟子,KubeSphere 後端研發工程師,雲原生愛好者,現專注於雲原生微服務方向。

KubeSphere 中為什麼需要網關?

如果需要將 K8s 集羣內的服務暴露到外部訪問有那些方式呢?可以通過將 Service 設置成 NodePort 方式暴露出去或者通過 Ingress 方式。另外使用 Ingress 方式可以實現將請求分發到一個或多個 Service,可以同一個 IP 地址下暴露多個服務等優勢。

但是對於 Ingress 方式而言,在 K8s 中只是內置了 Ingress CRD(可以創建 Ingress 資源),沒有內置 Ingress Controller,必須部署了 Ingress Controller 才能為 Ingress 資源提供外部訪問集羣內部服務的能力。而 KubeSphere 中的網關就是 Ingress Controller 。

網關的設計

KubeSphere v3.2 對網關進行了重構,在保留了原有網關功能的基礎上增加了以下幾點新功能:

  1. 啟用集羣和項目級別的網關:可以根據業務上的需求靈活選擇不同粒度的網關。
  2. 增減網關副本數:靈活調整副本數達到更高的可用性。
  3. 靈活配置 Ingress Controller 配置選項。
  4. 可指定網關應用負載安裝的位置:可選擇將網關應用負載安裝的位置指定某固定命名空間或分別讓其位於各自項目命名空間下。結合 KubeSphere 中的權限管理,若讓資源位於各個項目命名空間下,擁有該項目權限的用户也能查看到網關資源。
  5. 網關日誌:集中查詢網關日誌,將分佈在各個副本的網關日誌集中起來查詢。
  6. 網關監控指標:監控網關中的一些指標,包括請求總量/成功率/延遲 等指標。

網關的實現

目前 K8s 支持和維護 ​ ​AWS​ ​、 ​ ​GCE​ ​ 和 ​ ​Nginx​ ​ Ingress 控制器,KubeSphere 使用 ​ ​Ingress Nginx Controller​ ​ 作為默認的網關實現,沒有做任何代碼修改。

各個功能點的實現思路

  • 集羣和項目級別的網關:這個通過傳入參數覆蓋默認的 Helm Chart Values 來實現並在代碼邏輯裏控制,如果啟用了集羣網關就不能啟用項目網關了;若啟用了項目網關又啟用了集羣網關,那麼通過兩個網關入口都可以訪問,只是這樣會有兩個 Ingress Controller 同時 Watch 相同的 Ingress 對象。
  • 增減網關副本數&配置 Ingress Controller 配置選項:這個通過傳入參數覆蓋默認的 Helm Chart Values 來實現,實現過程用到的 Helm Operator 將在後面重點介紹。
  • 可指定網關應用負載安裝的位置:可選擇將網關應用負載安裝的位置指定某固定命名空間或分別讓其位於各自項目命名空間下。這個在代碼邏輯中控制,並做成了配置項,默認將所有資源安裝在 kubesphere-controls-system 下。
  • 網關日誌:使用到了 KubeSphere 中日誌組件,日誌組件會採集日誌數據然後存儲在 Elasticsearch 中,網關在查詢日誌過程就根據參數在 Elasticsearch 中查詢日誌。
  • 網關監控指標:使用到了 KubeSphere 中監控組件,KubeSphere 內部配置了 Prometheus 相關的參數採集 Ingress 相關指標,查詢監控信息過程就根據監控組件中的 API 查詢相關數據。

下面重點介紹設計實現過程抽象出的 CRD 和如何巧妙地用 Helm Operator 集成。

抽象出 Gateway CRD 做適配

在設計上抽象了一個 Gateway CRD 來適配不同的 Ingress Controller,Gateway CRD 中包含設置 Ingress Controller 所需的公共屬性。KubeSphere API 和 UI 只與 Gateway CRD 交互。

# Gateway sample
apiVersion: gateway.kubesphere.io/v1alpha1
kind: Gateway
metadata:
  name: kubesphere-router-proj1
  namespace: kubesphere-controls-system # all Gateway workload will be created in the kubesphere-controls-system namespace by default. However, it's configurable in kubesphere-config when calling KubeSphere API. 
spec:
  controller:
  # controlpanel replicas. For ingress Controler that has controlpanel and workers. *Reserved field. Changing on UI isn't supported yet. 
  replicas: 1
  # annotations of the controlpanel deployment. *Reserved field. Changing on UI isn't supported yet. 
  annotations: {}
  
  # Watching scope,
  # enabled =true, watching for the project only. The user needs to specify the watching namespace.
  # enabled =false, Global gateway, watching for all namespaces.
  scope:
    enabled: false
    namespace: ""  # defaults to .Release.Namespace

  # gateway configurations. only key-value pair supported currently.
  config:
    max-bucket: 1m

  # worker workload deployment configuration
  deployment:
    annotations: 
    "servicemesh.kubesphere.io/enabled": "false"
    replicas: 1

  # 
  service:
    # Cloud LoadBalancer configurations for service
    annotations: 
      "service.beta.kubernetes.io/qingcloud-load-balancer-eip-ids": "test-ip-id"
    # Service Type, only LoadBalancer and NodePort are supported
    type: LoadBalancer

集成 Nginx Ingress Controller

KubeSphere 使用 Nginx Ingress Controller 作為默認的網關實現。為了簡化部署步驟,我們集成了 ​ ​Helm-operator-plugins​ ​ 作為 ​ ​Helm Operator​ ​ 。

在 Helm Operator 中主要有以下關鍵點:

根據 watch.yaml 中配置的監聽指定 CRD 下的 CR 來創建或更新 Chart 資源。其中可以根據 CR spec 中的值覆蓋默認 Helm Chart 中的值,這是由 Helm Operator 中的機制決定的,​ ​詳見官方説明​ ​。

如下的含義是需要 Watch ​ ​gateway.kubesphere.io/v1alpha1​ ​ 的 Nginx CR,如果有變化就觸發 Reconcile ,根據 chart 中配置的地址創建或更新對應的資源。

- group: gateway.kubesphere.io
  version: v1alpha1
  kind: Nginx
  chart: /var/helm-charts/ingress-nginx

在 KubeSphere 中的使用:

watchs.yaml 中就做了如下配置:

- group: gateway.kubesphere.io
  version: v1alpha1
  kind: Nginx
  chart: /var/helm-charts/ingress-nginx
- group: gateway.kubesphere.io
  version: v1alpha1
  kind: Gateway
  chart: /var/helm-charts/gateway

其中對 chart 而言:

整體而言:

Helm Operator Watch 了 Gateway 和 Nginx 2 個 CRD 的資源,當前端發起創建或更新網關時是對 Gateway CR 發起創建或更新操作:

  1. 發起請求創建或更新 Gateway CR ;
  2. 根據 watchs.yaml 配置的 Gateway, Helm Operator 監聽到有 Gateway CR 資源變化,將創建或更新 Nginx CR ;
  3. 根據 watchs.yaml 配置的 Nginx,Helm Operator 監聽到 Nginx CR 資源變化後就根據 Nginx CR 中的 spec 中的值來覆蓋默認 Helm Chart 中的值來創建或更新 Nginx Ingress Contoller。

配置項的設計

為了方便更改網關的一些參數設計瞭如下配置項:

gateway:
  watchesPath: /var/helm-charts/watches.yaml
  repository: kubesphere/nginx-ingress-controller
  tag: v1.1.0
  namespace: kubesphere-controls-system
  • watchesPath:指定 Helm Operator Watch 的配置文件,如果需要禁用 Helm Operator 就可以刪掉這個配置項。
  • repository:指定 nginx-ingress-controller 的倉庫。
  • tag:指定 nginx-ingress-controller 的 tag。
  • namespace:指定網關應用負載安裝的位置位於指定的命名空間下,若刪掉這個配置項就會安裝在各個項目命名空間下。

使用過程注意事項

​nginx.ingress.kubernetes.io/upstream-vhost: [service-name].[service-namespace].svc.cluster.local​

參考:

  1. ​https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/​
  2. ​https://github.com/kubesphere/community/blob/master/sig-microservice/concepts-and-designs/KubeSphere-gateway-operator-design.md​
  3. ​https://github.com/kubesphere/kubesphere​
  4. ​https://sdk.operatorframework.io/docs/building-operators/helm/​