安全圈 | 专注于最新网络信息安全讯息新闻

首页

基於ansible的項目自動化部署管理·issue #57·abbshr/abbshr.github.io·github

作者 strmiska 时间 2020-03-02
all

正式走入工作崗位一個月,接著實習的工作內容繼續,還是承擔團隊的Develop & Operation & Research任務,恰好我個人也比較喜歡什麼都接觸一些.現時在應用開發部門設計了一套包括日誌處理,監控報警,持續集成,版本發佈與回滾,自動化管理在內的基礎平臺的架構,當然這套體系肯定還尚未成熟,這裡經過老大的許可先把項目的部署與回滾架構發上來,做個記錄也方便日後tuning.

為什麼是ansible?

8月初剛過來時我壓根沒聽過ansible只知道puppet,正好那時團隊準備做項目自動化管理相關的工作,也就把自動化配置管理工具搜了一遍,列了個優缺點比較表,發現ansible完勝.至於為什麼,我就一句話:“沒有agent,沒有server,用ssh批量管理主機”.玩過puppet和chef的同學應該秒懂了.

另外,ansible也是Devops工具集中躥升速度最快的配置管理工具之一.截止至本年度7月份,Devops使用度&接受度排行榜中前四比特分別是Puppet,Chef,Docker,Ansible.而後者預計很快將超越前兩個工具.

以其配寘上的簡潔,使用上的順手,功能上的强大,好了繼續下一節.

自動化管理

ansible的細節這裡略過,單說這套架構,現時包括如下功能:

接下來從整套機制的架構到細節逐步介紹.

規範化項目目錄結構

在未引入Docker情况下,為了做到項目(應用程序,配寘資訊,狀態數據,依賴工具鏈等)之間的隔離,這裡定義了一種項目的目錄規範.

線上項目一般都是位於某個目錄(比如/opt/app)下麵,不同的子目錄用以區分不同的項目,每個項目目錄的基本結構如下:

/opt/app /uopt/app/example-project ├── current # 指向项目最新发布的版本的软链接 ** 重要 ** ├── releases # 包含所有的历史发布版本(以及当前版本) ** 重要 ** ├── tmp # rsync 临时目录 ├── shared # 发布工具使用的目录 ** 重要 ** ├── log # 日志存放 ├── run # 运行时数据 ├── util # 外部工具 └── node_modules # Node.js Package 形式的外部工具, 如 pm2 ** 重要 **

每個項目可以在這個目錄結構上進行擴展,比如添加其他目錄,但上述標注**重要**的目錄不建議删除或修改.

其中current目錄指向的就是該項目的原代碼,即開發階段所熟悉的目錄結構.

Ansible Playbook目錄結構

在使用ansible時,current所指代的程式碼目錄中,應包含ansible playbook的配寘目錄,舉個例子:

/opt/app/my_app/current/deploy ❯❯❯ tree -a -L 4 # 以下结构参考 ansible 官方给出的最佳实践 . ├── group_vars │ ├── all │ ├── nodes │ │ └── vars │ └── proxy │ └── vars ├── host_vars # 测试环境下只需增加对应主机的变量文件即可覆盖预设变量 │ ├── 10.0.5.130 │ ├── 192.168.1.17 │ │ ├── vars │ │ └── vault # 加密变量 │ ├── 192.168.5.68 │ │ ├── vars │ │ └── vault │ └── 192.168.5.69 │ ├── vars │ └── vault ├── production # 线上环境 inventory ├── roles │ ├── config │ │ ├── tasks │ │ │ └── main.yml │ │ └── templates │ │ ├── config.json.j2 │ │ ├── logstash.conf.j2 │ │ └── macros.j2 │ ├── node │ │ └── tasks │ │ └── main.yml │ ├── proxy │ │ └── tasks │ │ └── main.yml │ ├── schedule │ │ └── tasks │ │ └── main.yml │ └── worker │ └── tasks │ └── main.yml ├── rollback.yml ├── .rsync_ignore # 从代理机到线上机同步时需要忽略的文件/目录列表 ├── site.yml └── staging # 测试环境 inventory

其餘檔案的解釋和作用見ansible官方檔案.

發佈和回滾

在執行發佈回滾操作上,我在開源roles ansistrano的基礎上做了不少改動以適配我們的應用場景,並以新的roles發佈在ansible galaxy上(https://github.com/upyun-dev/ansistrano-deploy | https://github.com/upyun-dev/ ansistrano-rollback),具體的程式碼實現這裡就不說了.

來看看怎麼用吧:

# 安装依赖 roles $ ansible-galaxy install upyun-dev.ansistrano-deploy $ ansible-galaxy install upyun-dev.ansistrano-rollback # 在所有机器上执行项目部署, 发布版本并重启服务任务 ansible-playbook -i <staging | production> site.yml # 在所有机器上执行项目回滚并重启服务任务 ansible-playbook -i <staging | production> rollback.yml

但是同構化proxy和nodes往往不是我們想要的結果,多數情况下我們可能只把proxy作為純粹的代理機使用,並不需要類比線上機器執行部署/回滾.這種情況可以通過指定--tag或者--limit來選擇要執行的任務:

# tag: proxy, nodes, config # 仅在 proxy 上执行部署发布 ansible-playbook -i hosts site.yml --tag="proxy" # 仅在 proxy 上执行回滚 ansible-playbook -i hosts rollback.yml --tag="proxy" # 仅在 nodes 上执行部署发布以及服务启动 ansible-playbook -i hosts site.yml --tag="nodes" # 只在属于proxy group的主机上执行tasks ansible-playbook -i <staging | production> site.yml --limit=proxy

本地測試/開發

在本地測試與開發上,ansible playbook配寘目錄中的一些變數可能需要稍做修改,囙此你可以創建一個host_var檔案,比如:

# 文件: host_vars/localhost # 项目名 app_name: my_app_test # 项目的父级目录 dest_prefix: "/tmp" # 分支/版本 version: test # 代理机的地址 sync_host: [email protected]

此外,inventory內容也可能根據測試主機的地址及ssh的配寘不同而需要修改.

確保以下正常

注意當你選擇使用rsync的ssh模式同步數據時,一定要保證代理機上的登入shell沒有多餘的輸出(當時被這個坑了…).

專案啟動腳本

由於引入規範化項目結構,導致了冗餘目錄的產生以及項目狀態數據路徑(如pm2)的變化.為了遮罩本地以及線上部署差异,透明化本地開發,這裡對項目的啟動腳本做了修改,使其根據不同的開發環境判斷如何啟動項目,如:

PRJ_DIR=$(cd $APP_ROOT_DIR/../.. && pwd) APP_DIR_PARENT=$(cd $APP_ROOT_DIR/.. && pwd) if [[ -L $APP_DIR_PARENT/current ]]; then PRJ_DIR=$APP_DIR_PARENT elif [[ ! -d $PRJ_DIR/releases || ! -L $PRJ_DIR/current ]]; then PRJ_DIR=${APP_ROOT_DIR} fi PM2_BIN="$PRJ_DIR/node_modules/pm2/bin/pm2" # 指定新的pm2可执行文件路径

最終結果體現為:如果並沒有遵循如上所述的規範化目錄結構,那麼將之後的部署作為本地開發環境下的部署.否則作為線上/測試環境下的部署.

[WIP] -執行流程