Categories
程式開發

為什麼 Terraform 可以用於多雲遷移?


最近我們的項目經理問了我一個直擊靈魂的問題:為什麼 Terraform 可以用於多雲遷移?

我差點脫口而出:那顯然是因為 …

因為啥呢?我突然意識到,這個問題的答案可能一點也不顯然,我默默的在心裡想了一個晚上,於是有了這篇文章。

什麼是多雲遷移

一般情況下,多雲遷移是指將整個業務系統的拓撲從一朵雲遷移到另外一朵雲上,包含基礎設施、應用,以及圍繞著基礎設施與應用的一整套工作流。

什麼時候會進行多雲遷移呢?例如你想從私有云遷移到公有云、想從一家云商遷移到另一家云商就是一個典型的多雲遷移場景。並且「在同一家云商創建一個災備集群」本質上也是這個場景的一種特例。

為什麼 Terraform 可以用於多雲遷移? 1

圖 1 使用 Terraform 進行拓撲發現

從頂層的視角來看,我們常說的多雲遷移其實是包括基礎設施的拓撲、網絡的拓撲以及應用的拓撲這三種拓撲關係的遷移。也就是說在遷移前後,我們要盡可能保證資源之間的關係,網絡之間的連通性,應用之間的調用關係和方式不發生變化。那麼 Terraform 在這裡可以扮演什麼角色呢?

什麼是 Terraform

首先來看,什麼是 Terraform?引用一段對 Terraform 的描述:

Terraform 是 Hashicorp 公司開源的一種多雲資源編排工具。使用者通過一種特定的配置語言(HCL, Hashicorp Configuration Language)來描述基礎設施,由Terraform 工具統一解析,構建資源之間的關係,生成執行計劃,並通過調用各家云廠商的具體實現來完成整個基礎設施生命週期的管理。

簡而言之就是用一種特殊的文本格式來描述基礎設施,之後對基礎設施進行 CRUD 的一種工具。

在生產環境實際的使用中,我們觀察到,大家非常喜歡把它當作一個命令行工具創建資源,不用擔心失敗,重試操作是冪等的,極為省心。這其實是一種極端的用法,在這種模式下,它相比手寫一個腳本或者串聯一些 Ansible Module 封裝成 Playbook,只是減少了一些工作量,實際上並沒有什麼不同。

而 Terraform 相比其它的工具來說,如何可以更適用於多雲遷移呢?

資源依賴圖

可能大家一看到標題,就知道我接下來要說什麼了。是的,Terraform 基於 DAG(有向無環圖),可以嚴格描述資源之間的拓撲關係。這也是它跟其他的工具最本質和最直觀的區別。多雲遷移時,如果想去映射資源與資源之間的拓撲,首先必須可以拿到一張完整的拓撲,Terraform 可以以極低的成本拿到它。

為什麼 Terraform 可以用於多雲遷移? 2

圖 2 Terraform 狀態文件示例

首先Terraform 將所有信息都存儲在一個狀態文件中,這個狀態文件中描述了完整的資源拓撲關係,社區也有一些可視化工具來讀取它(雖然並不是非常完備,參考Blast Radius),但對於自動化工具來說,這個帶有依賴關係的數據文件是後面一切工作的基石。

其次 Terraform 支持“導入已經存在的資源”這一能力,Google 牽頭的 Terraformer 項目更是加速了這一工程,可以一鍵導入一家云廠商存量資源的結構。並且 Terraform 對接了幾乎所有主流雲廠商的 API,省去了一個一個適配雲廠商 API 的成本。

最後 這個拓撲結構甚至是可以更新的!這一點至關重要,因為往往一個多雲遷移的項目往往跨越幾個月的時光,不能及時更新的拓撲,往往會產生災難性的後果。 Terraform 本身對於讀操作的冪等處理,使得重複導入是一個安全的過程,只需要妥善處理資源的 name 和 id,相同資源導入即刷新,就可以不斷更新這個拓撲的狀態。

不斷變化的網絡

在上一步我們已經拿到了一張完整的資源拓撲,也許我們已經做好了跨雲的資源映射,這個時候的網絡有兩種可能的情況:

1.我們通過新的集群虛擬網絡內的靜態 IP,幾乎完美復制了一套網絡拓撲過來,任何實例的內網 IP 都沒有變,以前的程序還能繼續用,Awesome!

2.我們沒有固定 IP,應用之間的連接通過名字服務還能用,但是我要通過腳本下發控制指令,怎麼辦!

第一反應是查 CMDB,但是 CMDB 還沒對接這朵雲怎麼辦?研發那邊已經催著我改文件描述符上限了,在線等,急!

Don’t Panic,Terraform 的狀態文件也可以作為CMDB 的基準,可以簡單粗暴地寫一個腳本,從狀態文件中讀取IP 等信息輸出Ansible dynamic inventory,如下圖這樣自定義分組,將Terraform 狀態直接當作Ansible inventory 使用(可參考terraform-inventory 項目)。但對於大多數業務來說,針對自身業務定制一個腳本也許是更好的選擇。

為什麼 Terraform 可以用於多雲遷移? 3

圖 3 Ansible 集成示例

在這個簡單的示例中,基於的一個事實是,在上一步我們拿到的資源拓撲是嚴格的,並且是可以更新的,我們才可以基於它拿到信息去做二次處理。

應用遷移

目前看來,Terraform 的定位是基礎設施編排,應用編排暫時不在此列,對於應用的遷移,Terraform 能做的有限,這裡也分為兩種情況:

為什麼 Terraform 可以用於多雲遷移? 3

圖 4 容器應用交付示意圖

第一種是應用已經在 K8S 上的,直接由 K8S 接管,Terraform 只負責拉起一個 K8S 集群即可,例如 TiDB Operator 項目,由於容器化的應用本身是跨平台的,可以完美遷移過來。

這裡不得不重點提及一個項目:Pulumi,它是新一代面向資源的多雲 SDK,類似於 AWS 的 CDK。 Pulumi 對於跨雲基礎設施編排的做法是,在Terraform 和Pulumi 之間架設了一個橋,直接將Terraform 的Schema 轉換成原生編程語言的Pulumi SDK,在運行時喚醒Terraform Provider 並通過RPC 來調用它完成基礎設施編排,巧妙地避免了與社區割裂。

Pulumi 在此基礎上增加了 Crosswalk 子項目,用於跟其他的編排引擎如 K8S 集成,既可以編排容器和基礎設施,也可以將應用代碼 Serverless 化,打破了基礎設施和應用編排的邊界。

Pulumi 作為 Terraform 與 Native Language 之間的一座橋樑,對於非常高階的用法,例如要在基礎設施與應用層中間做各種策略,可以考慮使用 Pulumi 來進行二次開發。

為什麼 Terraform 可以用於多雲遷移? 5

圖 5 傳統應用交付示意圖

第二種是應用不在 K8S 上的,也需要分兩種情況:

1.如果策略不復雜,可以考慮使用 Packer 打包系統鏡像,將應用以系統鏡像的形式交付,Terraform 僅用於完成“最後一公里”的計算資源拉起環節。或者在這一環節完全捨棄 Terraform。

2.如果策略很複雜,Terraform 能做的非常有限,最好加一個控制器層,用來分發鏡像和做一些複雜的邏輯等,或者使用一些成熟的抽象層,如基於Packer 做多雲發布的Spinnaker等工具,可以整合跨多雲的發布管道,這裡就不展開了。

讓我們回過頭來看這些應用編排相關的工具與技術,其實並不一定限定於一定要使用哪個,比如Spinnaker 一樣可以用於K8S、Pulumi 也一樣可以用於雲主機,只是Terraform 的定位在這裡不同。 Terraform 本身專注於基礎設施編排,對於擁有復雜策略和實時工作負載的應用編排,並不適合完全使用Terraform 來編寫,但可以藉助於Terraform 的生態整合能力去複用社區的力量,取得成本和收益的更好平衡。

總結

綜上所述,Terraform 可以用於多雲遷移的關鍵在於,它可以描述資源之間的拓撲關係,開箱即用,適配多雲 API。對於應用的遷移,Terraform 能做的有限,但可以作為生態內其他工具的基準,因地制宜,復用其它優秀工具的力量。

可以看到,在介紹多雲遷移的時候,有很多其他工具的身影,比如 Ansible、Pulumi、Spinnaker 等。我很欣喜地意識到,隨著雲資源、應用、甚至是安全合規的代碼化,基礎設施相關的工具鏈已經到了百花齊放的時期。這是最好的時代,希望我們一起前行!