写了 30 万行基础设施代码后,我们得出 5 个有用的经验
在 Gruntwork,我們創(chuàng)建并維護(hù)著一個(gè)包含 30 萬(wàn)行基礎(chǔ)設(shè)施代碼的庫(kù),有數(shù)百家公司在他們的生產(chǎn)環(huán)境中使用這個(gè)庫(kù)。在這篇文章中,我將分享我們?cè)陂_(kāi)發(fā)和維護(hù)這個(gè)庫(kù)的實(shí)踐過(guò)程中學(xué)到的非常重要的五課。
1 處于石器時(shí)代的 DevOps
雖然這個(gè)行業(yè)充斥著各種前沿的流行語(yǔ)——Kubernetes、微服務(wù)、服務(wù)網(wǎng)格、不可變基礎(chǔ)設(shè)施、大數(shù)據(jù)、數(shù)據(jù)湖,等等——但實(shí)際情況是,當(dāng)你在構(gòu)建基礎(chǔ)設(shè)施并陷入困境時(shí),它們看起來(lái)一點(diǎn)都不前沿。
對(duì)我來(lái)說(shuō),DevOps 感覺(jué)更像這樣:
構(gòu)建生產(chǎn)級(jí)的基礎(chǔ)設(shè)施其實(shí)很難,壓力很大,而且非常耗時(shí)。
根據(jù)我們?cè)谂c數(shù)百家不同公司合作時(shí)收集的經(jīng)驗(yàn)數(shù)據(jù),你大致可以估計(jì)你的下一個(gè)基礎(chǔ)設(shè)施項(xiàng)目需要多長(zhǎng)時(shí)間:
?
2 第 1 課:生產(chǎn)級(jí)基礎(chǔ)設(shè)施檢查清單
DevOps 項(xiàng)目總是比預(yù)期的要長(zhǎng),為什么會(huì)這樣?
第一個(gè)原因是 Yak Shaving(給牦牛擼毛),那么什么是 Yak Shaving?看看這個(gè)場(chǎng)景你就明白了:
經(jīng)理:你不是在開(kāi)發(fā)用戶登錄功能嗎?為什么現(xiàn)在在搗鼓一個(gè)我們根本用不到的數(shù)據(jù)庫(kù)?
工程師:是啊,我是打算開(kāi)發(fā)用戶登錄功能。然后我開(kāi)始評(píng)估要用哪個(gè)庫(kù),我發(fā)現(xiàn)一個(gè)非常好的庫(kù),但它只支持 Postgres。于是我試著搭建一個(gè) Postgres,看看值不值得這樣做。但切換數(shù)據(jù)庫(kù)會(huì)破壞索引,所以我現(xiàn)在在學(xué)習(xí)如何建立 Postgres 索引……這樣才能把用戶登錄功能做出來(lái),對(duì)吧?
第二個(gè)原因是構(gòu)建生產(chǎn)級(jí)的基礎(chǔ)設(shè)施涉及了太多的細(xì)節(jié)。絕大多數(shù)開(kāi)發(fā)人員并不知道這些細(xì)節(jié),因此,當(dāng)你在估算項(xiàng)目時(shí),你通常會(huì)忘記關(guān)鍵和耗時(shí)的細(xì)節(jié)。
為避免這個(gè)問(wèn)題,每次你開(kāi)始使用新的基礎(chǔ)設(shè)施時(shí),請(qǐng)檢查以下清單:
并非每個(gè)基礎(chǔ)設(shè)施都需要檢查清單中的每個(gè)項(xiàng)目,但你應(yīng)該有意識(shí)地記錄你已實(shí)現(xiàn)的項(xiàng)目、決定跳過(guò)的項(xiàng)目以及相應(yīng)的原因。
?
3 第 2 課:工具集
截至 2018 年,以下是我們?cè)?Gruntwork 中用于構(gòu)建和管理基礎(chǔ)設(shè)施的主要工具:
-
Terraform:我們使用 Terraform 來(lái)配置所有的基礎(chǔ)設(shè)施,包括網(wǎng)絡(luò)、負(fù)載均衡器、數(shù)據(jù)庫(kù)、用戶、權(quán)限以及我們所有的服務(wù)器。
-
Packer:我們使用 Packer 來(lái)定義和構(gòu)建在服務(wù)器上運(yùn)行的虛擬機(jī)鏡像。
-
Docker:我們的一些服務(wù)器組成了集群,上面運(yùn)行著托管應(yīng)用程序作的 Docker 容器。我們使用的主要 Docker 集群工具是 Kubernetes、ECS 和 Fargate。
現(xiàn)在,所有這些工具都很有用,但這不是重點(diǎn)。重點(diǎn)是,光是有這些工具還不夠,你還需要改變團(tuán)隊(duì)的行為。
特別是,如果你的團(tuán)隊(duì)不信賴這些工具,或者你的團(tuán)隊(duì)沒(méi)有足夠的時(shí)間學(xué)習(xí)使用這些工具,那么即使是世界上最好的工具都無(wú)法為你的團(tuán)隊(duì)帶來(lái)任何幫助。因此,關(guān)鍵的一點(diǎn)是,基礎(chǔ)設(shè)施即代碼是一項(xiàng)投資:需要前期預(yù)付成本,但如果你明智地進(jìn)行投資,將獲得長(zhǎng)期的巨大好處。
?
4第 3 課:大模塊是有害的
基礎(chǔ)設(shè)施即代碼新手通常在單個(gè)文件或作為一個(gè)單元進(jìn)行部署的一組文件中定義所有環(huán)境(dev、stage、prod 等)的所有基礎(chǔ)設(shè)施。這是一種糟糕的做法。
以下是這種做法的一些缺點(diǎn):
速度慢:如果你的所有基礎(chǔ)設(shè)施都在同一個(gè)地方定義,那么運(yùn)行任何命令都需要很長(zhǎng)時(shí)間。我們已經(jīng)看到公司的 terraform plan 需要 5-6 分鐘才能運(yùn)行完畢!
不安全:如果你的所有基礎(chǔ)設(shè)施都是一起管理的,那么在更改內(nèi)容時(shí)都需要可以訪問(wèn)所有內(nèi)容的權(quán)限。這意味著幾乎每個(gè)用戶都必須是管理員。
風(fēng)險(xiǎn):如果所有雞蛋都在一個(gè)籃子里,那么任意一個(gè)錯(cuò)誤都可能會(huì)破壞整個(gè)系統(tǒng)。你可能正在對(duì) dev 中的前端應(yīng)用程序進(jìn)行微小更改,但由于輸入錯(cuò)誤或運(yùn)行了錯(cuò)誤的命令,可能把生產(chǎn)數(shù)據(jù)庫(kù)給刪掉了。
難以理解:在一個(gè)地方擁有的代碼越多,人們理解它們的難度就越大。如果將它們捆綁在一起,你不理解的部分可能會(huì)影響到你。
難以測(cè)試:測(cè)試基礎(chǔ)設(shè)施代碼很難,測(cè)試大量基礎(chǔ)設(shè)施代碼幾乎是不可能的。
難以評(píng)審:諸如 terraform plan 之類(lèi)的命令的輸出變得毫無(wú)用處,因?yàn)闆](méi)有人想要查看數(shù)千行輸出。代碼評(píng)審也變得毫無(wú)用處。
你應(yīng)該使用小型、獨(dú)立、可重用、可組合的模塊來(lái)構(gòu)建代碼。這不是什么有爭(zhēng)議的新觀點(diǎn)。你之前可能已經(jīng)聽(tīng)過(guò)無(wú)數(shù)次了:
“一次做一件事,并把它做好”——Unix 哲學(xué)。
“函數(shù)的第一條規(guī)則是它們應(yīng)該很小。函數(shù)的第二個(gè)規(guī)則是它們應(yīng)該比小更小?!薄墩麧嵈a之道》
?
5 第 4 課:沒(méi)有自動(dòng)化測(cè)試的基礎(chǔ)設(shè)施代碼太脆弱
如果你的基礎(chǔ)設(shè)施代碼沒(méi)有經(jīng)過(guò)自動(dòng)化測(cè)試就很容易出問(wèn)題。你只是不知道一些暗藏的問(wèn)題。也就是說(shuō),測(cè)試基礎(chǔ)設(shè)施代碼很難。你沒(méi)有“l(fā)ocalhost”(例如,你無(wú)法在筆記本電腦上部署 AWS VPC),也沒(méi)有“單元測(cè)試”(例如,你無(wú)法將“Terraform”代碼與“外部”隔離開(kāi)來(lái),因?yàn)?Terraform 所做的事情就是與外界交互)。
因此,要正確測(cè)試你的基礎(chǔ)設(shè)施代碼,通常需要將代碼部署到真實(shí)環(huán)境,運(yùn)行真實(shí)的基礎(chǔ)設(shè)施,驗(yàn)證它們做它們?cè)撟龅氖虑?#xff08;對(duì)于這種測(cè)試方式,請(qǐng)參考 Terratest,一個(gè)開(kāi)源庫(kù),包括用于測(cè)試 Terraform、Packer 和 Docker 代碼的工具)。因此,對(duì)于基礎(chǔ)設(shè)施測(cè)試,你必須重新定義一些術(shù)語(yǔ):
-
單元測(cè)試是指部署和測(cè)試來(lái)自一種基礎(chǔ)設(shè)施的一個(gè)或少量密切相關(guān)的模塊(例如,測(cè)試單個(gè)數(shù)據(jù)庫(kù)模塊)。
-
集成測(cè)試是指部署和測(cè)試來(lái)自不同類(lèi)型的基礎(chǔ)設(shè)施的多個(gè)模塊,以驗(yàn)證它們是否能夠正常協(xié)同工作(例如,測(cè)試 Web 服務(wù)模塊和數(shù)據(jù)庫(kù)模塊)。
-
端到端測(cè)試是指部署并測(cè)試整個(gè)架構(gòu)。
這張圖是一個(gè)金字塔,我們有很多單元測(cè)試、較少數(shù)量的集成測(cè)試和極少數(shù)的端到端測(cè)試。為什么?這是由每種類(lèi)型的測(cè)試所需要的時(shí)間來(lái)決定的:
基礎(chǔ)設(shè)施測(cè)試的周期時(shí)間很慢,特別是金字塔越往上就越慢,所以你會(huì)想盡可能多地在金字塔底層捕捉到錯(cuò)誤。這意味著你應(yīng)該:
構(gòu)建小巧、簡(jiǎn)單的獨(dú)立模塊,并為它們編寫(xiě)大量單元測(cè)試。
將這些小型、簡(jiǎn)單、經(jīng)過(guò)實(shí)戰(zhàn)檢驗(yàn)的構(gòu)建塊組合在一起,創(chuàng)建更復(fù)雜的基礎(chǔ)設(shè)施,并進(jìn)行少量的集成和端到端測(cè)試。
6第 5 課:發(fā)布過(guò)程
現(xiàn)在讓我們把這一切都放在一起。以下是你從現(xiàn)在開(kāi)始應(yīng)該采用的構(gòu)建和管理基礎(chǔ)設(shè)施的方法:
-
對(duì)照生產(chǎn)級(jí)基礎(chǔ)設(shè)施檢查清單,確保你正在構(gòu)建正確的東西。
-
使用 Terraform、Packer 和 Docker 等工具將你的基礎(chǔ)設(shè)施定義為代碼。確保你的團(tuán)隊(duì)有時(shí)間掌握這些工具。
-
使用小型、獨(dú)立、可組合的模塊構(gòu)建代碼(或使用基礎(chǔ)設(shè)施中的現(xiàn)成模塊作為代碼庫(kù))。
-
使用 Terratest 為你的模塊編寫(xiě)自動(dòng)化測(cè)試。
-
提交拉取請(qǐng)求,讓別人來(lái)評(píng)審你的代碼。
-
發(fā)布新版本代碼。
-
將你的代碼從一個(gè)環(huán)境推到另一個(gè)環(huán)境。
?
英文原文
https://blog.gruntwork.io/5-lessons-learned-from-writing-over-300-000-lines-of-infrastructure-code-36ba7fadeac1
總結(jié)
以上是生活随笔為你收集整理的写了 30 万行基础设施代码后,我们得出 5 个有用的经验的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java当中的常量池
- 下一篇: 聊聊微服务的隔离和熔断