初創公司如何實現Ansible多機房自動部署發布
一、面臨的問題
一個完整的程序開發流程少不了部署發布這個環節,而部署發布是一個重復的過程,最基本的操作包含停止系統服務、更新軟件包、重啟系統服務,復雜的還需要做好監控、灰度發布、回滾等。
在只有少量服務器的情況下,大多數運維人員會選擇手動更新,減少自動化部署發布的開發成本。而當服務器數量增加,甚至服務器可能存在于跨地域的不同機房情況下,如何減少部署發布的人力和時間成本,實現自動化部署發布和無縫發布,而且在部署發布期間仍然能夠正常提供服務,就成為一個至關重要的問題。
在我們發布風控情報服務的時候,就遇到了自動化部署發布的問題。由于風控服務在用戶場景中處于非常重要的地位,對SLA要求極高,需要提供毫秒級別的訪問質量,為了達到這一點,消除掉公網的消耗,需要支持多機房服務,而同時帶來的問題就是,如何保持各機房的軟件版本統一,能夠做到快速的統一發布、運維,則成為了一大難題。
二、如何解決問題
目前自動化部署發布領域已經有了比較成熟的方案,中小公司會維護一些自動化腳本或開源軟件,而大公司由于復雜的網絡環境更多會選擇維護一套專屬的部署發布系統。而在我們這樣的創業型公司,為了減少人力資源成本,首先選擇的成熟的開源軟件。
工具對比
我們自己的項目后端開發語言為Python,目前主流的開源自動化配置工具有puppet、ansible、saltstack等,ansible和saltstack是基于Python開發,能夠很好的支持Python程序發布。在服務器數量不多,不需要考慮大規模并發性能的情況下,我們對比了ansible和saltstack,最終選用了ansible作為部署發布工具。
1. 通訊方式
ansible 無需安裝服務端和客戶端,管理機通過ssh協議將命令推送到服務器端執行,只需要管理機上安裝ansible,即可實現統一管理,同時ansible也支持使用ZeroMQ、Kerberos、LDAP等方式推送命令。
而saltstack需要分別安裝master和minion,master和minion之間可以通過ZeroMQ、RAET消息隊列進行通信,salt在升級時,master版本需向后兼容,minion版本不能高于master。
2. 響應速度
saltstack的master和minion是通過ZeroMQ推送命令,而ansible通過標準ssh推送命令,ZeroMQ的傳輸速度比標準SSH連接會快很多,在大規模服務器并發的情況下,saltstack執行效率會比ansible好,而在一般的運維場景下,ansible可以滿足需求。
3. 二次開發
ansible和saltstack是基于Python開發,支持使用Python進行二次開發。ansible 附帶很多可以直接在遠端主機或者通過Playbooks執行的模塊,用戶可以開發自己的模塊或者插件,而saltstack也有一些預裝的formulas,同樣可以執行自定義的formula,而他們都覆蓋了常用的軟件模塊,如文件傳輸、web服務器、MySQL命令等。
4. 安全性
ansible使用標準ssh協議通訊,標準ssh是加密傳輸,并且遠程服務器不需要運行守護進程,使得遠程服務器不容易受到攻擊。而saltstack雖然可以通過數據加密方法配置數據傳輸加密方式,但是遠程服務器必須運行守護進程,暴露了可攻擊的點。
在綜合考慮了上述幾點,結合了項目特點,在不需要維護大規模服務器的情況下,且項目遠程服務器部署在公有云上,需要通過訪問接口完成服務器的拉出集群、拉入集群操作,我們選用了ansible,開發插件簡單,只需要維護一臺可以連接到所有遠程服務器的管理機,盡量避免暴露網絡端口減少被攻擊的可能性,并且執行效率可以滿足需求。
三、Ansible 總體介紹
(一)Ansible 基礎架構
上圖為ansible的基礎架構圖,其由以下部分組成:
- ansible:核心
- core modules:ansible自帶的核心模塊
- custom modules:自定義模塊
- plugins:ansible插件,包括郵件插件、日志插件、連接插件等
- playbooks:劇本,ansible配置、部署、編排語言,定義主機執行的task集合
- host inventory:ansible管理遠程主機和組之間的關系清單,記錄主機ssh端口、賬號密碼等
在管理主機上,ansible模塊通過標準ssh協議(ZeroMQ、Kerberos)執行inventory文件中的主機對應的playbook task集合。
(二)Ansible 常用命令
1. ansible
核心命令,用于執行ad-hoc命令,既單條命令,可以通過ansible -h獲得幫助。
2. ansible-doc
該命令用于查看模塊信息,參數-l可以列出所有已安裝的模塊,參數-s可以查看具體某個模塊的用戶,如想查詢ping模塊的相關信息。
- $ ansible-doc ping
- > PING
- A trivial test module, this module always returns `pong' on successful contact. It does not make sense in playbooks, but it is useful from `/usr/bin/ansible' to verify the ability to login and that a usable
- python is configured. This is NOT ICMP ping, this is just a trivial test module.
- EXAMPLES:
- # Test we can logon to 'webservers' and execute python with json lib.
- ansible webservers -m ping
- MAINTAINERS: Ansible Core Team, Michael DeHaan
3. ansible-galaxy
用于從官方站點下載第三方擴展模塊,類似于centos的yum、Python的pip指令。
4. ansible-playbook
該命令是使用最多的命令,通過讀取playbook文件,執行相應的操作。
5. ansible-vault
配置文件中如果包含密碼等敏感信息,可以通過ansible-vault加密、解密文件。
四、Ansible 初試
(一)Ansible 安裝
官方提供了多種安裝方式,可從github的ansible project下載源碼編譯安裝,也可通過yum、apt-get指令安裝,這里僅介紹通過pip安裝ansible,其他可參考官方網站。
- $ sudo pip install ansible
(二)第一條命令
為了避免在建立ssh連接時,重復輸入密碼,可以設置遠程主機免密碼登錄。
- $ ssh-keygen –t rsa –P "
- $ ssh-copy-id -i ~/.ssh/id_rsa.pub user@remote_host
編輯(或創建)/etc/ansible/hosts文件,并在其中加入遠程主機,例:192.168.1.2
- $ ansible all -m ping
- 192.168.1.2 | SUCCESS => {
- "changed": false,
- "ping": "pong"
- }
(三)Inventory 文件
/etc/ansible/hosts文件格式與ini配置文件類似,可以指定連接方式,也可以指定連接用戶名。同時,再分配變量時,可以指定主機分配變量,也可以指定組分配變量。變量可以在多個地方定義,有優先級的差別。例如以下代碼顯示。
- mail.example.com
- [webservers]
- foo.example.com
- bar.example.com
- [databases]
- localhost ansible_connection=local
- other1.example.com ansible_connection=ssh ansible_ssh_user=mpdehaan
- other2.example.com ansible_connection=ssh ansible_ssh_user=mdehaan
- [raleigh]
- host1 http_port=80 maxRequestsPerChild=808
- host2 http_port=303 maxRequestsPerChild=909
- [atlanta]
- host1
- host2
- [atlanta:vars]
- ntp_server=ntp.atlanta.example.com
- proxy=proxy.atlanta.example.com
(四)Playbooks
playbooks的文件格式為yaml,遠程主機被定義成不同角色,每個角色需要根據playbook中不同的task執行不同的指令,比如一組主機在inventory文件中被定義成webservers,則可能會執行web服務器重啟等操作。
如下playbook,執行一組定義為webservers的主機,使用root賬號登錄,并且定義了http_port、max_clients變量,會執行三個task,分別為安裝最新hhtpd服務、拷貝/srv/httpd.j2文件到遠程主機的/etc/httpd.conf、重啟httpd服務。’
notify‘ action表示在playbook每一個task結束時被觸發,只會被觸發一次。handlers是一些task列表,通過名字引用。則該playbook中,配置文件拷貝結束后,執行'restart apache' task。
- ---
- - hosts: webservers
- vars:
- http_port: 80
- max_clients: 200
- remote_user: root
- tasks:
- - name: ensure apache is at the latest version
- yum: pkg=httpd state=latest
- - name: write the apache config file
- template: src=/srv/httpd.j2 dest=/etc/httpd.conf
- notify:
- - restart apache
- - name: ensure apache is running
- service: name=httpd state=started
- handlers:
- - name: restart apache
- service: name=httpd state=restarted
五、自動化部署發布示例
簡要說明下我們的項目如何使用ansible實現了多個環境的自動化部署發布。
- ├── group_vars
- │ ├── all
- │ ├── production
- │ │ ├── build_server.yml
- │ │ ├── web_server_bj.yml
- │ │ └── web_server_sh.yml
- │ └── staging
- │ ├── build_server.yml
- │ ├── web_server_bj.yml
- │ └── web_server_sh.yml
- ├── library
- │ ├── slb_op.py
- ├── roles
- │ ├── build
- │ │ └── tasks
- │ │ └── main.yml
- │ └── publish
- │ ├── tasks
- │ │ └── main.yml
- │ └── templates
- │ ├── config.conf
- │ ├── nginx.conf
- │ └── supervisord.conf
- ├── production
- ├── production.yml
- ├── staging
- └── staging.yml
如上目錄結構,是目前ansible比較受歡迎的實現方式。例如項目有生產和測試環境,則分為兩個inventory文件,分別為production、staging,inventory文件中定義對應環境的服務器所在的組,以staging為例,web_server_sh、web_server_bj表示兩個機房的主機,build_server為打包機器。
- [web_server_sh]
- 192.168.0.2
- [web_server_bj]
- 192.168.0.3
- [build_server]
- localhost ansible_connection=local
而每個inventory對應的playbook則為production.yml、staging.yml,指定不同的組需要執行的角色task。
以staging.yml為例,build_server組的主機需要執行build角色的task,并且變量文件為
group_vars/staging/build_server.yml,而web_server_sh、web_server_bj組的主機需要執行publish角色的task,并且指定變量文件不相同。
- ---
- - hosts: build_server
- serial: 1
- vars_files:
- - group_vars/staging/build_server.yml
- roles:
- - build
- - hosts: web_server_sh
- remote_user: root
- serial: 1
- vars_files:
- - group_vars/staging/web_server_sh.yml
- roles:
- - publish
- - hosts: web_server_bj
- remote_user: root
- serial: 1
- vars_files:
- - group_vars/staging/web_server_bj.yml
- roles:
- - publish
library目錄則為自定義插件,可直接在playbook中使用,slb_op.py為自定義的集群拉入拉出模塊。
六、總結
- ansible 很好的幫助了我們解決了自動化部署發布的事情,現在項目同步更新到幾個機房,已經只需要幾分鐘就可以完成,節省了許多人力。
- 在部署發布工具的選擇上,工具沒有好壞,應該結合自身項目來選擇,都能夠很好地提高工作效率。
- ansible解決了燃眉之急,而目前已經很好地與jenkins、docker結合,當集群數量越來越多,越來越難以維護時,是否需要更換工具,或是結合最新技術,都是一個考驗的難題。
作者 葉柴柴 豈安科技軟件工程師
負責豈安科技業務風險分析平臺后臺開發。鏟屎官里會寫代碼的,寫代碼里會鏟屎的,一個愛柯基、愛Python、愛生活的鏟屎官。
【本文是51CTO專欄機構“豈安科技”的原創文章,轉載請通過微信公眾號(bigsec)聯系原作者】