您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“API Basics怎么實現”,內容詳細,步驟清晰,細節處理妥當,希望這篇“API Basics怎么實現”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
所謂的云原生應用,能夠清楚自己運行在k8s上,并且使用k8s api 和資源當作其擴展。
一方面,云原生應用能夠輕便地在不同的云上遷移。另一方面,受益于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: 實現了一個控制循環,從API server監聽到的集群狀態,并且把當前狀態調整到預期狀態。
operator: 是指controller+ 自定義資源的方式,去做像應用生命周期管理相關的一些操作。
讀取資源的狀態,更傾向于事件驅動。
改變集群或外部集群的對象的狀態。
通過apiserver更新存儲在etcd中資源的狀態。
重復循環。回到步驟1.
不管controller的實現復雜與否,這三步驟都是一致的。讀取資源狀態->改變the world-> 更新資源狀態。
informers:
負責watch期望的狀態,實現resync機制加強周期性的調諧,通常用來確保集群狀態和存在內存中的期望狀態不飄動。
work queues:
在client-go的workqueue包中實現了,為event handler提供work queues來“存儲”狀態變更操作的隊列及其各種重試操作。當更新當前資源對象狀態出錯時,資源需要重新被排序。
k8s的控制面通過事件驅動 進行解耦,其他分布式系統通過遠程過程調用來觸發各種行為。controller 通過watch k8s對象的變化對APISERVER的增、刪、改請求。
example:
用戶 創建一個dp時,dp controller通過dp informer 創建一個rs。
rs controller通過 rs informer 創建一個新的rs,并且創建一個pod對象。
scheduler通過pod informer觀測到新的pod,且它的spec.nodeName 為空,就把這個pod放入調度隊列。
與此同時,kubelet通過pod informer觀測到新的pod,且它的spec.nodeName 為空。所以并沒有match到kubelet的nodeName,會忽略這個pod 繼續等待下一次事件。
scheduler從workqueue中拿出pod,并且通過更新spec.nodeName字段,調度到有足夠資源的指定node,并且寫入apiserver。
kubelet因為pod update事件,繼續比較spec.NodeName 和其本身的nodeName. 當match之后,通過啟動pod的container,并且把container啟動的狀態信息寫入pod status, 返回存儲到apiserver。
rs controller注意到pod改變。
最后pod銷毀時,kubelet watch到pod事件并且將pod狀態設置為“terminated”狀態,并更新到apiserver。
rs controller觀測到結束的pod,決定這個pod一定需要被替換。于是通過apiserver刪除 terminated狀態的pod,并且創建一個新的。
一系列獨立的控制循環,通過watch apiserver中對象的變化,并且這些變更事件通過informers來觸發變更。
watch events 和 event對象是兩個東西:
前者通過在apiserver和controllers之間建立http streaming 的鏈接用來驅動informers.
后者是一種資源,像pod,dp,services這些,帶有特殊的時效屬性并且自動從etcd里消失。
前者是基于某個狀態值變更的瞬間去觸發handler,后者是在某個時間段內、狀態被驗證與期望值相符,則去觸發handler。
后者更像是一種polling輪詢,能否擴容到指定數量、控制器注意到變更的延遲依賴于polling輪詢的時間間隔以及apiserver的響應時間。與很多異步的控制器相關,最終系統需要花費一段時間才能達到預期狀態。
前者效率更高,延遲則依賴在控制器處理事件時,運行的工作線程。因此k8s基于事件驅動,即edge-driven triggers.
reconciliation with resync:每5分鐘持續調諧。
edge-triggered, level-driven
level-triggering-and-reconciliation
單體式:
二階段:
共享狀態:
并行調度架構:
新一代的并發調度架構依賴共享狀態,使用樂觀并發控制達到實現可擴展和性能可伸縮。
k8s 中樂觀鎖的場景是:
retry loop中,獲取了foo對象最新的狀態后,嘗試根據foo spec更新real world 和foo status,實際修改的操作在Update事件之前執行。
通過client.Get返回的foo對象,包含資源的版本,ObjectMeta結構體。這個結構體會在client.Update調用時,通過寫操作更新etcd的數據。所謂的資源版本,在etcd中存儲的實際上是<string,int> 鍵值對。etcd維護了一個計數器counter,每次key的值被修改時,counter值加一。
在API machinery代碼中,資源版本的處理像是任意的string,實際上還是遵循一些規則。實際的實現細節在etcd存儲后端。
essence: 控制器中的沖突錯誤十分常見,處理和期待十分優雅。
operator是一種針對特定應用的控制器,擴展了k8s API的創建、配置、管理復雜的有狀態應用的實例。
一個operator包括一個 CRD+ controller。
apiserver作為擋在存儲etcd前的唯一組件,跟etcd進行直接交互。主要職責是作為k8s api的server 和集群組件的proxy。
伺服API意味著 讀取狀態和 操作狀態。
通過比較期望狀態的spec和當前實際狀態的值,
例如:當你在dp的聲明yaml里指定20個副本數,dp controller讀到dp spec并且創建rs,實際去接管rs- 即特定個數的pods。如果有任何副本跪了,dp controller會讓你在狀態中感知到。
DefaultBuildHandlerChain()
WithPanicRecovery(): 處理恢復和日志panic
Repos
k8s項目提供client-go(https://github.com/kubernetes/client-go) 作為用戶的開發工具集,提供了多種類型的API支持,以及包含許多通用庫代碼。
client-go管理了客戶端接口,像PODS,services,deployments這些接口,在這個repo中維護(https://github.com/kubernetes/api),pod等的類型在k8s.io/api/core/v1/types.go
中定義,而這些文件均由code gen自動生成維護。
// 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 ) 包含所有通用的構建模塊,不僅限于容器管理,還包括其他構建 APIs。在pkg/api/meta/v1 下可以查看到許多API類型的定義,包括如下:
ObjectMeta: Name + Namespaces + ResourceVersion + Labels + Annotations
TypeMeta : Kind + APIVersion
GetOptions,
ListOptions
構建模塊用來創建k8s客戶端對象,代表在k8s集群中能訪問的資源。
k8s 的api是按版本區分的,一方面client的不同版本去訪問API server,如果版本不匹配,請求會失敗。client 與特定的版本綁定,應用開發者需要選擇正確的
其版本與k8s版本對應關系如圖:
| 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作為一種資源結構體提供服務。
k8s中的object 實現了runtime.Object接口,來自于k8s.io/apimachinery/pkg/runtime包。其中,schema.ObjectKind主要實現的另一個接口,來自于k8s.io/apimachinery/pkg/runtime/schema.
這些Go實現的object作為數據結構主要是用來返回和設置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)來實現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的應用這些字段在內存中值為空,在實際序列化成json或者pb時,才會有實際的值。而這些約定在版本序列中自動實現。
出了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基本包含所有元數據信息,像name,namespace,resource version, 一些時間戳,以及labels 和annotation. 其中client-go并不能對resource version進行讀寫,但卻是整個k8s代碼中核心工作的重要信息.
它作為ObjectMeta信息的一部分,來源于etcd里所有數據的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有所謂的內部客戶端,為了對象在內存中存在的更加通用,并且遵循在需要的時候再定義的規范。這種規范為了從實際使用的API版本中抽象controller代碼,同時方便切換不同版本。事實上,為了遵循這種規范,增加了大量的復雜性,付出了不太值得的代價。 >此外,在client和APIServer之間的交互,并沒有自動協商的機制。盡管存在內部的版本和客戶端,controller硬編碼到指定版本導致并沒有很好兼容。 >在最近的版本,k8s代碼盡量避免用到這些內部版本。
所有clientset可以訪問discovery client,被用作RESTMappers;
type AppsV1beta1Interface interface { RESTClient() rest.Interface ControllerRevisionsGetter DeploymentsGetter ScalesGetter StatefulSetsGetter }
在每個GroupVersion(AppsV1beta1)下我們發現API group的資源都存在通用的RESTClient
讀到這里,這篇“API Basics怎么實現”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。