這篇文章已發布超過一年。較早的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

Gardener 專案更新

去年,我們在 Kubernetes 社群會議Kubernetes 部落格的一篇文章中介紹了 Gardener。在 SAP,我們已運行 Gardener 超過兩年,並成功地在所有主要超大規模供應商以及眾多基礎架構和私有雲上管理數千個各種版本的 符合規範的叢集,這些私有雲通常透過收購加入企業。

我們經常被問到,為什麼少數動態可擴展的叢集就足夠了。我們也以類似的心態開始了我們的 Kubernetes 之旅。但我們意識到,將 Kubernetes 的架構和原則應用於生產情境時,我們的內部和外部客戶很快就需要對關注點和所有權進行合理的劃分,這在大多數情況下導致了多個叢集的使用。因此,可擴展且受管理的 Kubernetes 即服務解決方案通常也是採用的基礎。特別是,當一個較大的組織在不同的供應商和不同的區域運行多個產品時,叢集的數量將很快增加到數百甚至數千個。

今天,我們想更新一下我們在過去一年中在可擴展性和可自訂性方面實作的功能,以及我們計劃在下一個里程碑中努力實現的功能。

簡短回顧:什麼是 Gardener?

Gardener 的主要原則是為其所有操作利用 Kubernetes 原語,通常被描述為初始或 kubeception。來自社群的回饋是,最初我們的 架構圖看起來「令人眼花撩亂」,但在稍微深入研究材料後,我們所做的一切都是「Kubernetes 方式」。人們可以重複使用所有關於 API、控制迴圈等的知識。
核心概念是,所謂的種子叢集用於託管終端使用者叢集(植物學上稱為幼苗)的控制平面。
Gardener 以同質的方式提供獨立於底層基礎架構供應商的原始 Kubernetes 叢集即服務,利用上游提供的 k8s.gcr.io/* 映像檔作為開放發布(更新:k8s.gcr.io 已被棄用,改用 registry.k8s.io)。 該專案完全建立在 Kubernetes 擴充概念之上,因此新增了一個自訂 API 伺服器、一個控制器管理器和一個排程器,以建立和管理 Kubernetes 叢集的生命週期。它使用自訂資源擴充了 Kubernetes API,最重要的是 Gardener 叢集規格 (Shoot 資源),可用於以宣告式的方式「訂購」Kubernetes 叢集(適用於第一天,但也協調第二天的所有管理活動)。

透過將 Kubernetes 作為基礎基礎架構,我們能夠設計一個結合的 水平和垂直 Pod 自動擴展器 (HVPA),當使用自訂啟發法進行配置時,可以自動向上/向下或向外/向內擴展所有控制平面組件。這使得快速向外擴展成為可能,甚至超出通常的一些固定數量的主要節點的容量。此架構特性是與許多其他 Kubernetes 叢集佈建工具相比的主要差異之一。但在我們的生產環境中,Gardener 不僅透過最佳化配置控制平面來有效降低總體擁有成本。它還簡化了「第二天操作」(如叢集更新或穩健性品質)的實作。再次強調,這主要是依賴所有成熟的 Kubernetes 功能和能力。

新引入的 Gardener 擴充概念現在使供應商只需維護其特定的擴充功能,而無需在核心原始碼樹中進行開發。

擴充性

由於 Kubernetes 在過去幾年中的成長,其程式碼庫包含了大量供應商特定的程式碼,這些程式碼現在正從其核心原始碼樹中外部化。Gardener 專案也發生了同樣的情況:隨著時間的推移,針對雲端供應商、作業系統、網路外掛程式等的許多特定細節已被累積。通常,這會導致在可維護性、可測試性或新版本發布方面的工作量顯著增加。我們的社群成員 Packet 為他們的基礎架構貢獻了 Gardener 支援,並深受上述缺點之苦。

因此,類似於 Kubernetes 社群決定將其雲端控制器管理器移出樹外,或將磁碟區外掛程式移至 CSI 等,Gardener 社群 提出並實作了類似的擴充概念。Gardener 核心原始碼樹現在沒有任何供應商特定的內容,這使得供應商可以專注於其基礎架構的細節,並使核心貢獻者再次變得更敏捷。

通常,設定叢集需要一系列相互依賴的步驟,從憑證產生和基礎架構準備開始,繼續到控制平面和工作節點的佈建,最後到系統組件的部署。我們想在此強調,所有這些步驟都是必要的(參見 Kubernetes 硬派之路),並且所有 Kubernetes 叢集建立工具都以某種方式實作了相同的步驟(在一定程度上自動化)。

Gardener 的擴充性概念的總體思路是使 此流程更通用,並為每個步驟劃出自訂資源,這些資源可以作為理想的擴充點。

Cluster reconciliation flow with extension points

圖 1 具有擴充點的叢集協調流程。

透過 Gardener 的流程框架,我們隱含地擁有適用於所有基礎架構和叢集所有可能狀態的可重現狀態機。

Gardener 擴充性方法定義了自訂資源,這些資源可作為以下類別的理想擴充點

  • DNS 供應商(例如,Route53、CloudDNS 等),
  • Blob 儲存供應商(例如,S3、GCS、ABS 等),
  • 基礎架構供應商(例如,AWS、GCP、Azure 等),
  • 作業系統(例如,CoreOS Container Linux、Ubuntu、FlatCar Linux 等),
  • 網路外掛程式(例如,Calico、Flannel、Cilium 等),
  • 非必要的擴充功能(例如,Let's Encrypt 憑證服務)。

擴充點

除了利用自訂資源定義之外,我們還有效地使用了種子叢集中的變更/驗證 Webhook。擴充控制器本身在這些叢集中執行,並對 CRD 和工作負載資源(如 DeploymentStatefulSet 等)做出反應,它們負責這些資源。類似於 Cluster API 的方法,這些 CRD 也可能包含供應商特定的資訊。

步驟 2.- 10. [參見圖 1] 涉及基礎架構特定的元數據,這些元數據參考基礎架構特定的實作,例如,對於 DNS 記錄,可能有 aws-route53google-clouddns,或者對於隔離的網路,甚至可能有 openstack-designate 等等。我們將在接下來的段落中檢查步驟 4 和 6,作為一般概念的範例(基於 AWS 的實作)。如果您有興趣,可以在我們的 擴充性文件中查閱完整記錄的 API 合約。

範例:Infrastructure CRD

AWS 上的 Kubernetes 叢集需要一定的基礎架構準備才能使用。這包括,例如,建立 VPC、子網路等。Infrastructure CRD 的目的是觸發此準備

apiVersion: extensions.gardener.cloud/v1alpha1
kind: Infrastructure
metadata:
  name: infrastructure
  namespace: shoot--foobar--aws
spec:
  type: aws
  region: eu-west-1
  secretRef:
    name: cloudprovider
    namespace: shoot--foobar—aws
  sshPublicKey: c3NoLXJzYSBBQUFBQ...
  providerConfig:
    apiVersion: aws.provider.extensions.gardener.cloud/v1alpha1
    kind: InfrastructureConfig
    networks:
      vpc:
        cidr: 10.250.0.0/16
      zones:
      - name: eu-west-1a
        internal: 10.250.112.0/22
        public: 10.250.96.0/22
        workers: 10.250.0.0/19

基於 Shoot 資源,Gardener 建立此 Infrastructure 資源作為其協調流程的一部分。AWS 特定的 providerConfig 是最終使用者在 Shoot 資源中的組態的一部分,不會由 Gardener 評估,而只是傳遞到種子叢集中的擴充控制器。

在其目前的實作中,AWS 擴充功能在 eu-west-1a 區域中建立一個新的 VPC 和三個子網路。此外,它還建立 NAT 和網際網路閘道、彈性 IP、路由表、安全群組、IAM 角色、執行個體設定檔和 EC2 金鑰對。

完成其任務後,它將報告狀態和一些供應商特定的輸出

apiVersion: extensions.gardener.cloud/v1alpha1
kind: Infrastructure
metadata:
  name: infrastructure
  namespace: shoot--foobar--aws
spec: ...
status:
  lastOperation:
    type: Reconcile
    state: Succeeded
  providerStatus:
    apiVersion: aws.provider.extensions.gardener.cloud/v1alpha1
    kind: InfrastructureStatus
    ec2:
      keyName: shoot--foobar--aws-ssh-publickey
    iam:
      instanceProfiles:
      - name: shoot--foobar--aws-nodes
        purpose: nodes
      roles:
      - arn: "arn:aws:iam::<accountID>:role/shoot..."
        purpose: nodes
    vpc:
      id: vpc-0815
      securityGroups:
      - id: sg-0246
        purpose: nodes
      subnets:
      - id: subnet-1234
        purpose: nodes
        zone: eu-west-1b
      - id: subnet-5678
        purpose: public
        zone: eu-west-1b

providerStatus 內的資訊可以用於後續步驟,例如,配置 cloud-controller-manager 或檢測 machine-controller-manager。

範例:叢集控制平面的部署

Gardener 的主要功能之一是它管理的叢集在不同基礎架構之間的同質性。因此,它仍然負責將供應商獨立的控制平面組件部署到種子叢集中(如 etcd、kube-apiserver)。供應商特定的控制平面組件(如 cloud-controller-manager 或 CSI 控制器)的部署由專用的 ControlPlane CRD 觸發。但是,在本段中,我們想專注於標準組件的自訂。

讓我們重點關注 kube-apiserver 和 kube-controller-manager Deployment。Gardener 的 AWS 擴充功能尚未使用 CSI,但依賴樹內 EBS 磁碟區外掛程式。因此,它需要啟用 PersistentVolumeLabel 准入外掛程式,並向 kube-apiserver 提供雲端供應商組態。同樣,kube-controller-manager 將被指示使用其樹內磁碟區外掛程式。

kube-apiserver Deployment 包含 kube-apiserver 容器,並由 Gardener 部署,如下所示

containers:
- command:
  - /hyperkube
  - apiserver
  - --enable-admission-plugins=Priority,...,NamespaceLifecycle
  - --allow-privileged=true
  - --anonymous-auth=false
  ...

使用 MutatingWebhookConfiguration,AWS 擴充功能注入提及的標誌並修改規格如下

containers:
- command:
  - /hyperkube
  - apiserver
  - --enable-admission-plugins=Priority,...,NamespaceLifecycle,PersistentVolumeLabel
  - --allow-privileged=true
  - --anonymous-auth=false
  ...
  - --cloud-provider=aws
  - --cloud-config=/etc/kubernetes/cloudprovider/cloudprovider.conf
  - --endpoint-reconciler-type=none
  ...
  volumeMounts:
  - mountPath: /etc/kubernetes/cloudprovider
    name: cloud-provider-config
volumes:
- configMap:
    defaultMode: 420
    name: cloud-provider-config
  name: cloud-provider-config

kube-controller-manager Deployment 以類似方式處理。

種子叢集中的 Webhook 可用於變更與 Gardener 或任何其他擴充功能部署的幼苗叢集控制平面相關的任何內容。在幼苗叢集中的資源中也有類似的 Webhook 概念,以防擴充控制器需要自訂 Gardener 部署的系統組件。

擴充控制器註冊

Gardener API 使用兩個特殊資源來註冊和安裝擴充功能。註冊本身透過 ControllerRegistration 資源宣告。最簡單的選項是定義 Helm Chart 以及一些值來呈現 Chart,但是,也支援透過自訂程式碼的任何其他部署機制。

Gardener 確定特定種子叢集中是否需要擴充控制器,並建立 ControllerInstallation,用於觸發部署。

迄今為止,每個註冊的擴充控制器都部署到每個種子叢集,這通常不是必要的。未來,Gardener 將變得更具選擇性,僅部署特定種子叢集上所需的擴充功能。

我們的動態註冊方法允許在運行系統中新增或移除擴充功能 - 而無需重建或重新啟動任何組件。

Gardener architecture with extension controllers

圖 2 具有擴充控制器的 Gardener 架構。

現狀

我們最近推出了新的 core.gardener.cloud API 群組,其中包含完全向前和向後相容的 Shoot 資源,並允許供應商使用 Gardener,而無需修改其核心原始碼樹中的任何內容。

我們已調整所有控制器以使用此新的 API 群組,並已棄用舊的 API。最終,幾個月後我們將移除它,因此建議最終使用者盡快開始遷移到新的 API。

除此之外,我們已啟用所有相關擴充功能以貢獻於幼苗健康狀態,並實作了相應的合約。基本概念是 CRD 可能具有 .status.conditions,這些條件由 Gardener 拾取,並與其標準健康檢查合併到 Shoot 狀態欄位中。

此外,我們希望實作一些易於使用的程式庫函數,以促進 CRD 的預設值和驗證 Webhook,以便驗證由最終使用者控制的 providerConfig 欄位。

最後,我們將把 gardener/gardener-extensions 儲存庫拆分為單獨的儲存庫,並僅將其保留用於可用於編寫擴充控制器的通用程式庫函數。

下一步

Kubernetes 已將許多基礎架構管理挑戰外部化。初始設計透過將生命週期操作委派給單獨的管理平面(種子叢集)來解決其中大部分問題。但是,如果花園叢集或種子叢集發生故障怎麼辦?我們如何擴展到數萬個需要平行協調的受管理叢集之外?我們正在進一步投資於加強 Gardener 可擴展性和災難復原功能。讓我們簡要重點介紹三個功能的更多細節

Gardenlet

從 Gardener 專案一開始,我們就開始實作 operator 模式:我們有一個作用於我們自己的自訂資源的自訂控制器管理器。現在,當您開始思考 Gardener 架構時,您會發現與 Kubernetes 架構有一些有趣的相似之處:幼苗叢集可以比作 Pod,而種子叢集可以視為工作節點。在這種觀察的引導下,我們引入了 gardener-scheduler。其主要任務是找到合適的種子叢集來託管新訂購叢集的控制平面,類似於 kube-scheduler 如何為新建立的 Pod 找到合適的節點。透過為區域(或供應商)提供多個種子叢集並分散工作負載,我們也減少了潛在故障的爆炸範圍。

Similarities between Kubernetes and Gardener architecture

圖 3 Kubernetes 和 Gardener 架構之間的相似之處。

然而,Kubernetes 和 Gardener 架構之間仍然存在顯著差異:Kubernetes 在每個節點上運行一個主要「代理程式」 kubelet,它主要負責管理其特定節點上的 Pod 和容器。Gardener 使用其控制器管理器,該管理器負責所有種子叢集上的所有幼苗叢集,並且它從花園叢集集中執行其協調迴圈。

雖然這在今天數千個叢集的規模下運作良好,但我們的目標是根據 Kubernetes 原則實現真正的可擴展性(超出單個控制器管理器的容量):我們現在正在努力將邏輯(或 Gardener operator)分散到種子叢集中,並將引入一個相應的組件,適當地命名為 gardenlet。它將是 Gardener 在每個種子叢集上的主要「代理程式」,並且僅負責位於其特定種子叢集中的幼苗叢集。

gardener-controller-manager 仍將保留其 Gardener API 其他資源的控制迴圈,但是,它將不再與種子/幼苗叢集對話。

反轉控制流程甚至允許將種子/幼苗叢集放置在防火牆後方,而不再需要直接存取(透過 VPN 隧道)。

Detailed architecture with Gardenlet

圖 4 具有 Gardenlet 的詳細架構。

種子叢集之間的控制平面遷移

當種子叢集發生故障時,使用者的靜態工作負載將繼續運作。但是,管理叢集將不再可能,因為在失敗種子中運行的幼苗叢集的 API 伺服器不再可訪問。

我們已實作將受種子災難影響的失敗控制平面重新定位到另一個種子,並且正在努力完全自動化此獨特功能。事實上,這種方法不僅可行,我們還在生產環境中多次執行了故障轉移程序。

自動化故障轉移功能將使我們能夠實作更全面的災難復原和可擴展性品質,例如,種子叢集的自動佈建和重新平衡,或所有不可預見情況的自動遷移。再次強調,考慮到 Pod 驅逐和節點排空,想想與 Kubernetes 的相似之處。

Gardener 環

Gardener 環是我們用於佈建和管理 Kubernetes 叢集的新穎方法,無需依賴外部佈建工具來建立初始叢集。透過以遞迴方式使用 Kubernetes,我們可以透過避免命令式工具組來大幅降低管理複雜性,同時透過自我穩定的循環系統創造新的品質。

環方法在概念上與自我託管和基於靜態 Pod 的部署不同。想法是建立一個由三個(或更多)幼苗叢集組成的環,每個叢集都託管其後繼者的控制平面。

一個叢集的停機不會影響環的穩定性和可用性,並且由於控制平面被外部化,失敗的叢集可以透過 Gardener 的自我修復功能自動恢復。只要至少有 n/2+1 個可用叢集的法定人數,環將始終自我穩定。在不同的雲端供應商(或至少在不同的區域/資料中心)上運行這些叢集降低了法定人數損失的可能性。

Self-stabilizing ring of Kubernetes clusters

圖 5 Kubernetes 叢集的自我穩定環。

Gardener 的分散式執行個體如何共享相同資料的方式是透過部署與同一個 etcd 叢集對話的單獨 kube-apiserver 執行個體。這些 kube-apiserver 正在形成一個無節點的 Kubernetes 叢集,可用作 Gardener 及其相關應用程式的資料容器。

我們在內部運行受環保護的測試環境,它使我們免於手動干預。有了自動化控制平面遷移,我們可以輕鬆啟動環,並解決初始叢集問題,並提高整體穩健性。

開始使用!

如果您有興趣編寫擴充功能,您可能需要查看以下資源

當然,也非常歡迎對我們專案的任何其他貢獻!我們一直都在尋找新的社群成員。

如果您想要試用 Gardener,請查看我們的 快速安裝指南。此安裝程式將在幾分鐘內設定完整的 Gardener 環境,即可用於測試和評估。

歡迎貢獻!

Gardener 專案以開放原始碼形式開發並託管在 GitHub 上:https://github.com/gardener

如果您看到 Gardener 專案的潛力,請透過 GitHub 加入我們。

我們每週五上午 10-11 點(中歐時間)安排了每週 公開社群會議,以及 Kubernetes 工作區中的公開 #gardener Slack 頻道。此外,我們計劃在 2020 年第一季舉辦 Gardener Hackathon,並期待在那裡與您見面!