【编者的话】Systemd并不是CoreOS特有的服务。本质上说Systemd是没有依附于任何一个Linux发行版的独立项目,但是很多行版Linux都在青睐Systemd管理服务的优势,所以CoreOS选择了它。Fleet是管理coreos和部署app的工具。有了fleet,你就可以把整个coreos集群当做一台节点来处理。让我们来一起学习一下关于此方面的内容。
这是深入浅出CoreOS系列文章中的第三篇,也是最后一篇。
在上一篇文章中,我们学习了cloud-config配置文件,在代理模式下运行etcd,以及关于etcd集群的一些常规设置。这篇文章中,我们将探讨Systemd、Unit文件、Fleet和fleetctl。
Systemd是一个在CoreOS的用于初始化系统的工具。它提供了许多强大的功能,例如启动服务、停止服务、监控和重启进程等。在CoreOS中,Systemd既可以用来管理Docker容器的生命周期,又可以管理不同系统的启动任务。
要深入学习Systemd,必须要深入查看一系列关于Systemd的博客。不过,在此我们只讨论需要CoreOS上的Docker容器上操作所需要的一些Systemd知识。
更多关于Systemd的内容,可以参考 官方文档 。
Systemd为每一个守护进程记录一个初始化结构文件,我们称之为一个Unit。Systemd系统取代了传统系统为每一个守护进程初始化一次脚本的做法。记录有很多不同种类的Unit文件,但是我们只会关注可以运行Docker容器的服务类型Unit文件。
下面列表,是按照顺序一个服务Unit(service unit)生命周期内的过程,以及作用:
下面我们演示创建一个Hello_world.service的简单Unit文件:
[Unit]
Description=HelloWorldApp
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker rm busybox1
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --rm --name busybox1 busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done"
ExecStop=/usr/bin/docker stop busybox1
[Install]
WantedBy=multi-user.target
让我们仔细来看一下刚才创建这个Unit文件:
如果要启动一个新的Unit,必须使用Systemd创建symlink然后启动文件:
$ sudo systemctl enable /etc/Systemd/system/hello.service
$ sudo systemctl start hello.service
要验证Unit已经启动,我们可以检查正在运行的容器列表:
Docker ps
然后,通过journalctl命令输出Unit,如下:
$ journalctl -f -u hello.service
-- Logs begin at Fri 2014-02-07 00:05:55 UTC. --
Feb 11 17:46:26 localhost docker[23470]: Hello World
Feb 11 17:46:27 localhost docker[23470]: Hello World
Feb 11 17:46:28 localhost docker[23470]: Hello World
[...]
-u指的是unit,-f指的是一起,可以按CTRL+C随时退出。Systemd服务Unit(services unit)只能运行在一台机器上。它只能用于单任务的场景,比如下载文件或者重启机器等。
更多关于Systemd units的知识, 请参考文档 。
Fleet运行在Systemd上层,在集群层次控制Systemd,负责创建分布式Systemd:
要想把服务发布进集群,就必须提交合规范的Systemd unit。
Fleetctl是官方推荐的控制fleet unit工具,它可以在本地或者远程CoreOS集群使用。Fleetctl命令类似于systemctl命令,必须在命令前面加上sudo命令在配合使用。Fleetctl命令可以直接在集群上运行。或者如果你喜欢从外部主机执行fleetctl(即你的工作站),可以通过SSH把系统环境变量作为参数传递给集群机器,像这样:
$ export FLEETCTL_TUNNEL=remote_machines_ip
让我们看一下你可以执行的任务,列出所需的命令。
开始单元服务:
$ fleetctl start hello_world.service
检查单元服务状态:
$ fleetctl status hello_world.service
停止服务:
$ fleetctl stop hello_world.service
查看服务文件:
$ fleetctl cat hello_world.service
提交服务:
$ fleetctl submit hello_world.service
查看日志:
$ fleetctl journal hello_world.service
SSH访问服务
$ fleetctl ssh hello_world.service
服务列表:
$ fleetctl list-units
列举集群机器:
$ fleetctl list-machines
Fleet主要是依赖Unit文件交互的。对于Systemd Unit,它定义了想要做什么以及fleet应该如何去做,在集群中Fleet安排一到多台机器,Fleet安排一个有效的Unit文件。在[X-Fleet]部分留意fleet的一些特殊部分,可以用来替换Systemd单元的[install]部分。其余Systemd部分保持与fleet相同。
我们一起看一下特殊的部分配置:
上面所有的都在单元文件的[X-Fleet]部分。除非单元文件上MachineMetadata提供配置Global=true,否则我们认为这个文件是无效的。如果你想在所有集群或者MachineMetadata指定值得机器上规定相同的单元,全局单元文件就非常有用了。
下面我们来看一下上述提到的Fleet Unit中使用的hello_world.service文件:
[Unit]例子中的hello_world@
Description=HelloWorldApp
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker rm busybox1
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --rm --name busybox1 busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done"
ExecStop=/usr/bin/docker stop busybox1
[X-Fleet]
MachineMetadata=group=hw_webservers
Conflicts=hello_world@*
是做什么的?
好的,让我们来说说 hello_world@1.servic e and hello_world@2.servic e两个完全相同的文件。
在集群上启动:
$ fleetctl start hello_world@*
这两个Fleet文件都部署在 MachineMetadata=group=hw_webservers配置的服务器,配置Conflicts=hello_world@意图是防止一个Unit使用了global-matching与Unit文件冲突。
让我们看另一个hello_world.service 单元的例子。
规定集群中所有的机器的这个单元:
[X-Fleet]
Global=true
规定机器上有some_other_unit.service单元:
[X-Fleet]
MachineOf=some_other_unit.service
规定单元机器的编号为:562999f8
[X-Fleet]
MachineID="562999f8"
获取机器ID:
$ fleetctl list-machines
寡欲fleet 单元更多的只是, 参考官方文档 。
你要做的就是提供一个严格格式的【install】部分Unit文件,如下:
[Unit]
Description=hello_docker
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker rm busybox1
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --rm --name busybox1 busybox /bin/sh -c "while true; do echo Hello Docker; sleep 1; done"
ExecStop=/usr/bin/docker stop busybox1
注意:如果你是手动运行docker命令,请确保不要在命令行中复制运行命令在分离模式中开启一个容器,这种做法将会使会造成容器运行几秒钟后自动退出。
这篇文章中:
请不要忘了系列的上两篇文章,在第一篇我们讲述了CoreOS的基础原理 ,自动升级,发布渠道,集群发现等。在第二篇文章中,我们熟悉了cloud-config,etcd等。
下一个系列中,主要学习Docker。
原文链接: CoreOS Overview, Part Three (翻译:张亚龙)