一種部署 Python 代碼的新方法

在Nylas,咱們喜歡使用Python進行開發。它的語法簡單並富有表現力,擁有大量可用的開源模塊和框架,並且這個社區既受歡迎又有多樣性。咱們的後臺是純用 Python 寫的,團隊也常常在 PyCon 和 meetups 上演講。你能夠認爲咱們是 Python 的超級粉。python

然而,Python 的一個大缺陷是沒有一個明確的工具來部署 Python 服務端應用。工做的狀況就像是「執行 git 的 pull 命令後剩下的就只有祈禱了」,但這並非一個好的方式,尤爲當用戶依賴於咱們的應用。當你的應用引用了不少仍在變化的依賴時,這會讓 Python 的部署工做變得更加複雜。下面 HN 上的評論歸納了 Python 部署的糟糕狀況。git

 

爲何這麼多年了,仍沒有一個有效的辦法幫我將 Python 編寫的軟件轉換成 deb 格式?github

—— 來自一個受挫的 HN 用戶web

在 Nylas,咱們開發了一種更好的方法能夠將 Python 代碼連同其依賴一塊兒部署,使得咱們可以輕鬆地對輕量級包進行安裝、升級或者刪除。該方式的實現並不須要將咱們的整個棧遷移到像 Docker、 CoreOS 或者AMIs 這樣的系統上。docker

新手才用 GIT 和 PIP 進行 Python 部署

Python 提供了豐富的模塊。無論你搭建的是一個web 服務器仍是機器學習分類器,總會有一個合適的模塊幫你啓動項目。如今獲取這些模塊的標準方法是經過 pip 從 Python 包索引 (亦稱 PyPI)中下載和安裝。這就跟 apt,yum,rubgem 等命令操做是同樣。緩存

大多數人搭建開發環境的第一步就是用 git 克隆份代碼,而後經過 pip 安裝其依賴。這也是大多數人第一次嘗試部署代碼的作法。部署腳本大體以下:安全

可是當部署大量生產服務時,這種策略有下面幾個緣由可能致使失敗:服務器

PIP 並無提供「部署回滾」策略網絡

pip unistall 並非每次都能正常工做,也沒有辦法「回滾」到上一個狀態。雖然能夠用Virtualenv 實現,但它並非用來管理歷史環境的。架構

用 pip 安裝依賴會讓部署變得極其慢

使用pip install 來安裝一個由C語言編寫的模塊常常須要從源碼進行編譯,對於一個新創建的virtualenv環境,這將花費幾分鐘的時間。但部署應用應該是一個以秒計算的快速而輕量的過程。

在每臺主機上分別構建代碼會有一致性問題

當你使用 pip 部署時,沒法保證不一樣服務器上運行的應用版本是一致的。構建過程或現有依賴中的錯誤致使的不一致,這是很難去調試的。

若是 PyPI 或者你的 git 服務器掛掉會致使部署失敗

pip install 和 git pull 一般依賴於外部服務器。你能夠選擇使用第三方平臺 (如 Github,PyPI)或者本身搭建服務器,重要的是確保部署過程知足正常運行時間和規模的預期。當擴展本身的基礎設施,尤爲是在大型部署時,外部服務每每是第一個掛掉的。

若是你在運營一我的們依賴的應用系統,並且它又是部署在多個服務器上,那麼採用 git + pip 部署策略只會讓你更加頭痛。咱們須要的部署策略應該是快速的、一致並且可靠的。更具體地說:

  1. 可以構建代碼成單1、有版本控制的工件
  2. 受版本控制的工件能夠進行單元測試和系統測試
  3. 一種簡單的機制能夠從遠程主機徹底的安裝或卸載工件

有了這三樣東西可讓咱們將更多的時間花在功能的構建上,以更少的時間進行代碼一致性遷移。

「乾脆用DOCKER吧」

初看下,這彷佛最適合用 Docker 了,Docker 是當前盛行的容器管理工具。在一個 Dockerfile裏,只要簡單地添加代碼倉庫的引用,安裝必要的庫和依賴。那麼咱們就建好 Docker 鏡像,將它做爲受版本控制的工件發往到遠程主機。

然而,當咱們嘗試這樣操做時遇到了幾個問題:

  • 咱們的內核版本 (3.2)並不完美支持 Docker,若是爲了更快的遷移代碼而升級內核,咱們以爲這有點像在用牛刀殺雞。
  • 在專用網絡裏分發 Docker 鏡像要有一個獨立服務,這樣咱們又須要對服務進行配置,測試和維護。
  •  ansible 自動化安裝轉換成 Dockerfile 的過程是痛苦的,須要對日誌配置、用戶權限和祕鑰管理等進行大量繁瑣的編輯。

即使咱們順利的解決了這些問題,爲了調試生產上的問題,咱們的工程師團隊又不得不學習如何跟 Docker 鏈接交互。咱們認爲更快地遷移代碼並不該該從新執行整個基礎架構自動化和編排層。因此咱們繼續調查其餘方案。

PEX

PEX 是 Twitter 開發的一個智能工具,它容許 Python 代碼以可執行壓縮文件進行傳送。這是一個很酷的想法,關於這個主題咱們建議去看Brian Wickman 在推特大學的演講

設置 PEX 比 Docker 還簡單,由於他只須要運行生成好的可執行壓縮文件,可是構建 PEX 文件倒是一項巨大的工程。咱們在構建第三方庫需求時遇到問題,特別是當中包含了靜態文件。咱們也遭遇到 PEX 源代碼產生的混亂的堆棧跟蹤,使得調試工做變得更加困難。這是個異份子,由於咱們主要目標是改善工程效率,讓事情更加易懂。

使用 Docker 會增長運行時的複雜度。而 PEX 會增長構建時的複雜度。咱們須要一個方案能夠最小化總體複雜度,同時提供可靠的部署,因此咱們繼續調查其餘方案。

包:原始的「容器」

幾年前,Spotify 悄悄發佈了一個工具叫 dh-virtualenv,你能夠用來構建內含 virtualenv 的 debian 包。咱們以爲這頗有意思,也已經有了不少 Debian 相關經驗並在生產環境上運行。(Christine,咱們的聯合創始人之一,就是一個 Debian 的開發者。)

dh-virtualenv能夠很簡單的建立一個 debian 包,它包含了 virtualenv 和羅列在requirement.txt 文件裏的全部依賴。當在主機上安裝這個 debian 包時, 它會將 virtualenv 放置在/usr/share/pyton/路徑下。就是它了。

這就是咱們在 Nylas 上部署代碼的關鍵。咱們的持續集成服務器 (Jenkins) 運行 dh-virtualenv 來構建包, 用 Python 的wheel 緩存來避免對依賴從新構建。這就建立一個捆綁式工件(debian 包),而後對其進行大量的單元測試和系統測試。若是經過測試,則可認爲生產上是安全的,能夠上傳到 s3.

這個過程的關鍵部分是經過均衡 Debian 的內置包管理器 dpkg,咱們能夠最小化部署腳本的複雜度。部署腳本大體以下:

要回滾的話,咱們只須要部署上一版本的工件。dpkg 工具能夠免費幫你清除舊代碼。

這個策略最重要的一方面是它實現了一致性和可靠性,同時匹配了咱們的開發環境。咱們的工程師已經在用virtualenv,而dh-virtualenv 只是一個將其遷往遠程主機的方式。若是咱們選擇 Docker 或者 PEX,明顯須要改變咱們本地開發的方式又增長了複雜度。咱們一樣不但願給使用咱們開源代碼的開發者帶來複雜度負擔。

如今,咱們用 Debian 包來遷移咱們全部的 Python 代碼。完整構建咱們代碼庫(包含數十個依賴)只要不到2分鐘時間,部署更是數秒便完成。

DH-VIRTUALENV 入門

若是你受夠了 Python 部署的折磨,那就試試 dh-virtualenv吧。它會是你不錯的選擇!

配置 Debian 包對於初學者而言是棘手的,因此咱們構建了 make-deb 工具來幫你入手。它會基於你 Python 項目裏的 setup.py 文件生成 Debian 配置。

首先安裝make-deb工具,而後在你項目的根目錄下運行它:

若是你的 setup.py 文件有缺失信息的話,make-deb會要求你添加。一旦它收齊所需的信息,make-deb會在你項目的根目錄下建立一個 debian 目錄,包含了 dh-virtualenv 須要的全部配置。

構建 Debian 包須要你在裝有 dh-virtualenv 的 Debian 系統上進行。若是你沒有 Debian 環境,咱們建議你在 Mac 或者 Windows 上用 Vagrant 和 Virtualbox 安裝一個 Debian 的虛擬機。你也能夠參考咱們放在 Git 倉庫下 sync-engine 項目裏的Vagrantfile 來做配置。

最後,運行dpkg-builpackage -us -uc來建立 Debian 包。你不須要直接調用 dh-virtualenv,由於它已經在以前make-deb建立好的配置規則裏了。當這條命令執行好後,你就構建好一個可部署的漂亮的工件。

一段簡單的部署腳本以下:

部署時,你須要將這個工件上傳到生產服務器上。運行dpkg -i my-package.deb命令來安裝。virtualenv 會被放在/usr/share/python/目錄下,全部預設在 setup.py 文件裏的腳本文件則會在bin目錄裏。就是它了!你這就走上了簡易部署的光明大道。

總結

在構建大型系統時,項目難點每每是在尋求合適的工具,而非從頭開始重構一個新的系統。咱們認爲使用 Debian 基於包的部署是部署 Python 應用的一個極佳方案,最重要的是它能夠幫咱們平穩而快速的遷移代碼。

 

聲明:

本文轉載自:http://python.jobbole.com/85057/

相關文章
相關標籤/搜索