從 Terraform 切換到 CloudFormation - 並感到遺憾

對於不需要擺弄滑鼠的系統來說,以可重複的文字格式將基礎設施表示為程式碼是一種簡單的最佳實踐。 這種做法有個名字—— 基礎架構即代碼,到目前為止有兩種流行的工具可以實現它,特別是在 AWS 中: Terraform и 雲形成.

從 Terraform 切換到 CloudFormation - 並感到遺憾
Terraform 和 CloudFormation 的經驗比較

來之前 Twitch (AKA 小型亞馬遜) 我工作 在一次啟動中 並使用 Terraform 三年了。 在新的地方,我也全力使用 Terraform,然後公司推動了向 Amazon 的一切過渡,包括 CloudFormation。 我努力為這兩種工具開發最佳實踐,並在非常複雜的組織範圍內的工作流程中使用這兩種工具。 後來,在深思熟慮地權衡從 Terraform 遷移到 CloudFormation 的影響後,我確信 Terraform 可能是該組織的最佳選擇。

可怕的地形

測試版軟體

Terraform 甚至還沒有發布 1.0 版本,這是不使用它的一個很好的理由。 自從我第一次親自嘗試以來,它已經改變了很多,但那時 terraform apply 經常在幾次更新後或僅在使用幾年後就出現故障。 我會說“現在一切都不同了”,但是……每個人似乎都這麼說,不是嗎? 有些變更與先前的版本不相容,儘管它們是合適的,甚至感覺資源儲存的語法和抽象現在正是我們所需要的。 儀器似乎真的變得更好了,但... :-0

另一方面,AWS在保持向後相容性方面做得很好。 這可能是因為他們的服務通常在組織內經過徹底測試,然後才重新命名並發布。 因此,「他們努力嘗試」是輕描淡寫的。 對於像 AWS 這樣多樣化且複雜的系統,要保持 API 的向後相容性非常困難。 任何必須維護如此廣泛使用的公共 API 的人都應該明白多年來這樣做是多麼困難。 但在我的記憶中,CloudFormation 的行為多年來從未改變過。

見見腿…這是一顆子彈

據我所知,刪除資源 局外人 您的 CF 堆疊中的 CloudFormation 堆疊是不可能的。 Terraform 也是。 它允許您將現有資源導入堆疊中。 功能可以說是令人驚嘆,但能力越大,責任越大。 您只需將資源新增至堆疊中,並且在使用堆疊時,無法刪除或變更該資源。 有一天,事與願違。 有一天,在 Twitch 上,有人無意中將別人的 AWS 安全群組匯入到自己的 Terraform 堆疊中,而沒有造成任何惡作劇。 我輸入了幾個命令,然後...安全群組(以及傳入流量)消失了。

地形偉大

從不完整狀態恢復

有時,CloudFormation 無法完全從一種狀態轉換到另一種狀態。 同時,他也會嘗試回到之前的狀態。 遺憾的是,這並不總是可行。 調試後來發生的事情可能會非常可怕 - 你永遠不知道 CloudFormation 是否會因為它被黑客攻擊而感到高興 - 即使只是修復它。 是否有可能回到之前的狀態,他真的不知道如何確定,並且默認掛起幾個小時等待奇蹟。

另一方面,Terraform 傾向於更優雅地從失敗的轉換中恢復,並提供高級偵錯工具。

更清晰地變更文件狀態

「好吧,負載平衡器,你要改變了。 但如何呢?”

——焦急的工程師,準備按下「接受」按鈕。

有時我需要對 CloudFormation 堆疊中的負載平衡器進行一些操作,例如新增連接埠號碼或更改安全性群組。 ClouFormation 顯示變化的效果很差。 我如坐針氈般地仔細檢查了 yaml 檔案十次,以確保我沒有刪除任何必要的內容,也沒有添加任何不必要的內容。

Terraform 在這方面要透明得多。 有時他甚至太透明了(讀作:煩人)。 幸運的是,最新版本改進了更改的顯示,以便您現在可以準確地看到正在更改的內容。

靈活性

向後編寫軟體。

說穿了,長壽命軟體最重要的特性就是適應變化的能力。 向後編寫任何軟體。 我最常犯的錯誤是採用「簡單」服務,然後開始將所有內容塞入單一 CloudFormation 或 Terraform 堆疊中。 當然,幾個月後我發現我理解錯了,服務其實也不簡單! 現在我需要以某種方式將大堆疊分解成小組件。 當您使用 CloudFormation 時,這只能透過先重新建立現有堆疊來完成,而我不會對我的資料庫執行此操作。 另一方面,Terraform 使得剖析堆疊並將其分解為更容易理解的較小部分成為可能。

git 中的模組

跨多個堆疊共享 Terraform 程式碼比共享 CloudFormation 程式碼容易得多。 使用 Terraform,您可以將程式碼放入 git 儲存庫中並使用語義版本控制來存取它。 任何有權存取此儲存庫的人都可以重複使用共用程式碼。 CloudFormation 的等價物是 S3,但它沒有相同的優點,而且我們根本沒有理由放棄 git 而選擇 S3。

組織不斷發展,共享通用堆疊的能力達到了關鍵水準。 Terraform 讓這一切變得簡單又自然,而 CloudFormation 會讓你在獲得這樣的東西之前先經歷一些困難。

操作即程式碼

“讓我們編寫腳本吧,好吧。”

——發明 Terraform 自行車 3 年前的工程師。

當談到軟體開發時,Go 或 Java 程式不僅僅是程式碼。

從 Terraform 切換到 CloudFormation - 並感到遺憾
程式碼即程式碼

還有它運作的基礎設施。

從 Terraform 切換到 CloudFormation - 並感到遺憾
基礎架構即代碼

但她是哪裡人? 如何監控呢? 你的程式碼在哪裡? 開發者需要存取權限嗎?

從 Terraform 切換到 CloudFormation - 並感到遺憾
操作即程式碼

身為軟體開發人員並不僅僅意味著編寫程式碼。

AWS 並不是唯一的提供者:您可能也會使用其他提供者。 SignalFx、PagerDuty 或 Github。 也許您有一個用於 CI/CD 的內部 Jenkins 伺服器或用於監控的內部 Grafana 儀表板。 選擇基礎設施作為程式碼有不同的原因,但每一個對於與軟體相關的一切都同樣重要。

當我在 Twitch 工作時,我們加速了 Amazon 混合嵌入式和 AWS 系統內的服務。 我們生產並支援許多微服務,增加了營運成本。 討論是這樣的:

  • Я:該死,超頻一個微服務需要很多手勢。 我將不得不使用這個垃圾來建立一個 AWS 帳戶(我們在 微服務),然後這個用於設置警報,這個用於代碼存儲庫,這個用於電子郵件列表,然後這個......
  • 帶領:讓我們編寫腳本吧,好吧。
  • Я:好的,但是劇本本身會改變。 我們需要一種方法來檢查所有這些內建的亞馬遜小玩意是否都是最新的。
  • 帶領: 聽起來不錯。 我們將為此編寫一個腳本。
  • Я: 偉大的! 並且腳本可能仍然需要設定參數。 他會接受他們嗎?
  • 帶領: 讓他去哪裡就去哪裡!
  • Я:進程可能會改變並且向後相容性將會遺失。 需要某種語意版本控制。
  • 帶領: 好想法!
  • Я:可以在使用者介面內手動更改工具。 我們需要一種方法來檢查和解決這個問題。

…3年後:

  • 帶領:我們得到了地形。

這個故事的寓意是:即使你 亞馬遜的一切都讓人神魂顛倒,您仍在使用不是來自 AWS 的東西,並且這些服務的狀態使用配置語言來保持該狀態同步。

CloudFormation lambda 與 git 模組 terraform

lambda 是 CloudFormation 針對自訂邏輯問題的解決方案。 使用 lambda 你可以 建立巨集使用者資源。 這種方法引入了 Terraform 的 git 模組語義版本控制中不存在的額外複雜性。 對我來說,最迫切的問題是管理所有這些使用者 lambda(這些是數十個 AWS 帳戶)的權限。 另一個重要問題是「先有雞還是先有蛋?」問題:它與 lambda 代碼有關。 這個功能本身就是基礎設施和程式碼,它本身就需要監控和更新。 棺材上的最後一根釘子是語義更新 lambda 代碼更改的困難; 我們還必須確保沒有直接命令的堆疊操作在運行之間不會改變。

我記得有一次我想使用經典的負載平衡器為 Elastic Beanstalk 環境創建金絲雀部署。 最簡單的方法是在生產環境旁邊對 EB 進行第二次部署,更進一步:將自動擴展金絲雀部署組與部署 LB 合併到生產環境中。 由於 Terraform 使用 ASG beantalk 作為結論,這將需要 Terraform 中額外的 4 行程式碼。 當我詢問 CloudFormation 中是否有類似的解決方案時,他們向我指出了一個完整的 git 儲存庫,其中包含部署管道和所有內容,這一切都是為了實現可憐的 4 行 Terraform 程式碼可以完成的事情。

它可以更好地檢測漂移

確保現實符合預期。

漂移檢測 是一個非常強大的操作程式碼功能,因為它有助於確保現實符合預期。 它可用於 CloudFormation 和 Terraform。 但隨著生產堆疊的成長,在 CloudFormation 中搜尋漂移會產生越來越多的錯誤偵測。

借助 Terraform,您可以擁有更高級的生命週期掛鉤來進行漂移檢測。 例如,您輸入命令 忽略更改 如果您想要忽略對特定任務定義的變更而不忽略整個 ECS 部署的更改,請直接在 ECS 任務定義中執行此操作。

CDK 和 CloudFormation 的未來

CloudFormation 很難在跨基礎架構的大規模範圍內進行管理。 其中許多困難已被認識到,並且該工具需要諸如 AWS CDK,一個用於在程式碼中定義雲端基礎設施並透過 AWS CloudFormation 運行它的框架。 看看 aws-cdk 的未來將會很有趣,但它將很難與 Terraform 的其他優勢競爭; 為了讓 CloudFormation 保持最新狀態,需要進行全域變更。

所以 Terraform 不會讓人失望

這是“基礎設施作為代碼”,而不是“作為文字”。

我對 Terraform 的第一印象相當糟糕。 我想我只是不理解這種方法。 幾乎所有工程師都會不自覺地將其視為需要轉換為所需基礎設施的文字格式。 不要這樣做。

優秀軟體開發的真理也適用於 Terraform。

我看到許多用於創建良好程式碼的實踐在 Terraform 中被忽略了。 你已經學習多年才能成為優秀的程式設計師。 不要因為您正在使用 Terraform 就放棄這種體驗。 優秀軟體開發的真理也適用於 Terraform。

程式碼怎麼能不被記錄呢?

我見過巨大的 Terraform 堆疊,但完全沒有文件。 如何在完全沒有文件的情況下在頁面中編寫程式碼? 新增解釋您的文檔 Terraform(強調「代碼」一詞),為什麼本節如此重要,以及您做什麼。

我們如何部署曾經是一大 main() 函數的服務?

我見過非常複雜的 Terraform 堆疊作為單一模組呈現。 我們為什麼不以這種方式部署軟體呢? 為什麼我們要把大函數拆分成更小的函數? 同樣的答案也適用於 Terraform。 如果您的模組太大,則需要將其分解為更小的模組。

你們公司不使用圖書館嗎?

我見過工程師如何使用 Terraform 啟動一個新項目,愚蠢地將其他項目的大量內容複製並貼上到自己的項目中,然後對其進行修改,直到它開始工作。 你會在你的公司裡這樣使用「戰鬥」代碼嗎? 我們不只是使用圖書館。 是的, 並非一切都必須是圖書館, 但是原則上如果沒有共享庫我們會怎麼樣呢?!

你沒有使用 PEP8 或 gofmt 嗎?

大多數語言都有一個標準的、可接受的格式方案。 在 Python 中,這是 PEP8。 在 Go 中 - gofmt。 Terraform 有自己的: terraform fmt。 為了您的健康,請享受它!

你會在不懂 JavaScript 的情況下使用 React 嗎?

Terraform 模組可以簡化您創建的複雜基礎架構的某些部分,但這並不意味著您根本無法對其進行修改。 想在不了解資源的情況下正確使用 Terraform? 你注定了:時間會過去,你永遠無法掌握 Terraform。

您使用單例還是依賴注入進行編碼?

依賴注入是公認的軟體開發最佳實踐,並且比單例更受青睞。 這在 Terraform 有何用處? 我見過依賴遠端狀態的 Terraform 模組。 不要寫檢索遠端狀態的模組,而是寫一個接受參數的模組。 然後將這些參數傳遞給模組。

您的圖書館在十件事上做得很好還是在一件事上做得很好?

效果最好的圖書館是那些專注於自己擅長的一項任務的圖書館。 不要編寫試圖同時完成所有事情的大型 Terraform 模組,而是建立其中只做好一件事的部分。 然後根據需要將它們組合起來。

如何在不向後相容的情況下對庫進行更改?

常見的 Terraform 模組與常規庫一樣,需要以某種方式向使用者傳達更改,而不需要向後相容。 當這些變更發生在庫中時,這很煩人,而且當 Terraform 模組中進行非向後相容的更改時,這也同樣令人煩人。 使用 Terraform 模組時建議使用 git tag 和 semver。

您的生產服務是在筆記型電腦上還是在資料中心中運作?

Hashicorp 有類似的工具 地形雲 運行你的地形。 這些集中式服務可以輕鬆管理、審核和批准 terraform 變更。

你不寫測驗嗎?

工程師意識到程式碼需要進行測試,但他們自己在使用 Terraform 時經常忘記測試。 對於基礎設施來說,這充滿了危險的時刻。 我的建議是使用可以在 CI/CD 期間正確部署進行測試的模組來「測試」或「建立範例」堆疊。

Terraform 和微服務

微服務公司的生死取決於新微服務工作堆疊的速度、創新和顛覆。

與微服務架構相關且無法消除的最常見的負面方面與工作有關,而不是與程式碼有關。 如果您認為 Terraform 只是一種僅自動化微服務架構的基礎架構方面的方法,那麼您就錯過了系統的真正優勢。 現在已經是 一切都像程式碼.

來源: www.habr.com

添加評論