设计自己的paas平台nap 1—-背景知识

写在前面

在理解了dokku,dokku-alt的基础上,我们设计自己的paas平台。我们的终极目标是在一个集群环境中设计一个paas平台,dokku只是单机环境下,为了我们的终极目标,我们最终选择的paas的底层平台是coreos集群环境。这几篇blog只是我们不断进行尝试的日志,并不是一个完整的教程,等我们最终搭建好了,可能会写一个完整的教程,但那都是后话。

coreos

coreos官网上,coreos的副标题就是Linux for massive server deployments。coreos简单来说,就是为云环境而生的操作系统,真正的云操作系统。它具有很多操作系统没有的优点,它最初的设计源自于google的chromeos,对系统结构重新设计,剔除了任何不必要的软件和服务。适合集群环境,而不是传统的服务器操作系统。 没有提供包管理工具,通过容器化,向应用程序提供运算环境。应用程序之间共享系统内核和资源,但是彼此之间又互不可见。应用程序将不会再被直接安装到操作系统中,而是通过 Docker 运行在容器中。这种方式使得操作系统、应用程序及运行环境之间的耦合度大大降低。 采用双系统分区设计。ChromeOS最大的优点。两个分区分别被设置成主动模式和被动模式并在系统运行期间各司其职。主动分区负责系统运行,被动分区负责系统升级。一旦新版本的操作系统被发布,一个完整的系统文件将被下载至被动分区,并在系统下一次重启时从新版本分区启动,原来的被动分区将切换为主动分区,而之前的主动分区则被切换为被动分区,两个分区扮演的角色将相互对调。同时在系统运行期间系统分区被设置成只读状态,这样也确保了 CoreOS 的安全性。CoreOS 的升级过程在默认条件下将自动完成,并且通过 cgroup 对升级过程中使用到的网络和磁盘资源进行限制,将系统升级所带来的影响降至最低。 使用Systemd取代SysV作为系统和服务的管理工具。具备优秀的并行化处理能力,按需启动等特点。

既然说到coreos是最好的云操作系统,那么coreos和集群就联系的十分紧密了。coreos集群中最重要的是三个概念。docker,fleet,etcd。

docker技术我们这里就不在介绍了,docker技术也是我们研究的主题,如果docker技术都不懂,那么你根本不会看这篇blog。

其次是fleet。fleet 是一个通过 Systemd对CoreOS 集群中进行控制和管理的工具。每个 fleet agent 之间通过 etcd 服务来注册和同步数据。fleet 提供的功能非常丰富,包括查看集群中服务器的状态、启动或终止 Docker container、读取日志内容等,某个服务器脱离集群,其上面的所有服务都会转移到别的服务器上。包括部署高可用的服务等。fleet提供了很多好用的api接口,在后面我们会详细介绍。

最后是etcd。etcd技术是coreos的骨架。etcd 是一个分布式 key/value 存储服务,CoreOS 集群中的程序和服务可以通过 etcd 共享信息或做服务发现 。etcd 基于 raft 一致性算法:通过选举形式在服务器之中选举 Lead 来同步数据,并以此确保集群之内信息始终一致和可用

systemd

在前面提到过,coreos是通过systemd来系统和服务的管理工具,同样的fleet也是通过systemd,看来,systemd的一些基本语法也是我们要了解的内容。

  • sudo systemctl status xx.service 查看某个服务的状态。
  • sudo systemctl start xx.service
  • sudo systemctl stop xx.service
  • sudo systemctl kill xx.service
  • sudo systemctl restart xx.service
  • sudo systemctl daemon-reload 如果重启一个修改了service文件的服务,你必须reload service文件

systemd由两个基本概念组成,unit和target。unit是一个配置文件,用来描述想要跑的进程的一些参数。target是一个grouping mechanism,用来允许systemd在同一时间起多个进程。systemd是coreos上启动的第一个进程。systemd进程读取不同的target,运行这些进程。每一个target一般是对unit文件的一个symlinks的集合,当运行systemctl enable foo.service 的时候,就会创建一个指向这个unit文件的symlinks,在multi-user.target.wants中。

在coreos中,unit files一般位于/etc/systemd/system中,这个文件系统是可读写的。

看个基本的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=MyApp
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"

[Install]
WantedBy=multi-user.target

after和requires,这个基本定义了运行这个程序在哪个区间里,上面的例子就是说,只有在docker.service运行起来之后,才可以运行这个东西。 execstart 在执行这个unit的时候,要干什么事情。这个进程的pid就是systemd监控的用来判断进程是否挂掉的进程。不要跑container用-d参数,这个参数会阻止container用这个pid的子进程来运行。这样systemd会认为这个进程已经退出了,那么这个unit也会被停止。 wantedby指出这个unit是哪个targt的一部分。

  • sudo systemctl enable /etc/systemd/system/hello.service会创建一个symlink。

  • sudo systemctl start hello.service

  • journalctl -f -u hello.service会读取hello.service的输出。

  • ExecStartPre 执行execstart之前要执行的命令。

  • execstart 这个unit的主要的执行命令。

  • execstartpost 当execstart执行结束,执行的命令。

  • execreload 当执行systemctl reload xx.service的时候,会执行的命令。

  • execstop 当unit被认为失败,或者执行systemctl stop xx.service的时候,执行的命令。

  • execstoppost 当execstop执行完成后,执行的操作。

  • RestartSec 当重启一个服务的时候,要睡眠多少秒,当预防失败的服务没100ms自己尝试restart的情况。

  • =-是忽视这条命令产生的错误。当我们删除一个不存在的container的时候,会报没有这个container错误,但是我们只是保险起见,所以这个并不能称为错误。

May 18th, 2015