深入淺出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幾乎可以運行在包括Vagrant, Amazon EC2, QEMU/KVM, VMware, OpenStack的任何平臺,甚至在未安裝任何軟件的裸機硬件環境都可以。
因爲CoreOS的設計初衷只爲運行應用容器,因此需要安裝很少系統級別的依賴包即可。相比典型的Linux服務器,這就意味着CoreOS需要很低耗的CPU和高效的RAM即可滿足需求。
例如下面是一個RAM使用率的對比:
除此之外,CoreOS還採用了一個主動/被動雙分區方案啓動。
系統啓動到根分區A:
目標一下子就變得非常清晰了。
CoreOS更新
滿足CoreOS頻繁更新是系統的理念,可靠的更新是良好安全性的關鍵。CoreOS通過合併經常需要更新的爲一個實體,實現最小化每一個複雜的更新:
- 操作系統級
- 應用程序代碼級
- 單一配置
FastPatch是一個主動-被動根分區方案, CoreOS的更新是通過使用FastPatch保持一致。它是通過將整個系統作爲一個單一的單位替換更新,而不是通過包與包的不斷替換更新。
一旦CoreOS的更新可用,所有的CoreOS都是通過訪問公共的更新服務來接收更新。包括渠道到渠道之間版本的升級更新服務都是由CoreOS工程師團隊親自管理的。每一次更新服務的發佈都很便捷。這些更新永遠是針對所有的用戶可用的,而不會再去考慮用戶地位等。
如何更新
上述所說的更新類型一直用於傳統電子元器件更新,現在大多數瀏覽器的更新也是這樣的。考慮一下,像Chrome和Firefox是怎麼實現頻繁無縫自動更新的?事實上,CoreOS團隊也使用了Chrome的更新引擎Omaha。Omaha使用的是一個基於XML客戶端-服務器協議。開始時,系統啓動進入A分區(主動),CoreOS開始啓動查詢更新服務,查詢獲取相關更新。如果更新可用,下載並安裝到B分區。
CoreOS會下載一個完整的新分區文件系統,而不是每次只更新一個包。
下載更新後,操作系統更新會被應用到B分區(被動),重新啓動之後B分區就會變成主動引導分區,並引導系統啓動。
下圖描述這個過程:
如果在重新啓動引導中更新不成功,則回滾在先前的啓動分區。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有三個更新渠道- Alpha
- Beta
- Stable
按照順序,CoreOS的發佈過程是:alpha,beta,最後是stable。低一級渠道的發行版都爲下一個版本發行版服務。一旦一個版本被認爲已經沒有Bug,就可以進入下一級發行渠道,一級一級往下。也會可能在stable渠道中下載安裝,然後轉換爲接收beta或者alpha渠道的更新,這都是很容易做到的。相似的,也可能會安裝beta渠道的版本,後來轉換接收alpha的更新。
注意:安裝alpha渠道版本,後續轉換爲beta或者stable渠道再請求更新,這樣是不可以的。
轉換系統發佈渠道時,我們創建一個update.conffile:
然後設置所需的釋放渠道:
現在重新啓動更新引擎,以便它可以選擇改變的渠道:
當下一個更新檢查完成時,新的發佈渠道已經被應用。
集羣發現
CoreOS使用etcd專門處理集羣上軟件之間的協調,它運行在每一個系統上。一組CoreOS機器組成一個集羣,他們的etcd進程需要互相連接。後續的文章將詳細講述etcd。發現服務是通過存儲每一個地址列表、元數據、唯一地址的初始化的集羣,提供免費連接etcd成員之間的通信的幫助,稱之爲發現URL,例如https://discovery.etcd.io。
你可以非常容易地生成一個發現URL。
這應該產生這樣的輸出:
這樣通過提供給每一個發現服務一個發現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的第二篇文章。在我上一篇文章中,主要闡述了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的配置參數,請參考文檔說明。
ETCD2.X
Etcd是一個開源的分佈式鍵值對存儲系統,專門爲集羣之間提供可靠的共享數據服務。Etcd運行在每一個etcd集羣的中央服務機器上(不用擔心,隨後我們會詳細講述此處),可以兼容機器運行的失敗,甚至是中心機器運行失敗(此時其他機器會替代中心機器)。
系統使用Raft一致性算法將數據的複製分發到etcd的節點。一致性是容錯分佈式系統的一個基本的要求,一致性也包含很多服務上的數據一致。這樣一旦系統得出結論,這就是最終的結論了。
Deis使用etcd來存儲數據,Kubernates同樣也在使用etcd存儲數據。
優化etcd集羣的大小
Etcd集羣的推薦3個、5個或者7個成員。儘管更大的集羣可以提供更好的容錯能力,但是它的寫操作性能會不斷降低,因爲此時數據需要被複制到更多的機器上。常規上,集羣中使用3或者5個成員就足夠滿足系統需求了。推薦集羣中的成員數量是奇數個的,奇數個成員的集羣不會更改大部分的需求數量,但可以通過增加額外的成員從而增加系統的容錯能力。下面的實踐中我們對比一下偶數個成員和奇數個成員的不同:
正如表中描述,增加額外一個成員擴充集羣的大小到奇數成員數量是值得的。
在網絡分區中,集羣奇數成員可以保證在網絡分區結束後總還會有大部分可以操作的集羣。
更多關於etcd的內容,請參考etcd的文檔說明。
下面是一箇中央服務器的etcd設置:
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,可以提供對集羣的讀寫請求操作。
通過集羣成員列表,代理可以週期性的輪轉到每個成員,這樣可以表面將所有的流量轉發給一個成員。
下面是一個設置代理的例子:
通過下面URL,這些經由本地的客戶端連接訪問etcd中央服務:
關於更多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
這是深入淺出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: 可以在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,然後啓動文件:
要驗證Unit是否啓動,我們可以檢查正在運行的容器列表:
然後,通過journalctl命令輸出Unit,如下:
-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把系統環境變量作爲參數傳遞給集羣機器,像這樣:讓我們看一下你可以執行的任務,列出所需的命令。
開始Unit服務:
檢查Unit服務狀態:
停止服務:
查看服務文件:
提交服務:
查看日誌:
SSH訪問服務
服務列表:
列舉集羣機器:
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文件:
例子中的
hello_world@*
是做什麼的?好的,讓我們來說說
[email protected]
and [email protected]
兩個完全相同的文件。在集羣上啓動:
這兩個Fleet文件都部署在
MachineMetadata=group=hw_webservers
配置的服務器,配置Conflicts=hello_world@*
意圖是防止一個Unit使用了global-matching
與Unit文件衝突。讓我們看另一個
hello_world.service
Unit文件的例子。規定集羣中所有的機器:
規定機器上有
some_other_unit.service
Unit:規定Unit機器的編號爲:562999f8
獲取機器ID:
關於fleet Unit更多的只是,參考官方文檔。
集羣中運行一個容器
你要做的就是提供一個嚴格格式的【install】部分Unit文件,如下:注意:如果你是手動運行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/