运行一个高可用的服务
使用CoreOS最大的好处就是你可以以高可用的方式来运行你的服务。接下来我们将部署两个一样的Apache web server容器。然后,我们将通过让一台机器出现故障,fleet将在其它机器上重新启动我们的任务。
首先,让我们写一个将会运行两个副本的unit文件。为了实现这个目标,我们用一个unit模板,名字是apache@.service。它将会是apache@1.service 和 apache@2.service的基础配置。
[Unit]
Description=My Apache Frontend
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill apache1
ExecStartPre=-/usr/bin/docker rm apache1
ExecStartPre=/usr/bin/docker pull coreos/apache
ExecStart=/usr/bin/docker run --rm --name apache1 -p 80:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUND
ExecStop=/usr/bin/docker stop apache1
[X-Fleet]
Conflicts=apache@*.service
fleet通过Conflicts
属性来知道这两个服务将不会运行在同一个机器上,提供了高可用。更详细的配置配置节点将会在fleet units guide找到。
让我们在启动两个unit在不同的机器吧。
$ fleetctl start apache@1
$ fleetctl start apache@2
$ fleetctl list-units
UNIT MACHINE ACTIVE SUB
myapp.service c9de9451.../10.10.1.3 active running
apache@1.service 491586a6.../10.10.1.2 active running
apache@2.service 148a18ff.../10.10.1.1 active running
就像你看到的一样,Apache单元现在已经运行在我们集群中的两个不同的机器中了。
那我们怎么样给这些容器分发请求呢?最好的策略就是运行一个搭档容器来履行相关的职责,而不是直接内置到应用里面。例如搭档容器就是用来服务发现和控制外部负载均衡或DNS
故障恢复
fleet集群中的机器不断地与集群中的其他人进行通信,并选出一个领导者做出决策。领导负责解析新提交units,并找到一个合格的机器运行(通过x-fleet参数),然后通知机器启动unit。
当一个机器没能给fleet leader发回心跳包,所有运行在这台机器上的units会被重新调度。通过这个流程,每个unit都能找到合适的机器来运行,他们将运行在新的机器上。在这个合适的机器没有找到之前,units不会重新运行。如果失败的机器恢复了,fleet leader 会告诉他停掉已经重新调度的units,并且这台机器将被用来新的工作。
你可以通过停掉一台机器上的fleet进程(sudo systemctl stop fleet
)来测试Apache unit。fleet的日志(sudo journalctl -u fleet
)将会体统更清晰的过程。
运行一个简单的搭档
这个简单的搭档的例子就是服务发现,这个unit连续的宣布我们的容器已经在运行了。我们可以为每一个已经运行了的Apache unit运行一个搭档,我们将要用一个unit的模板来启动两个实例。做一个模板叫做apache-discovery@.service。
[Unit]
Description=Announce Apache1
BindsTo=apache@%i.service
After=apache@%i.service
[Service]
ExecStart=/bin/sh -c "while true; do etcdctl set /services/website/apache@%i '{ "host": "%H", "port": 80, "version": "52c7248a14" }' --ttl 60;sleep 45;done"
ExecStop=/usr/bin/etcdctl rm /services/website/apache@%i
[X-Fleet]
MachineOf=apache@%i.service
这个unit有几个简单的特性。首先,它使用BindsTo
来连接我们的apache@%i.service unit。当Apache unit 停止运行的时候,他也会从我们的etcd中的/services/website
目录中移除。当我们的机器因某种原因突然停止的时候,60秒后将会把unit从我们的目录中移除。
第二就是%i
,一个内置的系统变量,代表一个实例化单元实例名称(一个单元推出一个模板)。这个变量在单元名称中的任何值之后扩展到任何值。在我们的例子中,它将扩大到1(Apache-discovery@1)和2(apache-discovery@2)。
Third is %H, a variable built into systemd, that represents the hostname of the machine running this unit. Variable usage is covered in our Getting Started with systemd guide as well as in systemd documentation.
第三为%H
,一个内置的系统变量,表示运行机器的主机名。变量使用说明详见Getting Started with systemd或是systemd documentation
第四是一个fleet特有的属性,叫做MachineOf
。这个属性的作用是让单元被放置在运行Apache服务的同一机器上(例如,apache-discovery@1.service将被安排在同一台机器上的Apache@1.service)。
让我们来验证每个单元被放置在Apache服务的同一台机器上:
$ fleetctl start apache-discovery@1
$ fleetctl start apache-discovery@2
$ fleetctl list-units
UNIT MACHINE ACTIVE SUB
myapp.service c9de9451.../10.10.1.3 active running
apache@1.service 491586a6.../10.10.1.2 active running
apache@2.service 148a18ff.../10.10.1.1 active running
apache-discovery@1.service 491586a6.../10.10.1.2 active running
apache-discovery@2.service 148a18ff.../10.10.1.1 active running
现在,我们来验证一下服务发现是否能正常工作
$ etcdctl ls /services/ --recursive
/services/website
/services/website/apache@1
/services/website/apache@2
$ etcdctl get /services/website/apache@1
{ "host": "ip-10-182-139-116", "port": 80, "version": "52c7248a14" }
运行一个外部的伙伴服务
如果你在云中运行,许多服务都可以在集群中的行为的基础上实现自动化。例如,您可以更新DNS记录或添加新的容器来负载均衡。我们的fleet的例子部署包含预存在容器更新亚马逊的弹性负载平衡器与新的后台。 视频地址