Kubernetes1.1源代码分析(二)

3、controller-manager模块

在controller manager模块中有几个重要的结构体,其中包括EndpointController、ReplicationManager、GCController、NodeController、ServiceController、RouteController、ResourceQuotaController,下面会进行介绍。在controller manager模块还有几个处于试验阶段的功能和结构体,这里不会进行介绍。

3.1、EndpointController

EndpointController是个入口控制器结构体,表示一组包含服务的Pods副本。里面有POD入口控制器podController变量和Service入口控制器serviceController变量,里面还有POD存储变量podStore和Service存储变量serviceStore,EndpointController结构体中还有queue变量和client变量。

type EndpointController struct {
    client *client.Client
    serviceStore cache.StoreToServiceLister
    podStore     cache.StoreToPodLister
    queue *workqueue.Type
    serviceController *framework.Controller
    podController     *framework.Controller
}

POD存储变量podStore和Service存储变量serviceStore都使用到了Store接口,Store接口其实就是一个通用的KEY/VALUE键值存储接口,这个接口用来实现对对象的操作,包括增加对象、更新对象、删除对象、列出所有KEY、列出所有对象、通过KEY查询对象等操作。KEY/VALUE键值存储接口的具体实现使用到了threadSafeMap结构体:

type threadSafeMap struct {
    lock  sync.RWMutex
    items map[string]interface{}
    indexers Indexers
    indices Indices
}

从中可以看出变量items其实就是GO语言的map类型,通过map来实现KEY到VALUE的映射。在threadSafeMap结构体中有个变量lock,这是一个读写互斥锁,通过这个锁来保证对map的操作是线程安全的,也就是多个线程同时操作map时不会产生不确定的结果。

POD存储变量podStore和Service存储变量serviceStore都是用来作为EndpointController端的缓存使用。

EndpointController结构体中queue变量是一个Type结构体:

type Type struct {
    queue []t
    dirty set
    processing set
    cond *sync.Cond
    shuttingDown bool
}

Type结构体就是一个工作队列,这个工作队列处理上有下面几个特点:

  1. 提供先进先出的处理模式
  2. 相同的内容放入这个工作队列多次后,这个工作队列只能处理一次
  3. 当一个内容被处理后,这个内容可以重新被放入队列中
  4. 队列关闭通知

EndpointController结构体中client变量是一个Client结构体:

type Client struct {
    *RESTClient
    *ExtensionsClient
    *DiscoveryClient
}

通过这个Client结构体来实现EndpointController结构体中serviceController和podController与kubernetes api-server的通讯。

POD入口控制器podController变量和Service入口控制器serviceController变量都使用到了Controller结构体:

type Controller struct {
    config         Config
    reflector      *cache.Reflector
    reflectorMutex sync.RWMutex
}

Controller结构体是一个通用的控制器结构体,这个结构体中有config、reflector和reflectorMutex三个变量。config变量是一个Config结构体,Config结构体的作用是负责控制器结构体所有的设置工作。Reflector变量是一个Reflector结构体,这个结构体是一个反射器结构体,负责监控指定的资源,并且通过反射机制对指定存储中的任何改变做出相应。ReflectorMutex这个变量同前面介绍过的threadSafeMap结构体中lock变量都使用到了RWMutex结构体,用来做读写互斥锁使用。

上面介绍了EndpointController这个结构体,下面介绍kuberneters controller manager如何使用这个结构体的。

首先controller manager创建Endpoint控制器,并且按照EndpointController结构体对Endpoint控制器中的serviceStore、podStore、queue、serviceController和podController几个变量进行初始化。

然后将serviceController和podController作为GO程序进行启动,也就是通过关键字“go”来运行,Go语言对并发编程的支持是天生的、自然的和高效的。Go语言为此专门创造出了一个关键字“go”。使用这个关键字,我们就可以很容易的使一个函数被并发的执行。

启动后,serviceController和podController两个控制器开始各自工作,这两个控制器都使用client变量同api-server进行通讯,将从api-server获取到的service和pod信息存放到本地serviceStore和podStore两个变量中缓存,之后都是通过对本地缓存进行处理,这两个控制器定期对缓存进行更新,以减少同api-server之间的通讯。这两个控制器都将需要处理的内容放入变量queue的队列中,getPodServiceMemberships函数会根据pod信息找到对应的service信息,这样就保证了变量queue的队列中只有service信息。

接着Endpoint控制器启动了几个worker程序,这些worker程序的作用在于处理queue队列中的service内容,在处理完之后标识service内容为已处理。Endpoint控制器默认启动5个worker来处理,当然可以启动更多的worker来加快queue队列中内容的处理速度,但是这样的话也会增加更多的CPU负载和网络负载。

每一个worker程序都从变量queue队列中取出一个service内容进行处理,最后同api-server进行通讯,对不存在的service创建endpoints,对已经存在的service更新endpoints。

3.2、ReplicationManager

下面介绍controller manager模块中ReplicationManager结构体,这是个副本控制器结构体,用来对kuberneters上已经运行的POD进行控制对象同步的,实际上这个副本控制器应该命名为ReplicationController,之所以没有这样命名,是为了同API对象“ReplicationController”进行区分。

type ReplicationManager struct {
    kubeClient client.Interface
    podControl controller.PodControlInterface
    burstReplicas int
    syncHandler func(rcKey string) error
    expectations controller.ControllerExpectationsInterface
    rcStore cache.StoreToReplicationControllerLister
    rcController *framework.Controller
    podStore cache.StoreToPodLister
    podController *framework.Controller
    podStoreSynced func() bool
    queue *workqueue.Type
}

ReplicationManager结构体中变量kubeClient是一个GO语言接口,用来同api-server通讯,变量podControl是一个GO语言接口,用来创建和删除POD。在ReplicationManager结构体中很多变量类型在上面EndpointController结构体中都已经介绍过,这里不在重复介绍,这里直接介绍kuberneters controller manager如何使用ReplicationManager这个结构体的。

首先controller manager创建ReplicationManager控制器,并且按照ReplicationManager结构体对ReplicationManager控制器中的几个变量进行初始化。

然后将rcController和podController作为GO程序进行启动,启动后,rcController和podController两个控制器开始各自工作,这两个控制器都使用client变量同api-server进行通讯,将从api-server获取到的replicationcontroller和pod信息存放到本地rcStore和podStore两个变量中缓存,之后都是通过对本地缓存进行处理,这两个控制器定期对缓存进行更新,以减少同api-server之间的通讯。这两个控制器都将需要处理的内容放入变量queue的队列中,由worker进行处理。

ReplicationManager控制器启动了几个worker程序,这些worker程序的作用在于处理queue队列中的replicationcontroller内容,在处理完之后标识replicationcontroller内容为已处理。ReplicationManager控制器默认启动5个worker来处理,每一个worker程序都从变量queue队列中取出一个replicationcontroller内容进行处理,最终会比较replicationcontroller中配置的POD副本数和系统中POD实际运行个数,如果这两个数值相同,那么不进行处理,如果replicationcontroller中配置的POD副本数大于系统中POD实际运行个数,那么会创建POD,如果replicationcontroller中配置的POD副本数小于系统中POD实际运行个数,那么会删除POD,删除的过程中会按照系统中POD运行状态进行排序,先删除比较早期状态的POD,比如如果同时not-ready状态和ready状态,那么会先删除not-ready状态的POD,如果unscheduled状态和scheduled状态,那么会先删除unscheduled状态的POD,如果pending状态和running状态,那么会先删除pending状态的POD。

创建POD或者删除POD都是向api-server发送POST请求,请求的过程作为GO程序进行启动,也就是通过关键字“go”来运行,前面已经介绍过了GO程序,每次启动一个GO程序,相当于一次并发执行,可以看出来如果并发数太多,会影响api-server以及整个kubernetes自身性能,所以基于kubernetes性能需求上的考虑,对于POD的创建或者删除,每次一批最多处理500个操作,也就是说kubernetes控制住了replicationcontroller操作POD副本的并发数。

3.3、GCController

在controller manager模块中还有个结构体叫做GCController:

type GCController struct {
    kubeClient     client.Interface
    podStore       cache.StoreToPodLister
    podStoreSyncer *framework.Controller
    deletePod      func(namespace, name string) error
    threshold      int
}

这个结构体负责对POD进行回收处理,当终止状态的POD数量超过了kubernetes设定的上限值,那么通过GCController结构体对POD进行回收处理,回收过程通过删除POD来完成,直到终止状态的POD数量在kubernetes设定的上限值以内,删除POD时,会先删除最早创建的POD,kubernetes设定的上限值默认是12500。

这个结构体的使用方式比较简单,通过对前面EndpointController结构体和ReplicationManager结构体的介绍,可以很容易的了解kubernetes如何使用GCController这个结构体的,这里就不详细进行介绍了。

到此为止,我们介绍了controll manager中三个结构体的使用,这三个结构体分别是EndpointController、ReplicationManager和GCController,controll manager都是通过GO程序来使用这三个结构体的,也就是通过关键字“go”来运行。

3.4、NodeController

下面介绍controller manager模块中NodeController结构体,这个结构体负责对Node进行监控。

type NodeController struct {
    allocateNodeCIDRs       bool
    cloud                   cloudprovider.Interface
    clusterCIDR             *net.IPNet
    deletingPodsRateLimiter util.RateLimiter
    knownNodeSet            sets.String
    kubeClient              client.Interface
    lookupIP func(host string) ([]net.IP, error)
    nodeStatusMap map[string]nodeStatusData
    now           func() unversioned.Time
    evictorLock *sync.Mutex
    podEvictor         *RateLimitedTimedQueue
    terminationEvictor *RateLimitedTimedQueue
    podEvictionTimeout time.Duration
    maximumGracePeriod time.Duration
    recorder           record.EventRecorder
    podController *framework.Controller
    podStore      cache.StoreToPodLister
    nodeController *framework.Controller
    nodeStore      cache.StoreToNodeLister
    forcefullyDeletePod func(*api.Pod)
}

这个结构体中变量knownNodeSet是一个字符串集合类型,在GO语言语法中是没有set类型的,所以kubernetes自己实现了一个set类型。变量podEvictor是一个NODE删除队列,用来存放已经不存在的NODE信息,目的是为了删除这些NODE上的POD信息。

controller manager创建NodeController控制器,接着NodeController控制器将结构体中nodeController和podController作为GO程序进行启动,然后使用GO程序启动三个处理逻辑,第一个处理逻辑是监控NODE状态,第二个处理逻辑是删除指定NODE上面所有的POD,第三个处理逻辑是删除指定NODE上所有终止状态的POD。

我们着重看看这三个处理逻辑。先看监控NODE状态这个处理逻辑。这个处理逻辑首先从api-server查询出来所有NODE信息,在变量knownNodeSet中进行查找,变量knownNodeSet用来存放在Kubernetes上已经注册的所有NODE名称,如果不在已经注册的NODE集合中,那么说明是新注册的NODE,插入到已经注册的集合中;然后查找是否存在已经被删除的NODE信息,如果存在,那么从已经注册的NODE集合中删除,并且将NODE名称放入NODE删除队列中。如果kubernetes是在云提供商的资源上部署的,那么这里还可以用云提供商的资源自动给NODE分配IP和掩码。

再看删除指定NODE上面所有的POD的处理逻辑。这个处理逻辑根据NODE删除队列中的NODE信息依次处理,将每个NODE上面所有的POD都删除掉,对于已经处于终止状态的POD不进行处理。

最后看删除指定NODE上所有终止状态的POD的处理逻辑。这个处理逻辑实际上是第二个删除逻辑的补充,它同第二个处理逻辑的区别在于,这个逻辑只处理NODE上面处于终止状态的POD,并且这些POD在冷却期时间内一直处于终止状态。

3.5、ServiceController

下面介绍controller manager模块中ServiceController结构体,这个结构体负责对用到云提供商负载均衡资源的service进行同步操作。

type ServiceController struct {
    cloud            cloudprovider.Interface
    kubeClient       client.Interface
    clusterName      string
    balancer         cloudprovider.TCPLoadBalancer
    zone             cloudprovider.Zone
    cache            *serviceCache
    eventBroadcaster record.EventBroadcaster
    eventRecorder    record.EventRecorder
    nodeLister       cache.StoreToNodeLister
}

controller manager创建ServiceController控制器,然后监控用到云提供商负载均衡资源的service变化,用来确保这些外部负载均衡被正确的创建和删除。Kubernetes可以对接多种云提供商,包括AWS、GCE、OpenStack、Mesos、rackspace,为了方便测试,kubernetes还提供了仿真云提供商。

3.6、RouteController

controller manager模块中还有一个RouteController结构体,这个结构体负责对云提供商路由规则进行同步操作,并不是所有的云提供商都支持这个功能,如果使用x86逻辑部署kubernetes,其实根本都用不到云提供商,在这里就不详细分析这个结构体的使用了。

3.7、ResourceQuotaController

controller manager模块中还有一个ResourceQuotaController结构体,这个结构体负责跟踪kubernetes中的配额使用状况。

type ResourceQuotaController struct {
    kubeClient client.Interface
    syncTime   <-chan time.Time
    syncHandler func(quota api.ResourceQuota) error
}

在kubernetes中允许对以下资源设置配额:POD数、Service数、ReplicationController数、ResourceQuota数、Secret数、persistent volume数、容器使用的总CPU大小、容器使用的总内存大小。

controller manager创建ResourceQuotaController后,就启动了一个GO程序,负责同步kuberneters中上述资源使用状况。同步过程首先查询上述资源使用状况,当发现现在资源使用情况同上一次资源使用情况不一致的时候,通过与api-server通讯,更新资源使用状况。

时间: 2024-08-26 04:03:38

Kubernetes1.1源代码分析(二)的相关文章

【原创】Kakfa utils源代码分析(二)

我们继续研究kafka.utils包 八.KafkaScheduler.scala 首先该文件定义了一个trait:Scheduler——它就是运行任务的一个调度器.任务调度的方式支持重复执行的后台任务或是一次性的延时任务.这个trait定义了三个抽象方法: 1. startup: 启动调度器,用于接收调度任务 2. shutdown: 关闭调度器.一旦关闭就不再执行调度任务了,即使是那些晚于关闭时刻的任务. 3. schedule: 调度一个任务的执行.方法接收4个参数 3.1 任务名称 3.

【原创】kafka server源代码分析(二)

十四.AbstractFetcherManager.scala 该scala定义了两个case类和一个抽象类.两个case类很简单: 1. BrokerAndFectherId:封装了一个broker和一个fetcher的数据结构 2. BrokerAndInitialOffset:封装了broker和初始位移的一个数据结构 该scala中最核心的还是那个抽象类:AbstractFetcherManager.它维护了一个获取线程的map,主要保存broker id + fetcher id对应的

【原创】Kafka console consumer源代码分析(二)

我们继续讨论console consumer的实现原理,本篇着重探讨ZookeeperConsumerConnector的使用,即后续所有的内容都由下面这条语句而起: val connector = Consumer.create(config) 那么问题来了?这条语句后面执行了什么呢?我们先看create方法的定义 def create(config: ConsumerConfig): ConsumerConnector = { val consumerConnect = new Zookee

[Android]Fragment源代码分析(二) 状态

我们上一讲,抛出来一个问题,就是当Activity的onCreateView的时候,是怎样构造Fragment中的View參数.要回答这个问题我们先要了解Fragment的状态,这是Fragment管理中很重要的一环.我们先来看一下FragmentActivity提供的一些核心回调: @Override protected void onCreate(Bundle savedInstanceState) { mFragments.attachActivity(this, mContainer,

【原创】kafka controller源代码分析(二)

四.TopicDeletionManager.scala 管理topic删除的状态机,具体逻辑如下: TopicCommand发送topic删除命令,在zk的/admin/delete_topics目录下创建topic节点 controller会监听该zk目录下任何节点的变更并为对应的topic开启删除操作 controller开启一个后台线程处理topic的删除.使用该线程主要为了以后能够增加TTL(time to live)的特性.无论何时开启或重启topic删除操作时都会通知该线程.当前,

Android 中View的绘制机制源代码分析 三

到眼下为止,measure过程已经解说完了,今天開始我们就来学习layout过程.只是在学习layout过程之前.大家有没有发现我换了编辑器,哈哈.最终下定决心从Html编辑器切换为markdown编辑器.这里之所以使用"下定决心"这个词.是由于毕竟Html编辑器使用好几年了.非常多习惯都已经养成了,要改变多年的习惯确实不易.相信这也是还有非常多人坚持使用Html编辑器的原因. 这也反应了一个现象.当人对某一事物非常熟悉时,一旦出现了新的事物想代替老的事物时,人们都有一种抵触的情绪,做

Spark SQL之External DataSource外部数据源(二)源代码分析

上周Spark1.2刚公布,周末在家没事,把这个特性给了解一下,顺便分析下源代码,看一看这个特性是怎样设计及实现的. /** Spark SQL源代码分析系列文章*/ (Ps: External DataSource使用篇地址:Spark SQL之External DataSource外部数据源(一)演示样例 http://blog.csdn.net/oopsoom/article/details/42061077) 一.Sources包核心 Spark SQL在Spark1.2中提供了Exte

HBase源代码分析之MemStore的flush发起时机、推断条件等详情(二)

在<HBase源代码分析之MemStore的flush发起时机.推断条件等详情>一文中,我们具体介绍了MemStore flush的发起时机.推断条件等详情.主要是两类操作.一是会引起MemStore数据大小变化的Put.Delete.Append.Increment等操作,二是会引起HRegion变化的诸如Regin的分裂.合并以及做快照时的复制拷贝等.相同会触发MemStore的flush流程.同一时候.在<HBase源代码分析之compact请求发起时机.推断条件等详情(一)>

&quot;别踩白块儿&quot;游戏源代码分析和下载(二)

四.游戏交互实现 1.前面已经介绍在 Block 类实现了每个block的触碰监听,block 实现触碰监听,当按下时,调起在GameScene中实现的touchBlock方法.下面来看改方法的实. /** * 点击到Block时进行的逻辑处理 * * @param pBlock *            所点击的block */ public void touchBlock(Block pBlock) { if (gameStatus == ConstantUtil.GAME_START) {