[转]深入浅出CoreOS



深入浅出CoreOS(一):概述



【编者的话】CoreOS是一款OS,但它是一款面向云的轻量级OS。CoreOS是以Linux系统为基础,为了建设数据中心的需要,而从Linux底层进行了内核裁减。CoreOS提供了一系列的机制和工具来保证CoreOS组建的云环境是安全,可靠和最新的。CoreOS设计之初就定位于可以提供一种动态缩放和管理集群的能力,可以方便管理类似google 这种庞大数据中心的集群。本系列文章从浅入深介绍了CoreOS的一些特性和细节,让我们一起来学习一下。

CoreOS是很多容器栈中的重要的组成部分。我们将通过这一系列的文章探讨CoreOS为什么这么重要,它到底是怎么工作的。如果您现在对CoreOS所知不多,请不用担心,让我们从头开始学习。

CoreOS的基础以及CoreOS与其他Linux系统的区别

CoreOS是以安全性、一致性、可靠性为设计目标的一款操作系统。
  • CoreOS采用主动/被动双分区方案来实现自动更新。自动更新以单一体为单位,而不是通过逐包替换的方式进行。稍后我们将详细介绍这个。
  • CoreOS使用Linux容器在更高抽象层次上管理服务,而没有采用通过yum或者APT工具做包的安装管理。单一的服务代码以及它所有的依赖会被打包到一个容器中,打包进入容器后就可以运行在单一的CoreOS机器,也可以运行在CoreOS集群中。
  • Linux容器提供与完整虚拟机相似的功能。但是容器聚焦在应用程序层次,而不是整个虚拟主机层次。因为容器不能运行独立的Linux内核,不需要一个中间件层,因此它几乎没有性能上的开销。低性能开销的特质意味着可以部署更少的机器、使用配置低的机器就可以完成虚拟机同样的功能,从而降低成本。

CoreOS几乎可以运行在包括VagrantAmazon EC2QEMU/KVMVMwareOpenStack的任何平台,甚至在未安装任何软件的裸机硬件环境都可以。

因为CoreOS的设计初衷只为运行应用容器,因此需要安装很少系统级别的依赖包即可。相比典型的Linux服务器,这就意味着CoreOS需要很低耗的CPU和高效的RAM即可满足需求。

例如下面是一个RAM使用率的对比:

4.png


除此之外,CoreOS还采用了一个主动/被动双分区方案启动。
系统启动到根分区A:

6.png


目标一下子就变得非常清晰了。

CoreOS更新

满足CoreOS频繁更新是系统的理念,可靠的更新是良好安全性的关键。
CoreOS通过合并经常需要更新的为一个实体,实现最小化每一个复杂的更新:
  • 操作系统级
  • 应用程序代码级
  • 单一配置

FastPatch是一个主动-被动根分区方案, CoreOS的更新是通过使用FastPatch保持一致。它是通过将整个系统作为一个单一的单位替换更新,而不是通过包与包的不断替换更新。

一旦CoreOS的更新可用,所有的CoreOS都是通过访问公共的更新服务来接收更新。包括渠道到渠道之间版本的升级更新服务都是由CoreOS工程师团队亲自管理的。每一次更新服务的发布都很便捷。这些更新永远是针对所有的用户可用的,而不会再去考虑用户地位等。

如何更新

上述所说的更新类型一直用于传统电子元器件更新,现在大多数浏览器的更新也是这样的。考虑一下,像Chrome和Firefox是怎么实现频繁无缝自动更新的?事实上,CoreOS团队也使用了Chrome的更新引擎Omaha。Omaha使用的是一个基于XML客户端-服务器协议

开始时,系统启动进入A分区(主动),CoreOS开始启动查询更新服务,查询获取相关更新。如果更新可用,下载并安装到B分区。

CoreOS会下载一个完整的新分区文件系统,而不是每次只更新一个包。
下载更新后,操作系统更新会被应用到B分区(被动),重新启动之后B分区就会变成主动引导分区,并引导系统启动。
下图描述这个过程:

9.png


如果在重新启动引导中更新不成功,则回滚在先前的启动分区。CoreOS中系统的更新是一个原子的操作,所以很容易回滚。
双分区方案在就地升级时具有很大的优势:
  • 安全回滚
    以前已知的稳定版本仍在第一个分区。CoreOS有一个内置的故障恢复区,如果升级结果不稳定可以执行恢复。这个过程也可以手动执行。
  • 签名验证
    每一个引导分区都是只读的,这样验证每一个下载的完整性就很容易了,我们还能确保在传输过程中不被篡改。
  • 超快速执行
    由于CoreOS体积很小,所以启动非常迅速。执行一次更新需要重启只用几秒就可以完成。这也意味着会最大限度地减少应用程序中断的时间。平台支持kexec,就可以跳过启动过程,进一步缩短启动的时间。

更新策略和自动更新

CoreOS默认会开启自动更新模式。
每一个CoreOS集群都有一个独特的风险承受能力和业务需求。为了满足每一个人的需求,我们有四个更新策略

让我们更详细地看一下这些更新策略:
  • Best-effort:
    • 这个策略是默认的。它会检测机器是否是集群的一部分,如果属于集群,则Etcd-lock策略启用;否则Reboot策略启用。
    • 建议在生产集群中使用此策略。
  • Etcd-lock:
    • 这一策略授权给每一个机器,而且会在重启之前获取Reboot锁,才可以重新启动。这一策略的主要目标是允许更新快速应用到集群中,而不用在etcd丢失全体用户或者在集群中减少服务的负载容积。重启锁会在更新成功前一直起作用。
  • Reboot:
    • 这一策略是重启机器后尽快将更新安装到被动分区。
    • 这一策略对准确时间定时启动的机器比较有适用。例如,通过云配置维护窗口自动更新的机器。
  • Off:
    • 该机器在成功更新到被动分区后不会重新启动。
    • 该策略用户本地开发环境下,重启控制在用户自己手中;或者在生产集群中,集群在固定的时间或晚上重新启动。

CoreOS自动重启由重启管理工具locksmith完成,locksmith是CoreOS更新引擎,使用etcd确保集群的子集可以在任何时间重启主机。locksmith只在CoreOS上运行一个守护进程,负责更新后控制系统的重启任务。

更新的策略在更新部分的cloud-configfile配置:
#cloud-config
coreos:
update:
reboot-strategy: best-effort


我们将在以后的文章中讲述配置文件cloud-config的细节。

发行渠道

CoreOS有三个更新渠道
  • Alpha
  • Beta
  • Stable

按照顺序,CoreOS的发布过程是:alpha,beta,最后是stable。低一级渠道的发行版都为下一个版本发行版服务。一旦一个版本被认为已经没有Bug,就可以进入下一级发行渠道,一级一级往下。也会可能在stable渠道中下载安装,然后转换为接收beta或者alpha渠道的更新,这都是很容易做到的。相似的,也可能会安装beta渠道的版本,后来转换接收alpha的更新。

注意:安装alpha渠道版本,后续转换为beta或者stable渠道再请求更新,这样是不可以的。

转换系统发布渠道时,我们创建一个update.conffile:
$ sudo vi /etc/coreos/update.conf


然后设置所需的释放渠道:
GROUP=beta


现在重新启动更新引擎,以便它可以选择改变的渠道:
$ sudo systemctl restart update-engine


当下一个更新检查完成时,新的发布渠道已经被应用。

集群发现

CoreOS使用etcd专门处理集群上软件之间的协调,它运行在每一个系统上。一组CoreOS机器组成一个集群,他们的etcd进程需要互相连接。后续的文章将详细讲述etcd。

发现服务是通过存储每一个地址列表、元数据、唯一地址的初始化的集群,提供免费连接etcd成员之间的通信的帮助,称之为发现URL,例如https://discovery.etcd.io
你可以非常容易地生成一个发现URL。
$ curl -w "\n" 'https://discovery.etcd.io/new?size=3' 


这应该产生这样的输出:
https://discovery.etcd.io/6a28e078895c5ec737174db2419bb2f3


这样通过提供给每一个发现服务一个发现Token,这也就是为什么这个服务能被发现相应。
这仅仅用于初步的发现,一旦一台机器位于一个对等的位置,所有的通信沟通都将在整个集群内部进行。

发现服务URL可以通过cloud-config(编者注)提供每个CoreOS配置,cloud-config是一个很小的配置工具,主要用于连接在网络和集群的机器。本系列后续的部分将解释发生在幕后的一些细节,但是如果你想尽可能迅速获取集群,你要做的就是提供一个新鲜独特的发现,配置在cloud-config文件中。

有其他的etcd集群引导方法:
  • Static:在etcd集群 静态IP地址被用于引导
  • DNS发现:SRV记录作为一个发现机制

你能够在说明文档中读到更多关于集群发现的信息

总结:

在这篇文章中,我们讲述到:
  • CoreOS与其他Linux系统的区别
  • 自动更新机制与发布渠道
  • 集群发现的原理

在接下来这个系列的文章中,我们着重探讨一下cloud-config、etcd,当然也会涉及一部分集群架构的内容。




深入浅出CoreOS(二):Cloud-Config和etcd

【编者的话】CoreOS是一款OS,但它是一款面向云的轻量级OS。CoreOS是以Linux系统为基础,为了建设数据中心的需要,而从Linux底层进行了内核裁减。cloud-config、etcd都是CoreOS离不开的话题,它们对CoreOS的作用何在呢?让我们一起来学习吧。

这是关于深入浅出CoreOS的第二篇文章。在我上一篇文章中,主要阐述了CoreOS与其他Linux系统之间的不同、CoreOS的自动更新机制、发布渠道和集群发现的原理等。这篇文章中,我主要介绍一下cloud-config和etcd,文章最后会谈一些常见的集群架构。

Cloud-Config

Cloud-Config允许用户以声明的方式自定义各种级别的系统项目,例如网络配置,用户账户,systemd units(这将在下一篇文章中叙述)。Cloud-Config起源于Ubuntu,但在CoreOS中做了一些简单的修改。

在每一个CoreOS集群的核心,都有CoreOS-Cloudinit,我们用cloud-config文件来做初始化配置操作,在系统启动或者运行时用于配置系统。

什么是Cloud-Config?

Cloud-config是用YAML格式编写,规定使用空格和换行来限制列表、关联数组和值。这是关键性的格式化配置,所以在cloud-config部署到一个节点之前,必须使用CoreOS提供的在线工具进行验证。一个cloud-config文件必须使用#cloud-config开头,后续可以跟一个或多个关键字组成的关联数组。

下面是一些经常用到的关键字:
  • CoreOS: 处理CoreOS的一些比如更新策略、etcd2,、fleet、flannel、units等的细节
  • write_files: 使用命令在本地文件系统定义一系列文件
  • ssh-authorized-keys 添加可以验证核心用户的ssh公钥

下面是一个cloud-config的例子:
#cloud-config
hostname: core-01
coreos:
update:
reboot-strategy: off
etcd2:
name: core-01
initial-advertise-peer-urls: http://127.0.0.1:2380
initial-cluster-token: core-01_etcd
initial-cluster: core-01=http://127.0.0.1:2380
initial-cluster-state: new
listen-peer-urls: http://0.0.0.0:2380,http://0.0.0.0:7001
listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
advertise-client-urls:  http://0.0.0.0:2379,http://0.0.0.0:4001
units:
- name: etcd2.service
  command: start
- name: fleet.service
  command: start
- name: docker-tcp.socket
  command: start
  enable: true
  content: |
    [Unit]
    Description=Docker Socket for the API

    [Socket]
    ListenStream=2375
    BindIPv6Only=both
    Service=docker.service

    [Install]
    WantedBy=sockets.target
- name: docker.service
  command: start
  drop-ins:
    - name: 50-insecure-registry.conf
      content: |
        [Unit]
        [Service]
        Environment=DOCKER_OPTS='--insecure-registry="0.0.0.0/0"'
write-files:
- path: /etc/conf.d/nfs
permissions: '0644'
content: |
 OPTS_RPC_MOUNTD=""
ssh_authorized_keys:
- ssh-rsa 121313dqx1e123e12… user@my_mac

想了解更过关于cloud-config的配置参数,请参考文档说明

ETCD2.X

Etcd是一个开源的分布式键值对存储系统,专门为集群之间提供可靠的共享数据服务。

Etcd运行在每一个etcd集群的中央服务机器上(不用担心,随后我们会详细讲述此处),可以兼容机器运行的失败,甚至是中心机器运行失败(此时其他机器会替代中心机器)。

系统使用Raft一致性算法将数据的复制分发到etcd的节点。一致性是容错分布式系统的一个基本的要求,一致性也包含很多服务上的数据一致。这样一旦系统得出结论,这就是最终的结论了。

Deis使用etcd来存储数据,Kubernates同样也在使用etcd存储数据。

优化etcd集群的大小

Etcd集群的推荐3个、5个或者7个成员。尽管更大的集群可以提供更好的容错能力,但是它的写操作性能会不断降低,因为此时数据需要被复制到更多的机器上。常规上,集群中使用3或者5个成员就足够满足系统需求了。推荐集群中的成员数量是奇数个的,奇数个成员的集群不会更改大部分的需求数量,但可以通过增加额外的成员从而增加系统的容错能力。

下面的实践中我们对比一下偶数个成员和奇数个成员的不同:
2222222.png

正如表中描述,增加额外一个成员扩充集群的大小到奇数成员数量是值得的。

在网络分区中,集群奇数成员可以保证在网络分区结束后总还会有大部分可以操作的集群。

更多关于etcd的内容,请参考etcd的文档说明

下面是一个中央服务器的etcd设置:
#cloud-config
coreos:
etcd2:
# generate a new token for each unique cluster from https://discovery.etcd.io/new
discovery: https://discovery.etcd.io/60887e46255f4efew37077ccf12b5f06a54a
initial-advertise-peer-urls: http://$private_ipv4:2380
# listen on both the official ports and the legacy ports
# legacy ports can be omitted if your application doesn't depend on them
listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
listen-peer-urls: http://$private_ipv4:2380,http://$private_ipv4:7001
data-dir: /var/lib/etcd2


https://discovery.etcd.io/new?size=3 已经定义使用,因此在初始化etcd是必须满足是3个成员的集群。

代理模式

当你为提供一个中央服务而启动一个隔离的etcd集群,worker机器就需要连接到etcd集群,并把自己作为一个集群成员注册进去,这样就可以接收部署集群 fleet units,获取操作系统的更新等等。

运行在每一个工作节点最容易的方式是通过代理,而不是启动etcd本地服务。运行etcd作为代理允许你网络上的etcd容易被发现,因为它可以作为本机服务运行在每一台机器上。在这个模式下,etcd作为一个反向代理主动向etcd节点发送客户端请求。由于etcd代理不能参与etcd的一致性复制,所以它既增加了还原力,也不减少集群的写操作。

需要通信的etcd服务可以连接到本机。

Etcd目前支持两种代理模式:readwrite和readonly。

默认的代理模式是readwrite,可以提供对集群的读写请求操作。

通过集群成员列表,代理可以周期性的轮转到每个成员,这样可以表面将所有的流量转发给一个成员。

下面是一个设置代理的例子:
#cloud-config
coreos:
etcd2:
listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
advertise-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
discovery: https://discovery.etcd.io/60887e46255f4efew37077ccf12b5f06a54a
proxy: on

通过下面URL,这些经由本地的客户端连接访问etcd中央服务:
https://discovery.etcd.io/60887e46255f4efew37077ccf12b5f06a54a

关于更多etcd代理的介绍可以参考文档

集群架构

根据集群的大小和集群的使用场景,下面有几条共同的集群架构准则是必须遵守的。

我们强烈建议设置固定数量的机器运行etcd中央集群服务,再分离出一个单独固定数量的机器专门用于分布式应用控制,例如Deis,kubernetes,Mesos,OpenStack等。

分离出这些服务到固定数量的机器,可以确保它们能跨数据中心和可用区域分配,设置的静态网络允许简单启动。

如果你担心依赖发现服务,这种设计可以消除你的后顾之忧。

然后就可以设置你的worker机器连接到中央服务。在这种设置中,你可以放大或者缩小你的机器从而满足你的需求,再也不用担心超多集群的额定人数。

想获得通过cloud-config文件配置设计不同集群的架构的更多信息,请参考文档

下面我们一起看几个例子:

笔记本上的Docker开发环境

如果你在本地开发,但是计划在生产环境运行容器,本地环境将帮助你获取镜像。

在本地笔记本上很容易就可以运行Docker命令,从而操作VMware或者VituralBox中的CoreOS VM。

下面是一个CoreOS VM开发环境:


一个容易开发测试的集群

下面的CoreOS集群开发测试被充分利用:


这种设置对运行你的开发环境,测试环境,裸机环境或者云虚拟主机都十分有用。

如果你是第一次使用CoreOS,你会经常调整你的cloud-config文件,需要启动,重启甚至重装好多机器。

这样不用通过生成新的发现URL和重启etcd,很容易就可以开启一个etcd节点。通过这种方式,你就可以根据你的需求从etcd节点自由地引导更多的机器。

fleet、locksmith、和 etcdctl的所有功能照常工作,但是通过etcd代理连接集群,而不是使用本地etcd实例。因为etcd只通过代理模式访问所有的机器,你的CPU和RAM会减少一些压力。

现在设置的这种环境具有最佳的性能。

一个CoreOS生产集群分为中央服务部分和worker部分:


将集群划分为中央服务和worker利于生产环境。对于大的集群,我们推荐要有三到四台机器运行中央服务。这样设置完成后,就可以在worker部门增加任意多的机器完成任务。每一个worker机器通过本地etcd代理使用在中央机器的分布式etcd集群。Fleet通过使用机器元数据和全局fleet units引导中央服务和worker机器上的jobs。我们将在下一篇文章中叙述这些。

注意:如果你有Deis,Kubernetes,或者需要专门机器的其他服务,不要把这些服务放到etcd集群机器中。相反专门使用固定数量的机器完成。我们推荐使用etcd集群奇迹运行其他任何etcd服务。

总结

这篇文章中我们讲到:
  • Cloud-config配置文件
  • 为什么建议etcd集群的机器数量为奇数
  • 代理模式运行etcd
  • 一些etcd集群的常规设置

在下一篇文章中我们就会更详细地学习一下sytemd和fleet


深入浅出CoreOS(三):Systemd和Fleet

【编者的话】Systemd并不是CoreOS特有的服务。本质上说Systemd是没有依附于任何一个Linux发行版的独立项目,但是很多发行版Linux都在青睐Systemd管理服务的优势,所以CoreOS选择了它。Fleet是管理CoreOS和部署app的工具。有了Fleet,你就可以把整个CoreOS集群当做一台节点来处理。让我们一起学习关于此方面的内容。

这是深入浅出CoreOS系列文章中的第三篇,也是最后一篇。

上一篇文章中,我们学习了cloud-config配置文件,在代理模式下运行etcd,以及关于etcd集群的一些常规设置。这篇文章中,我们将探讨Systemd、Unit文件、Fleet和Fleetctl。

Systemd概述

Systemd是CoreOS用于初始化系统的工具。它能提供许多强大的功能,例如启动服务、停止服务、监控和重启进程等。在CoreOS中,Systemd既可以用来管理Docker容器的生命周期,又可以管理不同系统的启动任务。

要想进一步学习Systemd,必须要深入查看一系列关于Systemd的博客。不过,在此我们只讨论需要CoreOS上的Docker容器上操作所需要的一些Systemd知识。

更多关于Systemd的内容,可以参考官方文档

Unit文件

Systemd为每一个守护进程记录一个初始化结构文件,我们称之为Unit文件。Systemd系统取代了传统系统为每一个守护进程初始化一次脚本的做法。这样的记录会有很多不同种类的Unit文件,但是我们只会关注可以运行Docker容器的服务类型Unit文件。

下面列表,按照顺序是一个服务Unit(service unit)生命周期内的过程,以及作用描述:
  • ExecStartPre: ExecStart之前运行的命令(指定在启动执行 ExecStart 的命令前的准备工作,可以有多个,如前面第二个例子中所示,所有命令会按照文件中书写的顺序依次被执行。编者注)
  • ExecStart:运行这个Unit最主要的命令(这个参数是几乎每个 .service 文件都会有的,指定服务启动的主要命令,在每个配置文件中只能使用一次。编者注)
  • ExecStartPost:ExecStart 运行完成后要执行的命令(指定在启动执行 ExecStart 的命令后的收尾工作,也可以有多个。编者注)
  • ExecReload:当使用 systemctl重新加载服务所需执行的命令
  • ExecStop:通过执行systemctl 确认Unit服务失败或者停止时执行的命令
  • ExecStopPost:ExecStop 执行完成之后所执行的命令(指定在 ExecStop 命令执行后的收尾工作,也可以有多个。编者注)
  • RestartSec:在重启服务之前系统休眠时间(很有效的防止失败服务少于100ms重启一次)(如果服务需要被重启,这个参数的值为服务被重启前的等待秒数。编者注)

下面我们演示创建一个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文件:
  • Description: 可以在Systemd日志展示(可以通过journalctl和Systemdctl来检查日志文件)
  • After=docker.service 和 Requires=docker.service 意思是只有docker.service启动后才可以被激活。当然也可以定义自己的动作.你也可以使用多个After来做限制,多个after使用空格分开即可
  • =- 是Systemd忽略错误的一个语法.在这种情况下,docker会发挥一个非0的退出码,如果想停止一个不存在的容器,这对我们来说并不是一个错误。
  • ExecStartPre=-/usr/bin/docker rm busybox1 如果 busybox1镜像存在,则删除它。 如果镜像不存在,则脚本继续往下运行。
  • ExecStartPre=/usr/bin/docker pull busybox 将从注册中心获取最新的busybox
  • ExecStart= 当Unit开始启动,这里允许你执行想运行的命令。但是不要用-d来启动Docker容器,因为这样讲组织docker作为一个子进程被启动. Systemd会认为进程已经退出,相应的Unit也会停止。
  • ExecStop=/usr/bin/docker stop busybox1 busybox1容器将会被停止.
  • WantedBy=multi-user.target" 当启动 multi-user.target时,Systemd将会将获取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 概述

Fleet运行在Systemd上层,在集群层次控制Systemd,负责创建分布式Systemd:


要想把服务发布进集群,就必须提交合规范的Systemd unit。

FLEETCTL

Fleetctl是官方推荐的控制fleet unit工具,它可以在本地或者远程CoreOS集群使用。Fleetctl命令类似于systemctl命令,必须在命令前面加上sudo命令在配合使用。Fleetctl命令可以直接在集群上运行。或者如果你喜欢从外部主机执行fleetctl(即你的工作站),可以通过SSH把系统环境变量作为参数传递给集群机器,像这样:
$ export FLEETCTL_TUNNEL=remote_machines_ip

让我们看一下你可以执行的任务,列出所需的命令。
开始Unit服务:
$ fleetctl start hello_world.service

检查Unit服务状态:
$ 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

Unit 文件

Fleet主要是依赖Unit文件交互的。对于Systemd Unit,它定义了想要做什么以及fleet应该如何去做,在集群中Fleet安排一到多台机器,Fleet安排一个有效的Unit文件。在[X-Fleet]部分留意fleet的一些特殊部分,可以用来替换Systemd Unit的[install]部分。其余Systemd部分保持与fleet相同。
我们一起看一下特殊的部分配置:
  • MachineID: 规定每一个机器的唯一字符串编号
  • MachineOf: 对那些有特定Unit,限制的机器才可以有
  • MachineMetadata: 限制那些有特定元数据的机器
  • Conflicts: 防止一个Unit使用其他Unit名字glob-matching合并其它Unit
  • Global: 在所有集群机器上规定这个Unit

上面所有的都在Unit文件的[X-Fleet]部分。除非Unit文件上MachineMetadata提供配置Global=true,否则我们认为这个文件是无效的。如果你想在所有集群或者MachineMetadata指定值得机器上规定相同的Unit,全局Unit文件就非常有用了。
下面我们来看一下上述提到的Fleet Unit中使用的hello_world.service文件:
[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

[X-Fleet]
MachineMetadata=group=hw_webservers
Conflicts=hello_world@*

例子中的hello_world@*是做什么的?

好的,让我们来说说hello_world@1.serviceand hello_world@2.service两个完全相同的文件。

在集群上启动:
$ fleetctl start hello_world@*

这两个Fleet文件都部署在MachineMetadata=group=hw_webservers配置的服务器,配置Conflicts=hello_world@*意图是防止一个Unit使用了global-matching与Unit文件冲突。

让我们看另一个hello_world.serviceUnit文件的例子。
规定集群中所有的机器:
[X-Fleet]
Global=true

规定机器上有some_other_unit.service Unit:
[X-Fleet]
MachineOf=some_other_unit.service

规定Unit机器的编号为:562999f8
[X-Fleet]
MachineID="562999f8"

获取机器ID:
$ fleetctl list-machines

关于fleet Unit更多的只是,参考官方文档

集群中运行一个容器

你要做的就是提供一个严格格式的【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命令,请确保不要在命令行中复制运行命令在分离模式中开启一个容器,这种做法将会使会造成容器运行几秒钟后自动退出。

总结

这篇文章中:
  • 为Systemd写入Unit文件
  • 如何用Fleet创建分布式Systemd
  • 为Fleet写入Unit文件

请不要忘了系列的上两篇文章,在第一篇我们讲述了CoreOS的基础原理 ,自动升级,发布渠道,集群发现等。在第二篇文章中,我们熟悉了cloud-config,etcd等。

文章来源:http://dockone.io/topic/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BACoreOS 


英文版:

https://deis.com/blog/2016/coreos-overview-p1/

https://deis.com/blog/2016/coreos-overview-p2/

https://deis.com/blog/2016/coreos-overview-p3/


展开阅读全文

没有更多推荐了,返回首页