亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

深入剖析Kubernetes核心組件:apiserver、scheduler的源碼級分析

2024-05-30 03:12:55
13
0

Kubernetes的架構中,apiserver、scheduler和controller-manager這三個核心組件扮演著至關重要的角色。它們共同協作,維護著整個集群的狀態和運行。本文將從源碼層面深入分析這三個組件的工作原理,揭示Kubernetes背后的設計思想和實現細節。

一、apiserver:Kubernetes的門戶

apiserver是Kubernetes的核心組件之一,它提供了集群的統一入口,負責接收、驗證和處理所有的REST請求。同時,它也是集群狀態的唯一真實來源(Single Source of Truth),維護著所有資源對象的最新狀態。

讓我們從kubernetes/cmd/kube-apiserver/apiserver.goRun函數開始,追蹤apiserver的啟動流程。

func Run(completeOptions completedServerRunOptions, stopCh <-chan struct{}) error {

    // ...

    server, err := CreateServerChain(completeOptions, stopCh)

    if err != nil {

        return err

    }

 

    return server.PrepareRun().Run(stopCh)

}

CreateServerChain函數中,apiserver會創建一個名為GenericAPIServer的通用API服務器,并注冊各種資源對象的RESTful API。

func CreateKubeAPIServerConfig(s completedConfig, nodeTunneler tunneler.Tunneler, proxyTransport *http.Transport) (*master.Config, error) {

    // ...

    genericConfig := genericapiserver.NewConfig(legacyscheme.Codecs)

    // ...

    config := &master.Config{

        GenericConfig: genericConfig,

        // ...

    }

    return config, nil

}

當一個請求到達apiserver時,會經過一系列的過濾器(Filter)和攔截器(Interceptor)的處理,例如認證、授權、準入控制等。這些插件式的擴展點使得Kubernetes能夠靈活地控制請求的訪問和操作。

k8s.io/apiserver/pkg/server/handler.go中,我們可以看到請求的處理鏈:

func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {

    handler := genericapifilters.WithAuthorization(apiHandler, c.Authorization.Authorizer, c.Serializer)

    handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.LongRunningFunc)

    handler = genericapifilters.WithImpersonation(handler, c.Authorization.Authorizer, c.Serializer)

    // ...

    handler = genericfilters.WithPanicRecovery(handler)

    return handler

}

經過一系列的處理后,請求最終會被轉發到對應的REST資源上,由相應的處理函數進行操作。

二、scheduler:智能調度的核心

scheduler是Kubernetes中負責Pod調度的核心組件。它根據預定義的調度策略和算法,將新創建的Pod分配到最優的Node上運行。

讓我們從kubernetes/cmd/kube-scheduler/app/server.goRun函數開始,追蹤scheduler的啟動流程。

func Run(cc schedulerserverconfig.CompletedConfig, stopCh <-chan struct{}) error {

    // ...

    sched, err := scheduler.New(cc.Client,

        cc.InformerFactory.Core().V1().Nodes(),

        cc.PodInformer,

        cc.InformerFactory.Core().V1().PersistentVolumes(),

        cc.InformerFactory.Core().V1().PersistentVolumeClaims(),

        cc.InformerFactory.Core().V1().ReplicationControllers(),

        cc.InformerFactory.Apps().V1().ReplicaSets(),

        cc.InformerFactory.Apps().V1().StatefulSets(),

        cc.InformerFactory.Core().V1().Services(),

        cc.InformerFactory.Policy().V1beta1().PodDisruptionBudgets(),

        cc.InformerFactory.Storage().V1().StorageClasses(),

        cc.Recorder,

        cc.ComponentConfig.AlgorithmSource,

        stopCh,

        scheduler.WithName(cc.ComponentConfig.SchedulerName),

        scheduler.WithHardPodAffinitySymmetricWeight(cc.ComponentConfig.HardPodAffinitySymmetricWeight),

        scheduler.WithPreemptionDisabled(cc.ComponentConfig.DisablePreemption),

        scheduler.WithPercentageOfNodesToScore(cc.ComponentConfig.PercentageOfNodesToScore),

        scheduler.WithBindTimeoutSeconds(*cc.ComponentConfig.BindTimeoutSeconds))

    // ...

    sched.Run()

    return nil

}

scheduler.New函數中,scheduler會創建一個名為Scheduler的對象,并配置各種調度算法和策略。Scheduler會監聽Kubernetes的資源事件,當有新的Pod需要調度時,會執行預選(Predicates)和優選(Priorities)兩個階段的調度算法。

預選階段會根據Pod的資源需求和約束條件,過濾掉不滿足要求的Node。例如,如果Pod要求GPU,但Node沒有GPU資源,則該Node會被過濾掉。

優選階段則會對預選階段篩選出的Node進行打分,根據Node的負載、親和性、資源使用率等指標,選出得分最高的Node作為最優的調度結果。

k8s.io/kubernetes/pkg/scheduler/core/generic_scheduler.go中,我們可以看到調度算法的核心邏輯:

func (g *genericScheduler) Schedule(pod *v1.Pod, pluginContext *framework.PluginContext) (result ScheduleResult, err error) {

    // ...

    feasibleNodes, diagnosis, err := g.findNodesThatFitPod(ctx, extenders, fwk, state, pod)

    if err != nil {

        return result, err

    }

    // ...

    priorityList, err := g.prioritizeNodes(ctx, extenders, fwk, state, pod, feasibleNodes)

    if err != nil {

        return result, err

    }

    // ...

    host, err := g.selectHost(priorityList)

    return ScheduleResult{

        SuggestedHost:  host,

        EvaluatedNodes: len(feasibleNodes) + len(diagnosis.NodeToStatusMap),

        FeasibleNodes:  len(feasibleNodes),

    }, err

}

最終,scheduler會將調度結果通過apiserver更新到Pod對象上,將Pod分配到選定的Node上運行。

三、controller-manager:狀態協調的守護者

controller-manager是Kubernetes中負責維護集群狀態的核心組件。它運行著各種控制器(Controller),通過apiserver監聽資源對象的變化,并觸發相應的控制循環(Control Loop),使得集群的實際狀態不斷地向期望狀態收斂。

讓我們從kubernetes/cmd/kube-controller-manager/app/controllermanager.goRun函數開始,追蹤controller-manager的啟動流程。

func Run(c *config.CompletedConfig, stopCh <-chan struct{}) error {

    // ...

    run := func(ctx context.Context, startSATokenController InitFunc, initFuncs map[string]InitFunc) {

        controllerContext, err := CreateControllerContext(c, rootClientBuilder, clientBuilder, ctx.Done())

        if err != nil {

            klog.Fatalf("error building controller context: %v", err)

        }

        // ...

        for controllerName, initFn := range initFuncs {

            if !ctx.Err() {

                klog.V(1).Infof("Starting %q", controllerName)

                started, err := initFn(ctx, controllerContext)

                // ...

            }

        }

        // ...

    }

 

    run(context.TODO(), saTokenControllerInitFunc, NewControllerInitializers(completedConfig.ControllerClientBuilder))

    return nil

}

run函數中,controller-manager會為每個控制器創建一個上下文對象ControllerContext,并調用每個控制器的初始化函數initFn,啟動控制循環。

例如,讓我們以ReplicaSet控制器為例,看看它是如何工作的。

kubernetes/pkg/controller/replicaset/replica_set.go中,我們可以找到ReplicaSet控制器的核心邏輯:

func (rsc *ReplicaSetController) syncReplicaSet(key string) error {

    // ...

    rs, err := rsc.rsLister.ReplicaSets(namespace).Get(name)

    // ...

    selector, err := metav1.LabelSelectorAsSelector(rs.Spec.Selector)

    // ...

    allPods, err := rsc.podLister.Pods(rs.Namespace).List(labels.Everything())

    // ...

    filteredPods := controller.FilterActivePods(allPods)

    filteredPods, err = rsc.claimPods(rs, selector, filteredPods)

    // ...

    diff := len(filteredPods) - int(*(rs.Spec.Replicas))

    if diff < 0 {

        diff *= -1

        if diff > rsc.burstReplicas {

            diff = rsc.burstReplicas

        }

        // ...

        rsc.expectations.ExpectCreations(rsKey, diff)

        // ...

    } else if diff > 0 {

        if diff > rsc.burstReplicas {

            diff = rsc.burstReplicas

        }

        // ...

        rsc.expectations.ExpectDeletions(rsKey, getPodKeys(podsToDelete))

        // ...

    }

    return nil

}

ReplicaSet控制器會通過apiserver監聽ReplicaSet和Pod對象的變化,當實際的Pod數量與期望的副本數不一致時,會觸發控制循環,根據差值創建或刪除Pod,使得ReplicaSet的實際狀態與期望狀態保持一致。

類似地,Kubernetes中的其他控制器,如Deployment、DaemonSet、StatefulSet等,都遵循類似的工作模式,通過不斷地協調集群狀態,維護著Kubernetes的高可用和穩定性。

總結

本文從源碼層面深入剖析了Kubernetes的三個核心組件:apiserver、scheduler和controller-manager。我們追蹤了它們的啟動流程,分析了其中的關鍵邏輯和設計思想。

apiserver作為Kubernetes的門戶,提供了統一的REST API接口,并通過一系列的過濾器和攔截器,實現了靈活的準入控制和安全策略。

scheduler則負責Pod的調度,通過預選和優選兩個階段的調度算法,將Pod分配到最優的Node上運行,提高了集群的資源利用率和性能。

controller-manager通過各種控制器,不斷地監聽集群狀態的變化,并觸發控制循環,使得集群的實際狀態向期望狀態收斂,維護著Kubernetes的高可用和穩定性。

掌握了這三個核心組件的工作原理和源碼實現,對于深入理解Kubernetes的架構設計和運行機制有著重要的意義。同時,這也為我們進一步擴展和優化Kubernetes,以滿足更加復雜多變的業務場景提供了堅實的基礎。

 

0條評論
0 / 1000
易乾
593文章數
0粉絲數
易乾
593 文章 | 0 粉絲
原創

深入剖析Kubernetes核心組件:apiserver、scheduler的源碼級分析

2024-05-30 03:12:55
13
0

Kubernetes的架構中,apiserver、scheduler和controller-manager這三個核心組件扮演著至關重要的角色。它們共同協作,維護著整個集群的狀態和運行。本文將從源碼層面深入分析這三個組件的工作原理,揭示Kubernetes背后的設計思想和實現細節。

一、apiserver:Kubernetes的門戶

apiserver是Kubernetes的核心組件之一,它提供了集群的統一入口,負責接收、驗證和處理所有的REST請求。同時,它也是集群狀態的唯一真實來源(Single Source of Truth),維護著所有資源對象的最新狀態。

讓我們從kubernetes/cmd/kube-apiserver/apiserver.goRun函數開始,追蹤apiserver的啟動流程。

func Run(completeOptions completedServerRunOptions, stopCh <-chan struct{}) error {

    // ...

    server, err := CreateServerChain(completeOptions, stopCh)

    if err != nil {

        return err

    }

 

    return server.PrepareRun().Run(stopCh)

}

CreateServerChain函數中,apiserver會創建一個名為GenericAPIServer的通用API服務器,并注冊各種資源對象的RESTful API。

func CreateKubeAPIServerConfig(s completedConfig, nodeTunneler tunneler.Tunneler, proxyTransport *http.Transport) (*master.Config, error) {

    // ...

    genericConfig := genericapiserver.NewConfig(legacyscheme.Codecs)

    // ...

    config := &master.Config{

        GenericConfig: genericConfig,

        // ...

    }

    return config, nil

}

當一個請求到達apiserver時,會經過一系列的過濾器(Filter)和攔截器(Interceptor)的處理,例如認證、授權、準入控制等。這些插件式的擴展點使得Kubernetes能夠靈活地控制請求的訪問和操作。

k8s.io/apiserver/pkg/server/handler.go中,我們可以看到請求的處理鏈:

func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {

    handler := genericapifilters.WithAuthorization(apiHandler, c.Authorization.Authorizer, c.Serializer)

    handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.LongRunningFunc)

    handler = genericapifilters.WithImpersonation(handler, c.Authorization.Authorizer, c.Serializer)

    // ...

    handler = genericfilters.WithPanicRecovery(handler)

    return handler

}

經過一系列的處理后,請求最終會被轉發到對應的REST資源上,由相應的處理函數進行操作。

二、scheduler:智能調度的核心

scheduler是Kubernetes中負責Pod調度的核心組件。它根據預定義的調度策略和算法,將新創建的Pod分配到最優的Node上運行。

讓我們從kubernetes/cmd/kube-scheduler/app/server.goRun函數開始,追蹤scheduler的啟動流程。

func Run(cc schedulerserverconfig.CompletedConfig, stopCh <-chan struct{}) error {

    // ...

    sched, err := scheduler.New(cc.Client,

        cc.InformerFactory.Core().V1().Nodes(),

        cc.PodInformer,

        cc.InformerFactory.Core().V1().PersistentVolumes(),

        cc.InformerFactory.Core().V1().PersistentVolumeClaims(),

        cc.InformerFactory.Core().V1().ReplicationControllers(),

        cc.InformerFactory.Apps().V1().ReplicaSets(),

        cc.InformerFactory.Apps().V1().StatefulSets(),

        cc.InformerFactory.Core().V1().Services(),

        cc.InformerFactory.Policy().V1beta1().PodDisruptionBudgets(),

        cc.InformerFactory.Storage().V1().StorageClasses(),

        cc.Recorder,

        cc.ComponentConfig.AlgorithmSource,

        stopCh,

        scheduler.WithName(cc.ComponentConfig.SchedulerName),

        scheduler.WithHardPodAffinitySymmetricWeight(cc.ComponentConfig.HardPodAffinitySymmetricWeight),

        scheduler.WithPreemptionDisabled(cc.ComponentConfig.DisablePreemption),

        scheduler.WithPercentageOfNodesToScore(cc.ComponentConfig.PercentageOfNodesToScore),

        scheduler.WithBindTimeoutSeconds(*cc.ComponentConfig.BindTimeoutSeconds))

    // ...

    sched.Run()

    return nil

}

scheduler.New函數中,scheduler會創建一個名為Scheduler的對象,并配置各種調度算法和策略。Scheduler會監聽Kubernetes的資源事件,當有新的Pod需要調度時,會執行預選(Predicates)和優選(Priorities)兩個階段的調度算法。

預選階段會根據Pod的資源需求和約束條件,過濾掉不滿足要求的Node。例如,如果Pod要求GPU,但Node沒有GPU資源,則該Node會被過濾掉。

優選階段則會對預選階段篩選出的Node進行打分,根據Node的負載、親和性、資源使用率等指標,選出得分最高的Node作為最優的調度結果。

k8s.io/kubernetes/pkg/scheduler/core/generic_scheduler.go中,我們可以看到調度算法的核心邏輯:

func (g *genericScheduler) Schedule(pod *v1.Pod, pluginContext *framework.PluginContext) (result ScheduleResult, err error) {

    // ...

    feasibleNodes, diagnosis, err := g.findNodesThatFitPod(ctx, extenders, fwk, state, pod)

    if err != nil {

        return result, err

    }

    // ...

    priorityList, err := g.prioritizeNodes(ctx, extenders, fwk, state, pod, feasibleNodes)

    if err != nil {

        return result, err

    }

    // ...

    host, err := g.selectHost(priorityList)

    return ScheduleResult{

        SuggestedHost:  host,

        EvaluatedNodes: len(feasibleNodes) + len(diagnosis.NodeToStatusMap),

        FeasibleNodes:  len(feasibleNodes),

    }, err

}

最終,scheduler會將調度結果通過apiserver更新到Pod對象上,將Pod分配到選定的Node上運行。

三、controller-manager:狀態協調的守護者

controller-manager是Kubernetes中負責維護集群狀態的核心組件。它運行著各種控制器(Controller),通過apiserver監聽資源對象的變化,并觸發相應的控制循環(Control Loop),使得集群的實際狀態不斷地向期望狀態收斂。

讓我們從kubernetes/cmd/kube-controller-manager/app/controllermanager.goRun函數開始,追蹤controller-manager的啟動流程。

func Run(c *config.CompletedConfig, stopCh <-chan struct{}) error {

    // ...

    run := func(ctx context.Context, startSATokenController InitFunc, initFuncs map[string]InitFunc) {

        controllerContext, err := CreateControllerContext(c, rootClientBuilder, clientBuilder, ctx.Done())

        if err != nil {

            klog.Fatalf("error building controller context: %v", err)

        }

        // ...

        for controllerName, initFn := range initFuncs {

            if !ctx.Err() {

                klog.V(1).Infof("Starting %q", controllerName)

                started, err := initFn(ctx, controllerContext)

                // ...

            }

        }

        // ...

    }

 

    run(context.TODO(), saTokenControllerInitFunc, NewControllerInitializers(completedConfig.ControllerClientBuilder))

    return nil

}

run函數中,controller-manager會為每個控制器創建一個上下文對象ControllerContext,并調用每個控制器的初始化函數initFn,啟動控制循環。

例如,讓我們以ReplicaSet控制器為例,看看它是如何工作的。

kubernetes/pkg/controller/replicaset/replica_set.go中,我們可以找到ReplicaSet控制器的核心邏輯:

func (rsc *ReplicaSetController) syncReplicaSet(key string) error {

    // ...

    rs, err := rsc.rsLister.ReplicaSets(namespace).Get(name)

    // ...

    selector, err := metav1.LabelSelectorAsSelector(rs.Spec.Selector)

    // ...

    allPods, err := rsc.podLister.Pods(rs.Namespace).List(labels.Everything())

    // ...

    filteredPods := controller.FilterActivePods(allPods)

    filteredPods, err = rsc.claimPods(rs, selector, filteredPods)

    // ...

    diff := len(filteredPods) - int(*(rs.Spec.Replicas))

    if diff < 0 {

        diff *= -1

        if diff > rsc.burstReplicas {

            diff = rsc.burstReplicas

        }

        // ...

        rsc.expectations.ExpectCreations(rsKey, diff)

        // ...

    } else if diff > 0 {

        if diff > rsc.burstReplicas {

            diff = rsc.burstReplicas

        }

        // ...

        rsc.expectations.ExpectDeletions(rsKey, getPodKeys(podsToDelete))

        // ...

    }

    return nil

}

ReplicaSet控制器會通過apiserver監聽ReplicaSet和Pod對象的變化,當實際的Pod數量與期望的副本數不一致時,會觸發控制循環,根據差值創建或刪除Pod,使得ReplicaSet的實際狀態與期望狀態保持一致。

類似地,Kubernetes中的其他控制器,如Deployment、DaemonSet、StatefulSet等,都遵循類似的工作模式,通過不斷地協調集群狀態,維護著Kubernetes的高可用和穩定性。

總結

本文從源碼層面深入剖析了Kubernetes的三個核心組件:apiserver、scheduler和controller-manager。我們追蹤了它們的啟動流程,分析了其中的關鍵邏輯和設計思想。

apiserver作為Kubernetes的門戶,提供了統一的REST API接口,并通過一系列的過濾器和攔截器,實現了靈活的準入控制和安全策略。

scheduler則負責Pod的調度,通過預選和優選兩個階段的調度算法,將Pod分配到最優的Node上運行,提高了集群的資源利用率和性能。

controller-manager通過各種控制器,不斷地監聽集群狀態的變化,并觸發控制循環,使得集群的實際狀態向期望狀態收斂,維護著Kubernetes的高可用和穩定性。

掌握了這三個核心組件的工作原理和源碼實現,對于深入理解Kubernetes的架構設計和運行機制有著重要的意義。同時,這也為我們進一步擴展和優化Kubernetes,以滿足更加復雜多變的業務場景提供了堅實的基礎。

 

文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0