寫了 30 萬行基礎設施代碼後,我們得出 5 個有用的經驗
作者 | Yevgeniy Brikman
譯者 | 無明
在 Gruntwork,我們創建並維護著一個包含 30 萬行基礎設施代碼的庫,有數百家公司在他們的生產環境中使用這個庫。在這篇文章中,我將分享我們在開發和維護這個庫的實踐過程中學到的非常重要的五課。
1
處於石器時代的 DevOps
雖然這個行業充斥著各種前沿的流行語——Kubernetes、微服務、服務網格、不可變基礎設施、大數據、數據湖,等等——但實際情況是,當你在構建基礎設施並陷入困境時,它們看起來一點都不前沿。
對我來說,DevOps 感覺更像這樣:
構建生產級的基礎設施其實很難,壓力很大,而且非常耗時。
根據我們在與數百家不同公司合作時收集的經驗數據,你大致可以估計你的下一個基礎設施項目需要多長時間:
2
第 1 課:生產級基礎設施檢查清單
DevOps 項目總是比預期的要長,為什麼會這樣?
第一個原因是 Yak Shaving(給氂牛擼毛),那麼什麼是 Yak Shaving?看看這個場景你就明白了:
經理:你不是在開發用戶登錄功能嗎?為什麼現在在搗鼓一個我們根本用不到的資料庫?
工程師:是啊,我是打算開發用戶登錄功能。然後我開始評估要用哪個庫,我發現一個非常好的庫,但它只支持 Postgres。於是我試著搭建一個 Postgres,看看值不值得這樣做。但切換資料庫會破壞索引,所以我現在在學習如何建立 Postgres 索引……這樣才能把用戶登錄功能做出來,對吧?
第二個原因是構建生產級的基礎設施涉及了太多的細節。絕大多數開發人員並不知道這些細節,因此,當你在估算項目時,你通常會忘記關鍵和耗時的細節。
為避免這個問題,每次你開始使用新的基礎設施時,請檢查以下清單:
並非每個基礎設施都需要檢查清單中的每個項目,但你應該有意識地記錄你已實現的項目、決定跳過的項目以及相應的原因。
3
第 2 課:工具集
截至 2018 年,以下是我們在 Gruntwork 中用於構建和管理基礎設施的主要工具:
Terraform:我們使用 Terraform 來配置所有的基礎設施,包括網路、負載均衡器、資料庫、用戶、許可權以及我們所有的伺服器。
Packer:我們使用 Packer 來定義和構建在伺服器上運行的虛擬機鏡像。
Docker:我們的一些伺服器組成了集群,上面運行著託管應用程序作的 Docker 容器。我們使用的主要 Docker 集群工具是 Kubernetes、ECS 和 Fargate。
現在,所有這些工具都很有用,但這不是重點。重點是,光是有這些工具還不夠,你還需要改變團隊的行為。
特別是,如果你的團隊不信賴這些工具,或者你的團隊沒有足夠的時間學習使用這些工具,那麼即使是世界上最好的工具都無法為你的團隊帶來任何幫助。因此,關鍵的一點是,基礎設施即代碼是一項投資:需要前期預付成本,但如果你明智地進行投資,將獲得長期的巨大好處。
4
第 3 課:大模塊是有害的
基礎設施即代碼新手通常在單個文件或作為一個單元進行部署的一組文件中定義所有環境(dev、stage、prod 等)的所有基礎設施。這是一種糟糕的做法。
以下是這種做法的一些缺點:
速度慢:如果你的所有基礎設施都在同一個地方定義,那麼運行任何命令都需要很長時間。我們已經看到公司的 terraform plan 需要 5-6 分鐘才能運行完畢!
不安全:如果你的所有基礎設施都是一起管理的,那麼在更改內容時都需要可以訪問所有內容的許可權。這意味著幾乎每個用戶都必須是管理員。
風險:如果所有雞蛋都在一個籃子里,那麼任意一個錯誤都可能會破壞整個系統。你可能正在對 dev 中的前端應用程序進行微小更改,但由於輸入錯誤或運行了錯誤的命令,可能把生產資料庫給刪掉了。
難以理解:在一個地方擁有的代碼越多,人們理解它們的難度就越大。如果將它們捆綁在一起,你不理解的部分可能會影響到你。
難以測試:測試基礎設施代碼很難,測試大量基礎設施代碼幾乎是不可能的。
難以評審:諸如 terraform plan 之類的命令的輸出變得毫無用處,因為沒有人想要查看數千行輸出。代碼評審也變得毫無用處。
你應該使用小型、獨立、可重用、可組合的模塊來構建代碼。這不是什麼有爭議的新觀點。你之前可能已經聽過無數次了:
「一次做一件事,並把它做好」——Unix 哲學。
「函數的第一條規則是它們應該很小。函數的第二個規則是它們應該比小更小。」——《整潔代碼之道》
5
第 4 課:沒有自動化測試的基礎設施代碼太脆弱
如果你的基礎設施代碼沒有經過自動化測試就很容易出問題。你只是不知道一些暗藏的問題。也就是說,測試基礎設施代碼很難。你沒有「localhost」(例如,你無法在筆記本電腦上部署 AWS VPC),也沒有「單元測試」(例如,你無法將「Terraform」代碼與「外部」隔離開來,因為 Terraform 所做的事情就是與外界交互)。
因此,要正確測試你的基礎設施代碼,通常需要將代碼部署到真實環境,運行真實的基礎設施,驗證它們做它們該做的事情(對於這種測試方式,請參考 Terratest,一個開源庫,包括用於測試 Terraform、Packer 和 Docker 代碼的工具)。因此,對於基礎設施測試,你必須重新定義一些術語:
單元測試是指部署和測試來自一種基礎設施的一個或少量密切相關的模塊(例如,測試單個資料庫模塊)。
集成測試是指部署和測試來自不同類型的基礎設施的多個模塊,以驗證它們是否能夠正常協同工作(例如,測試 Web 服務模塊和資料庫模塊)。
端到端測試是指部署並測試整個架構。
這張圖是一個金字塔,我們有很多單元測試、較少數量的集成測試和極少數的端到端測試。為什麼?這是由每種類型的測試所需要的時間來決定的:
基礎設施測試的周期時間很慢,特別是金字塔越往上就越慢,所以你會想儘可能多地在金字塔底層捕捉到錯誤。這意味著你應該:
構建小巧、簡單的獨立模塊,並為它們編寫大量單元測試。
將這些小型、簡單、經過實戰檢驗的構建塊組合在一起,創建更複雜的基礎設施,並進行少量的集成和端到端測試。
6
第 5 課:發布過程
現在讓我們把這一切都放在一起。以下是你從現在開始應該採用的構建和管理基礎設施的方法:
對照生產級基礎設施檢查清單,確保你正在構建正確的東西。
使用 Terraform、Packer 和 Docker 等工具將你的基礎設施定義為代碼。確保你的團隊有時間掌握這些工具。
使用小型、獨立、可組合的模塊構建代碼(或使用基礎設施中的現成模塊作為代碼庫)。
使用 Terratest 為你的模塊編寫自動化測試。
提交拉取請求,讓別人來評審你的代碼。
發布新版本代碼。
將你的代碼從一個環境推到另一個環境。
英文原文
https://blog.gruntwork.io/5-lessons-learned-from-writing-over-300-000-lines-of-infrastructure-code-36ba7fadeac1
7
本文彩蛋
矽谷一直以其「不斷創新、鼓勵冒險、包容失敗、崇尚競爭、平等開放」的文化聞名於世。在矽谷,軟體開發的流程、迭代都非常迅速,許多科技公司形成了各自行之有效的開發模式與工程師文化,其中尤以 Facebook 為代表。你可以在 InfoQ 公眾號對話框回復關鍵詞:矽谷,獲取一篇以 Facebook 為例的項目開發流程和工程師的績效管理機制文章。
※分散式系統中最容易被忽視的六大「暗流」
※今年最常見的前端面試題,你會做幾道?
TAG:InfoQ |