
從聊天說起
有一次和朋友聊天,他說他們有一次部署出事了,影響還挺大,那次事故后,他們公司對于部署流程增加了更多的審批。
當(dāng)朋友說完前半句時,我已經(jīng)猜到下半句,那是很多公司或個人會做出的反應(yīng)。至于為什么會做出這樣的反應(yīng),我也不知道。
我問:為什么那次部署會“出事”?
他說:當(dāng)時部署的人忘記了那臺機(jī)器上有一條 Iptable 規(guī)則,導(dǎo)致了事故。
我就在想,如果有人審批,那次事故就不會發(fā)生嗎?審批的人就知道那臺機(jī)器上有一條規(guī)則導(dǎo)致事故的發(fā)生?然后駁回這次部署嗎?連一線的開發(fā)和運(yùn)維都忘記了的 Iptable 規(guī)則,“高高在上的審批領(lǐng)導(dǎo)”就更不知道了。
題外話:增加審批流程并不能避免這次事故,只不過當(dāng)出現(xiàn)事故時,可以更好的定責(zé)。然而我又好奇了,這種“審批”是為了解決問題,解決什么問題?,還是為了逃避責(zé)任?誰逃避了責(zé)任?誰又有責(zé)任?
對于這類問題,我心里已經(jīng)有數(shù)了,但想知道這位朋友的回答,就接著問:那么怎么杜絕這類問題呢?
他說:因為那條 Iptable 規(guī)則的設(shè)置太久遠(yuǎn)了,是誰都記不起。如果能把每次部署的步驟記錄下來,這樣下次部署的時候,過一下以前的部署記錄,就會知道那個 Iptable 規(guī)則了。(作者:大概原意,已經(jīng)記不清原話)
這位朋友說的做法,我之前待的一個團(tuán)隊的做法也差不多:會有一個頁面專門記錄下每次部署的步驟,步驟由開發(fā)人員寫,然后由運(yùn)維人員執(zhí)行。只是我不知道他們會不會回顧之前所有針對這臺機(jī)器的部署步驟。
這個團(tuán)隊里有某某大型互聯(lián)網(wǎng)公司來的架構(gòu)師和某財務(wù)軟件公司來的運(yùn)維,所以,我不負(fù)責(zé)地推測,我們這個行業(yè)很多公司對于配置的管理還沒有達(dá)到足夠的重視,也沒有正確的看待。
我笑了,接著問朋友:那我要知道當(dāng)前機(jī)器的“最終狀態(tài)”,是不是要找出所有部署記錄,還要過濾出對這次部署有影響的每一個細(xì)節(jié)?比如那條 Iptable 規(guī)則。
接下來的對話細(xì)節(jié)已經(jīng)記不清,也不重要了。重要的是找出針對這類運(yùn)維事故根本原因及解決辦法。
我個人認(rèn)為這類問題的根本原因在于:
- 配置管理的失控:
已經(jīng)沒有人完整知道線上環(huán)境配置是什么了?要了解時,只能一個個查。 - 測試環(huán)境與生產(chǎn)環(huán)境的配置不一致:
如果那位倒霉的同學(xué)在測試環(huán)境部署出現(xiàn)這樣的問題,到生產(chǎn)環(huán)境部署時,自然就會注意相關(guān)配置項了。
以上只是我個人認(rèn)為的,不一定正確,歡迎各位讀者討論。
那如何杜絕這類問題呢?
這兩個原因可以看作一個,也可以看作兩個。但方法都是一樣的:
- 使用聲明式的配置管理方法,而不是腳本式
- 版本化這些聲明的配置
- 所有環(huán)境使用同一套裝配置管理方法
使用聲明式的配置管理方法,而不是腳本式的
腳本式的配置管理是這樣的:
apt-get install build-essential
apt-get install libtool
cd /usr/local/src
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.37.tar.gz
tar -zxvf pcre-8.37.tar.gz
cd pcre-8.34
./configure
make
make install
而聲明式的配置管理是這樣的:
# ./ansible-nginx/tasks/install_nginx.yml
# 使用這個7-0.el7版本的yum包
- name: NGINX | Installing NGINX repo rpm
yum:
name: http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
# 當(dāng)前機(jī)器的nginx的狀態(tài)應(yīng)該是最新版本
- name: NGINX | Installing NGINX
yum:
name: nginx
state: latest
# 當(dāng)前機(jī)器的 nginx service 的狀態(tài)應(yīng)該是已經(jīng)啟動的。至于如何確保 nginx 這個 service,當(dāng)前是什么狀態(tài)的,又是如何啟動的,我們不需要關(guān)心。
- name: NGINX | Starting NGINX
service:
name: nginx
state: started
聲明式的配置里寫的是當(dāng)前環(huán)境的“狀態(tài)”,語意上,聲明式的配置不論你執(zhí)行多少次,你得到最終的“狀態(tài)”就是你所聲明的,這也就實現(xiàn)了《持續(xù)交付》里說的:
確保部署流程是冪等的
無論開始部署時目標(biāo)環(huán)境處于何種狀態(tài),部署流程應(yīng)該總是令目標(biāo)環(huán)境達(dá)到同樣(正確)的狀態(tài),并以之為結(jié)束點(diǎn)。
這樣,你就不用在第1000次部署時,根據(jù)前999次部署腳本找出對這一次部署有影響的細(xì)節(jié)了。
具體實踐時,我發(fā)現(xiàn) Ansible 就能很好的做到這點(diǎn)。
版本化這些聲明式的配置
將這些配置版本化的好處,就不需要重點(diǎn)說明了。
所有環(huán)境使用同一套裝配置管理方法
具體一點(diǎn)的說就是所有環(huán)境都使用相同的聲明配置,具體到不同環(huán)境時,使用變量替換。這樣就可以保證所有環(huán)境的一致性了。
具體實踐方法,還需要根據(jù)所在團(tuán)隊調(diào)整。你也可以通過本文附錄里鏈接,參考其他人是如何實踐的。
小結(jié)
- 關(guān)于銀彈:如果真的按照以上方法就可以確保運(yùn)維萬無一失了嗎?很遺憾,答案是否定的。就連亞馬遜這樣的行業(yè)標(biāo)桿都沒有辦法做到萬無一失。
- 關(guān)于定責(zé):見過一些企業(yè)凡事都講究“定責(zé)”。定責(zé)可以有,但是定責(zé)了,是否真的能解決問題了?是值得討論的。
- 關(guān)于配置:團(tuán)隊對于“配置”的理解達(dá)成共識很重要
- 關(guān)于成本:要實現(xiàn)以上所說的實踐成本高嗎?是不是需要一個DevOps團(tuán)隊?
說實話,找到懂這些并有實踐經(jīng)驗的人很難,從這一方面看,成本很高。但是這并不是我們不朝這個方向發(fā)展的借口。另,對于軟件工程的“成本”,大家沒有統(tǒng)一的定義,所以也就更不好討論下去了。
附錄
關(guān)于配置管理
多環(huán)境配置管理