分布式init系统fleet

  categories:资料  author:

Fleet是管理coreos和部署app的工具。

有了fleet,你就可以把整个coreos集群当做一台节点来处理。Fleet鼓励用户将应用都封装成轻量级的服务,这些服务很容易在集群中进行管理和部署。

devops team通过fleet,就可以集中精力来关注app应用,而不用关心基础环境如何,哪个container应该部署在哪台节点上。如果你的app需要5 个container同时运行,fleet将保证这5个container在集群中同时运行。如果某台节点出现异常,或者需要重启更新,fleet也会将 此台节点上面的container转移到其他节点上。

而这些都是automatic的! 运行和管理container就是这样so easy!

管理coreos和部署app的工具:Fleet

Fleet的功能如下:

  • 在当前coreos集群中随机部署docker container
  • 在集群中跨主机进行服务分发
  • 负责维护集群中的服务实例,当服务实例异常时,重新进行任务调度来恢复服务
  • 发现集群中的各个节点
  • 自动SSH到其它节点来执行job

Fleet再进行任务调度时,就会读取etcd存储的数据。下图就是Fleet的任务调度流程图:

20150117171531_786

fleet 详细介绍

fleet 绑定了 systemd 和 etcd 到一个分布式 init 系统,可以认为是 systemd 的扩展,但是并不是机器级别的,而是集群级别的。

此项目现在是个预览版本,如要使用请看安全提示。

特性

fleet 允许你定义灵活的架构来运行你的服务:

  • 可以在集群的任意地方部署单个容器
  • 支持部署多个同样容器的副本
  • 确保同一个机器上容器都是部署在一起的
  • 禁止指定 co-habitation 的服务
  • 服务的 Maintain N 容器不能重新部署
  • 匹配指定的元数据在机器上部署容器

示例

在集群中列出 Machines 列表

$ fleetctl list-machines
MACHINE                                 IP          METADATA
148a18ff-6e95-4cd8-92da-c9de9bb90d5a    19.4.0.112  region=us-west
491586a6-508f-4583-a71d-bfc4d146e996    19.4.0.113  region=us-east

Submit & Start Units

ls examples/
hello.service   ping.service    pong.service
fleetctl submit examples/*
fleetctl start hello.service

List Units

$ fleetctl list-units
UNIT            LOAD    ACTIVE  SUB     DESC    MACHINE
hello.service   loaded  active  running -       148a18ff-6e95-4cd8-92da-c9de9bb90d5a
ping.service    -       -       -       -       -
pong.service    -       -       -       -       -

集群上的服务生命周期

刚刚的启动流程看起来很简单,不是么?在实际的使用中,如果为了省事,用Fleet启动一个服务,这样做就可以了。但这种做法其实会带来的服务管理上的麻烦,特别当启动出错的时候。因此比较全面的理解Fleet在背后默默做了哪些工作,详细的了解一下Fleet模型中,集群上的服务生命周期是很有必要的。

下面这个图描述了Fleet中的服务从初始到运行,最后终止结束的完整过程中实际存在的几个阶段。

Fleet中的服务生命周期
  • 提交服务

服务的提交阶段,这个步骤仅仅是在Fleet服务中完成的,目的是将指定的Unit文件添加到Fleet的记录缓存。此时Fleet并不会与Systemd进行通信。通过 fleetctl list-unit-files 和 fleetctl list-units 命令可以看到,Unit文件被提交后,并没有出现在后者的记录中。此时这个Unit文件已经被注册为一个Fleet可识别的Unit名称,但还不是一个可以执行的的服务。

$ fleetctl submit ${HOME}/hello.service
$ fleetctl list-unit-files
UNIT  HASH  DSTATE  STATE  TARGET
hello.service  4bff33d  inactive  inactive  –
$ fleetctl list-units
UNIT  MACHINE  ACTIVE  SUB

值得指出的是,这一步需要将完整的Unit文件路径作为参数传递给fleetctl,这也是服务在集群的整个Fleet生命周期中唯一一次需要提供完整路径的地方。

使用 fleetctl cat 命令可以打印出已经缓存了的Unit文件内容。

$ fleetctl cat hello.service
[Unit]
Description=Hello World
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill busybox1
ExecStartPre=-/usr/bin/docker rm busybox1
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run –name busybox1 busybox /bin/sh -c “while true; do echo Hello World; sleep 1; done”
ExecStop=/usr/bin/docker kill busybox1
[X-Fleet]
X-Conflicts=hello.service

和Systemd相似的,这里同样有一个容易犯错地方。由于Fleet已经缓存了整个Unit文件,之后如果原来的Unit文件内容发生改变,单纯的停止并重新启动服务并不会加载新变化的内容。此时若是需要让新的Unit文件被使用,需要重新提交这个文件,也就是再次执行这个submit操作。因此,这里再次强调使用者应该对Fleet管理服务的生命周期有一定了解。

  • 加载服务

加载服务实际上是根据Unit文件的 X-Fleet 配置段条件,将服务传递到符合条件的特定节点的本地Systemd系统的过程,这个过程中Fleet通过DBus API与节点的Systemd进行了通信。

$ fleetctl load hello.service
Unit hello.service loaded on 0acdd9bf…/110.0.2.15
$ fleetctl list-unit-files
UNIT  HASH  DSTATE  STATE  TARGET
hello.service  4bff33d  loaded  loaded  0acdd9bf…/10.0.2.15
$ fleetctl list-units
UNIT  MACHINE  ACTIVE  SUB
hello.service  0acdd9bf…/10.0.2.15  failed  failed

可以看到,现在 fleetctl list-units 已经识别到这个服务了。至此,这个服务的准备工作已经全部就绪。

  • 启动服务

启动服务是完成的服务运行周期的最后一个步骤。如之前所提过的,这里如果传递的参数不是服务的名称而是Unit文件的路径,Fleet也会自动完成Unit文件的提交和加载,并启动相应服务。这种做法仅仅在手工操作时可取,若是在自动操作脚本中,假如服务启动出现异常,单纯的从脚本的输出中就很难判断是哪个环节出了问题,会带来管理和排查的困难。

$ fleetctl start hello.service
Unit hello.service launched on 0acdd9bf…/10.0.2.15
$ fleetctl list-unit-files
UNIT  HASH  DSTATE  STATE  TARGET
hello.service  4bff33d  launched  launched  0acdd9bf…/10.0.2.15
$ fleetctl list-units
UNIT  MACHINE  ACTIVE  SUB
hello.service  0acdd9bf…/10.0.2.15  activating  start-pre

刚刚启动的服务会处于start-pre状态(服务正在执行Unit文件中的ExecStartPre部分操作),几分钟后再次查看服务的状态,服务状态就会变为running了。

$ fleetctl list-units
UNIT  MACHINE  ACTIVE  SUB
hello.service  0acdd9bf…/10.0.2.15  active  running

  • 停止服务

服务不能无休止的运行,终归有需要停止的时候。服务的停止同样会经过三个过程,依次为stop、unload和destroy,其本质上与启动过程一一对应。

$ fleetctl stop hello.service
Unit hello.service loaded on 0acdd9bf…/10.0.2.15
$ fleetctl unload hello.service
Unit hello.service inactive
$ fleetctl destroy hello.service
Destroyed hello.service

服务移除后系统又回到了初始的状态。

$ fleetctl list-unit-files
UNIT  HASH  DSTATE  STATE  TARGET
$ fleetctl list-units
UNIT  MACHINE  ACTIVE  SUB

  • 服务自动启动

在一边阅读一边实际操作的读者可能已经发现,Fleet的管理工具fleetctl没有enable和disable这两个操作。实际上,只要服务通过fleetctl start运行起来以后,就已经是自动启动的了。可以通过运行节点本地的Systemd证实(在做这个验证前最好移除之前通过Systemd添加的本地Hello服务,以免影响结果可信度)。

$ fleetctl ssh hello  # 跳转到运行Hello服务的节点
$ systemctl list-units | grep hello
hello2.service  loaded  active running  Hello World
$ systemctl list-unit-files | grep hello
hello2.service  enabled

服务状态和日志

Fleet同样具有跨节点查看服务状态和日志的能力。通过fleetctl status加上服务的名称就能查看服务的基本状态,而不用关心服务运行在哪一个节点上面。

$ fleetctl status hello.service

Are you sure you want to continue connecting (yes/no)? yes  <= 第一次使用的时候需要确认
● hello.service – Hello World

Main PID: 4964 (docker)
CGroup: /system.slice/hello.service
└─4964 /usr/bin/docker run –name busybox1 busybox /bin/sh -c while true; do echo Hello World; sleep 1; done
Jan 10 08:58:07 core-03 docker[4964]: Hello World
Jan 10 08:58:08 core-03 docker[4964]: Hello World
Jan 10 08:58:09 core-03 docker[4964]: Hello World

同样的方式可以查看到任意节点上查看服务输出的日志,相应的命令是 fleetctl journal 。顺带一提,当服务程序使用Systemd/Fleet的方式管理后,其运行过程中输出到std::out 的内容都会被重定向到日志中。

$ fleetctl journal hello.service
— Logs begin at Sat 2015-01-10 02:41:59 UTC, end at Sat 2015-01-10 08:58:56 UTC. —
Jan 10 08:58:46 core-03 docker[4964]: Hello World
Jan 10 08:58:47 core-03 docker[4964]: Hello World
Jan 10 08:58:48 core-03 docker[4964]: Hello World

fleetctl fournal常用的参数有:指定输出日志行数的 –lines 和跟随日志输出的 –follow (或-f) 。

fleetctl journal –lines 20 hello.service
fleetctl journal -f hello.service

小结

在这一篇中,我们详细了解了在CoreOS集群中通过Fleet查看和管理集群的操作。CoreOS中的Fleet服务通过Etcd(一种分布式数据存储服务)获得集群的服务信息并通过DBus接口操作Systemd控制集群中任意节点的服务状态,在CoreOS集群上提供了跨节点,分布式,高容错的服务部署和管理能力。

 



快乐成长 每天进步一点点      京ICP备18032580号-1