• k8s基础 ~ 4


    client-go,这个很牛,k8s大部分交互都靠它

    discovery/dynamic动态客户端;informers是非常重要的通讯机制;kubernetes是clientset客户端;rest是rest客户端;util包含队列等

    RESTClient是最基础的客户端。RESTClient对HTTP Request进行了封装,实现了RESTful风格的API。ClientSet、DynamicClient及DiscoveryClient客户端都是基于RESTClient实现的。

    type Interface interface {
        GetRateLimiter() flowcontrol.RateLimiter
        Verb(verb string) *Request
        Post() *Request
        Put() *Request
        Patch(pt types.PatchType) *Request
        Get() *Request
        Delete() *Request
        APIVersion() schema.GroupVersion
    }

    client

    type RESTClient struct {
        // base is the root URL for all invocations of the client
        base *url.URL
        // versionedAPIPath is a path segment connecting the base URL to the resource root
        versionedAPIPath string
    
        // content describes how a RESTClient encodes and decodes responses.
        content ClientContentConfig
    
        // creates BackoffManager that is passed to requests.
        createBackoffMgr func() BackoffManager
    
        // rateLimiter is shared among all requests created by this client unless specifically
        // overridden.
        rateLimiter flowcontrol.RateLimiter
    
        // warningHandler is shared among all requests created by this client.
        // If not set, defaultWarningHandler is used.
        warningHandler WarningHandler
    
        // Set specific behavior of the client.  If not set http.DefaultClient will be used.
        Client *http.Client
    }

    ClientSet在RESTClient的基础上封装了对Resource和Version的管理方法。每一个Resource可以理解为一个客户端,而ClientSet则是多个客户端的集合,每一个Resource和Version都以函数的方式暴露给开发者。ClientSet只能够处理Kubernetes内置资源,它是通过client-gen代码生成器自动生成的。

    type Clientset struct {
        *discovery.DiscoveryClient
        admissionregistrationV1      *admissionregistrationv1.AdmissionregistrationV1Client
        admissionregistrationV1beta1 *admissionregistrationv1beta1.AdmissionregistrationV1beta1Client
        internalV1alpha1             *internalv1alpha1.InternalV1alpha1Client
        appsV1                       *appsv1.AppsV1Client
        appsV1beta1                  *appsv1beta1.AppsV1beta1Client
        appsV1beta2                  *appsv1beta2.AppsV1beta2Client
        authenticationV1             *authenticationv1.AuthenticationV1Client
        authenticationV1beta1        *authenticationv1beta1.AuthenticationV1beta1Client
        authorizationV1              *authorizationv1.AuthorizationV1Client
        authorizationV1beta1         *authorizationv1beta1.AuthorizationV1beta1Client
        autoscalingV1                *autoscalingv1.AutoscalingV1Client
        autoscalingV2beta1           *autoscalingv2beta1.AutoscalingV2beta1Client
        autoscalingV2beta2           *autoscalingv2beta2.AutoscalingV2beta2Client
        batchV1                      *batchv1.BatchV1Client
        batchV1beta1                 *batchv1beta1.BatchV1beta1Client
        certificatesV1               *certificatesv1.CertificatesV1Client
        certificatesV1beta1          *certificatesv1beta1.CertificatesV1beta1Client
        coordinationV1beta1          *coordinationv1beta1.CoordinationV1beta1Client
        coordinationV1               *coordinationv1.CoordinationV1Client
        coreV1                       *corev1.CoreV1Client
        discoveryV1                  *discoveryv1.DiscoveryV1Client
        discoveryV1beta1             *discoveryv1beta1.DiscoveryV1beta1Client
        eventsV1                     *eventsv1.EventsV1Client
        eventsV1beta1                *eventsv1beta1.EventsV1beta1Client
        extensionsV1beta1            *extensionsv1beta1.ExtensionsV1beta1Client
        flowcontrolV1alpha1          *flowcontrolv1alpha1.FlowcontrolV1alpha1Client
        flowcontrolV1beta1           *flowcontrolv1beta1.FlowcontrolV1beta1Client
        networkingV1                 *networkingv1.NetworkingV1Client
        networkingV1beta1            *networkingv1beta1.NetworkingV1beta1Client
        nodeV1                       *nodev1.NodeV1Client
        nodeV1alpha1                 *nodev1alpha1.NodeV1alpha1Client
        nodeV1beta1                  *nodev1beta1.NodeV1beta1Client
        policyV1                     *policyv1.PolicyV1Client
        policyV1beta1                *policyv1beta1.PolicyV1beta1Client
        rbacV1                       *rbacv1.RbacV1Client
        rbacV1beta1                  *rbacv1beta1.RbacV1beta1Client
        rbacV1alpha1                 *rbacv1alpha1.RbacV1alpha1Client
        schedulingV1alpha1           *schedulingv1alpha1.SchedulingV1alpha1Client
        schedulingV1beta1            *schedulingv1beta1.SchedulingV1beta1Client
        schedulingV1                 *schedulingv1.SchedulingV1Client
        storageV1beta1               *storagev1beta1.StorageV1beta1Client
        storageV1                    *storagev1.StorageV1Client
        storageV1alpha1              *storagev1alpha1.StorageV1alpha1Client
    }

    DynamicClient与ClientSet最大的不同之处是,ClientSet仅能访问Kubernetes自带的资源(即Client集合内的资源),不能直接访问CRD自定义资源。DynamicClient能够处理Kubernetes中的所有资源对象,包括Kubernetes内置资源与CRD自定义资源。

    DiscoveryClient发现客户端,用于发现kube-apiserver所支持的资源组、资源版本、资源信息(即Group、Versions、Resources)

    type DiscoveryClient struct {
        restClient restclient.Interface
        LegacyPrefix string
    }

    在Kubernetes系统中,组件之间通过HTTP协议进行通信,在不依赖任何中间件的情况下需要保证消息的实时性、可靠性、顺序性等。Kubernetes的其他组件都是通过client-go的Informer机制与Kubernetes API Server进行通信的

    1.Reflector
    Reflector用于监控(Watch)指定的Kubernetes资源,当监控的资源发生变化时,触发相应的变更事件,例如Added(资源添加)事件、Updated(资源更新)事件、Deleted(资源删除)事件,并将其资源对象存放到本地缓存DeltaFIFO中。

    type Reflector struct {
        // name identifies this reflector. By default it will be a file:line if possible.
        name string
    
        // The name of the type we expect to place in the store. The name
        // will be the stringification of expectedGVK if provided, and the
        // stringification of expectedType otherwise. It is for display
        // only, and should not be used for parsing or comparison.
        expectedTypeName string
        // An example object of the type we expect to place in the store.
        // Only the type needs to be right, except that when that is
        // `unstructured.Unstructured` the object's `"apiVersion"` and
        // `"kind"` must also be right.
        expectedType reflect.Type
        // The GVK of the object we expect to place in the store if unstructured.
        expectedGVK *schema.GroupVersionKind
        // The destination to sync up with the watch source
        store Store
        // listerWatcher is used to perform lists and watches.
        listerWatcher ListerWatcher
    
        // backoff manages backoff of ListWatch
        backoffManager wait.BackoffManager
        // initConnBackoffManager manages backoff the initial connection with the Watch calll of ListAndWatch.
        initConnBackoffManager wait.BackoffManager
    
        resyncPeriod time.Duration
        // ShouldResync is invoked periodically and whenever it returns `true` the Store's Resync operation is invoked
        ShouldResync func() bool
        // clock allows tests to manipulate time
        clock clock.Clock
        // paginatedResult defines whether pagination should be forced for list calls.
        // It is set based on the result of the initial list call.
        paginatedResult bool
        // lastSyncResourceVersion is the resource version token last
        // observed when doing a sync with the underlying store
        // it is thread safe, but not synchronized with the underlying store
        lastSyncResourceVersion string
        // isLastSyncResourceVersionUnavailable is true if the previous list or watch request with
        // lastSyncResourceVersion failed with an "expired" or "too large resource version" error.
        isLastSyncResourceVersionUnavailable bool
        // lastSyncResourceVersionMutex guards read/write access to lastSyncResourceVersion
        lastSyncResourceVersionMutex sync.RWMutex
        // WatchListPageSize is the requested chunk size of initial and resync watch lists.
        // If unset, for consistent reads (RV="") or reads that opt-into arbitrarily old data
        // (RV="0") it will default to pager.PageSize, for the rest (RV != "" && RV != "0")
        // it will turn off pagination to allow serving them from watch cache.
        // NOTE: It should be used carefully as paginated lists are always served directly from
        // etcd, which is significantly less efficient and may lead to serious performance and
        // scalability problems.
        WatchListPageSize int64
        // Called whenever the ListAndWatch drops the connection with an error.
        watchErrorHandler WatchErrorHandler
    }

    watch

    func (r *Reflector) watchHandler(start time.Time, w watch.Interface, resourceVersion *string, errc chan error, stopCh <-chan struct{}) error {
        eventCount := 0
    
        // Stopping the watcher should be idempotent and if we return from this function there's no way
        // we're coming back in with the same watch interface.
        defer w.Stop()
    
    loop:
        for {
            select {
            case <-stopCh:
                return errorStopRequested
            case err := <-errc:
                return err
            case event, ok := <-w.ResultChan():
                if !ok {
                    break loop
                }
                if event.Type == watch.Error {
                    return apierrors.FromObject(event.Object)
                }
                if r.expectedType != nil {
                    if e, a := r.expectedType, reflect.TypeOf(event.Object); e != a {
                        utilruntime.HandleError(fmt.Errorf("%s: expected type %v, but watch event object had type %v", r.name, e, a))
                        continue
                    }
                }
                if r.expectedGVK != nil {
                    if e, a := *r.expectedGVK, event.Object.GetObjectKind().GroupVersionKind(); e != a {
                        utilruntime.HandleError(fmt.Errorf("%s: expected gvk %v, but watch event object had gvk %v", r.name, e, a))
                        continue
                    }
                }
                meta, err := meta.Accessor(event.Object)
                if err != nil {
                    utilruntime.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", r.name, event))
                    continue
                }
                newResourceVersion := meta.GetResourceVersion()
                switch event.Type {
                case watch.Added:
                    err := r.store.Add(event.Object)
                    if err != nil {
                        utilruntime.HandleError(fmt.Errorf("%s: unable to add watch event object (%#v) to store: %v", r.name, event.Object, err))
                    }
                case watch.Modified:
                    err := r.store.Update(event.Object)
                    if err != nil {
                        utilruntime.HandleError(fmt.Errorf("%s: unable to update watch event object (%#v) to store: %v", r.name, event.Object, err))
                    }
                case watch.Deleted:
                    // TODO: Will any consumers need access to the "last known
                    // state", which is passed in event.Object? If so, may need
                    // to change this.
                    err := r.store.Delete(event.Object)
                    if err != nil {
                        utilruntime.HandleError(fmt.Errorf("%s: unable to delete watch event object (%#v) from store: %v", r.name, event.Object, err))
                    }
                case watch.Bookmark:
                    // A `Bookmark` means watch has synced here, just update the resourceVersion
                default:
                    utilruntime.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", r.name, event))
                }
                *resourceVersion = newResourceVersion
                r.setLastSyncResourceVersion(newResourceVersion)
                if rvu, ok := r.store.(ResourceVersionUpdater); ok {
                    rvu.UpdateResourceVersion(newResourceVersion)
                }
                eventCount++
            }
        }
    
        watchDuration := r.clock.Since(start)
        if watchDuration < 1*time.Second && eventCount == 0 {
            return fmt.Errorf("very short watch: %s: Unexpected watch close - watch lasted less than a second and no items received", r.name)
        }
        klog.V(4).Infof("%s: Watch close - %v total %v items received", r.name, r.expectedTypeName, eventCount)
        return nil
    }

    2.DeltaFIFO
    DeltaFIFO可以分开理解,FIFO是一个先进先出的队列,它拥有队列操作的基本方法,例如Add、Update、Delete、List、Pop、Close等,而Delta是一个资源对象存储,它可以保存资源对象的操作类型,例如Added(添加)操作类型、Updated(更新)操作类型、Deleted(删除)操作类型、Sync(同步)操作类型等。

    const (
        Added   DeltaType = "Added"
        Updated DeltaType = "Updated"
        Deleted DeltaType = "Deleted"
        // Replaced is emitted when we encountered watch errors and had to do a
        // relist. We don't know if the replaced object has changed.
        //
        // NOTE: Previous versions of DeltaFIFO would use Sync for Replace events
        // as well. Hence, Replaced is only emitted when the option
        // EmitDeltaTypeReplaced is true.
        Replaced DeltaType = "Replaced"
        // Sync is for synthetic events during a periodic resync.
        Sync DeltaType = "Sync"
    )

    3.Indexer
    Indexer是client-go用来存储资源对象并自带索引功能的本地存储,Reflector从DeltaFIFO中将消费出来的资源对象存储至Indexer。Indexer与Etcd集群中的数据完全保持一致。client-go可以很方便地从本地存储中读取相应的资源对象数据,而无须每次从远程Etcd集群中读取,以减轻Kubernetes API Server和Etcd集群的压力。

  • 相关阅读:
    9_输出表.md
    8_输入表详解.md
    3_imageoptionalheader32.md
    5_节表续.md
    1.md
    10_基址重定向.md
    4_节表.md
    如何优雅的写单词_lduoj_kmp
    杀人游戏_lduoj_Tarjan_强联通
    All in the Family_upc_模拟 or lca + 并查集
  • 原文地址:https://www.cnblogs.com/it-worker365/p/15216857.html
Copyright © 2020-2023  润新知