|
在Nylas,我們喜歡使用Python進(jìn)行開發(fā)。它的語法簡單并富有表現(xiàn)力,擁有大量可用的開源模塊和框架,而且這個(gè)社區(qū)既受歡迎又有多樣性。我們的后臺(tái)是 純用 Python 寫的,團(tuán)隊(duì)也經(jīng)常在 PyCon 和meetups上演講。你可以認(rèn)為我們是 Python 的超級粉。 然而,Python 的一個(gè)大缺陷是沒有一個(gè)明確的工具來部署 Python 服務(wù)端應(yīng)用。工作的情況就像是“執(zhí)行 git 的 pull 命令后剩下的就只有祈禱了”,但這并不是一個(gè)好的方式,尤其當(dāng)用戶依賴于我們的應(yīng)用。當(dāng)你的應(yīng)用引用了很多仍在變化的 依賴時(shí),這會(huì)讓 Python 的部署工作變得更加復(fù)雜。下面HN 上的評論概括了 Python 部署的糟糕情況。 為什么這么多年了,仍沒有一個(gè)有效的辦法幫我將 Python 編寫的軟件轉(zhuǎn)換成 deb 格式? —— 來自一個(gè)受挫的 HN 用戶 在 Nylas,我們開發(fā)了一種更好的方法可以將 Python 代碼連同其依賴一起部署,使得我們能夠輕松地對輕量級包進(jìn)行安裝、升級或者刪除。該方式的實(shí)現(xiàn)并不需要將我們的整個(gè)棧遷移到像 Docker、 CoreOS 或者AMIs 這樣的系統(tǒng)上。 Python 提供了豐富的模塊。不管你搭建的是一個(gè)web 服務(wù)器還是機(jī)器學(xué)習(xí)分類器,總會(huì)有一個(gè)合適的模塊幫你啟動(dòng)項(xiàng)目。現(xiàn)在獲取這些模塊的標(biāo)準(zhǔn)方法是通過 pip 從 Python 包索引 (亦稱 PyPI)中下載和安裝。這就跟 apt,yum,rubgem 等命令操作是一樣。 大多數(shù)人搭建開發(fā)環(huán)境的第一步就是用 git 克隆份代碼,然后通過 pip 安裝其依賴。這也是大多數(shù)人第一次嘗試部署代碼的做法。部署腳本大致如下: gitclone https://github.com/company/somerepo.gitcd /opt/myprojectpipinstall -r requirements.txtpythonstart_server.py 但是當(dāng)部署大量生產(chǎn)服務(wù)時(shí),這種策略有下面幾個(gè)原因可能導(dǎo)致失?。?/p>PIP 并沒有提供“部署回滾”策略
使用pip install 來安裝一個(gè)由C語言編寫的模塊經(jīng)常需要從源碼進(jìn)行編譯,對于一個(gè)新建立的virtualenv環(huán)境,這將花費(fèi)幾分鐘的時(shí)間。但部署應(yīng)用應(yīng)該是一個(gè)以秒計(jì)算的快速而輕量的過程。 在每臺(tái)主機(jī)上分別構(gòu)建代碼會(huì)有一致性問題當(dāng)你使用 pip 部署時(shí),無法保證不同服務(wù)器上運(yùn)行的應(yīng)用版本是一致的。構(gòu)建過程或現(xiàn)有依賴中的錯(cuò)誤導(dǎo)致的不一致,這是很難去調(diào)試的。 如果 PyPI 或者你的 git 服務(wù)器掛掉會(huì)導(dǎo)致部署失敗
如果你在運(yùn)營一個(gè)人們依賴的應(yīng)用系統(tǒng),而且它又是部署在多個(gè)服務(wù)器上,那么采用 git + pip 部署策略只會(huì)讓你更加頭痛。我們需要的部署策略應(yīng)該是快速的、一致而且可靠的。更具體地說:
有了這三樣?xùn)|西可以讓我們將更多的時(shí)間花在功能的構(gòu)建上,以更少的時(shí)間進(jìn)行代碼一致性遷移。 “干脆用DOCKER吧”初看下,這似乎最適合用 Docker了,Docker 是當(dāng)前盛行的容器管理工具。在一個(gè) Dockerfile里,只要簡單地添加代碼倉庫的引用,安裝必要的庫和依賴。那么我們就建好 Docker 鏡像,將它作為受版本控制的工件發(fā)往到遠(yuǎn)程主機(jī)。 然而,當(dāng)我們嘗試這樣操作時(shí)遇到了幾個(gè)問題:
即便我們順利的解決了這些問題,為了調(diào)試生產(chǎn)上的問題,我們的工程師團(tuán)隊(duì)又不得不學(xué)習(xí)如何跟 Docker 連接交互。我們認(rèn)為更快地遷移代碼并不應(yīng)該重新執(zhí)行整個(gè)基礎(chǔ)架構(gòu)自動(dòng)化和編排層。所以我們繼續(xù)調(diào)查其他方案。 PEXPEX是 Twitter 開發(fā)的一個(gè)智能工具,它允許 Python 代碼以可執(zhí)行壓縮文件進(jìn)行傳送。這是一個(gè)很酷的想法,關(guān)于這個(gè)主題我們建議去看Brian Wickman 在推特大學(xué)的演講。 設(shè)置 PEX 比 Docker 還簡單,因?yàn)樗恍枰\(yùn)行生成好的可執(zhí)行壓縮文件,但是構(gòu)建 PEX 文件卻是一項(xiàng)巨大的工程。我們在構(gòu)建第三方庫需求時(shí)遇到問題,特別是當(dāng)中包含了靜態(tài)文件。我們也遭遇到 PEX 源代碼產(chǎn)生的混亂的堆棧跟蹤,使得調(diào)試工作變得更加困難。這是個(gè)異份子,因?yàn)槲覀冎饕繕?biāo)是改善工程效率,讓事情更加易懂。 使用 Docker 會(huì)增加運(yùn)行時(shí)的復(fù)雜度。而 PEX 會(huì)增加構(gòu)建時(shí)的復(fù)雜度。我們需要一個(gè)方案可以最小化整體復(fù)雜度,同時(shí)提供可靠的部署,所以我們繼續(xù)調(diào)查其他方案。 包:原始的“容器”幾年前,Spotify 悄悄發(fā)布了一個(gè)工具叫 dh-virtualenv,你可以用來構(gòu)建內(nèi)含 virtualenv 的 debian 包。我們覺得這很有意思,也已經(jīng)有了很多 Debian 相關(guān)經(jīng)驗(yàn)并在生產(chǎn)環(huán)境上運(yùn)行。(Christine,我們的聯(lián)合創(chuàng)始人之一,就是一個(gè) Debian 的開發(fā)者。) 用 這就是我們在 Nylas 上部署代碼的關(guān)鍵。我們的持續(xù)集成服務(wù)器 (Jenkins) 運(yùn)行 dh-virtualenv 來構(gòu)建包, 用 Python 的 wheel緩存來避免對依賴重新構(gòu)建。這就創(chuàng)建一個(gè)捆綁式工件(debian 包),然后對其進(jìn)行大量的單元測試和系統(tǒng)測試。如果通過測試,則可認(rèn)為生產(chǎn)上是安全的,可以上傳到 s3. 這個(gè)過程的關(guān)鍵部分是通過均衡 Debian 的內(nèi)置包管理器 dpkg,我們可以最小化部署腳本的復(fù)雜度。部署腳本大致如下: temp=$(mktemp /tmp/deploy.deb.XXXXX)curl “https://artifacts./sync-engine-3k48dls.deb” -o $tempdpkg -i $tempsvreloadsync-engine 要回滾的話,我們只需要部署上一版本的工件。dpkg 工具可以免費(fèi)幫你清除舊代碼。 這個(gè)策略最重要的一方面是它實(shí)現(xiàn)了一致性和可靠性,同時(shí)匹配了我們的開發(fā)環(huán)境。我們的工程師已經(jīng)在用virtualenv,而dh-virtualenv 只是一個(gè)將其遷往遠(yuǎn)程主機(jī)的方式。如果我們選擇 Docker 或者 PEX,明顯需要改變我們本地開發(fā)的方式又增加了復(fù)雜度。我們同樣不希望給使用我們開源代碼的開發(fā)者帶來復(fù)雜度負(fù)擔(dān)。 現(xiàn)在,我們用 Debian 包來遷移我們所有的 Python 代碼。完整構(gòu)建我們代碼庫(包含數(shù)十個(gè)依賴)只要不到2分鐘時(shí)間,部署更是數(shù)秒便完成。 DH-VIRTUALENV 入門如果你受夠了 Python 部署的折磨,那就試試 dh-virtualenv吧。它會(huì)是你不錯(cuò)的選擇! 配置 Debian 包對于初學(xué)者而言是棘手的,所以我們構(gòu)建了 make-deb工具來幫你入手。它會(huì)基于你 Python 項(xiàng)目里的 setup.py 文件生成 Debian 配置。 首先安裝 cd /my/projectpipinstallmake-debmake-deb 如果你的 setup.py 文件有缺失信息的話, 構(gòu)建 Debian 包需要你在裝有 dh-virtualenv 的 Debian 系統(tǒng)上進(jìn)行。如果你沒有 Debian 環(huán)境,我們建議你在 Mac 或者 Windows 上用 Vagrant 和 Virtualbox 安裝一個(gè) Debian 的虛擬機(jī)。你也可以參考我們放在 Git 倉庫下 sync-engine項(xiàng)目里的Vagrantfile 來作配置。 最后,運(yùn)行 一段簡單的部署腳本如下: scpmy-package.deb remote-host.example.org:sshremote-host.example.org # Run the next commands on remote-host.example.orgdpkg -i my-package.deb /usr/share/python/myproject/bin/python>>> importmyproject # it works! 部署時(shí),你需要將這個(gè)工件上傳到生產(chǎn)服務(wù)器上。運(yùn)行 在構(gòu)建大型系統(tǒng)時(shí),項(xiàng)目難點(diǎn)往往是在尋求合適的工具,而非從頭開始重構(gòu)一個(gè)新的系統(tǒng)。我們認(rèn)為使用 Debian 基于包的部署是部署 Python 應(yīng)用的一個(gè)極佳方案,最重要的是它可以幫我們平穩(wěn)而快速的遷移代碼。 |
|
|