天天看點

想要優化 K8S 叢集管理?Cluster API 幫你忙 | K8S Internals 系列第 5 期

作者:BoCloud博雲

K8S Internals 系列第五期

容器編排之争在 Kubernetes 一統天下局面形成後,K8S 成為了雲原生時代的新一代作業系統。K8S 讓一切變得簡單了,但自身逐漸變得越來越複雜。【K8S Internals 系列專欄】圍繞 K8S 生态的諸多方面,将由博雲容器雲研發團隊定期分享有關排程、安全、網絡、性能、存儲、應用場景等熱點話題。希望大家在享受 K8S 帶來的高效便利的同時,又可以如庖丁解牛般領略其核心運作機制的魅力。

本文将結合 CNCF 社群中面向多叢集管理的 Cluster API 項目,來和大家談談 K8S 叢集的管理方式。

1. 為什麼選擇 Cluster API?

Kubernetes 已經成為雲原生容器平台的事實标準,越來越多不同行業的企事業機關開始将業務從傳統的實體機、虛拟機遷移過來。利用 Kubernetes 讓應用管理變得既快又穩,同時降低成本。

在這個過程中,一個企業内部建設了數量不少的 K8S 叢集,這些叢集的部署方式、版本、配置參數、業務部署都不盡相同。可以說,在 K8S 帶來便捷高效的同時,如何管理這些 K8S 叢集也成為了不可忽略的問題,例如:如何安裝部署 Kubernetes 叢集、如何管理多個 Kubernetes 叢集、異構叢集如何管理、叢集如何更新擴容、叢集的配置參數如何規範的變更?一系列靈魂發問成了不少企業的痛楚。

結合 CNCF 社群中面向多叢集管理的 Cluster API 項目,我們來和大家談談社群的解決方案。

Cluster API 由 Kubernetes 特别興趣小組 Cluster Lifecycle 發起,旨在提供 K8S 即服務能力。用 Kubernetes 的能力管理 Kubernetes,用 Kubernetes 的方式提供 Kubernetes 叢集生命周期管理,并且支援管理叢集相關的基礎設施(虛拟機、網絡、負載均衡器、VPC 等)。通過以上種種方式,讓 K8S 基礎設施的生命周期管理也變得非常雲原生化。

看到這裡,熟悉 Kubernetes 的小夥伴們肯定心想:用 cluster API 項目,是不是隻用送出一個 yaml 就好了?沒錯就是這樣。Cluster API 提供了聲明式的叢集管理方式。那麼對比之前叢集的部署方式又有什麼差別呢?以使用 Kubernetes 的官方部署工具 kubeadm 為例,請看下圖。

想要優化 K8S 叢集管理?Cluster API 幫你忙 | K8S Internals 系列第 5 期

使用或部署過 Kubernetes 叢集的小夥伴們知道,Kubernetes 叢集依賴于幾個元件協同工作才能正常運作,對這些元件的部署往往吓退了很多人,kubeadm 的出現很大程度減輕了這一痛楚,并且對叢集重複部署的問題也給出了一個很好的答案。不過正如上圖所示,幾乎每一步都需要人工手動操作,部署人員輾轉多台伺服器之間重複着相同的操作。同時面對日益增長的叢集環境,kubeadm 并沒有解決如何對自己已部署的叢集進行管理。除此之外還包括以下問題:

  • 如何針對異構叢集一緻地配置機器、負載均衡器、VPC 等?
  • 如何自動化管理叢集生命周期,包括更新和叢集删除?
  • 如何擴充并管理任意數量的叢集?

Cluster API 給出了答案,通過申明式的建構具有 Kubernetes 風格的 API,完成諸如叢集自動建立、配置和管理等功能。同時支援您使用不同的基礎設施提供商以及引導程式提供商來建構管理您的叢集。

2. Cluster API 架構

想要優化 K8S 叢集管理?Cluster API 幫你忙 | K8S Internals 系列第 5 期

(圖源 Cluster API 官方網站)

  • Management Cluster

Cluster API 工作的叢集,該叢集往往通過 kind 等工具生成,在該叢集上運作着一個或多個基礎設施提供程式,并儲存着 Cluster API 相關的 CRD 資源。是負責管理工作叢集生命周期的叢集。

  • Target Cluster

工作叢集,由管理叢集建立并管理其生命周期。

  • Infrastructure provider

基礎設施提供商,工作叢集基礎設施的實際提供者(如 AWS、Azure 和 Google 等),由各大廠商實作,但需要遵循 Cluster API 的規範去實作相應的接口和邏輯。

  • Control plane provider

控制平面提供者,負責 Target Cluster 控制平面的節點生成,Cluster API 預設使用 kubeadm 引導控制平面。對于不同廠商可實作适配自己的控制平面引導程式。

  • Bootstrap Provider

引導程式提供者,負責叢集證書生成,初始化控制平面,并控制其他節點(控制平面和工作節點)加入叢集。Cluster API 預設使用基于 kubeadm 的引導程式。對于不同廠商可實作适配自己的節點引導程式。

  • Custom Resources

自定義資源,Cluster API 提供并依賴于幾個自定義資源:Machine、MachineDeployment、MachineSet、Cluster。作為廠商,在實作自己的 provider 時應當遵循這些自定義資源規範。

3. Cluster API 資源介紹

我們以kubeadm-control-plane-provider(Control plane provider)、kubeadm-bootstrap-provider(bootstrap-provider)以及cluster-api-provider-docker(Infrastructure Provider)元件,資源版本 v1beta1 為例,梳理一下 Cluster API 的自定義資源關系圖。

在 Cluster API 中對于工作叢集的控制平面節點和工作節點的控制是獨立分開的,由此對應的資源關系又可劃分為控制平面節點機器關系和工作節點機器關系。

控制平面節點機器關系圖

對于kubeadm-control-plane-provider,工作叢集控制平面節點由KubeadmControlplane資源控制。該資源直接控制了一組Machine資源,每一個Machine資源又分别關聯了一個DockerMachine和KubeadmBootstrapConfig資源。對于使用者來說實際工作叢集中的一個控制平面節點都在管理叢集中以一個Machine資源的形式存在,KubeadmControlplane則是整個工作叢集控制平面節點的展現。即每個實際的控制平面節點及其對應的引導配置都在管理叢集中以資源的形式存在,管理叢集通過控制這些資源,最終由基礎設施提供者(如 cluster-api-provider-docker)作用到實際的節點或基礎設施之上。

想要優化 K8S 叢集管理?Cluster API 幫你忙 | K8S Internals 系列第 5 期

工作節點機器關系圖

相比于控制平面節點機器的關系圖,工作節點機器的關系圖更為複雜。這是因為 Cluster API 對于工作節點機器的管理使用了類似 Kubernetes 中Deployment的MachineDeployment,由MachineDeployment管理一組MachineSet,再由MachineSet管理一組Machine。和控制平面節點機器關系中所述一緻,每個實際的控工作節點及其對應的引導配置都在管理叢集中以資源的形式存在,管理叢集通過控制這些資源,最終由基礎設施提供者(如 cluster-api-provider-docker)作用到實際的節點或基礎設施之上。

想要優化 K8S 叢集管理?Cluster API 幫你忙 | K8S Internals 系列第 5 期

資源介紹

下面我們對涉及到的具體資源做一些簡單介紹。

  • Cluster

Cluster 資源是整個工作叢集在管理叢集中以資源形式的存在。在對工作叢集生命周期過程中,尤其是在工作叢集部署階段中,兼具部署狀态收集的功能。通過檢視 Cluster 資源狀态便可掌控整個工作叢集部署狀态。同時在其資源字段中對整個工作叢集的叢集網絡進行了配置。

關鍵字段展示:

spec.ClusterNetwork

type ClusterNetwork struct {
 // APIServerPort specifies the port the API Server should bind to.
 // Defaults to 6443.
 // +optional
 APIServerPort *int32 `json:"apiServerPort,omitempty"`


 // The network ranges from which service VIPs are allocated.
 // +optional
 Services *NetworkRanges `json:"services,omitempty"`


 // The network ranges from which Pod networks are allocated.
 // +optional
 Pods *NetworkRanges `json:"pods,omitempty"`


 // Domain name for services.
 // +optional
 ServiceDomain string `json:"serviceDomain,omitempty"`
}           
  • MachineDeployment

MachineDeployment 的工作方式與 Kubernetes Deployment 類似。MachineDeployment 通過對 2 個 MachineSet(舊的和新的)進行更改來協調對 Machine Spec 的更改。

關鍵字段展示:

spec.ClusterName

// ClusterName is the name of the Cluster this object belongs to.
 // +kubebuilder:validation:MinLength=1
 ClusterName string `json:"clusterName"`           

spec.Replicas

Replicas 就像 Kubernetes Deployment 那樣定義期望的 Pod 副本數定義期望的 Machine 數量。

// Number of desired machines. Defaults to 1.
 // This is a pointer to distinguish between explicit zero and not specified.
 // +optional
 // +kubebuilder:default=1
 Replicas *int32 `json:"replicas,omitempty"`           

spec.Selector

比對具有對應 lable 的 Machine。

// Label selector for machines. Existing MachineSets whose machines are
 // selected by this will be the ones affected by this deployment.
 // It must match the machine template's labels.
 Selector metav1.LabelSelector `json:"selector"`           

spec.Template

建立 Machine 的模闆,此處不展示,請繼續向下看 Machine 資源介紹。

spec.Strategy

Machine 更新政策,預設為滾動更新(RollingUpdate),可選政策 RollingUpdate;OnDelete。

type MachineDeploymentStrategy struct {
 // Type of deployment.
 // Default is RollingUpdate.
 // +kubebuilder:validation:Enum=RollingUpdate;OnDelete
 // +optional
 Type MachineDeploymentStrategyType `json:"type,omitempty"`


 // Rolling update config params. Present only if
 // MachineDeploymentStrategyType = RollingUpdate.
 // +optional
 RollingUpdate *MachineRollingUpdateDeployment `json:"rollingUpdate,omitempty"`
}           
  • MachineSet

MachineSet 的目的是維護在任何給定時間運作的一組穩定的 Machine。但并不是直接獨立使用,而是與 MachineDeployment 一起工作,由 Machine Deployments 來協調其狀态。

關鍵字段展示:

spec.ClusterName

// ClusterName is the name of the Cluster this object belongs to.
 // +kubebuilder:validation:MinLength=1
 ClusterName string `json:"clusterName"`           

spec.Replicas

// Replicas is the number of desired replicas.
 // This is a pointer to distinguish between explicit zero and unspecified.
 // Defaults to 1.
 // +optional
 // +kubebuilder:default=1
 Replicas *int32 `json:"replicas,omitempty"`           

sepc.DeletePolicy

當縮減節點時删除節點的政策,預設為随機(Random),可選 Random;Newest;Oldest。

// DeletePolicy defines the policy used to identify nodes to delete when downscaling.
 // Defaults to "Random".  Valid values are "Random, "Newest", "Oldest"
 // +kubebuilder:validation:Enum=Random;Newest;Oldest
 // +optional
 DeletePolicy string `json:"deletePolicy,omitempty"`           

spec.Selector

// Selector is a label query over machines that should match the replica count.
 // Label keys and values that must match in order to be controlled by this MachineSet.
 // It must match the machine template's labels.
 // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
 Selector metav1.LabelSelector `json:"selector"`           

spec.Template

建立 Machine 的模闆,此處不展示,請繼續向下看 Machine 資源介紹。

  • Machine

Machine 是具體工作叢集中具體節點在管理叢集以資源形式的存在,當一個 Machine 被删除或建立,對應的工作叢集的節點也會随之被删除或建立。如果 Machine 資源的字段被修改,那麼控制器将會建立新的 Machine 對舊的 Machine 進行替換。

關鍵字段展示:

spec.ClusterName

// ClusterName is the name of the Cluster this object belongs to.
 // +kubebuilder:validation:MinLength=1
 ClusterName string `json:"clusterName"`           

spec.Bootstrap

關聯的引導程式資源,對于 kubeadm-bootstrap-provider,關聯的是 kubeadmBootstrapConfig。其中 DataSecretName 将會被存儲 Bootstrap data 的 secret 的 name 填充。

// Bootstrap encapsulates fields to configure the Machine’s bootstrapping mechanism.
type Bootstrap struct {
 // ConfigRef is a reference to a bootstrap provider-specific resource
 // that holds configuration details. The reference is optional to
 // allow users/operators to specify Bootstrap.DataSecretName without
 // the need of a controller.
 // +optional
 ConfigRef *corev1.ObjectReference `json:"configRef,omitempty"`


 // DataSecretName is the name of the secret that stores the bootstrap data script.
 // If nil, the Machine should remain in the Pending state.
 // +optional
 DataSecretName *string `json:"dataSecretName,omitempty"`
}           

spec.InfrastructureRef

關聯基礎設施提供程式,Machine 所有字段定義以及引導工作都由基礎設施提供者實作

// InfrastructureRef is a required reference to a custom resource
 // offered by an infrastructure provider.
 InfrastructureRef corev1.ObjectReference `json:"infrastructureRef"`           

spec.Version

Vesion 定義了對應工作叢集節點上所需要安裝的 Kubernetes 版本

// Version defines the desired Kubernetes version.
 // This field is meant to be optionally used by bootstrap providers.
 // +optional
 Version *string `json:"version,omitempty"`           

spec.ProviderID

此字段與此 Machine 對應的工作叢集 node 對象上的 ProviderID 一緻,通過此字段比對工作叢集 node 對象,并通過工作叢集的 API Server 對 node 對象進行通路以及控制。

// ProviderID is the identification ID of the machine provided by the provider.
 // This field must match the provider ID as seen on the node object corresponding to this machine.
 // This field is required by higher level consumers of cluster-api. Example use case is cluster autoscaler
 // with cluster-api as provider. Clean-up logic in the autoscaler compares machines to nodes to find out
 // machines at provider which could not get registered as Kubernetes nodes. With cluster-api as a
 // generic out-of-tree provider for autoscaler, this field is required by autoscaler to be
 // able to have a provider view of the list of machines. Another list of nodes is queried from the k8s apiserver
 // and then a comparison is done to find out unregistered machines and are marked for delete.
 // This field will be set by the actuators and consumed by higher level entities like autoscaler that will
 // be interfacing with cluster-api as generic provider.
 // +optional
 ProviderID *string `json:"providerID,omitempty"`           

4. 結束語

Cluster API 是一個十分優秀的項目,從工作叢集的部署到伸縮、删除和更新都有非常好的體驗(送出 yaml 然後等待 Cluster API 完成工作)。無論您是在何種基礎設施上搭建叢集,都能在社群找到合适您的 provider。又或許您想自建 provider 适配,隻需遵循 Cluster API 的 provider 規範便可快速編寫出您的定制程式。

下一篇,我們将帶您深入了解 Cluster API 的運作原理。

繼續閱讀