溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

API Basics怎么實現(xiàn)

發(fā)布時間:2022-01-11 17:57:09 來源:億速云 閱讀:325 作者:iii 欄目:云計算

本文小編為大家詳細(xì)介紹“API Basics怎么實現(xiàn)”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“API Basics怎么實現(xiàn)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。

Introduction

所謂的云原生應(yīng)用,能夠清楚自己運(yùn)行在k8s上,并且使用k8s api 和資源當(dāng)作其擴(kuò)展。

一方面,云原生應(yīng)用能夠輕便地在不同的云上遷移。另一方面,受益于k8s提供的簡潔可定義聲明式api。

Extension Patterns

  1. cloud providers: in-tree controller manager:

  2. kubelet: network, devices, storage, container runtimes

  3. extend kubectl with plugins

  4. extensions in the API server, dynamic admission control with webhook

  5. Custom resources and custom controllers.

  6. custom apiserver

  7. scheduler extensions.

Controllers and operators

  1. controller: 實現(xiàn)了一個控制循環(huán),從API server監(jiān)聽到的集群狀態(tài),并且把當(dāng)前狀態(tài)調(diào)整到預(yù)期狀態(tài)。

  2. operator: 是指controller+ 自定義資源的方式,去做像應(yīng)用生命周期管理相關(guān)的一些操作。

the controller loop

  1. 讀取資源的狀態(tài),更傾向于事件驅(qū)動。

  2. 改變集群或外部集群的對象的狀態(tài)。

  3. 通過apiserver更新存儲在etcd中資源的狀態(tài)。

  4. 重復(fù)循環(huán)。回到步驟1.

不管controller的實現(xiàn)復(fù)雜與否,這三步驟都是一致的。讀取資源狀態(tài)->改變the world-> 更新資源狀態(tài)。

API Basics怎么實現(xiàn)

informers:

負(fù)責(zé)watch期望的狀態(tài),實現(xiàn)resync機(jī)制加強(qiáng)周期性的調(diào)諧,通常用來確保集群狀態(tài)和存在內(nèi)存中的期望狀態(tài)不飄動。

work queues:

在client-go的workqueue包中實現(xiàn)了,為event handler提供work queues來“存儲”狀態(tài)變更操作的隊列及其各種重試操作。當(dāng)更新當(dāng)前資源對象狀態(tài)出錯時,資源需要重新被排序。

Events

k8s的控制面通過事件驅(qū)動 進(jìn)行解耦,其他分布式系統(tǒng)通過遠(yuǎn)程過程調(diào)用來觸發(fā)各種行為。controller 通過watch k8s對象的變化對APISERVER的增、刪、改請求。

example:

  1. 用戶 創(chuàng)建一個dp時,dp controller通過dp informer 創(chuàng)建一個rs。

  2. rs controller通過 rs informer 創(chuàng)建一個新的rs,并且創(chuàng)建一個pod對象。

  3. scheduler通過pod informer觀測到新的pod,且它的spec.nodeName 為空,就把這個pod放入調(diào)度隊列。

  4. 與此同時,kubelet通過pod informer觀測到新的pod,且它的spec.nodeName 為空。所以并沒有match到kubelet的nodeName,會忽略這個pod 繼續(xù)等待下一次事件。

  5. scheduler從workqueue中拿出pod,并且通過更新spec.nodeName字段,調(diào)度到有足夠資源的指定node,并且寫入apiserver。

  6. kubelet因為pod update事件,繼續(xù)比較spec.NodeName 和其本身的nodeName. 當(dāng)match之后,通過啟動pod的container,并且把container啟動的狀態(tài)信息寫入pod status, 返回存儲到apiserver。

  7. rs controller注意到pod改變。

  8. 最后pod銷毀時,kubelet watch到pod事件并且將pod狀態(tài)設(shè)置為“terminated”狀態(tài),并更新到apiserver。

  9. rs controller觀測到結(jié)束的pod,決定這個pod一定需要被替換。于是通過apiserver刪除 terminated狀態(tài)的pod,并且創(chuàng)建一個新的。

一系列獨立的控制循環(huán),通過watch apiserver中對象的變化,并且這些變更事件通過informers來觸發(fā)變更。

watch events 和 event對象是兩個東西:

  1. 前者通過在apiserver和controllers之間建立http streaming 的鏈接用來驅(qū)動informers.

  2. 后者是一種資源,像pod,dp,services這些,帶有特殊的時效屬性并且自動從etcd里消失。

Edge-driven triggers or Level-driven triggers 

前者是基于某個狀態(tài)值變更的瞬間去觸發(fā)handler,后者是在某個時間段內(nèi)、狀態(tài)被驗證與期望值相符,則去觸發(fā)handler。

后者更像是一種polling輪詢,能否擴(kuò)容到指定數(shù)量、控制器注意到變更的延遲依賴于polling輪詢的時間間隔以及apiserver的響應(yīng)時間。與很多異步的控制器相關(guān),最終系統(tǒng)需要花費(fèi)一段時間才能達(dá)到預(yù)期狀態(tài)。

前者效率更高,延遲則依賴在控制器處理事件時,運(yùn)行的工作線程。因此k8s基于事件驅(qū)動,即edge-driven triggers.

API Basics怎么實現(xiàn)

reconciliation with resync:每5分鐘持續(xù)調(diào)諧。

edge-triggered, level-driven

level-triggering-and-reconciliation

Changing Cluster Objects or the External world

Optimistic Concurrency

單體式:

二階段:

共享狀態(tài):

并行調(diào)度架構(gòu):

新一代的并發(fā)調(diào)度架構(gòu)依賴共享狀態(tài),使用樂觀并發(fā)控制達(dá)到實現(xiàn)可擴(kuò)展和性能可伸縮。

k8s 中樂觀鎖的場景是:

retry loop中,獲取了foo對象最新的狀態(tài)后,嘗試根據(jù)foo spec更新real world 和foo status,實際修改的操作在Update事件之前執(zhí)行。

通過client.Get返回的foo對象,包含資源的版本,ObjectMeta結(jié)構(gòu)體。這個結(jié)構(gòu)體會在client.Update調(diào)用時,通過寫操作更新etcd的數(shù)據(jù)。所謂的資源版本,在etcd中存儲的實際上是<string,int> 鍵值對。etcd維護(hù)了一個計數(shù)器counter,每次key的值被修改時,counter值加一。

在API machinery代碼中,資源版本的處理像是任意的string,實際上還是遵循一些規(guī)則。實際的實現(xiàn)細(xì)節(jié)在etcd存儲后端。

essence: 控制器中的沖突錯誤十分常見,處理和期待十分優(yōu)雅。

Operators

operator是一種針對特定應(yīng)用的控制器,擴(kuò)展了k8s API的創(chuàng)建、配置、管理復(fù)雜的有狀態(tài)應(yīng)用的實例。

一個operator包括一個 CRD+ controller。

API Basics怎么實現(xiàn)

Kubernetes API Basics

apiserver作為擋在存儲etcd前的唯一組件,跟etcd進(jìn)行直接交互。主要職責(zé)是作為k8s api的server 和集群組件的proxy。

伺服API意味著 讀取狀態(tài)和 操作狀態(tài)。

聲明式狀態(tài)管理

通過比較期望狀態(tài)的spec和當(dāng)前實際狀態(tài)的值,

例如:當(dāng)你在dp的聲明yaml里指定20個副本數(shù),dp controller讀到dp spec并且創(chuàng)建rs,實際去接管rs- 即特定個數(shù)的pods。如果有任何副本跪了,dp controller會讓你在狀態(tài)中感知到。

APIServer Processes Requests

API Basics怎么實現(xiàn)

DefaultBuildHandlerChain()

WithPanicRecovery(): 處理恢復(fù)和日志panic

Basics of client-go

Repos

ClientLibrary

k8s項目提供client-go(https://github.com/kubernetes/client-go) 作為用戶的開發(fā)工具集,提供了多種類型的API支持,以及包含許多通用庫代碼。

K8S API Types

client-go管理了客戶端接口,像PODS,services,deployments這些接口,在這個repo中維護(hù)(https://github.com/kubernetes/api),pod等的類型在k8s.io/api/core/v1/types.go中定義,而這些文件均由code gen自動生成維護(hù)。

// Pod is a collection of containers that can run on a host. This resource is created
// by clients and scheduled onto hosts.
type Pod struct {
   metav1.TypeMeta `json:",inline"`
   // Standard object's metadata.
   // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
   // +optional
   metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`

   // Specification of the desired behavior of the pod.
   // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
   // +optional
   Spec PodSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`

   // Most recently observed status of the pod.
   // This data may not be up to date.
   // Populated by the system.
   // Read-only.
   // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
   // +optional
   Status PodStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`

}

API machinery

第三個repo(https://github.com/kubernetes/apimachinery ) 包含所有通用的構(gòu)建模塊,不僅限于容器管理,還包括其他構(gòu)建 APIs。在pkg/api/meta/v1 下可以查看到許多API類型的定義,包括如下:

ObjectMeta: Name + Namespaces + ResourceVersion + Labels + Annotations

TypeMeta : Kind + APIVersion

GetOptions,

ListOptions

構(gòu)建模塊用來創(chuàng)建k8s客戶端對象,代表在k8s集群中能訪問的資源。

版本和兼容

k8s 的api是按版本區(qū)分的,一方面client的不同版本去訪問API server,如果版本不匹配,請求會失敗。client 與特定的版本綁定,應(yīng)用開發(fā)者需要選擇正確的

其版本與k8s版本對應(yīng)關(guān)系如圖:

| Branch | Canonical source code location | Maintenance status |
| `release-1.4` | Kubernetes main repo, 1.4 branch | = - |
| `release-1.5` | Kubernetes main repo, 1.5 branch | = - |
| `release-2.0` | Kubernetes main repo, 1.5 branch | = - |
| `release-3.0` | Kubernetes main repo, 1.6 branch | = - |
| `release-4.0` | Kubernetes main repo, 1.7 branch | = - |
| `release-5.0` | Kubernetes main repo, 1.8 branch | = - |
| `release-6.0` | Kubernetes main repo, 1.9 branch | = - |
| `release-7.0` | Kubernetes main repo, 1.10 branch | = - |
| `release-8.0` | Kubernetes main repo, 1.11 branch | =- |
| `release-9.0` | Kubernetes main repo, 1.12 branch | =- |
| `release-10.0` | Kubernetes main repo, 1.13 branch | =- |
| `release-11.0` | Kubernetes main repo, 1.14 branch | ? |
| `release-12.0` | Kubernetes main repo, 1.15 branch | ? |
| `release-13.0` | Kubernetes main repo, 1.16 branch | ? |
| `release-14.0` | Kubernetes main repo, 1.17 branch | ? |
| client-go HEAD | Kubernetes main repo, master branch | ? |

Key:

  • ? Changes in main Kubernetes repo are actively published to client-go by a bot

  • = Maintenance is manual, only severe security bugs will be patched.

  • - Deprecated; please upgrade.

你看代碼有哪些用的較多的公用庫呀:  sharedInformer、workqueue、event、leaderelection、rest、scheme、flowcontrol、codec

K8S objects in Go

k8s資源是一種kind的實例,在API server作為一種資源結(jié)構(gòu)體提供服務(wù)。

k8s中的object 實現(xiàn)了runtime.Object接口,來自于k8s.io/apimachinery/pkg/runtime包。其中,schema.ObjectKind主要實現(xiàn)的另一個接口,來自于k8s.io/apimachinery/pkg/runtime/schema.

這些Go實現(xiàn)的object作為數(shù)據(jù)結(jié)構(gòu)主要是用來返回和設(shè)置GroupVersionKind, 以及用來深度拷貝。

type Object interface { 
  GetObjectKind () schema.ObjectKind 
  DeepCopyObject () Object 
}&nbsp;
type ObjectKind interface { 
// SetGroupVersionKind sets or clears the intended serialized kind of an 
// object. Passing kind nil should clear the current setting. 
  SetGroupVersionKind ( kind GroupVersionKind ) 
// GroupVersionKind returns the stored group, version, and kind of an // object, or nil if the object does not expose or provide these fields. 
  GroupVersionKind () GroupVersionKind 
}&nbsp;

TypeMeta

通過嵌套metav1.TypeMeta(k8s.io/apimachinery/meta/v1)來實現(xiàn)k8s對象schema.ObjectMeta(k8s.io/api)的getter和setter類型。

// TypeMeta describes an individual object in an API response or request
// with strings representing the type of the object and its API schema version.
// Structures that are versioned or persisted should inline TypeMeta.
//
// +k8s:deepcopy-gen=false
type TypeMeta struct {
   // Kind is a string value representing the REST resource this object represents.
   // Servers may infer this from the endpoint the client submits requests to.
   // Cannot be updated.
   // In CamelCase.
   // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
   // +optional
   Kind string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"`

   // APIVersion defines the versioned schema of this representation of an object.
   // Servers should convert recognized schemas to the latest internal value, and
   // may reject unrecognized values.
   // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources
   // +optional
   APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,2,opt,name=apiVersion"`
}
// Pod is a collection of containers that can run on a host. This resource is created
// by clients and scheduled onto hosts.
type Pod struct {
   metav1.TypeMeta `json:",inline"`
   // Standard object's metadata.
   // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
   // +optional
   metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`

   // Specification of the desired behavior of the pod.
   // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
   // +optional
   Spec PodSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`

   // Most recently observed status of the pod.
   // This data may not be up to date.
   // Populated by the system.
   // Read-only.
   // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
   // +optional
   Status PodStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`

}

基于client-go的應(yīng)用這些字段在內(nèi)存中值為空,在實際序列化成json或者pb時,才會有實際的值。而這些約定在版本序列中自動實現(xiàn)。

ObjectMeta

出了TypeMeta,大部分top-level對象還會包括metav1.ObjectMeta,來自k8s.io/apimachinery/pkg/meta/v1。

(staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go)

type ObjectMeta struct { 
Name string `json:"name,omitempty"` 
Namespace string `json:"namespace,omitempty"` 
UID types.UID `json:"uid,omitempty"` 
ResourceVersion string `json:"resourceVersion,omitempty"` CreationTimestamp Time `json:"creationTimestamp,omitempty"` DeletionTimestamp * Time `json:"deletionTimestamp,omitempty"` 
Labels map [ string ] string `json:"labels,omitempty"` 
Annotations map [ string ] string `json:"annotations,omitempty"` 
... 
}

metav1.ObjectMeta基本包含所有元數(shù)據(jù)信息,像name,namespace,resource version, 一些時間戳,以及l(fā)abels 和annotation. 其中client-go并不能對resource version進(jìn)行讀寫,但卻是整個k8s代碼中核心工作的重要信息.

它作為ObjectMeta信息的一部分,來源于etcd里所有數(shù)據(jù)的key字段。

Client Sets

kubernetes.NewForConfig(config)返回一個 client set, 用它可以訪問定義在k8s.io/api中的大部分API groups和resources,除了APIServices(aggregated API servers)和CRD。

clientSet主接口如下:

type Interface interface {
   Discovery() discovery.DiscoveryInterface
   AdmissionregistrationV1alpha1() admissionregistrationv1alpha1.AdmissionregistrationV1alpha1Interface
   AdmissionregistrationV1beta1() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface
   // Deprecated: please explicitly pick a version if possible.
   Admissionregistration() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface
   AppsV1beta1() appsv1beta1.AppsV1beta1Interface
   AppsV1beta2() appsv1beta2.AppsV1beta2Interface
   AppsV1() appsv1.AppsV1Interface
   // Deprecated: please explicitly pick a version if possible.
   Apps() appsv1.AppsV1Interface
   AuthenticationV1() authenticationv1.AuthenticationV1Interface
   // Deprecated: please explicitly pick a version if possible.
   Authentication() authenticationv1.AuthenticationV1Interface
   AuthenticationV1beta1() authenticationv1beta1.AuthenticationV1beta1Interface
   AuthorizationV1() authorizationv1.AuthorizationV1Interface
   // Deprecated: please explicitly pick a version if possible.
   Authorization() authorizationv1.AuthorizationV1Interface
   AuthorizationV1beta1() authorizationv1beta1.AuthorizationV1beta1Interface
   AutoscalingV1() autoscalingv1.AutoscalingV1Interface
   // Deprecated: please explicitly pick a version if possible.
   Autoscaling() autoscalingv1.AutoscalingV1Interface
   AutoscalingV2beta1() autoscalingv2beta1.AutoscalingV2beta1Interface
   BatchV1() batchv1.BatchV1Interface
   // Deprecated: please explicitly pick a version if possible.
   Batch() batchv1.BatchV1Interface
   BatchV1beta1() batchv1beta1.BatchV1beta1Interface
   BatchV2alpha1() batchv2alpha1.BatchV2alpha1Interface
   CertificatesV1beta1() certificatesv1beta1.CertificatesV1beta1Interface
   // Deprecated: please explicitly pick a version if possible.
   Certificates() certificatesv1beta1.CertificatesV1beta1Interface
   CoreV1() corev1.CoreV1Interface
   // Deprecated: please explicitly pick a version if possible.
   Core() corev1.CoreV1Interface
   EventsV1beta1() eventsv1beta1.EventsV1beta1Interface
   // Deprecated: please explicitly pick a version if possible.
   Events() eventsv1beta1.EventsV1beta1Interface
   ExtensionsV1beta1() extensionsv1beta1.ExtensionsV1beta1Interface
   // Deprecated: please explicitly pick a version if possible.
   Extensions() extensionsv1beta1.ExtensionsV1beta1Interface
   NetworkingV1() networkingv1.NetworkingV1Interface
   // Deprecated: please explicitly pick a version if possible.
   Networking() networkingv1.NetworkingV1Interface
   PolicyV1beta1() policyv1beta1.PolicyV1beta1Interface
   // Deprecated: please explicitly pick a version if possible.
   Policy() policyv1beta1.PolicyV1beta1Interface
   RbacV1() rbacv1.RbacV1Interface
   // Deprecated: please explicitly pick a version if possible.
   Rbac() rbacv1.RbacV1Interface
   RbacV1beta1() rbacv1beta1.RbacV1beta1Interface
   RbacV1alpha1() rbacv1alpha1.RbacV1alpha1Interface
   SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface
   SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface
   // Deprecated: please explicitly pick a version if possible.
   Scheduling() schedulingv1beta1.SchedulingV1beta1Interface
   SettingsV1alpha1() settingsv1alpha1.SettingsV1alpha1Interface
   // Deprecated: please explicitly pick a version if possible.
   Settings() settingsv1alpha1.SettingsV1alpha1Interface
   StorageV1beta1() storagev1beta1.StorageV1beta1Interface
   StorageV1() storagev1.StorageV1Interface
   // Deprecated: please explicitly pick a version if possible.
   Storage() storagev1.StorageV1Interface
   StorageV1alpha1() storagev1alpha1.StorageV1alpha1Interface
}

在這個接口中存在一些沒有版本的方法:appsv1beta1.AppsV1beta1Interface。

>在過去k8s有所謂的內(nèi)部客戶端,為了對象在內(nèi)存中存在的更加通用,并且遵循在需要的時候再定義的規(guī)范。這種規(guī)范為了從實際使用的API版本中抽象controller代碼,同時方便切換不同版本。事實上,為了遵循這種規(guī)范,增加了大量的復(fù)雜性,付出了不太值得的代價。 >此外,在client和APIServer之間的交互,并沒有自動協(xié)商的機(jī)制。盡管存在內(nèi)部的版本和客戶端,controller硬編碼到指定版本導(dǎo)致并沒有很好兼容。 >在最近的版本,k8s代碼盡量避免用到這些內(nèi)部版本。

所有clientset可以訪問discovery client,被用作RESTMappers;

type AppsV1beta1Interface interface {
   RESTClient() rest.Interface
   ControllerRevisionsGetter
   DeploymentsGetter
   ScalesGetter
   StatefulSetsGetter
}

在每個GroupVersion(AppsV1beta1)下我們發(fā)現(xiàn)API group的資源都存在通用的RESTClient

讀到這里,這篇“API Basics怎么實現(xiàn)”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

api
AI