Seal AppManager如何基於Terraform簡化基礎設施管理

2023-07-17 12:00:34

作者簡介

陳燦,數澈軟體Seal 後端研發工程師,曾在騰訊負責敏捷研發體系建設以及 DevOps 解決方案的敏捷實踐。在敏捷研發和產品效能提升有著豐富的經驗,致力於構建一站式研發友好的平臺工程解決方案。現在是 Seal 平臺工程團隊核心研發人員。

 

平臺工程(Platform Engineering)是近幾年大火的技術概念,指專注於通過減少現代軟體交付的複雜性和不確定性來提高開發人員的生產力的一種軟體工程方法。內部開發平臺則是平臺工程的具體實現之一。本文將結合平臺工程的理念介紹 Terraform 的基本概念和使用方法,包括在使用 Terraform 的過程中所面臨的一些挑戰以及 Seal AppManager 是如何解決這些問題的。
 

什麼是內部開發者平臺(IDP)

內部開發平臺, Internal Development Platform(IDP),是建立在工程團隊現有技術工具之上的一個自助服務層。IDP 是一個由平臺團隊開發的平臺,使開發人員能夠輕鬆地設定、部署和啟動應用基礎設施,無需依賴運維團隊。IDP 有助於進一步自動化運維工作流程,並通過簡化應用程式設定和基礎設施管理來彌補和提升工作效率。同時,IDP 讓開發人員擁有更多的自主權,使開發人員從編寫程式碼到軟體交付,都能夠處理自如。
 

在傳統的基礎設施部署和管理中,通常會使用手動設定和管理的方式。這意味著管理員需要手動操作伺服器、網路裝置和儲存等基礎設施元件,安裝和設定軟體,以及處理各種依賴關係和環境變化。這種方式需要花費大量的時間和精力,並且容易出現設定錯誤和不一致性。
 


 

平臺工程的首要任務之一是降低開發人員使用基礎設施的難度。因為絕大多數的開發人員並不關心底層服務的複雜概念和建立方式,比如開發需要用儲存服務,但不關心它們是如何建立的,再如一些專有名詞如物件儲存、磁碟陣列等,也不屬於開發人員的關心範疇。
 

在大多數的業務場景中,開發人員只關注如何使用這些服務、資料是否可以持久化地儲存在指定目錄中。因此,平臺工程完全可以提供一個適應大多數場景的儲存服務,開發人員只需要選擇自己所需要的服務型別,利用平臺工程的能力建立服務,獲取服務的地址,即可使用該服務。
 

平臺工程通過抽象定義,在服務的基礎上抽象出應用這一概念,多個應用可以組合成一個業務場景,應用之間存在顯式或者隱式的關係。彼此之間通過這種關係有機地組合成一個完整的業務整體,並對外提供服務。
 


 

什麼是 Terraform

Terraform 是一個基礎設施即程式碼(IaC)工具,它允許你安全、高效地構建、改變和更新基礎設施。這包括低階別的元件,如計算範例、儲存和網路,以及高階別的元件,如 DNS 條目、SaaS 功能等。
 

在 Terraform 誕生之前,基礎設施的管理是一個非常繁瑣的工作,需要人工操作,而且易出錯,而 Terraform 的出現,讓基礎設施的管理變得簡單、高效、可靠。Terraform 特別適合雲環境:AWS、GCP、Azure、阿里雲等, 通過豐富的 Provider 管理不同型別的資源,一切都像外掛一樣,可以輕鬆地擴充套件。
 

Terraform 採用 HCL 程式碼管理和維護基礎設施資源,並且在執行之前可以通過terraform plan命令可以看到資源的變化,而這些變化是通過 Terraform 的狀態檔案來管理的。
 

Terraform 的 State(狀態)是一個關鍵概念,用於記錄當前基礎設施的狀態和設定。使用 Terraform 進行部署時,它會跟蹤已建立的資源和其設定狀態,並將其儲存在原生的.tfstate檔案中或使用遠端儲存(如AWS S3、Azure Blob儲存)進行管理。
 

State 檔案記錄了資源的狀態,當資源發生變化時,設定狀態也會變化。因此,Terraform 支援在部署前預覽資源變化而不需要真正的執行。Terrafrom 的設定狀態檔案可以儲存在本地,也支援儲存在遠端的儲存中,如:S3、Consul、gcs、kubernetes 或者其他自定義的 HTTP Backend 中。
 

 

安裝 Terraform

 

macOS
 

brew tap hashicorp/tap
brew install hashicorp/tap/terraform

 

Linux Ubuntu
 

wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform

 

Linux CentOS
 

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install terraform

 

Linux 二進位制安裝
 
Linux 使用者也可以通過二進位制的方式安裝 Terraform,從官方下載對應的版本。

https://www.terraform.io/downloads.html
 

通過二進位制安裝 1.4.6 版本的 Terraform:
 

curl -sfL https://releases.hashicorp.com/terraform/1.4.6/terraform_1.4.6_linux_amd64.zip -o /tmp/terraform.zip
unzip /tmp/terraform.zip -d /usr/bin/
rm -f /tmp/terraform.zip

 

Windows
 

windows 使用者可以通過 Chocolatey 來安裝 Terraform, Chocolatey 是一個 Windows 的包管理器,類似於 Linux 的 yum 或者 apt-get,它可以幫助你快速的安裝和解除安裝軟體。
 

choco install terraform

 

或者去 Terraform 官網下載對應的版本,然後解壓後設定 PATH 環境變數。最後,通過terraform version命令來驗證是否安裝成功。
 

Terraform 管理 Kubernetes 資源範例

設定 Kubernetes Provider,通過後~/.kube/config檔案來管理 Kubernetes 資源,這裡也可以使用其他的 kubeconfig 檔案。
 

provider "kubernetes" {
  config_path = "~/.kube/config"
}

 

建立一個 Kubernetes Deployment
 

resource "kubernetes_deployment" "nginx" {
  metadata {
    name = "nginx"
    labels = {
      app = "nginx"
    }
  }

  spec {
    replicas = 1

    selector {
      match_labels = {
        app = "nginx"
      }
    }

    template {
      metadata {
        labels = {
          app = "nginx"
        }
      }

      spec {
        container {
          image = "nginx:latest"
          name = "nginx"
          port {
            container_port = 80
          }
        }
      }
    }
  }
}

 

Kubernetes Deployment 服務
 

resource "kubernetes_service" "nginx" {
  metadata {
    name = "nginx"
  }

  spec {
    selector = {
      app = kubernetes_deployment.nginx.metadata[0].labels.app
    }

    type = "NodePort"

    port {
      port = 80
      target_port = 80
      node_port = 30080
    }
  }
}

 

將上面的設定複製並在目標目錄如~/terraform-demo
 

mkdir ~/terraform-demo && cd ~/terraform-demo

 

建立 main.tf 檔案,將上述設定複製到 main.tf 並儲存,完整的檔案設定如下:
 


 

開啟終端,進入到目標目錄,初始化 Terraform 環境

cd ~/terraform-demo && terraform init

 

 

執行terraform plan來預覽資源的變化
 


 

執行terraform apply來建立資源
 


 

最後在瀏覽器中存取http://localhost:30080即可看到 nginx 的歡迎頁面。
 


 

如果想要刪除資源,可以執行terraform destroy命令來刪除資源。
 

通過上述例子,我們可以看到 Terraform 的管理 Kubernetes 資源非常簡單,只需要通過 HCL 語言來描述資源的設定,然後通過terraform apply來建立資源。此外 Terraform 還支援通過terraform import來匯入已經存在的資源,這樣就可以將已經存在的資源納入到 Terraform 的中進行管理。
 

Terraform 狀態管理

Terraform 通過 HCL 描繪了資源的設定,但它如何知道資源是否已經被建立了呢?資源的新增、修改和刪除是如何決定的?它怎樣管理資源之間的依賴關係呢?要了解這些問題,就得依賴 Terraform 的狀態管理機制了。
 

Terraform 將每次執行基礎設施變更操作時的狀態資訊儲存在一個狀態(State)檔案中,預設情況下會儲存在當前工作目錄下的terraform.tfstate檔案裡,依託於狀態檔案來決定執行資源的變更方式。
 

在上述範例中,可以看到生成的狀態(State) 檔案中包含所建立的資源,如kubernetes_deploymentkubernetes_service,這與我們編寫 HCL 檔案的資源也是相對應的,我們所建立的 resource 和 data 資源都會被記錄到這個檔案。
 

狀態(State) 檔案中還包含了一些後設資料資訊,如資源的 ID、資源的屬性值等,這些資訊都是 Terraform 用來管理資源的重要依據。
 


 

我們知道獲取雲資源狀態常見的方式之一是通過各個平臺自身提供的 API 服務來獲取,比較 API 資源和組態檔資源的異同來決定建立或者刪除資源,而 Terraform 卻選擇狀態(State)檔案來管理對映雲平臺的資源,而不是API 的方式來檢查資源是否已經被建立,原因是什麼呢?
 

Terraform 採取狀態(State)檔案的方式的好處有:
 

  1. Terraform 可以直接通過該檔案獲取建立的雲資源狀態。對於小型基礎設施,Terraform 可以查詢並同步所有資源的最新屬性,這樣在每次 apply 的時候只需要檢查資源和狀態檔案的設定是否一致。如果一致則不需要做任何操作,如果不一致則需要建立、更新或者刪除資源。

  2. 通過狀態檔案可以記錄不同資源之間的關係,Terraform 可以通過依賴關係來管理建立或者銷燬的順序。

  3. 另外,對於大型基礎設施,查詢每個資源的耗時會較長。許多雲提供商不提供同時查詢多個資源的 API,每個資源的往返時間為數百毫秒。除此之外,雲提供商幾乎總是有 API 速率限制,因此 Terraform 在一段時間內只能請求一定數量的資源,通過 state 狀態管理可以大大提升效能。

  4. 遠端的 Backend 可以管理狀態檔案,這樣可以實現多人共同作業,多人共用同一個狀態檔案。
     

然而,採用這種方式管理資源並非十全十美,當執行terraform apply時,Terraform 會直接讀取 State 檔案來判斷是否需要建立、更新或者刪除資源。如果我們手動刪除這個檔案,再次執行terraform apply時,Terraform 會認為這是一個全新的環境,從而會重新建立所有的資源,進而導致資源的管控混亂——原先建立的資源就再也沒法通過terraform destroy來刪除了。因此妥善保管好這個狀態檔案非常重要,任何時候都不要手動修改或者刪除這個檔案。
 

細心的你可能會發現,狀態(State)檔案中的所有資訊都是明文的,這意味著如果這個檔案洩露,裡面包含密碼等關鍵資訊都會被洩露,這將會對你的基礎設施造成巨大的安全風險。除此之外,如果因裝置損壞或者其他因素導致檔案損壞,那麼 tfstate 所記錄的資源資訊也會丟失,這樣也會導致資源的洩露、管控混亂。
 

因此,Terraform 還提供了一種 Backend 的狀態管理方案。這樣就可以將狀態檔案儲存在遠端的儲存中,比如 AWS S3、GCS、HTTP 等,這樣就可以避免狀態檔案被洩露的風險。團隊成員之間可以利用 Backend 解決檔案儲存和共用的問題。
 

使用 Terraform 所面臨的挑戰

通過上面的範例,我們可以看到 Terraform 管理 Kubernetes 資源非常簡單,但是正如前文中提到過的 Terraform 也存在一些問題,這些問題可能會影響到我們對資源管理的使用體驗。比如:
 

  • 使用 HCL 語言來描述資源的設定,意味著開發人員需要學習一門新的語言,而且如果想要使用 Terraform 來管理其他資源,比如 AWS、GCP 等,那麼就需要學習這些資源的 Provider 的設定,導致學習成本增加。另外一些語法問題也會增加使用的難度。

  • 狀態管理問題,Terraform 通過狀態檔案來管理資源,而狀態檔案所記錄的資源都是明文的。如果狀態檔案遭受洩露、損壞等情況,會對資源的管控造成巨大的風險。

  • 基礎設施資源管理者需要擁有對資源的知識經驗,這樣才能夠正確的設定資源,否則就會導致資源的設定錯誤導致資源的建立失敗,或者資源的設定不符合預期。

  • 大量的資源管控需要編寫大量的 HCL 檔案,資源的使用者需要花費大量的時間來查詢資源和組態檔,管理資源的成本也會隨著資源的增加而增加。

  • 資源的狀態不能實時獲取,如 Kubernetes 的資源狀態,檢視紀錄檔和執行終端等等,這些需要通過其他的方式管理。
     

利用 Seal AppManager 降低管理基礎設施難度

Seal AppManager 是一款基於平臺工程理念的應用部署管理平臺,底層基於 Terraform 技術構建,上週剛剛釋出新版本。它可以幫助開發人員和運維快速地搭建一個生產或者測試環境,同時也可以幫助運維人員快速地管理這些環境,通過平臺工程的能力解決上述問題。
 

Seal AppManager 可以將資源抽象成服務,利用應用來控制這些服務,進而將資源的底層設定和實際使用分離開,簡化基礎設施的管理。
 

通過管理多個環境和設定的方法,確保開發、測試和生產環境的一致性,降低錯誤和不一致的風險,並確保應用程式始終準確執行。
 

由於平臺提供控制和治理功能,開發人員還可以確保所使用的環境是安全的,並且符合最佳實踐和安全標準。資源的使用者只需要關注資源的使用,而不需要關注資源的底層原理及設定。
 


 

通過定義的資源模版,開發人員無需再關注 HCL 語言的語法,Terraform Provider 引數該如何設定以及基礎設施的底層實現是什麼原理,只需要通過平臺提供的 UI 介面,通過定義好的模組填寫引數就可以自助使用資源。這大大降低了開發人員使用資源的難度,提升了整體的開發效率。
 

除此之外,Terraform 的狀態管理的不便之處也得到了解決。Seal AppManager 平臺通過將狀態檔案儲存在 HTTP Backend 遠端,這樣就可以避免狀態檔案被洩露的風險。不同的服務之間會自動管理所屬的狀態,這樣團隊成員之間可以利用 Backend 解決狀態儲存和共用的問題。