寫了30萬行基礎設施代碼後,我們得出5個有用的經驗

在Gruntwork,我們創建並維護着一個包含30萬行基礎設施代碼的庫,有數百家公司在他們的生產環境中使用這個庫。在這篇文章中,我將分享我們在開發和維護這個庫的實踐過程中學到的非常重要的五課。

處於石器時代的DevOps

雖然這個行業充斥着各種前沿的流行語——Kubernetes、微服務、服務網格、不可變基礎設施、大數據、數據湖,等等——但實際情況是,當你在構建基礎設施並陷入困境時,它們看起來一點都不前沿。

對我來說,DevOps感覺更像這樣:

image

構建生產級的基礎設施其實很難,壓力很大,而且非常耗時。

根據我們在與數百家不同公司合作時收集的經驗數據,你大致可以估計你的下一個基礎設施項目需要多長時間:

image

第1課:生產級基礎設施檢查清單

DevOps項目總是比預期的要長,爲什麼會這樣?

第一個原因是Yak Shaving(給犛牛擼毛),那麼什麼是Yak Shaving?看看這個場景你就明白了:

經理:你不是在開發用戶登錄功能嗎?爲什麼現在在搗鼓一個我們根本用不到的數據庫?

工程師:是啊,我是打算開發用戶登錄功能。然後我開始評估要用哪個庫,我發現一個非常好的庫,但它只支持Postgres。於是我試着搭建一個Postgres,看看值不值得這樣做。但切換數據庫會破壞索引,所以我現在在學習如何建立Postgres索引……這樣才能把用戶登錄功能做出來,對吧?

第二個原因是構建生產級的基礎設施涉及了太多的細節。絕大多數開發人員並不知道這些細節,因此,當你在估算項目時,你通常會忘記關鍵和耗時的細節。

爲避免這個問題,每次你開始使用新的基礎設施時,請檢查以下清單:

image

並非每個基礎設施都需要檢查清單中的每個項目,但你應該有意識地記錄你已實現的項目、決定跳過的項目以及相應的原因。

第2課:工具集

截至2018年,以下是我們在Gruntwork中用於構建和管理基礎設施的主要工具:

image

Terraform:我們使用Terraform來配置所有的基礎設施,包括網絡、負載均衡器、數據庫、用戶、權限以及我們所有的服務器。
Packer:我們使用Packer來定義和構建在服務器上運行的虛擬機鏡像。
Docker:我們的一些服務器組成了集羣,上面運行着託管應用程序作的Docker容器。我們使用的主要Docker集羣工具是Kubernetes、ECS和Fargate。

現在,所有這些工具都很有用,但這不是重點。重點是,光是有這些工具還不夠,你還需要改變團隊的行爲。

特別是,如果你的團隊不信賴這些工具,或者你的團隊沒有足夠的時間學習使用這些工具,那麼即使是世界上最好的工具都無法爲你的團隊帶來任何幫助。因此,關鍵的一點是,基礎設施即代碼是一項投資:需要前期預付成本,但如果你明智地進行投資,將獲得長期的巨大好處。

第3課:大模塊是有害的

基礎設施即代碼新手通常在單個文件或作爲一個單元進行部署的一組文件中定義所有環境(dev、stage、prod等)的所有基礎設施。這是一種糟糕的做法。

以下是這種做法的一些缺點:

  1. 速度慢:如果你的所有基礎設施都在同一個地方定義,那麼運行任何命令都需要很長時間。我們已經看到公司的terraform plan需要5-6分鐘才能運行完畢!
  2. 不安全:如果你的所有基礎設施都是一起管理的,那麼在更改內容時都需要可以訪問所有內容的權限。這意味着幾乎每個用戶都必須是管理員。
  3. 風險:如果所有雞蛋都在一個籃子裏,那麼任意一個錯誤都可能會破壞整個系統。你可能正在對dev中的前端應用程序進行微小更改,但由於輸入錯誤或運行了錯誤的命令,可能把生產數據庫給刪掉了。
  4. 難以理解:在一個地方擁有的代碼越多,人們理解它們的難度就越大。如果將它們捆綁在一起,你不理解的部分可能會影響到你。
  5. 難以測試:測試基礎設施代碼很難,測試大量基礎設施代碼幾乎是不可能的。
  6. 難以評審:諸如terraform plan之類的命令的輸出變得毫無用處,因爲沒有人想要查看數千行輸出。代碼評審也變得毫無用處。

你應該使用小型、獨立、可重用、可組合的模塊來構建代碼。這不是什麼有爭議的新觀點。你之前可能已經聽過無數次了:

“一次做一件事,並把它做好”——Unix哲學。

“函數的第一條規則是它們應該很小。函數的第二個規則是它們應該比小更小。”——《整潔代碼之道》

第4課:沒有自動化測試的基礎設施代碼太脆弱

如果你的基礎設施代碼沒有經過自動化測試就很容易出問題。你只是不知道一些暗藏的問題。也就是說,測試基礎設施代碼很難。你沒有“localhost”(例如,你無法在筆記本電腦上部署AWS VPC),也沒有“單元測試”(例如,你無法將“Terraform”代碼與“外部”隔離開來,因爲Terraform所做的事情就是與外界交互)。

因此,要正確測試你的基礎設施代碼,通常需要將代碼部署到真實環境,運行真實的基礎設施,驗證它們做它們該做的事情(對於這種測試方式,請參考Terratest,一個開源庫,包括用於測試Terraform、Packer和Docker代碼的工具)。因此,對於基礎設施測試,你必須重新定義一些術語:

image

  • 單元測試是指部署和測試來自一種基礎設施的一個或少量密切相關的模塊(例如,測試單個數據庫模塊)。
  • 集成測試是指部署和測試來自不同類型的基礎設施的多個模塊,以驗證它們是否能夠正常協同工作(例如,測試Web服務模塊和數據庫模塊)。
  • 端到端測試是指部署並測試整個架構。

這張圖是一個金字塔,我們有很多單元測試、較少數量的集成測試和極少數的端到端測試。爲什麼?這是由每種類型的測試所需要的時間來決定的:

image

基礎設施測試的週期時間很慢,特別是金字塔越往上就越慢,所以你會想儘可能多地在金字塔底層捕捉到錯誤。這意味着你應該:

  1. 構建小巧、簡單的獨立模塊,併爲它們編寫大量單元測試。
  2. 將這些小型、簡單、經過實戰檢驗的構建塊組合在一起,創建更復雜的基礎設施,並進行少量的集成和端到端測試。

第5課:發佈過程

現在讓我們把這一切都放在一起。以下是你從現在開始應該採用的構建和管理基礎設施的方法:

  • 對照生產級基礎設施檢查清單,確保你正在構建正確的東西。
  • 使用Terraform、Packer和Docker等工具將你的基礎設施定義爲代碼。確保你的團隊有時間掌握這些工具。
  • 使用小型、獨立、可組合的模塊構建代碼(或使用基礎設施中的現成模塊作爲代碼庫)。
  • 使用Terratest爲你的模塊編寫自動化測試。
  • 提交拉取請求,讓別人來評審你的代碼。
  • 發佈新版本代碼。
  • 將你的代碼從一個環境推到另一個環境。

image

英文原文:https://blog.gruntwork.io/5-lessons-learned-from-writing-over-300-000-lines-of-infrastructure-code-36ba7fadeac1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章