您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何使用Docker Compose 和 Ansible來改善此設計,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
我們已經通過Jenkins server實現了鏡像的自動化構建。我們使用腳本將Docker命令進行封裝,將其存儲到GitHub中并且設置版本。目前我們正采取措施,通過逐步改善現有過程來實現持續部署。然而,仍有一些痛點需要我們去解決。我們將看看如何使用Docker Compose 和 Ansible來改善此設計。
在部署鏡像時,工程師需要登錄到服務器,并從shell運行我們的Docker wrapper腳本。這不是很好的解決方法,因為它也需要開發者進行等待。沒有任何一方會從在這種方式中獲益(作為一個工程師,當你去做某件你很了解并且很容易自動化的事情時,你有多少次被打斷了?)由于每一次部署都是通過操作者電腦中的SSH會話來執行的,因此部署過程是不可見的。
如果你對我們的部署腳本還有印象,你會發現它看起來像下面的代碼段:
實際上,我們做的是將Docker run命令語句進行抽象,由此工程師將不需要知道每個圖像成功運行時所需要的確切的參數。雖然這改善了必須全部記住并且手動輸入所有Docker參數的現狀,但同時也會帶來新的問題:
每個容器的邏輯都存儲在同一文件中,這使得對應用程序部署邏輯的更改更難追蹤;
當開發者需要測試或者修改參數時,需要被迫理清腳本中的邏輯,而不是能夠在某一特定的程序中輕松地閱讀和修改參數。
在我們的工作流中,Docker Compose是一個更適合使用的工具,它同樣可以將部署參數進行編碼,并且在YAML文件中指定,此文件就是docker-compose.yml。Docker Compose不僅幫助我們解決了上面提到的難點,而且也可以使我們從社區未來的工作中獲益。下面讓我們理清部署腳本,并且為我們的JAVA程序示例創建一個Compose文件。首先,我們需要基于原來的部署邏輯創建一個docker-compose.yml文件:
現在,部署容器只需要在與docker-compose.yml文件相同目錄下輸入以下命令:
docker-compose up
它將根據compose文件中設置的參數啟動一個容器。在compose文件中一個重要的變量是${VERSION} 。Docker Compose可以從當前的shell環境中插入compose文件里所列出的參數。我們可以通過簡單地運行以下語句來設置參數:
VERSION=1.0.0 docker-compose up
它將從我們的私有鏡像倉庫挑出標記1.0.0的鏡像,以此啟動java-service-1程序。如果沒有設置VERSION變量,Docker Compose將產生一條警告信息,并且用空字符串代替變量值,由此,具有最新版本標簽的鏡像將會被挑出。因此,正確地設置變量是相當重要的。
作為開發過程的一部分,我們希望開發人員能夠在本地建立服務并且測試他們的服務。然而,由于docker-compose.yml指向私有鏡像倉庫的鏡像,運行docker-compose將從最近構建的鏡像中開啟服務而不是從本地資源中開啟。理想情況下,開發者可以通過運行以下代碼使用典型的docker-compose工作流:
Docker Compose能在不修改docker-compose.yml文件的情況下,讓我們做到這一點。我們可以使用多個文件來覆蓋我們在本地測試中想要改變的任何參數。在docker-compose.override.yml中,我們指定一個key而不是一個鏡像,并且移除了對VERSION變量的需求。由于這是一個覆蓋文件,我們不需要復制任何額外的設置,如端口設置:
使用Docker Compose而非部署腳本之后,我們可以:
在源代碼中存儲每個compose文件,這與Dockerfile類似;
不再需要復雜的部署腳本;
允許開發人員在本地輕松地測試并修改應用程序。
現在我們有了java-service-1程序的compose文件,我們可以將它從我們的部署腳本中刪除,因此文件組織與下面的結構類似:
此時,我們仍然沒有解決鏡像構建和部署之間的問題。在docker-compose.yml文件中包含了所有的部署邏輯,但是它如何在環境中運行直至結束的呢?正好現在我們在運行與UNIX和TPC socket相關的Docker守護進程,是時候討論一些與安全有關的問題了。
我們的情況是,工程師登錄到服務器上,手動運行每個服務器所需容器的部署腳本。默認情況下,當在局部運行Docker命令時,它將使用UNIX socket /var/run/docker.sock連接Docker守護進程;或者讓守護進程監聽TCP socket,這允許用戶遠程連接到每個Docker守護進程,使得工程師能夠像登錄到主機一樣運行命令。這為連接方式提供了更大的靈活性,但是沒有考慮到一些開銷和安全問題:
通過網絡連接增加了安全隱患;
增加了對于基于主機或者基于網絡的ACLs需求;
保護守護進程需要分布式CA和客戶端認證。
另一種可能的方法是不使用基于UNIX socket的方式運行Docker守護進程,而使用SSH來運行命令。已經建立的ACLs將保護SSH端口,并且它只允許通過SSH授權的特定的用戶才能使用Docker守護進程。雖然這不是最簡潔的方法,但是它有助于保持較低的運行開銷,并且使安全隱患降到最低。這點是非常重要的,尤其是對于細粒度的稀疏的任務隊列而言。
為了有利于通過SSH運行Docker命令,我們可以使用Ansible——一個流行的編排和配置管理工具。它是無代理的,并且允許通過SSH連接運行“劇本”(服務器任務集合)。一個運行docker-compose命令的簡單的劇本如下所示:
如果你對Ansible沒有過多了解,你也許可以通過上面的劇本大致了解到我們想做什么。它們按順序一步步執行,具體如下所示:
Ansible將通過SSH連接到目標服務器(允許通過使用DESTINATION變量來指定主機)
在每個服務器中,Ansible會通過執行shell命令登錄到公司私有的鏡像倉庫
Ansible將位于Jenkins(運行ansible劇本的服務器)中的docker-compose.yml文件復制到每個目標服務器中的/tmp/docker-compose.yml下
在每個目標服務器中運行docker-compose命令
通過刪除遠程的/tmp/docker-compose.yml文件進行清理
一個shell腳本可以被運用在同一個事件中。然而在Ansible中,我們將很容易的使任務并行化并且得到經過良好測試的模塊,通過使Ansible與新的部署劇本相結合,我們可以遠程啟動容器,相較于工程師登錄到主機、人工運行命令,這是一個重要的進步。為了在部署過程和狀態中提供更大的可視性,我們將建立Jenkins任務來運行Ansible代碼。通過使用Jenkins,在未來我們可以輕松地將構建和部署任務集成起來,從而得到額外的好處。
Jenkins任務需要兩個參數:目標主機(傳遞給劇本中的DESTINATION變量)和部署鏡像的版本(在docker-compose.yml文件中插入VERSION變量)。大多數任務的構建部分是一個shell構建器,它將試圖找到程序中的docker-compose.yml文件,然后通過傳遞變量(用-e)到劇本中,運行ansible-playbook命令:
雖然看起來我們似乎只對工作流做了微小的變化,但是我們正一步一步地向構建一個持續部署模型邁進:
部署是可以被審查的。我們使用日志來記錄輸出什么、何時輸出、以及哪些主機是目標主機等信息,這一切都歸功于Jenkins。
程序部署邏輯已經從一個單一的腳本分散到存儲在程序源代碼中的單獨的docker-compose.yml文件中,這意味著我們可以輕松地通過git更改程序部署邏輯。在程序源文件或者部署文件發生變化時,我們也可以容易地進行構建和部署。
雖然這些改進解決了某些問題,但是它們所帶來的新的問題也成為了焦點:
哪個容器的哪個版本會被部署到何地?
容器在被部署后會處于哪種狀態?
我們如何確定哪個主機成為程序的目標主機?
在這一系列接下來的文章中,我們將探討怎樣運行Rancher以及使用它的原因,尤其是它如何解決上述的問題。與此同時,我們也討論它在業務和開發團隊中所起到的意想不到的橋梁作用。
關于如何使用Docker Compose 和 Ansible來改善此設計就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。