docker swarmkit 源码阅读: Orchestrator 部分

在 swarmkit 中 Orchestrator 负责 service 的运行管理,官方文档这么描述:

The Orchestrator ensures that services have the appropriate set of tasks running in the cluster according to the service configuration and polices.

 

swarmkit 支持两种 service 类型,一种是 global service,一种是 replicated service,对于 global service 它的 task 会运行在所有的 node 中,除非 node 被 drain 掉;对于 replicated service,需要一个 num,即运行 task 的数量,比如 task 数量是 10,那么 service 的 Slot 从 1 到 10。

 

先看看 global service。

7b635512-79a5-4ff2-ab2c-2d82ff5fa2f4

它的 struct 如上图。

1. 从 store 监控 event;

2. 从 store 获取 cluster,放入 cluster;

3.  从 store 中获取所有 node,如果不是 drain 状态,放入 nodes 中;

4. 从 store 获取所有 service,如果是 global service,放入 globalServices,并且 reconcile  此 service。

5. reconcile 的过程是:从 store 中拿到 service 的所有 task,放入以 node 为 key 的 map 中,如果某一个 node 中的一个 task 是 Completed 状态,则把此 node 的其他 task 都 delete 掉;如果一个 node 中没有 task,则在此 node 中增加 task;对于其他情形的 task,则 Update;

6. 然后进行循环,等待 event,分别对下面的 event 类型做处理:

1). state.EventUpdateCluster

更新 cluster

2). state.EventCreateService 和 state.EventUpdateService

增加或修改 service 信息到 globalServices,并 reconcile 此 service

3). state.EventDeleteService

删除 service 的所有 task,在 globalServices 删除此 service,清除 restart 中的 ServiceHistory

4). state.EventCreateNode

reconcile 此 node,如果此 node 是 drain,从 nodes 删除 node 信息和上面的 task,否则保存 node 信息到 nodes,然后对每一个 service reconcileServiceOneNode,方式类似第 5 点所说。

5). state.EventUpdateNode

如果 node 状态是 NodeStatus_DOWN,删除 node 中的 task;

如果状态是 NodeStatus_READY,reconcileOneNode。

6). state.EventDeleteNode

删除 node 中的 task,从 nodes 中删除 node

7). state.EventUpdateTask

如果 task 的 service 不在 globalServices 中,不处理;

否则重启 task

8). state.EventDeleteTask

如果 task 的 service 不在 globalServices 中,不处理;

否则 reconcileServiceOneNode。

 

 

然后是 replicated service。

17ffa76a-028d-4c5c-99e3-f7c34d862186

它的 struct 如上图。

1.  从 store 监控 event;

2. 执行 initTasks,这个函数从 store 里拿到所有 task,对于有绑定 node 的「状态」小于等于 TaskStateRunning 的「目标状态」小于等于 TaskStateRunning 的 task,放入 restartTasks,这些是需要监控重启的 task;然后删除没有绑定 service 的 task;对于状态是 TaskStateReady 的 task,进行启动或延迟启动。

3. 执行 initServices,把是 replicated service 的 service 加入 reconcileServices;

4. 执行 initCluster,从 store 中获取 cluster 放入 cluster;

5. 先进行一次 tick,包括 tickTasks 和 tickServices,即重启 restartTasks 的 task 和 reconcile reconcileServices 中的 service。对于 reconcile service,如果指定的 Slot 数量大于当前 Slot 数量,会进行扩容,如果小于,则会进行缩减,缩减的优先级是已经停止的 Slot 和较多运行在某一个 node 上的 Slot。不动的 Slot 会进行 Update;

6. 接下来会处理 event,如果是以下 event:

EventDeleteNode
EventCreateNode
EventUpdateNode
EventDeleteTask
EventUpdateTask
EventCreateTask
EventDeleteService
EventCreateService
EventUpdateService

这些 event 最终都会反馈到 restartTasks 和 reconcileServices,最终被 tick 掉。

7. 如果是 EventCommit,则进行 tick。

8. 如果是 EventUpdateCluster,则更新 cluster。

 

 

上面提到了对 task 的 Restart 和 Update,Restart 就是重启,Update 则是检查 task 的配置( Spec )是否有变更,比如 cpu、mem 等,task 的 Spec 其实就是 service 的 Spec,当 service 有变化时,必须要 Update 以保证 task 运行在正确的配置下。

另外要注意一点,当 service Update 时,如果 Update 失败,有三种处理的选择:UpdateConfig_PAUSE、UpdateConfig_CONTINUE 和 UpdateConfig_ROLLBACK,第一种是暂停,不能继续 Update 了,第二种可以继续,第三种也可以,但是会回滚 service 配置。而且,如果 Update 失败了,由于 Update 失败会产生 event ( task 启动失败,是 EventCommit 还是 EventUpdateTask ?),这个 event 会被 replicated service 的 tick 捕获,从而进行不断重启(此点没有经过实践验证)。

 

 

总结一下,Orchestrator 负责从「数据库」拿到 service 的变更并执行,至于资源分配和调度就不是它的工作了。

 

参考:

https://github.com/docker/swarmkit/blob/master/design/nomenclature.md

 

Puppet file 指令删除目标目录中的不在源目录中的文件

file {‘/home/op/open-falcon-agent/plugin’:
path => ‘/home/op/open-falcon-agent/plugin/’,
source => ‘puppet:///modules/sre-scripts/’,
recurse => true,
ignore => ‘.git’,
group => root,
owner => root,
mode => 755,
purge => true,
force => true,
require => Package[‘open-faclon-agent’]
}

这段配置,把 puppet:///modules/sre-scripts/ 中的目录和文件同步到 /home/op/open-falcon-agent/plugin,如果想把 /home/op/open-falcon-agent/plugin 中不在 puppet:///modules/sre-scripts/ 中的文件和目录删除掉,可以使用:

purge => true,
force => true,

purge => 默认会删除文件,不会删除目录,再配合使用 force => true,可以把不存在的目录删掉。

2F7828D7-1698-4746-A268-0D7C3965B027

 

参考:

https://docs.puppet.com/puppet/latest/reference/type.html