啥都不说了,先来张图镇压一下场子

先说说集群

集群对我来说是个“老”东西,也可以说是个新鲜的东西了,因为我对集群的文章也是看多了、听腻了,可是却一直没有将其收入生产环境上。我对集群的看法:其实上集群与否,完全取决于公司的情况,它不是一个必需品,如果就几台服务器,一只手都可以数的过来的服务,直接手动管理就好。但是学集群管理与否,那应该是一个运维人员所应具备的素质,运维人员永远都应该走在服务前面,牵着服务往前走,而不是被服务推着走。那怎么能做到这样呢,唯一的方法就是不断学习,不断的了解新产品,每一个产品出来,都绝非造轮子,必定是解决了某些当面无法解决的痛点,而这些痛点肯定有你遇到过的。

先讲讲我们公司的现状(或者叫痛点)吧。其实目前来说,服务不是很多,三十多个的样子吧,手动ssh裸机管理还是可以管理过来的,只是稍微麻烦了一些而已。最麻烦的是服务器断电之后,重启过来时,常会某些服务会因为某些原因导致没正常启动,时间长了,有时也会记漏掉一两个,所以当时的做法是ssh到各个服务器上验证服务是否启动,有些还不是容器化服务,排查起来很不直观。

如果:要是能在我的平时使用的普通笔记本上直接xx ls machines就能看到所有的节点是否健康,xx ls services一下,就能看到所有的服务启动是否正常,xx journal service就能看到服务的日志,那估计能省我不少去验证服务的时间吧,那有没这种软件呢?当然有,而且还很多,包括coreos的fleet,就能满足我上面提出的功能点。

fleet 介绍

先介绍一下fleet,后面再介绍安装使用

fleet是CoreOS的产品,同时也是CoreOS的默认集群管理工具,它的目的是让使用者花很短时间写一个很小的unit文件(服务的描述文件,和systemd类似),就可以将服务启动起来,并能在CoreOS的服务器集群上随意迁移。

fleet的一些特点:

  • systemd风格的服务配置unit。一个服务对应的是一个unit文件,写好unit文件后提交到fleet server,即可在任意的节点启动服务(unit可以指定运行机器)
  • 去中心化。这是fleet的一大特点,在任意的机器都可以去查看、部署和控制集群的服务,也就是说我把我自己的笔记本接入到集群中,就可以方便的去检修集群。
  • 自动迁移服务。当一个节点宕机后,自动将该节点正在运行的服务重新部署到其他节点。
  • 服务的高可用性。可以使用unit文件的X-Fleet部分的限定同类型的服务不要在同一节点启动。如在使用负载均衡时,需要启动多个backend,这时候可以在unit文件的X-Fleet部分指定X-Conflicts=backend*.service,启动backend.1.servicebackend.2.servicebackend.3.service的时候,它们将会运行在不同的节点,避免在节点宕机后所有的backend都全军覆没了。
  • …(我觉得这些特性对我来说就差不多够了,还有其他的特性待读者去深究吧^_^)

fleet配置&安装

fleet的使用分为三种情况吧:

  • 在裸机安装CoreOS上使用fleet
    官方推荐的,写好Cloud-Config配置文件后,下载CoreOS ISO,进入Live模式即可安装,具体可参考Using Cloud-Config
  • Vagrant虚拟化的方式安装CoreOS使用fleet
    使用官方提供的vagrant配置https://github.com/coreos/coreos-vagrant.git,能快速启动一个安装好的CoreOS集群,具体可参考Running CoreOS on Vagrant
  • 还有就是在非CoreOS系统上自己安装fleet
    这一种方式是我接下来要讲的,系统没什么要就,只要是linux,有systemd就行(我使用的是deepin-server,基于debian jessie的服务器发行版)

step 1: 准备fleet和etcd二进制文件

# fleet我使用的是0.11.7版本,其他版本请参考 https://github.com/coreos/fleet/releases
wget https://github.com/coreos/fleet/releases/download/v0.11.7/fleet-v0.11.7-linux-amd64.tar.gz
tar zxf fleet-v0.11.7-linux-amd64.tar.gz
cd fleet-v0.11.7-linux-amd64
sudo mv fleetctl /usr/bin
sudo mv fleetd /usr/sbin

# etcd我使用的是3.0.2版本,其他版本请参考 https://github.com/coreos/etcd/releases
wget https://github.com/coreos/etcd/releases/download/v3.0.2/etcd-v3.0.2-linux-amd64.tar.gz
tar zxf etcd-v3.0.2-linux-amd64.tar.gz
cd etcd-v3.0.2-linux-amd64
sudo mv etcd /usr/bin
sudo mv etcdctl /usr/bin

step 2: 准备fleet和etcd的systemd unit文件

创建以下文件:

  • /lib/systemd/system/fleet.socket
[Socket]
ListenStream=/var/run/fleet.sock
  • /lib/systemd/system/fleet.service
[Unit]
Description=fleet daemon
Wants=fleet.socket
After=fleet.socket
After=network.target

[Service]
ExecStart=/usr/sbin/fleetd
Restart=on-abnormal

[Install]
WantedBy=multi-user.target
  • /lib/systemd/system/etcd.service
[Unit]
Description=etcd - highly-available key value store
After=network.target
Wants=network-online.target

[Service]
Environment=DAEMON_ARGS=
Environment=ETCD_NAME=%H
Environment=ETCD_DATA_DIR=/var/lib/etcd/default
EnvironmentFile=-/etc/default/%p
Type=notify
ExecStart=/usr/bin/etcd
Restart=on-abnormal

[Install]
WantedBy=multi-user.target

刷新systemd daemon,让systemd重新读取服务配置文件

sudo systemctl daemon-reload

step 3: fleet配置etcd的URL

fleet启动时默认会去读取/etc/fleet/fleet.conf的配置,在这个文件加上etcd的URL地址

如果文件不存在则创建

  • /etc/fleet/fleet.conf
etcd_servers=["http://10.0.3.106:2379", "http://10.0.3.106:4001"]

上面的10.0.3.106换成etcd所在机器的IP

fleet其他参数配置可参考fleet.conf.sample

step 4: 启动

先拉起etcd服务
sudo systemctl start etcd.service
# 查看服务状态
sudo systemctl status etcd.service

# ● etcd.service - etcd - highly-available key value store
#    Loaded: loaded (/lib/systemd/system/etcd.service; disabled)
#    Active: active (running) since Sun 2016-07-10 16:33:13 CST; 31min ago
#  Main PID: 12155 (etcd)
#    CGroup: /system.slice/etcd.service
#            └─12155 /usr/bin/etcd
# 
# Jul 10 16:33:13 deepin etcd[12155]: 8e9e05c52164694d became candidate at term 2
# Jul 10 16:33:13 deepin etcd[12155]: 8e9e05c52164694d received vote from 8e9e05c52164694d at term 2
# Jul 10 16:33:13 deepin etcd[12155]: 8e9e05c52164694d became leader at term 2
# Jul 10 16:33:13 deepin etcd[12155]: raft.node: 8e9e05c52164694d elected leader 8e9e05c52164694d at term 2
# Jul 10 16:33:13 deepin etcd[12155]: published {Name:deepin ClientURLs:[http://localhost:2379]} to cluster cdf818194e3a8c32
# Jul 10 16:33:13 deepin etcd[12155]: ready to serve client requests
# Jul 10 16:33:13 deepin etcd[12155]: setting up the initial cluster version to 3.0
# Jul 10 16:33:13 deepin etcd[12155]: serving insecure client requests on localhost:2379, this is strongly discouraged!
# Jul 10 16:33:13 deepin etcd[12155]: set the initial cluster version to 3.0
# Jul 10 16:33:14 deepin etcd[12155]: enabled capabilities for version 3.0

etcd启动成功

启动fleet

sudo systemctl start fleet

查看启动状态

sudo systemctl status fleet.service 
# ● fleet.service - fleet daemon
#    Loaded: loaded (/lib/systemd/system/fleet.service; disabled)
#    Active: active (running) since Sun 2016-07-10 17:08:55 CST; 5s ago
#  Main PID: 12486 (fleetd)
#    CGroup: /system.slice/fleet.service
#            └─12486 /usr/sbin/fleetd
# 
# Jul 10 17:08:55 deepin fleetd[12486]: INFO fleetd.go:64: Starting fleetd version 0.11.7
# Jul 10 17:08:55 deepin fleetd[12486]: INFO fleetd.go:165: Using default config file /etc/fleet/fleet.conf
# Jul 10 17:08:55 deepin fleetd[12486]: INFO server.go:157: Establishing etcd connectivity
# Jul 10 17:08:55 deepin fleetd[12486]: INFO server.go:168: Starting server components
# Jul 10 17:08:55 deepin fleetd[12486]: INFO engine.go:185: Engine leadership acquired

fleet启动成功

这个时候,fleet集群就已经架设起来了,剩下的就是添加其他节点了

step 5: 添加fleet节点

fleet节点的添加和上面的fleet部署一样,总结一下就是这几个步骤:

  • 下载fleet二进制文件
  • 添加systemd配置(/lib/systemd/system/fleet.socket, /lib/systemd/system/fleet.service
  • 添加fleet配置,添加etcd server的URL(/etc/fleet/fleet.conf
  • 启动fleet

节点添加是否成功可以使用fleetctl list-machines查看:

fleetctl list-machines -l
# (我添加了两个fleet节点)
# MACHINE                   IP      METADATA
# 0c783e057d36465c9704171a095cb9c7  10.0.3.106  -
# 1f56e7c346a5a5f47676100b50a30afe  10.0.3.105  -
# 58ac997be9c34037be90d93741228b99  10.0.1.62   -

fleet使用

step 1: 上传服务文件

Ok, 集群搭建起来了,那怎么使用这个集群的资源呢?前面说过,fleet的服务配置使用了systemd unit书写格式,如果你曾了解过systemd,那么就可以节约这个入门时间咯:P (个人觉得systemd的unit格式还是很清晰,很人性化的^_^)

一言不合,就上Hello world >.<

将以下内容保存为hello.service文件

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

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

[X-Fleet]
X-Conflicts=hello*.service

上传unit文件

fleetctl submit hello.service

# check
fleetctl list-unit-files -full
# UNIT      HASH    DSTATE      STATE       TARGET
# hello.service 27749ef inactive    inactive    -

step 2: 在集群中启动服务

fleetctl start hello.service
# Unit hello.service launched on 0c783e05.../10.0.3.106

fleet会自动根据其负载均衡调度算法在集群中选择合适的机器启动服务(上面我是在10.0.1.62节点上执行启动命令的)

step 3: 查看服务的输出

fleetctl journal hello.service
# Error running remote command: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain

提示验证失败,为什么服务能启动,可是输出确捕获不到?因为服务配置文件的存储和调度是基于etcd的,而日志的存储则是systemd/journal所做的,fleet捕获日志的方式是通过journal获取,而journal获取远程服务日志的方式是ssh到对应的节点去捕获服务的输出,那怎么搞?

先把你使用中的机器上传一个ssh-pubkey到对应的节点(最好是每个节点都上传过去)如果已经上传过了可以跳过这一步

ssh-copy-id deepin@10.0.3.106 # deepin@10.0.3.106改成目标节点实际的user和ip

准备ssh agent session

# 启动`ssh-agent`并导入环境变量到当前的shell环境
eval $(ssh-agent)

# 添加ssh-private-key到当前的ssh agent session
ssh-add ~/.ssh/id_rsa

链接并查看输出

fleetctl --ssh-username=deepin journal -f hello.service                                                        tmp/fleet choldrim-pc
# -- Logs begin at 四 2016-07-07 16:32:48 CST. --
# 7月 10 18:27:59 deepin-pc docker[31512]: Using default tag: latest
# 7月 10 18:28:14 deepin-pc docker[31512]: latest: Pulling from library/busybox
# 7月 10 18:28:14 deepin-pc docker[31512]: Digest: sha256:a59906e33509d14c036c8678d687bd4eec81ed7c4b8ce907b888c607f6a1e0e6
# 7月 10 18:28:14 deepin-pc docker[31512]: Status: Image is up to date for busybox:latest
# 7月 10 18:28:14 deepin-pc systemd[1]: Started Hello World.
# 7月 10 18:28:20 deepin-pc docker[31524]: Hello World
# 7月 10 18:28:21 deepin-pc docker[31524]: Hello World
# ...

其他

  • ssh
    做法和fleetctl journal类似,创建ssh agent session环境,然后fleetctl --ssh-username=deepin ssh hello.service即可登录到对应的节点
  • metadata
    可以在/etc/fleet/fleet.conf配置文件中添加metadata="disk=ssd,fs=lvm,foo=bar",然后在unit文件中的[X-Fleet]部分添加MachineMetadata=disk=ssd,就可以做到让服务匹配启动节点了

还有其他功能就没有一一列举了,总得来说,fleet还是蛮不错的,和systemd服务绑在一起,使得使用也变得简单了 ^_^

参考

Using fleet with CoreOS
CoreOS — fleet 初探
Launching containers with fleet

(end)

One thought on “CoreOS fleet之初体验”

发表评论

电子邮件地址不会被公开。 必填项已用*标注