您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“API Basics怎么實現(xiàn)”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“API Basics怎么實現(xiàn)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。
所謂的云原生應(yīng)用,能夠清楚自己運(yùn)行在k8s上,并且使用k8s api 和資源當(dāng)作其擴(kuò)展。
一方面,云原生應(yīng)用能夠輕便地在不同的云上遷移。另一方面,受益于k8s提供的簡潔可定義聲明式api。
cloud providers: in-tree controller manager:
kubelet: network, devices, storage, container runtimes
extend kubectl with plugins
extensions in the API server, dynamic admission control with webhook
Custom resources and custom controllers.
custom apiserver
scheduler extensions.
controller: 實現(xiàn)了一個控制循環(huán),從API server監(jiān)聽到的集群狀態(tài),并且把當(dāng)前狀態(tài)調(diào)整到預(yù)期狀態(tài)。
operator: 是指controller+ 自定義資源的方式,去做像應(yīng)用生命周期管理相關(guān)的一些操作。
讀取資源的狀態(tài),更傾向于事件驅(qū)動。
改變集群或外部集群的對象的狀態(tài)。
通過apiserver更新存儲在etcd中資源的狀態(tài)。
重復(fù)循環(huán)。回到步驟1.
不管controller的實現(xiàn)復(fù)雜與否,這三步驟都是一致的。讀取資源狀態(tài)->改變the world-> 更新資源狀態(tài)。
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)出錯時,資源需要重新被排序。
k8s的控制面通過事件驅(qū)動 進(jìn)行解耦,其他分布式系統(tǒng)通過遠(yuǎn)程過程調(diào)用來觸發(fā)各種行為。controller 通過watch k8s對象的變化對APISERVER的增、刪、改請求。
example:
用戶 創(chuàng)建一個dp時,dp controller通過dp informer 創(chuàng)建一個rs。
rs controller通過 rs informer 創(chuàng)建一個新的rs,并且創(chuàng)建一個pod對象。
scheduler通過pod informer觀測到新的pod,且它的spec.nodeName 為空,就把這個pod放入調(diào)度隊列。
與此同時,kubelet通過pod informer觀測到新的pod,且它的spec.nodeName 為空。所以并沒有match到kubelet的nodeName,會忽略這個pod 繼續(xù)等待下一次事件。
scheduler從workqueue中拿出pod,并且通過更新spec.nodeName字段,調(diào)度到有足夠資源的指定node,并且寫入apiserver。
kubelet因為pod update事件,繼續(xù)比較spec.NodeName 和其本身的nodeName. 當(dāng)match之后,通過啟動pod的container,并且把container啟動的狀態(tài)信息寫入pod status, 返回存儲到apiserver。
rs controller注意到pod改變。
最后pod銷毀時,kubelet watch到pod事件并且將pod狀態(tài)設(shè)置為“terminated”狀態(tài),并更新到apiserver。
rs controller觀測到結(jié)束的pod,決定這個pod一定需要被替換。于是通過apiserver刪除 terminated狀態(tài)的pod,并且創(chuàng)建一個新的。
一系列獨立的控制循環(huán),通過watch apiserver中對象的變化,并且這些變更事件通過informers來觸發(fā)變更。
watch events 和 event對象是兩個東西:
前者通過在apiserver和controllers之間建立http streaming 的鏈接用來驅(qū)動informers.
后者是一種資源,像pod,dp,services這些,帶有特殊的時效屬性并且自動從etcd里消失。
前者是基于某個狀態(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.
reconciliation with resync:每5分鐘持續(xù)調(diào)諧。
edge-triggered, level-driven
level-triggering-and-reconciliation
單體式:
二階段:
共享狀態(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)雅。
operator是一種針對特定應(yīng)用的控制器,擴(kuò)展了k8s API的創(chuàng)建、配置、管理復(fù)雜的有狀態(tài)應(yīng)用的實例。
一個operator包括一個 CRD+ controller。
apiserver作為擋在存儲etcd前的唯一組件,跟etcd進(jìn)行直接交互。主要職責(zé)是作為k8s api的server 和集群組件的proxy。
伺服API意味著 讀取狀態(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)中感知到。
DefaultBuildHandlerChain()
WithPanicRecovery(): 處理恢復(fù)和日志panic
Repos
k8s項目提供client-go(https://github.com/kubernetes/client-go) 作為用戶的開發(fā)工具集,提供了多種類型的API支持,以及包含許多通用庫代碼。
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"`
}
第三個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資源是一種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 } 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 }
通過嵌套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)。
出了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字段。
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è)資訊頻道。
免責(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)容。