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

ub31hn15 8年前發布 | 14K 次閱讀 Systemd CoreOS

來自: http://dockone.io/article/1055

【編者的話】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:運行這個單元最主要的命令(這個參數是幾乎每個 .service 文件都會有的,指定服務啟動的主要命令,在每個配置文件中只能使用一次。編者注)
  • ExecStartPost: ExecStart 運行完成后要執行的命令(指定在啟動執行 ExecStart 的命令后的收尾工作,也可以有多個。編者注)
  • ExecReload:當使用 systemctl重新加載服務所需執行的命令
  • ExecStop: 通過執行systemctl 確認單元服務失敗或者停止時執行的命令
  • 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</pre>

讓我們仔細來看一下剛才創建這個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= 當單元開始啟動,這里允許你執行想運行的命令。但是不要用-d來啟動Docker容器,因為這樣講組織docker作為一個子進程被啟動. Systemd會認為進程已經退出,相應的單元也會停止。
  • ExecStop=/usr/bin/docker stop busybox1 busybox1容器將會被停止.
  • WantedBy=multi-user.target" 當啟動 multi-user.target時,Systemd將會將獲取單元.

如果要啟動一個新的Unit,必須使用Systemd創建symlink然后啟動文件:

$ sudo systemctl enable /etc/Systemd/system/hello.service

$ sudo systemctl start hello.service</pre>

要驗證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

[...]</pre>

-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

讓我們看一下你可以執行的任務,列出所需的命令。

開始單元服務:

$ fleetctl start hello_world.service

檢查單元服務狀態:

$ 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</pre>

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單元的[install]部分。其余Systemd部分保持與fleet相同。

我們一起看一下特殊的部分配置:

  • MachineID: 規定每一個機器的唯一字符串編號
  • MachineOf: 對那些有特定單元的,限制的機器才可以有
  • MachineMetadata: 限制那些有特定元數據的機器
  • Conflicts: 防止一個單元使用其他單元名字glob-matching合并其它Unit
  • Global: 在所有集群機器上規定這個Unit

上面所有的都在單元文件的[X-Fleet]部分。除非單元文件上MachineMetadata提供配置Global=true,否則我們認為這個文件是無效的。如果你想在所有集群或者MachineMetadata指定值得機器上規定相同的單元,全局單元文件就非常有用了。

下面我們來看一下上述提到的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@*</pre> 例子中的hello_world@

是做什么的?

好的,讓我們來說說 hello_world@1.servic e and hello_world@2.servic e兩個完全相同的文件。

在集群上啟動:

$ fleetctl start hello_world@*

這兩個Fleet文件都部署在 MachineMetadata=group=hw_webservers配置的服務器,配置Conflicts=hello_world@意圖是防止一個Unit使用了global-matching與Unit文件沖突。

讓我們看另一個hello_world.service 單元的例子。

規定集群中所有的機器的這個單元:

[X-Fleet]

Global=true</pre>

規定機器上有some_other_unit.service單元:

[X-Fleet]

MachineOf=some_other_unit.service</pre>

規定單元機器的編號為:562999f8

[X-Fleet]

MachineID="562999f8"</pre>

獲取機器ID:

$ fleetctl list-machines

寡欲fleet 單元更多的只是, 參考官方文檔

集群中運行一個容器

你要做的就是提供一個嚴格格式的【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</pre>

注意:如果你是手動運行docker命令,請確保不要在命令行中復制運行命令在分離模式中開啟一個容器,這種做法將會使會造成容器運行幾秒鐘后自動退出。

總結

這篇文章中:

  • 為Systemd寫入Unit文件
  • 如何用Fleet創建分布式Systemd
  • 為Fleet寫入Unit文件

請不要忘了系列的上兩篇文章,在第一篇我們講述了CoreOS的基礎原理 ,自動升級,發布渠道,集群發現等。在第二篇文章中,我們熟悉了cloud-config,etcd等。

下一個系列中,主要學習Docker。

原文鏈接: CoreOS Overview, Part Three (翻譯:張亞龍)

</div>

 本文由用戶 ub31hn15 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!