使用Docker,Chef和Amazon OpsWorks进行集群范围的Java / Scala应用程序部署
Docker非常適合在單個節點上運行隔離的容器。 但是,大多數軟件系統都在多個節點上運行,因此,除了Docker之外,我們還需要某種方法來指定哪些容器應在哪些節點上運行。
我要解決的特定問題如下:我有兩個Scala守護程序,我想在多個節點上運行(取決于配置,每個節點可以運行一個或兩個守護程序)。 我想要一種在集群中部署修改后的二進制文件的快速方法。 我也不想花費太多時間來設置服務器。 (我的Gentoo日子已經過去了。)
我到達的最終解決方案涉及Docker , OpsWorks , Chef和Vagrant 。 但是,一步一步來。
順便說一句-您將如何解決上述問題? 請評論。
打包Java / Scala應用程序
首先,我需要能夠打包和上傳二進制文件。 在這里,Docker非常完美。 我編寫了一個簡單的Dockerfile ,其中:
- 基于受信任的ubuntu + java7映像–無需在服務器上安裝Java!
- 將胖子從我的磁盤復制到映像
- 指定使用復制的jar運行Java的入口點
完整的Dockerfile可以在這里找到: https ://gist.github.com/adamw/166b82ec04c9c0f67453。
有了這樣的映像,我可以將其推送到(公共或私有) Docker注冊表中 ,群集中的節點可以將其下載。
如果需要,我還可以安裝我的應用程序需要的任何其他操作系統級別的依賴項,而不必擔心版本沖突并在實際服務器上進行設置。
如果看一下Dockerfile,您可能會注意到有兩個jar。 這樣做是為了最小化每次代碼更改后必須上傳的Docker映像的大小。 第一個jar僅包含依賴項(Scala庫,日志記錄庫,框架等)。 第二個jar包含已編譯的應用程序代碼。 從Dockerfile構建Docker映像時,將創建一系列中間映像,每個步驟之后一個。 對于涉及相同文件的相同命令,不會創建新映像,但會從Docker緩存中重新使用映像。
依賴關系很少更改,因此通常dep-jar保持不變,因此緩存的版本會被重用(并且中間映像會上傳一次)。 另一方面,應用程序代碼始終會更改。 重要的是,首先將依賴項jar添加到映像,以便中間映像包含deps,但不包含應用程序代碼(更改后的代碼)。 最后,通常只需要上傳2-3MB。
不過,這里要注意一件事。 在確定是否可以在ADD命令(該命令將文件從本地磁盤復制到該映像)之后重新使用該映像時,Docker僅檢查該文件的最后修改時間戳。 這將導致依賴項fat-jar在每次重新構建時都被重新添加,即使它們是相同的。 因此,我創建了一個簡單的bash腳本,僅當其md5校驗和發生更改時,該腳本才會復制dockerfile旁邊的fat-jar(作為Docker上下文的一部分從該文件上傳): https : //gist.github.com/adamw/ ba5d8b79ff553fba83fd 。
如何用SBT創建這樣兩個單獨的jar? 非常簡單。 只需使用SBT Assembly插件并更改其設置即可:
assemblyOption in assembly ~= { _.copy(includeBin = true, includeScala = false, includeDependency = false) }然后, assemblyPackageDependency目標將創建僅依賴項的jar,而assembly將創建僅應用程序的jar。
設置服務器
隨著包含我們應用程序的Docker映像在云中(在Docker集線器上)等待,現在是時候設置服務器了,Docker守護程序將在其中運行容器。
為了配置服務器,我選擇了Amazon OpsWorks的Chef,這有兩個原因:可以使用Stacks和Layers清楚地分離和組織EC2實例,這些服務器與Chef具有現成的集成,并且使用自定義廚師食譜非常容易。 完全不需要手動實例設置!
以下步驟部分是摘要,部分是ShopIgniter博客上描述的內容的擴展。
Chef安裝程序(由OpsWorks運行)將是最少的,并且僅包含運行Docker所需的內容。
首先,我們需要創建一個具有更新內核的基于Ubuntu 12.04的AMI(14.04尚不能與OpsWorks配合使用)–有關詳細信息,請參閱ShopIgniter的博客。
其次,我們將使用自定義的廚師食譜; 為此,您需要創建一個專用的存儲庫(例如在GitHub上)。 食譜非常基本和簡單: https : //gist.github.com/adamw/792f8c22abb09699b6d5 。
總結一下:
- docker::setup安裝Docker
- docker::kill_containers殺死并刪除所有正在運行的容器
- docker::myapp從Docker注冊表中提取myapp映像并運行一個容器,該容器具有例如Chef-JSON配置文件的每個應用程序部分中指定的命令行參數和環境變量(此處我們的應用程序使用單個命令-line參數,并且需要環境中的AWS憑證):
配置OpsWorks
要配置OpsWorks,我們需要使用自定義Chef食譜和自定義配置JSON創建一個Stack,例如上面的示例(對于要運行的每個應用程序/容器類型,我們需要在配置JSON中有一個部分)。 其次,對于我們要部署的每個應用程序(容器),我們需要創建一個圖層。 由于這些層將僅運行Docker,因此我們不使用任何預先配置的層,而使用“自定義”層。
該層將包含我們的自定義配方:在Setup階段,我們需要使用docker::setup配方,在Deploy階段,我們需要使用docker::kill_containers和docker::kill_containers docker::myapp配方。
現在,每次在該層上運行Deploy階段時,Docker都會提取映像并運行指定的容器! 通過創建具有適當配方的圖層,我們可以在任何節點上啟動容器的任何組合。
運行部署階段
要一次單擊即可實際運行“ Deploy階段,我們需要創建一個虛擬的OpsWorks應用程序:只需選擇“類型:其他”和“存儲庫類型:其他”。 現在,每次要在服務器上部署應用程序(運行更新的Docker容器)時,只需將此虛擬應用程序部署在所需的實例或層上即可。
這也可以通過API調用來完成(就像AWS上的一切一樣)! 因此,構建應用程序,創建Docker映像,推送該映像以及在OpsWorks上運行部署的整個過程可以非常容易地實現自動化-例如在成功構建之后。
一切就緒后,我們現在可以將新實例添加到圖層,啟動和停止它們,并讓多節點集群運行我們的應用程序! 要更新應用程序,只需將二進制文件推送到注冊表即可。
在本地測試廚師
雖然Chef的食譜非常少,但仍然可以在本地對其進行測試仍然很有用。 使用Vagrant可以輕松實現。 使用Vagrant,我們可以輕松地創建安裝了Chef的VM,該VM可以運行我們的配方,從而可以運行Docker容器。 此特定情況的Vagrantfile在這里: https ://gist.github.com/adamw/bf6fa803b6b13fd7430b。
Vagrantfile包含對我們正在開發的Chef食譜的引用(通過chef.cookbooks_path ),并且具有與我們在OpsWorks中使用的相同的配置JSON。
發布vagrant up ,我們將運行虛擬機。 更改食譜或上載新容器后,我們可以通過使用vagrant provision --provision-with chef_solo輕松地重新運行Chef食譜。
加起來
我們最終得到以下關注點分離:
- Docker-在隔離的容器中運行應用程序,具有所有必需的依賴項
- Chef –在定義的節點上設置docker,運行并鏈接具有指定參數/環境的容器
- OpsWorks –管理實例,觸發部署
- 流浪漢–整個設置的本地測試
盡管在上述整個過程中肯定有一些事情需要簡化(我希望Atomic項目能夠做到這一點!)最后,在集群中輕松地部署新版本的修改后的應用程序非常容易,而且很輕松,開發環境。
翻譯自: https://www.javacodegeeks.com/2014/06/cluster-wide-javascala-application-deployments-with-docker-chef-and-amazon-opsworks.html
總結
以上是生活随笔為你收集整理的使用Docker,Chef和Amazon OpsWorks进行集群范围的Java / Scala应用程序部署的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 下头了是什么意思梗 下头了是啥意思梗
- 下一篇: h61电脑主板怎么样(h61主板性能怎么