提供:ZStack云計算
本教程為CoreOS上手指南系列九篇中的第三篇。
CoreOS為我們提供了一套跨越多服務器環境的Docker容器管理平臺,而其中的fleet服務則能夠顯著簡化整套集群的管理難度。
Fleet允許用戶將Docker容器作為服務對整體集群進行管理。它既作為接口存在,同時亦作為各集群成員中systemd init系統的抽象層。用戶可以設定約束條件,從而對服務的運行方式加以限定。通過這種方式,管理員能夠要求特定應用程序運行在同一或者不同主機之上,并以此實現基礎設施調整。
在今天的教程中,我們將了解fleet并學習利用fleetctl工具控制該守護進程。
要完成本篇教程,大家首先需要擁有一套可用CoreOS集群。
在之前的系列教程如何利用DigitalOcean創建一套CoreOS集群當中,我們已經完成了集群創建工作。
此集群配置包含三個節點。它們能夠利用專有網絡接口實現彼此通信。這三臺節點亦擁有公共接口以運行公共服務。各節點名稱分別為:
coreos-1coreos-2coreos-3在集群準備就緒后,下面繼續這場fleet之旅。
在探討fleetctl工具之前,我們應當首先聊聊服務單元文件。
單元文件由systemd init系統用于描述每項可用服務,定義對其進行管理的必要命令并設定服務啟動時確保系統處于正常狀態的各關聯性信息。其中fleet守護進程構建在systemd基礎之上,從而立足于集群層面進行服務管理。有鑒于此,它使用的systemd單元文件與標準版本略有不同。
為了進一步了解fleet單元文件,請參閱深度解析一文。在今天的教程內,我們只會對這些文件的格式進行概述。我們還會提供一個示例單元文件以幫助大家了解fleetctl。
大多數單元文件都包含以下幾個基礎區段:
Unit: 此區段用于提供與該單元相關的普通信息,且與單元的“type”無關。其中包括元數據信息及關聯性信息。其在fleet中主要用于提供描述并指定該單元如何與其它其它服務單元對接。Unit Type Section: fleet守護進程能夠容納多種不同單元類型,包括: ServiceSocketDeviceMountAutomountTimerPath如果該類型已經擁有特定選項,則允許其中包含一個與類型相關的區段。Service區段類型最為常見,其用于定義特定類型的屬性。對于Service單元而言,這些屬性通常包括定義命令的啟動與停止,或者以前置及后置方式啟動或停止命令。
X-Fleet: 此區段用于提供特定fleet配置選項。具體來講,這意味著大家可以指定某項服務必須或者絕不可以特定方式進行調度,具體條件包括設備ID、當前正在運行的服務以及元數據信息等等。單元文件的一般格式如下:
[Unit]Generic_option_1Generic_option_2[Service]Service_specific_option_1Service_specific_option_2[X-Fleet]Fleet_option_1Fleet_option_2要開始本篇教程,我們需要首先獲取單元文件。大家可通過CoreOS快速上手頁面中獲取。在任一CoreOS設備中輸入:
vim hello.service而后,輸入我們的示例服務文件:
[Unit]Description=My ServiceAfter=docker.service[Service]TimeoutStartSec=0ExecStartPRe=-/usr/bin/docker kill helloExecStartPre=-/usr/bin/docker rm helloExecStartPre=/usr/bin/docker pull busyboxExecStart=/usr/bin/docker run --name hello busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done"ExecStop=/usr/bin/docker stop hello下面來看其具體作用。
在[Unit]區段設定一條描述,意味著我們告知systemd此服務只能在docker.service單元啟動之后開始運行。這是因為我們的單元需要配合Docker才能正常起效。
而在[Service]區段,我們禁用啟動超時,而后設置一系列操作以完成服務啟動前需要首先運行的組件。其中ExecStartPre會在主ExecStart操作之前執行。如果其由=-調用,則表明無論其是否成功啟動皆不會對服務本身造成影響。這一點非常重要,因為我們的預啟動操作基本上清除了任何先前正在運行的服務。如果找不到已經在運行的服務,則操作自然會失敗——但由于其僅僅屬于清理流程,因此我們不希望其影響到服務的正常執行。
最后的pre-start區段負責提取運行命令所需要的基礎busybox鏡像。由于這項操作具有 必要性,因此我們不可使用=-語法。接下來,我們利用該鏡像啟動一套容器,并以初始循環每秒輸出一次“Hello World”。其停止操作則會直接關閉此容器。
如果大家希望了解更多與fleet文件開發相關的知識,請查閱我們的fleet單元文件指南。
先來介紹fleetctl工具。作為一款集群管理工具,fleetctl將成為我們管理設備集群的主要接口。其中大部分語法都直接照搬自systemctl——systemd的管理工具。
作為第一步,我們利用以下命令獲取一份集群成員清單:
fleetctl list-machinesMACHINE IP METADATA14ffe4c3... 10.132.249.212 -1af37f7c... 10.132.249.206 -9e389e93... 10.132.248.177 -如大家所見,每臺可用設備都被羅列了出來。其中每個成員在啟動時都使用cloud-config文件對自身進行引導,生成一個惟一設備ID并借此區分各個節點。這部分信息被寫入至/etc/machine-id文件當中。
在默認情況下,fleet會使用設備的公共IPv4地址實現不同成員間的通信。不過在我們的cloud-config文件當中,也可以要求fleet使用專有接口進行通信。以上輸出結果正是這些IP地址。
其中“METADATA”一列目前還是空白,我們可以在cloud-config文件內的元數據屬性中為其添加任意鍵-值對。如下所示:
#cloud-config. . .coreos:fleet:public-ip: $private_ipv4metadata: region=europe,public_ip=$public_ipv4如果大家在cloud-config文件中這樣設置以引導全部設備,則輸出結果應如下所示:
MACHINE IP METADATA14ffe4c3... 10.132.249.212 public_ip=104.131.36.200,region=europe1af37f7c... 10.132.249.206 public_ip=104.131.15.192,region=europe9e389e93... 10.132.248.177 public_ip=104.131.15.192,region=europe這部分額外數據可在管理工作當中用于快速從節點中提取信息,但其同時亦可在服務定義中用于指向特定主機。
為了接入集群中的特定設備,大家可以使用fleetctl ssh命令。如此一來,我們就能夠根據設備ID或者與給定單元名稱相對應的設備識別所接入的設備身份。
舉例來說,如果大家擁有一個名為nginx.service的運行中單元,則可通過以下命令直接接入運行該服務的對應主機:
fleetctl ssh nginx運行后,我們會直接進入對應主機中的shell會話。大家也可以在遠程主機上運行單一命令,具體方式與運行普通ssh可執行文件一樣。舉例來說,要從/etc/environment文件(基于cloud-config參數以及可用網絡接口)當中獲取CoreOS設定的COREOS_PRIVATE_IPV4與COREOS_PUBLIC_IPV4兩條變量,大家可以使用以下命令:
fleetctl ssh nginx cat /etc/environmentCOREOS_PRIVATE_IPV4=10.132.249.212COREOS_PUBLIC_IPV4=104.131.29.80在其它可用于fleetctl的命令中,大部分與服務管理相關。
啟動一項服務需要涉及多個步驟。該服務文件必須被載入至fleet當中,從而保證其感知到目標單元。接下來,其需要被調度至集群中的特定設備之上,最后才能完成啟動。每個步驟都需要使用fleetctl命令,而這些命令分別負責執行各個階段的對應操作。
大家只可以使用submit命令將我們的單元文件提交至fleet。通過這種方式,fleet會將該文件內容讀取至內存,以備后續操作使用。
fleetctl submit hello.service我們的hello.service文件現在已經為fleet所感知。要查看已經提交完成的單元文件,大家可以使用以下命令:
fleetctl list-unit-filesUNIT HASH DSTATE STATE TMACHINEhello.service 0d1c468 inactive inactive -如大家所見,該單元文件顯示如上,但尚未被調度至任何主機或者實際啟動。
要查看fleet已經識別出的單元文件內容,大家可以使用以下命令:
fleetctl cat hello.service[Unit]Description=My ServiceAfter=docker.service[Service]TimeoutStartSec=0ExecStartPre=-/usr/bin/docker kill helloExecStartPre=-/usr/bin/docker rm helloExecStartPre=/usr/bin/docker pull busyboxExecStart=/usr/bin/docker run --name hello busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done"ExecStop=/usr/bin/docker stop hello這樣大家就能查看fleet所感知的當前文件內容了。
注意:submit命令是冪等的,就是說在進行重復提交時,fleet將不會更新內存內單元文件。如果大家需要更新自己的單元文件,則必須將其徹底移除,而后重新提交。我們將在后面具體進行討論。
在單元提交完成后,下一步是將其調度至某臺設備。在單元調度過程中,fleet引擎會檢查該單元以保證其運行在最合適的集群節點之上。具體結果取決于該單元中[X-Fleet]區段的約束條件以及集群中各臺設備的當前負載量。當該單元被調度完成后,其將被傳遞至特定設備并加入至本地systemd實例當中。
使用load命令以加載并調度該單元:
fleetctl load hello.serviceUnit hello.service loaded on 14ffe4c3.../10.132.249.212如果大家之前還沒有以手動方式載入單元,則此流程會在當前目錄中搜索合適的文件名稱并進行自動加載。
現在,如果我們檢查自己的單元文件,就會發現其已經被加載完畢。我們甚至能夠查看其被調度至哪臺設備上:
fleetctl list-unit-filesUNIT HASH DSTATE STATE TMACHINEhello.service 0d1c468 loaded loaded 14ffe4c3.../10.132.249.212這也是我們第一次使用list-units命令。該命令用于顯示任意運行中或者已調度的單元及其狀態:
fleetctl list-unitsUNIT MACHINE ACTIVE SUBhello.service 14ffe4c3.../10.132.249.212 inactive dead要啟動一個單元,大家可以使用start命令。其會根據單元文件內的start命令定義在特定設備上啟動該單元:
fleetctl start hello.serviceUnit hello.service launched on 14ffe4c3.../10.132.249.212再次檢查list-unit-files:
fleetctl list-unit-filesUNIT HASH DSTATE STATE TMACHINEhello.service 0d1c468 launched launched 14ffe4c3.../10.132.249.212在以上輸出結果中,我們可以看到該服務已經啟動完成。其中DSTATE列所示為“理想狀態”,而STATE則指示實際狀態。如果二者相符,則意味著操作已經成功。
下面再次查看list-units:
fleetctl list-unitsUNIT MACHINE ACTIVE SUBhello.service 14ffe4c3.../10.132.249.212 active running在這里我們可以看到與systemd狀態相關的信息。其直接收集自本地守護進程,因此能夠幫助我們更好地掌握本地系統獲取到的服務狀態。其中ACTIVE列為該單元的一般性狀態,而SUB則為更為較低層級的狀態。
以上各條命令都擁有一條與之對應的反義命令。
舉例來說,我們可以使用stop命令停止一項運行中的服務。在執行后,本地設備的systemd實例將執行單元定義中的停止指令:
fleetctl stop hello.serviceUnit hello.service loaded on 14ffe4c3.../10.132.249.212如大家所見,該服務已經恢復至已載入狀態。這意味著其仍被加載至設備的systemd當中,但已經不再繼續運行。我們可以通過以下命令進行確認:
fleetctl list-unit-filesUNIT HASH DSTATE STATE TMACHINEhello.service 0d1c468 loaded loaded 14ffe4c3.../10.132.249.212要移除該設備systemd中的單元,且同時保證其在fleet中的可用性,我們可以對該單元進行unload。如果該單元目前正處于活動狀態,則會在被卸載前首先停止:
fleetctl unload hello.service如果檢查該狀態,可以看到其現在已被標記為非活動狀態。另外目標設備一項亦被留空:
fleetctl list-unit-filesUNIT HASH DSTATE STATE TMACHINEhello.service 0d1c468 inactive inactive -如果我們需要將該單元從fleet中完全移除,則可使用destroy命令。其會停止并卸載該單元,而后將其從fleet中移除:
fleetctl destroy hello.service如果我們修改某個單元文件,則必須摧毀fleet中的現有單元,而后再重新提交/啟動。
大家應該已經了解到幾種獲取單元狀態信息的方式了。
舉例來說,list-units會列出全部當前被調度至某設備上的單元:
fleetctl list-unitsUNIT MACHINE ACTIVE SUBhello.service 14ffe4c3.../10.132.249.212 active running而list-unit-files則提供一套包含_全部_fleet已知單元的清單。其還會提供理想與實際狀態信息:
fleetctl list-unit-filesUNIT HASH DSTATE STATE TMACHINEhello.service 0d1c468 launched launched 14ffe4c3.../10.132.249.212要獲取更為具體的已啟動單元信息,我們還可以使用其它幾條命令。其中status命令會將返回目標主機上運行中單元的systemctl狀態:
fleetctl status hello.service● hello.service - My ServiceLoaded: loaded (/run/fleet/units/hello.service; linked-runtime)Active: active (running) since Mon 2014-09-08 21:51:22 UTC; 3min 57s agoProcess: 7630 ExecStartPre=/usr/bin/docker pull busybox (code=exited, status=0/SUCCESS)Process: 7618 ExecStartPre=/usr/bin/docker rm hello (code=exited, status=0/SUCCESS)Process: 7609 ExecStartPre=/usr/bin/docker kill hello (code=exited, status=0/SUCCESS)Main PID: 7638 (docker)CGroup: /system.slice/hello.service └─7638 /usr/bin/docker run --name hello busybox /bin/sh -c while true; do echo Hello World; sleep 1; doneSep 08 21:55:11 coreos-3 docker[7638]: Hello WorldSep 08 21:55:12 coreos-3 docker[7638]: Hello WorldSep 08 21:55:13 coreos-3 docker[7638]: Hello WorldSep 08 21:55:14 coreos-3 docker[7638]: Hello WorldSep 08 21:55:15 coreos-3 docker[7638]: Hello WorldSep 08 21:55:16 coreos-3 docker[7638]: Hello WorldSep 08 21:55:17 coreos-3 docker[7638]: Hello WorldSep 08 21:55:18 coreos-3 docker[7638]: Hello WorldSep 08 21:55:19 coreos-3 docker[7638]: Hello WorldSep 08 21:55:20 coreos-3 docker[7638]: Hello World如大家所見,我們最終證明示例單元的輸出結果正在正常顯示。
同樣的,如果大家請在相關設備上查看該服務的journal條目,則可使用journal命令:
fleetctl journal hello.service-- Logs begin at Mon 2014-09-08 14:22:14 UTC, end at Mon 2014-09-08 21:55:47 UTC. --Sep 08 21:55:38 coreos-3 docker[7638]: Hello WorldSep 08 21:55:39 coreos-3 docker[7638]: Hello WorldSep 08 21:55:40 coreos-3 docker[7638]: Hello WorldSep 08 21:55:41 coreos-3 docker[7638]: Hello WorldSep 08 21:55:42 coreos-3 docker[7638]: Hello WorldSep 08 21:55:43 coreos-3 docker[7638]: Hello WorldSep 08 21:55:44 coreos-3 docker[7638]: Hello WorldSep 08 21:55:45 coreos-3 docker[7638]: Hello WorldSep 08 21:55:46 coreos-3 docker[7638]: Hello WorldSep 08 21:55:47 coreos-3 docker[7638]: Hello World在默認情況下,其會顯示最后十行。大家也可以通過添加–行參數對此進行調整:
fleetctl journal --lines 20 hello.service大家也可以使用-f參數,其代表“follow”。通過添加-f參數的命令,系統會不斷發回最新日志條目:
fleetctl journal -f hello.service通過學習如何使用fleet與fleetctl,大家可以輕松控制自己的CoreOS集群。我們的服務與容器亦可非常順暢地在不同設備之間往來遷移。
在下一篇教程中,我們將更為深入地探討how to create fleet unit files如何創建fleet單元文件。通過這種方式,大家能夠創建出可充分發揮CoreOS架構優勢的、靈活且強大的服務。
本文來源自DigitalOcean Community。英文原文:How To Use Fleet and Fleetctl to Manage your CoreOS Cluster By Justin Ellingwood
翻譯:diradw
新聞熱點
疑難解答