CoreOS 折腾笔记(二)Fleet 进阶

如果要说什么样子的分布式集群对用户是最友好的,那无疑是对客户来说,像本地执行命令一样方便的执行集群命令肯定是最舒服的了。这个我们在上一节 集群部署 里面就提到了一个叫做 “fleetctl” 的命令,这个命令是做什么用的呢?

fleet 是什么

工具

是一个在集群层面上的 ```systemd``` 管理工具。它的配置文件语法基于 ```systemd``` 的语法,另外添加了一些自有的属性。如果你希望在集群中运行你的服务,那么使用 ```fleet``` 管理 ```systemd``` 单元是再有必要不过的了。
1
2
3
4

在比较新的系统 (CentOS 7+、Ubuntu 16+、Debian 8+) 中均采用了 ```systemd``` 作为启动项管理工具。如果你对 ```systemd``` 有疑问的话,请到其 [官方网站](https://www.freedesktop.org/wiki/Software/systemd/) 查看具体的介绍,这里不做赘述。

之前使用的 ```fleetctl``` 就是 ```fleet``` 的管理工具,默认是在集群中的某台机器上进行管理。当然,```fleetctl``` 同样也可以通过远程进行管理,可以通过如下命令连接远程集群。

FLEETCTL_ENDPOINT=http://IP:[PORT] fleetctl list-units

1
2
3
4

## fleetctl 常见命令

比较常见的 ```fleetctl``` 命令有:

core@core-01 ~ $ fleetctl -h

COMMANDS:
cat 查看已经提交的单元文件内容
destroy 销毁集群中的一个或多个单元
fd-forward 将标准输入输出转向到一个 unix socket 中
journal 将集群中的某个 unit 的日志输出到当前
list-machines 查看集群中的已知机器
list-unit-files 查看集群中存在的单元
list-units 查看集群中的单元状态
load 将一个或多个单元加载到集群中,必要时会先执行 submit 功能
ssh 连接到集群中的某台机器
start 启动集群中一个或多个单元,必要时会先执行 submit 和 load 功能
status 输出集群中一个或多个单元的状态
stop 停止集群中一个或多个单元
submit 上传一个或多个单元到集群中,并不会加载执行
unload 卸载集群中的一个或多个单元

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

## fleet 单元文件

以一个 ```Hello World``` 程序作为演示来讲解:

```ini
[Unit]
Description=Echo Hello World
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill busybox
ExecStartPre=-/usr/bin/docker rm busybox
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name busybox busybox /bin/sh -c "trap'exit 0'INT TERM; while true; do echo Hello World; sleep 1; done"
ExecStop=/usr/bin/docker stop busybox

看起来基本与

语法一致。保存成 ```helloworld.service```,然后执行命令:
1
2


core@core-01 ~ $ fleetctl start helloworld.service
Unit helloworld.service inactive
Unit helloworld.service launched on 6e1b9fae…/172.17.8.104

1
2

可以通过 ```fleetctl``` 查看状态:

core@core-01 ~ $ fleetctl list-units
UNIT MACHINE ACTIVE SUB
helloworld.service 6e1b9fae…/172.17.8.104 active running
core@core-01 ~ $ fleetctl list-unit-files
UNIT HASH DSTATE STATE TARGET
helloworld.service ce68bd4 launched launched 6e1b9fae…/172.17.8.104

1
2

同时,可以通过 ```fleetctl journal``` 查看程序是否正常运行了。

core@core-01 ~ $ fleetctl journal helloworld
The authenticity of host ‘172.17.8.104’ can’t be established.
ECDSA key fingerprint is 11:63:ee:93:e4:b9:5e:06:e9:c6:cd:63:e2:df:ef:9e.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ‘172.17.8.104’ (ECDSA) to the list of known hosts.
– Logs begin at Sat 2016-05-28 08:45:39 UTC, end at Sat 2016-05-28 10:09:13 UTC. –
May 28 10:09:04 core-04 docker[1163]: Hello World
May 28 10:09:05 core-04 docker[1163]: Hello World
May 28 10:09:06 core-04 docker[1163]: Hello World
May 28 10:09:07 core-04 docker[1163]: Hello World
May 28 10:09:08 core-04 docker[1163]: Hello World
May 28 10:09:09 core-04 docker[1163]: Hello World
May 28 10:09:10 core-04 docker[1163]: Hello World
May 28 10:09:11 core-04 docker[1163]: Hello World
May 28 10:09:12 core-04 docker[1163]: Hello World
May 28 10:09:13 core-04 docker[1163]: Hello World

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

## 通过 fleet 单元文件实现高可用服务

实现高可用服务需要多个服务实例:当其中一个服务实例出现问题时,不会干扰其它服务实例的运行。这里我们还是使用上一节中提到的单元文件,但是需要做额外的修改让其支持多实例运行:

```ini
[Unit]
Description=Echo Hello World
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill busybox
ExecStartPre=-/usr/bin/docker rm busybox
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name busybox busybox /bin/sh -c "trap'exit 0'INT TERM; while true; do echo Hello World; sleep 1; done"
ExecStop=/usr/bin/docker stop busybox

[X-Fleet]
Conflicts=helloworld@*.service

最后新增的内容是 fleet 的专属语法,使用

可以限定每台机器上仅允许一个 ```helloworld``` 服务运行。
1
2


core@core-01 ~ $ fleetctl stop helloworld
Unit helloworld.service loaded on 6e1b9fae…/172.17.8.104
core@core-01 ~ $ fleetctl unload helloworld
Unit helloworld.service inactive
core@core-01 ~ $ mv helloworld.service helloworld@.service
core@core-01 ~ $ fleetctl start helloworld@1
Unit helloworld@1.service inactive
Unit helloworld@1.service launched on 6e1b9fae…/172.17.8.104
core@core-01 ~ $ fleetctl start helloworld@2
Unit helloworld@2.service inactive
Unit helloworld@2.service launched on 91060182…/172.17.8.103
core@core-01 ~ $ fleetctl start helloworld@3
Unit helloworld@3.service inactive
Unit helloworld@3.service launched on af1494a6…/172.17.8.102
core@core-01 ~ $ fleetctl start helloworld@4
Unit helloworld@4.service inactive
Unit helloworld@4.service launched on c99fef8a…/172.17.8.101
core@core-01 ~ $ fleetctl list-unit-files
UNIT HASH DSTATE STATE TARGET
helloworld.service ce68bd4 inactive inactive -
helloworld@1.service ce68bd4 launched launched 6e1b9fae…/172.17.8.104
helloworld@2.service ce68bd4 launched launched 91060182…/172.17.8.103
helloworld@3.service ce68bd4 launched launched af1494a6…/172.17.8.102
helloworld@4.service ce68bd4 launched launched c99fef8a…/172.17.8.101
`

卸载之前的 helloworld,执行了新的 4 个实例,通过观察可以看到目前实例都是运行在了 4 台不同机器上。

fleet 的一些疑问

事实上,通过 fleet,可以将服务进行多副本部署,同时通过 fleet 守护程序的正常运行。但是在实际使用中你会发现有一个实际问题,在微服务化场景中,每个服务部署的机器是无法控制的,那么我们怎么知道服务究竟在哪呢?

如何控制流量流向,或者说服务发现问题,这个我会在下一个 Etcd 的介绍中说一下,敬请期待。