後Kubernetes時代的虛擬機器管理技術之Virtual-Kubelet篇

在瞭解virtual-Kubelet之前,我們先了解下什麼是Kubelet。

Kubelet 是在每個Node節點上執行的主要 “節點代理”。在Kubernetes叢集中每個節點都會啟動一個kubelet程序,kubelet基於PodSpec來工作。每個Pod Spec是一個描述Pod的YAML或JSON物件。Kubelet接受透過各種機制(主要是透過Apiserver)提供的一組Pod Spec,並確保這些Pod Spec中描述的容器處於執行狀態且執行狀況良好。同時Kubelet還透過cAdvisor監控容器和節點資源,定期向上報當前節點的健康狀態以及資源使用情況,可以把Kubelet理解成[Server-Agent]架構中的Agent。

Virtual-Kubelet是基於Kubelet的典型特性實現,向上偽裝成Kubelet,從而模擬出Node物件,對接Kubernetes的原生資源物件;向下提供API,可對接其他資源管理平臺提供的Provider。不同的平臺透過實現Virtual-Kubelet定義的方法,允許節點由其對應的Provider提供(如ACI,AWS Fargate,IoT Edge,Tensile Kube等)支援,實現Serverless,或者將其擴充套件到如Docker Swarm、Openstack Zun等容器平臺中,也可以透過Provider納管其他Kubernetes叢集,甚至是原生的IaaS層平臺(VMware、zstack、openstack)。

最好的描述是Kubernetes API on top,programmable back。

Virtual-Kubelet如何管理虛擬機器是本文討論重點。

Virutal-Kubelet的架構

後Kubernetes時代的虛擬機器管理技術之Virtual-Kubelet篇

Virtual-Kubelet 模擬了Node資源物件,並負責對Pod排程到Virtual-Kubelet偽裝的虛擬節點之後,對Pod進行生命週期管理。

當前支援原生Kubernetes特性:

l 建立,刪除和更新Pod

l Container的日誌,管理和監控

l 獲取單個Pod或多個Pod狀態

l 節點地址,節點容量,節點守護程式端點

l 管理作業系統

l 攜帶私有虛擬網路

Virtual-Kubelet如何管理虛擬機器?

虛擬機器生命週期管理

Virtual-Kubelet在虛擬機器排程和操作方面可以複用Kubernetes原生的資源物件,但Pod在Kubelet管理下的生命週期僅存在建立、執行和銷燬,實際對於虛擬機器的開關機、備份和遷移等操作無法實現對映關係,因此對於複雜的生命週期管理,需要透過自定義CRD方式支援不同型別的IaaS平臺,每一個VM-CR對應一個IaaS層VM例項。

對於VM-CR操作主要可以分為兩類:

l 對VM執行狀態變更

l 建立和銷燬:可以對應一個VM-CR的create/delete

l VM啟停操作對應VM-CR replicas數量的變更:開機0→1關機1→0

l VM規格變更:修改VM-CR Spec資源定義

l kubectl logs/exec VM-pod:實現對Pod的訪問

l 對VM進行備份/遷移

l VM備份採用建立對應Backup-Job物件,透過與VM-CR例項pod親和方式,將Backup-Job排程置VM實際節點所執行的Virtual-Kubelet節點上,備份狀態與Job執行狀態一致

l VM遷移採用Kubernetes原生的節點排程方式,IaaS平臺每一個負載VM的物理機對應一個Kubernetes叢集內的Virtual-Kubelet,VM-CR例項Pod的排程由Kubernetes控制面管理

虛擬機器儲存管理

由於Virtual-Kubelet中Pod僅作為邏輯概念,IaaS層儲存無法與Kubernetes叢集公用,但可抽象為Kubernetes原生定義的PV/PVC,PV的access mode能力依賴IaaS層能力,並需要實現對應平臺和底層儲存的Provider和Provisioner。

Virtual-Kubelet如何實現容器與虛擬機器互動

容器和虛擬機器互通

l Virtual-Kubelet對應的Node會上報節點上Pod的Endpoint,假定Kubernetes叢集和IaaS層平臺部署在同一個二層網路下,則叢集內容器Pod可以訪問VM-Pod,但容器Pod對於VM-Pod不可見;

l 針對上一點可以透過Macvlan等網路外掛,將容器-Pod,降維至二層網路上,實現容器-Pod和虛擬機器互通,有一定硬體要求。

如何實現一套叢集下虛擬機器與容器的混合排程與資源隔離

l Virtual-Kubelet提供的是一個虛擬節點用來向Kubernetes上報Node物件和Pod的狀態和資源情況,虛擬機器資源和叢集內節點資源完全隔離;

l 在引入Virtual-Kubelet的情況下,需要對Virtual-Kubelet節點配置Taint和Tolerations,保證容器-Pod和VM-Pod排程分離。

服務發現

Virtual-Kubelet,透過Provider實現的API將IaaS層VM資訊抽象成對應Pod物件的資訊的方式來上報Endpoints,可以透過給CR新增no selector Service,待VM-Pod拉起後補充address至對應的Service。

Virutal-Kubelet適用場景

後Kubernetes時代的虛擬機器管理技術之Virtual-Kubelet篇

適用場景

Virtual-Kuberlet適合在已有IaaS層管理平臺和Kubernetes叢集環境下進行二者的打通,實現在Kubernetes叢集上統一管理容器和非容器平臺,同時由於Virtual-Kubelet在Serverless和納管其他已有容器平臺(Openstack Zun,Docker Swarm)方面也具有很高適配性,Virtual-Kubelet可以提供一套統一的API,方便開發者打通全流程。

Virtual-Kubelet的優缺點

優點

l 一個開源的Kubelet實現,使用Kubernetes源語,使構建、部署更簡單

l 提供Kubelet典型特性介面,Provider僅需實現對應服務管理平臺資源到Node和Pod物件特性的實現,不需要考慮如何訪問Kubernetes

l 靈活性高,Severless實踐、對接現有容器平臺、對接現有IaaS平臺均有一定前景

l Virtual-Kubelet設計將virtual-kubelet和Provider高度分離,Virtual-Kubelet使對於異構服務平臺具有很高的相容性(不同架構如:ARM、S390x,不同CRI如:Kata、PodMan),不光是可以納關IaaS平臺對於其他Kubernetes叢集也可以實現管理

缺點

l 將非叢集內資源抽象成Node和Pod物件對資源使用上有一定侷限性,很難提供超出原有kubelet和IaaS平臺能力範疇,IaaS深度整合需要自行實現CRD

l 僅能作為轉換器,用於容器和虛擬機器統一管理時還是需要依託已有的平臺能力,無法像Kubevirt等方案作為一個單獨的Iaas管理平臺使用

Virtual-Kubelet開發及部署

開發自定義的Provider

Virtual-Kubelet專案本身並不提供Provider,而是提供一系列定義Kubelet典型操作的介面,開發者需要根據應用場景實現對應的Provider。使Kubernetes可以進行按需和幾乎即時的Container的計算、排程,而無需管理VM基礎結構,同時仍可利用可移植的KubernetesAPI。

實現遵循以下三個準則:

l 提供必要的後端管道(back-end plumbing),以在Kubernetes的Context中支援Pods,Containers和相關資源的的生命週期管理

l 符合Virtual-Kubelet當前提供的API

l 沒有訪問Kubernetes APIServer的許可權,透過實現具有定義良好的回撥機制來獲取Secrets或Configmap之類的資料

建立一個新的Provider主要需要透過呼叫Virtual-Kubelet提供的庫實現如下三個介面:

l PodLifecylceHandler:用於Pod生命週期的管理

type

PodLifecycleHandler

interface

{

// CreatePod takes a Kubernetes Pod and deploys it within the provider。

CreatePod(ctx context。Context, pod *corev1。Pod)

error

// UpdatePod takes a Kubernetes Pod and updates it within the provider。

UpdatePod(ctx context。Context, pod *corev1。Pod)

error

// DeletePod takes a Kubernetes Pod and deletes it from the provider。

DeletePod(ctx context。Context, pod *corev1。Pod)

error

// GetPod retrieves a pod by name from the provider (can be cached)。

GetPod(ctx context。Context, namespace, name

string

) (*corev1。Pod,

error

// GetPodStatus retrieves the status of a pod by name from the provider。

GetPodStatus(ctx context。Context, namespace, name

string

) (*corev1。PodStatus,

error

// GetPods retrieves a list of all pods running on the provider (can be cached)。

GetPods(context。Context) ([]*corev1。Pod,

error

}

l PodNotifier:該介面允許Provider提供非同步通知Virtual-Kubelet有關Pod狀態更新的資訊,如未實現該介面的話,Virtual-Kubelet會定期檢查所有Pod的狀態,在計劃執行大量Pod的場景中強烈推薦實現該介面

type

PodNotifier

interface

{

// NotifyPods instructs the notifier to call the passed in function when

// the pod status changes。

//

// NotifyPods should not block callers。

NotifyPods(context。Context,

func

(*corev1。Pod))

}

l NodeProvider:NodeProvider負責通知虛擬小程式有關節點狀態更新的資訊。Virtual-Kubelet將定期檢查節點的狀態並相應地更新Kubernetes,如果不打算額外定義Node特性,可以直接使用Virtual-Kubelet提供的NativeNodeProvider

type

NodeProvider

interface

{

// Ping checks if the node is still active。

// This is intended to be lightweight as it will be called periodically as a

// heartbeat to keep the node marked as ready in Kubernetes。

Ping(context。Context)

error

// NotifyNodeStatus is used to asynchronously monitor the node。

// The passed in callback should be called any time there is a change to the

// node‘s status。

// This will generally trigger a call to the Kubernetes API server to update

// the status。

//

// NotifyNodeStatus should not block callers。

NotifyNodeStatus(ctx context。Context, cb

func

(*corev1。Node))

}

l API Endpoints:用於實現kubectl logs和kubectl exec

部署

Provider部署簡單僅需要在要新增目標叢集的主機中新增二進位制程式並根據IaaS層配置啟動即可:

。/bin/virtual-kubelet ——provider=

“hc-vmware-provider”

——exsi=

“X。X。X。X”