自動化部署工具Fabric簡介

在持續集成/灰度發佈越來越流行的今天,模塊在預覽或生產環境的部署流程自動化顯得越來越重要。本文要介紹的Fabric就是一個幫助我們在上線時減少重複/繁瑣操作的自動化部署利器,對於缺乏成熟運維平臺的衆多小公司的運維或開發人員來說,掌握這個工具是有必要的。

1. Fabric是什麼

Fabric官方文檔的描述如下:
Fabric is a Python (2.5-2.7) library and command-line tool for streamlining the use of SSH for application deployment or systems administration tasks.
具體來說,Fabric是一個Python庫,只要目標機器支持ssh訪問,就可以藉助fabric來進行遠程操作(如在host1上對host2遠程運行shell命令),顯然,由於fabric是個Python package,故其它Python package都可以被import到fabric特有的fabfile.py腳本中,這使得fabric如虎添翼,在功能的豐富程度和運維腳本的可維護性上,遠遠超過用shell實現的自動化部署腳本,更不要說與純手工敲命令的上線方式相比所體現出的巨大優勢了。

在系統運維和部署自動化領域,與fabric類似的工具還有很多(如Puppet, Chef),感興趣的話,可以參考這篇文章48 Best Cloud Tools for Infrastructure Automation的介紹。

Fabric的安裝非常方便,pip install fabric就可以搞定,這裏不贅述。

2. Fabric支持的操作

Fabric支持的常用命令列出如下:
1)local
Run a command on the local system.
它是對subprocess模塊的封裝(Shell=True),可以通過設置Capture = True/False來捕獲其執行結果。
2)run
Run a shell command on a remote host.
該命令的返回值包含了遠程命令是否執行成功以及遠程命令的返回碼等信息。通過run執行命令時,通常會要求輸入目標機器密碼,如果對多臺機器進行部署,可以通過設置env.passwords來避免手動輸入密碼,具體的設置方法會在下篇筆記中介紹。
3)get
Download one or more files from a remote host.
4)put
Upload one or more files to a remote host.
5)sudo
Run a shell command on a remote host, with superuser privileges.
功能與run操作類似,它可以對當前用戶臨時提權來執行某些需要root權限的命令。

此外,還有些不常用的命令(如:prompt, reboot, open_shell, require)這裏沒有列出,感興趣的話,可以參考Fabric Operations文檔

需要特別注意的是,fabric通過run或sudo執行遠程任務時,每次都會新建ssh連接,也即任務之間是不會耦合狀態的,所以在實現需要多步操作的任務時,需要把多個命令放入同一行,命令間用逗號隔開。實例說明如下:
假設要在遠程機器上cd至/home/work/tmp目錄後創建test目錄,則下面的命令無法實現預期目的:

run('cd /home/work/tmp')
run('mkdir test')  ## 第2run會重新創建ssh連接,且不會記憶上次cd到的目錄!!

需要用下面的命令來實現:

run('cd /home/work/tmp; mkdir test')

run('cd /home/work/tmp && mkdir test')

當然,還可以藉助fabric提供的context manager來實現:

with cd('/home/work/tmp'):
    run('mkdir test')

關於fabric支持的context managers,還有很多強大且好玩的功能,請參考官方文檔Fabric Context Managers,不會讓你失望的。

上面介紹了fabric支持的元操作,那麼如何基於這些操作實現複雜功能呢?
在fabric中,一組具有邏輯關係的操作通常被封裝成一個task,fabric以task爲粒度來執行命令,下面開始介紹如何定義task。

3. 在fabfile中定義tasks

3.1 fabfile是什麼

根據fabric的約定,當運行例如”fab deploy”這樣的命令時,fab會默認搜索名爲fabfile.py的python文件或名爲fabfile的package,故基於fabric的部署腳本通常以fabfile.py命名且應該位於當期工作目錄下以便於fab進行搜索,在該文件中實現我們想要的任務即可。當然,如果要實現的部署任務比較複雜,這些任務也可以寫在多個腳本中,統一置於fabric package下。關於fabfile的細節,可以參考官方文檔Fabfile construction and use,這裏不贅述。

3.2 定義task

在語法約定上,fabric有兩種定義task的方式:
1)經典方式(classic method)
所有定義在fabfile中的可調用對象(如函數、類)均可被當作task被fab執行,這種方式不支持嵌套,也即:若fabfile.py中import了其它模塊,則即使這些模塊中定義了可調用對象,這些不是直接定義在fabfile中的可調用對象也不會被當作fab task。

以classic方式定義的task示例下(摘自Fabric Overview and Tutorial):

from fabric.api import local

def prepare_deploy():
    local("./manage.py test my_app")
    local("git add -p && git commit")
    local("git push")

上述示例代碼在fabfile.py中定義了一個普通函數prepare_deploy,不難看出,其功能是在本地執行代碼測試後,將本地的最新codebase更新到版本管理系統中以便後續以該codebase進行部署。

2)基於Task類的新風格task
從fabric 1.1開始,這種new-style的task定義方式被引入。該方式約定,所有的fab任務必須定義成Task類的實例或子類,其最大的優點是支持嵌套namespaces,也即,task可以定義在其它文件,fabfile.py通過import引入該文件後,定義在該文件的task也是可以被fab識別並支持的。

在new-style方式定義task的具體實現上,由2種方法:a. 定義一個繼承自Task的子類併爲其實現run()方法; b. 藉助@task裝飾器。示例分別如下:

class MyTask(Task):
    name = "deploy"  ## 指定task name,會在fab --list輸出中顯示
    def run(self, environment, domain="whatever.com"):
        run("git clone foo")
        sudo("service apache2 restart")

instance = MyTask()

上述示例與藉助@task定義task的方式等價:

@task
def deploy(environment, domain="whatever.com"):
    run("git clone foo")
    sudo("service apache2 restart")

被@task裝飾的函數默認繼承自Task類,我們可以讓函數繼承自定義的類,具體的用法可以參考文檔Defining tasks的”Using custom subclasses with @task”部分,這裏只是拋磚引玉,不再贅述。

需要特別注意的是,這兩種task的定義方式是互斥的!具體而言,如果fabric在fabfile或它import的文件中發現了基於Task類的new-style定義,那麼,所有以classic方式定義的task(s)均會被fabric忽略。個人認爲,如果要用fabric實現複雜系統的自動化部署,最好以new-style定義任務,因爲這種方式支持嵌套namespace,可以用不同的腳本文件分層組織不同的任務,更方便維護。

備註:可以運行”fab –list”來查看fabric可以識別的任務。

完成task定義後,fabric是如何執行的?尤其是遠程部署多臺機器時,如何更好地管理這些機器(如角色、密碼等)?

這些問題會在下篇筆記中進行說明。

參考資料

[1] 48 Best Cloud Tools for Infrastructure Automation
[2] Deployment Management Tools: Chef vs. Puppet vs. Ansible vs. SaltStack vs. Fabric
[3] Fabric Doc: Overview and Tutorial
[4] Fabric Doc: Operations
[5] Fabric Doc: Context Managers
[6] Fabric Doc: Defining tasks

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章