初創(chuàng)公司如何實(shí)現(xiàn)Ansible多機(jī)房自動部署發(fā)布
一、面臨的問題
一個完整的程序開發(fā)流程少不了部署發(fā)布這個環(huán)節(jié),而部署發(fā)布是一個重復(fù)的過程,最基本的操作包含停止系統(tǒng)服務(wù)、更新軟件包、重啟系統(tǒng)服務(wù),復(fù)雜的還需要做好監(jiān)控、灰度發(fā)布、回滾等。
在只有少量服務(wù)器的情況下,大多數(shù)運(yùn)維人員會選擇手動更新,減少自動化部署發(fā)布的開發(fā)成本。而當(dāng)服務(wù)器數(shù)量增加,甚至服務(wù)器可能存在于跨地域的不同機(jī)房情況下,如何減少部署發(fā)布的人力和時間成本,實(shí)現(xiàn)自動化部署發(fā)布和無縫發(fā)布,而且在部署發(fā)布期間仍然能夠正常提供服務(wù),就成為一個至關(guān)重要的問題。
在我們發(fā)布風(fēng)控情報服務(wù)的時候,就遇到了自動化部署發(fā)布的問題。由于風(fēng)控服務(wù)在用戶場景中處于非常重要的地位,對SLA要求極高,需要提供毫秒級別的訪問質(zhì)量,為了達(dá)到這一點(diǎn),消除掉公網(wǎng)的消耗,需要支持多機(jī)房服務(wù),而同時帶來的問題就是,如何保持各機(jī)房的軟件版本統(tǒng)一,能夠做到快速的統(tǒng)一發(fā)布、運(yùn)維,則成為了一大難題。
二、如何解決問題
目前自動化部署發(fā)布領(lǐng)域已經(jīng)有了比較成熟的方案,中小公司會維護(hù)一些自動化腳本或開源軟件,而大公司由于復(fù)雜的網(wǎng)絡(luò)環(huán)境更多會選擇維護(hù)一套專屬的部署發(fā)布系統(tǒng)。而在我們這樣的創(chuàng)業(yè)型公司,為了減少人力資源成本,首先選擇的成熟的開源軟件。
工具對比
我們自己的項(xiàng)目后端開發(fā)語言為Python,目前主流的開源自動化配置工具有puppet、ansible、saltstack等,ansible和saltstack是基于Python開發(fā),能夠很好的支持Python程序發(fā)布。在服務(wù)器數(shù)量不多,不需要考慮大規(guī)模并發(fā)性能的情況下,我們對比了ansible和saltstack,最終選用了ansible作為部署發(fā)布工具。
1. 通訊方式
ansible 無需安裝服務(wù)端和客戶端,管理機(jī)通過ssh協(xié)議將命令推送到服務(wù)器端執(zhí)行,只需要管理機(jī)上安裝ansible,即可實(shí)現(xiàn)統(tǒng)一管理,同時ansible也支持使用ZeroMQ、Kerberos、LDAP等方式推送命令。
而saltstack需要分別安裝master和minion,master和minion之間可以通過ZeroMQ、RAET消息隊列進(jìn)行通信,salt在升級時,master版本需向后兼容,minion版本不能高于master。
2. 響應(yīng)速度
saltstack的master和minion是通過ZeroMQ推送命令,而ansible通過標(biāo)準(zhǔn)ssh推送命令,ZeroMQ的傳輸速度比標(biāo)準(zhǔn)SSH連接會快很多,在大規(guī)模服務(wù)器并發(fā)的情況下,saltstack執(zhí)行效率會比ansible好,而在一般的運(yùn)維場景下,ansible可以滿足需求。
3. 二次開發(fā)
ansible和saltstack是基于Python開發(fā),支持使用Python進(jìn)行二次開發(fā)。ansible 附帶很多可以直接在遠(yuǎn)端主機(jī)或者通過Playbooks執(zhí)行的模塊,用戶可以開發(fā)自己的模塊或者插件,而saltstack也有一些預(yù)裝的formulas,同樣可以執(zhí)行自定義的formula,而他們都覆蓋了常用的軟件模塊,如文件傳輸、web服務(wù)器、MySQL命令等。
4. 安全性
ansible使用標(biāo)準(zhǔn)ssh協(xié)議通訊,標(biāo)準(zhǔn)ssh是加密傳輸,并且遠(yuǎn)程服務(wù)器不需要運(yùn)行守護(hù)進(jìn)程,使得遠(yuǎn)程服務(wù)器不容易受到攻擊。而saltstack雖然可以通過數(shù)據(jù)加密方法配置數(shù)據(jù)傳輸加密方式,但是遠(yuǎn)程服務(wù)器必須運(yùn)行守護(hù)進(jìn)程,暴露了可攻擊的點(diǎn)。
在綜合考慮了上述幾點(diǎn),結(jié)合了項(xiàng)目特點(diǎn),在不需要維護(hù)大規(guī)模服務(wù)器的情況下,且項(xiàng)目遠(yuǎn)程服務(wù)器部署在公有云上,需要通過訪問接口完成服務(wù)器的拉出集群、拉入集群操作,我們選用了ansible,開發(fā)插件簡單,只需要維護(hù)一臺可以連接到所有遠(yuǎn)程服務(wù)器的管理機(jī),盡量避免暴露網(wǎng)絡(luò)端口減少被攻擊的可能性,并且執(zhí)行效率可以滿足需求。
三、Ansible 總體介紹
(一)Ansible 基礎(chǔ)架構(gòu)
上圖為ansible的基礎(chǔ)架構(gòu)圖,其由以下部分組成:
- ansible:核心
- core modules:ansible自帶的核心模塊
- custom modules:自定義模塊
- plugins:ansible插件,包括郵件插件、日志插件、連接插件等
- playbooks:劇本,ansible配置、部署、編排語言,定義主機(jī)執(zhí)行的task集合
- host inventory:ansible管理遠(yuǎn)程主機(jī)和組之間的關(guān)系清單,記錄主機(jī)ssh端口、賬號密碼等
在管理主機(jī)上,ansible模塊通過標(biāo)準(zhǔn)ssh協(xié)議(ZeroMQ、Kerberos)執(zhí)行inventory文件中的主機(jī)對應(yīng)的playbook task集合。
(二)Ansible 常用命令
1. ansible
核心命令,用于執(zhí)行ad-hoc命令,既單條命令,可以通過ansible -h獲得幫助。
2. ansible-doc
該命令用于查看模塊信息,參數(shù)-l可以列出所有已安裝的模塊,參數(shù)-s可以查看具體某個模塊的用戶,如想查詢ping模塊的相關(guān)信息。
- $ 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
用于從官方站點(diǎn)下載第三方擴(kuò)展模塊,類似于centos的yum、Python的pip指令。
4. ansible-playbook
該命令是使用最多的命令,通過讀取playbook文件,執(zhí)行相應(yīng)的操作。
5. ansible-vault
配置文件中如果包含密碼等敏感信息,可以通過ansible-vault加密、解密文件。
四、Ansible 初試
(一)Ansible 安裝
官方提供了多種安裝方式,可從github的ansible project下載源碼編譯安裝,也可通過yum、apt-get指令安裝,這里僅介紹通過pip安裝ansible,其他可參考官方網(wǎng)站。
- $ sudo pip install ansible
(二)第一條命令
為了避免在建立ssh連接時,重復(fù)輸入密碼,可以設(shè)置遠(yuǎn)程主機(jī)免密碼登錄。
- $ ssh-keygen –t rsa –P "
- $ ssh-copy-id -i ~/.ssh/id_rsa.pub user@remote_host
編輯(或創(chuàng)建)/etc/ansible/hosts文件,并在其中加入遠(yuǎn)程主機(jī),例:192.168.1.2
- $ ansible all -m ping
- 192.168.1.2 | SUCCESS => {
- "changed": false,
- "ping": "pong"
- }
(三)Inventory 文件
/etc/ansible/hosts文件格式與ini配置文件類似,可以指定連接方式,也可以指定連接用戶名。同時,再分配變量時,可以指定主機(jī)分配變量,也可以指定組分配變量。變量可以在多個地方定義,有優(yōu)先級的差別。例如以下代碼顯示。
- 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,遠(yuǎn)程主機(jī)被定義成不同角色,每個角色需要根據(jù)playbook中不同的task執(zhí)行不同的指令,比如一組主機(jī)在inventory文件中被定義成webservers,則可能會執(zhí)行web服務(wù)器重啟等操作。
如下playbook,執(zhí)行一組定義為webservers的主機(jī),使用root賬號登錄,并且定義了http_port、max_clients變量,會執(zhí)行三個task,分別為安裝最新hhtpd服務(wù)、拷貝/srv/httpd.j2文件到遠(yuǎn)程主機(jī)的/etc/httpd.conf、重啟httpd服務(wù)。’
notify‘ action表示在playbook每一個task結(jié)束時被觸發(fā),只會被觸發(fā)一次。handlers是一些task列表,通過名字引用。則該playbook中,配置文件拷貝結(jié)束后,執(zhí)行'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
五、自動化部署發(fā)布示例
簡要說明下我們的項(xiàng)目如何使用ansible實(shí)現(xiàn)了多個環(huán)境的自動化部署發(fā)布。
- ├── 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
如上目錄結(jié)構(gòu),是目前ansible比較受歡迎的實(shí)現(xiàn)方式。例如項(xiàng)目有生產(chǎn)和測試環(huán)境,則分為兩個inventory文件,分別為production、staging,inventory文件中定義對應(yīng)環(huán)境的服務(wù)器所在的組,以staging為例,web_server_sh、web_server_bj表示兩個機(jī)房的主機(jī),build_server為打包機(jī)器。
- [web_server_sh]
- 192.168.0.2
- [web_server_bj]
- 192.168.0.3
- [build_server]
- localhost ansible_connection=local
而每個inventory對應(yīng)的playbook則為production.yml、staging.yml,指定不同的組需要執(zhí)行的角色task。
以staging.yml為例,build_server組的主機(jī)需要執(zhí)行build角色的task,并且變量文件為
group_vars/staging/build_server.yml,而web_server_sh、web_server_bj組的主機(jī)需要執(zhí)行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為自定義的集群拉入拉出模塊。
六、總結(jié)
- ansible 很好的幫助了我們解決了自動化部署發(fā)布的事情,現(xiàn)在項(xiàng)目同步更新到幾個機(jī)房,已經(jīng)只需要幾分鐘就可以完成,節(jié)省了許多人力。
- 在部署發(fā)布工具的選擇上,工具沒有好壞,應(yīng)該結(jié)合自身項(xiàng)目來選擇,都能夠很好地提高工作效率。
- ansible解決了燃眉之急,而目前已經(jīng)很好地與jenkins、docker結(jié)合,當(dāng)集群數(shù)量越來越多,越來越難以維護(hù)時,是否需要更換工具,或是結(jié)合最新技術(shù),都是一個考驗(yàn)的難題。
作者 葉柴柴 豈安科技軟件工程師
負(fù)責(zé)豈安科技業(yè)務(wù)風(fēng)險分析平臺后臺開發(fā)。鏟屎官里會寫代碼的,寫代碼里會鏟屎的,一個愛柯基、愛Python、愛生活的鏟屎官。
【本文是51CTO專欄機(jī)構(gòu)“豈安科技”的原創(chuàng)文章,轉(zhuǎn)載請通過微信公眾號(bigsec)聯(lián)系原作者】