iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0
自我挑戰組

Terraform 繁體中文系列 第 19

Day19-【入門教程】Terraform 命令行及命令列設定檔(.terraformrc或terraform.rc)

  • 分享至 

  • xImage
  •  

原簡體中文教程連結: Introduction.《Terraform入門教程》


1.6.1. Terraform 命令列

我們在前面的章節中主要介紹如何書寫和組織 Terraform程式碼,下面我們要介紹如何使用 Terraform命令列工具來應用這些程式碼,並且管理和操作我們的雲端基礎架構。

Terraform 是用 Go 語言寫的,所以它的交付物只有一個可執行命令列檔案:terraform。當 Terraform 執行發生錯誤時,terraform 進程會回傳一個非零值,所以在腳本程式碼中我們可以輕鬆判斷執行是否成功。

我們可以在命令列中輸入 terraform 來查看所有可用的子命令:

$ terraform
Usage: terraform [-version] [-help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    login              Obtain and save credentials for a remote host
    logout             Remove locally-stored credentials for a remote host
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    0.12upgrade        Rewrites pre-0.12 module source code for v0.12
    0.13upgrade        Rewrites pre-0.13 module source code for v0.13
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    push               Obsolete command for Terraform Enterprise legacy (v1)
    state              Advanced state management

1.6.1.1. 透過 -chdir 參數切換工作目錄

執行 Terraform 時一般要先切換目前工作目錄到包含想要執行的根模組程式碼 .tf 檔案的目錄下(例如使用 cd 指令),這樣 Terraform 才能夠自動發現要執行的程式碼檔案以及參數檔。

在某些情況下-尤其是將 Terraform 封裝進某些自動化腳本時,如果能夠從其他路徑直接執行特定路徑下的根模組程式碼將會十分的方便。為了達到這個目的,Terraform 目前支援一個全域參數 -chdir=... ,你可以在任意子指令的參數中使用該參數指定要執行的程式碼路徑:

$ terraform -chdir=environments/production apply

-chdir 參數指引 Terraform 在執行特定子指令之前切換工作目錄,這表示使用該參數後 Terraform 將會在指定路徑下讀寫文件,而非目前工作目錄下的文件。

在兩個場景下 Terraform 會堅持使用目前工作目錄而非指定的目錄,即使是我們透過 -chdir 指定了一個目標路徑:

  • Terraform 處理命令列設定檔中的設定而非執行某個特定的子指令時,此階段發生在解析 -chdir 參數之前
  • 如果你需要使用目前工作目錄下的檔案作為你配置的一部分時,你可以透過在程式碼中使用變數來 path.cwd 獲得對目前工作路徑的引用,而不是 -chdir 所指定的路徑。可以透過使用 path.root 來獲取代表根模組所在的路徑。

1.6.1.2. 自動補全

如果你使用的是 bash 或是 zsh,那麼可以輕鬆安裝自動補全:

$ terraform -install-autocomplete

卸載自動補全也很容易:

$ terraform -uninstall-autocomplete

目前自動補全並沒有覆蓋到所有子指令。

1.6.1.3. 版本信息

Terraform 命令列會與 HashiCorp 的 Checkpoint 服務互動來檢查目前版本是否有更新或是關鍵的安全公告。

可以透過執行 terraform version 指令來檢查是否有新版本可用。

1.6.1.4. Checkpoint服務

Terraform 會收集一些不涉及使用者識別資訊或是主機資訊的資料傳送給 Checkpoint 服務。一個匿名 ID 會被傳送到 Checkpoint 來消除重複的警告訊息。我們可以關閉與 Checkpoint 的互動。

我們可以設定 CHECKPOINT_DISABLE 環境變數的值為任意非空值來完全關閉 HashiCorp 所有產品與 Checkpoint 的交互作用。另外,我們也可以透過設定命令列設定檔來關閉這些功能:

  • disable_checkpoint:設定為 true 可以完全關閉與 Checkpoint 的交互
  • disable_checkpoint_signature:設定為 true 可以阻止向 Checkpoint 發送匿名 ID

1.6.1.1. 命令列設定檔(.terraformrc或terraform.rc)

命令列設定檔為每個使用者配置了命令列的行為,適用於所有的 Terraform 工作目錄,這與我們寫的 Terraform 程式碼是分開的。

1.6.1.1.1. 位置

設定檔的位置取決於使用者使用的作業系統:

  • Windows 平台上,檔案名稱必須是 terraform.rc,位置必須在相關使用者的 %APPDATA% 目錄下。這個目錄的實體路徑取決於 Windows 的版本以及系統配置;在 PowerShell 中查看 $env:APPDATA 可以找到對應的路徑
  • 在其他作業系統上,檔案名稱必須是 .terraformrc(注意第一個是 "."),位置必須是在相關使用者的 HOME 目錄

在 Windows 上建立設定檔時,請注意 Windows Explorer 預設隱藏檔案副檔名的行為。Terraform 不會把 terraform.rc.txt 檔案辨識為命令列設定文件,而預設情況下 Windows Explorer 會將它的檔案名稱顯示為terraform.rc(隱藏了副檔名的緣故)。可以在 PowerShell 或命令列中使用 dir 命令來確認檔案名稱。

可以透過設定 TF_CLI_CONFIG_FILE 環境變數的方式來修改設定檔的位置。

1.6.1.1.2. 設定檔語法

設定檔本身如同 .tf 檔一樣也採用 HCL 語法,但使用不同的屬性和區塊。以下是常見語法的演示,後續的部分會詳細介紹這些配置:

plugin_cache_dir   = "$HOME/.terraform.d/plugin-cache"
disable_checkpoint = true

1.6.1.1.3. 可用配置

命令列設定檔中可以設定的設定項有:

  • credentials:使用 Terraform Cloud 服務或 Terraform 企業版時使用的憑證
  • credentials_helper:設定一個外部的讀取與寫入 Terraform Cloud 或 Terraform 企業版憑證的幫助程序
  • disable_checkpoint:設定為 true 可以完全關閉與 Checkpoint 的交互
  • disable_checkpoint_signature:設定為 true 可以阻止向 Checkpoint 發送匿名 ID
  • plugin_cache_dir:開啟套件暫存,我們在介紹 Provider 的章節中介紹過
  • provider_installation:客製化執行 terraform init 時安裝外掛程式的行為

鑑於本教學無意涉及與 Terraform Cloud 或企業版相關的部分,所以我們會略過對 credentials 和 credentials_helper 的介紹;套件快取的相關知識我們在 Provider 章節中已做過介紹,在此先偷懶略過。有興趣的讀者可以自行查閱相關文件

1.6.1.1.4. Provider 的安裝

預設情況下 Terraform 從官方 Provider Registry 下載安裝 Provider 套件。Provider 在 Registry 中的原始位址採用類似的 registry.terraform.io/hashicorp/aws 編碼規則。通常為了簡單,Terraform 允許省略位址中的主機名稱部分 registry.terraform.io,所以我們可以直接使用位址 hashicorp/aws

有時無法直接從官方 Registry下載套件,例如我們要在一個與公網隔離的環境中執行 Terraform。為了讓 Terraform 工作在這樣的環境下,有一些可選方法可以讓我們從其他地方取得 Provider 外掛。

1.6.1.1.4.1. 明確安裝方法配置

可以在命令列設定檔中定義一個 provider_installation 區塊來修改 Terraform 預設的套件安裝行為,命令 Terraform 使用本地的 Registry 鏡像服務,或是使用一些使用者修改過的套件。

通常 provider_installation 塊的結構如下:

provider_installation {
  filesystem_mirror {
    path    = "/usr/share/terraform/providers"
    include = ["example.com/*/*"]
  }
  direct {
    exclude = ["example.com/*/*"]
  }
}

provider_installation 區塊中每一個內嵌區塊都指定了一種安裝方式。每一種安裝方式都可以同時包含 includeexclude 模式來指定安裝方式所使用的Provider類型。在上面的例子裡,我們把所有原先位於 example.com 這個 Registry 儲存中的 Provider 設定成只能從本機檔案系統的 /usr/share/terraform/providers 鏡像儲存中尋找並安裝,而其他的 Provider 只能從它們原先的 Registry 儲存下載安裝。

如果你同時為一種安裝方式設定了 includeexclude,那麼 exclude 模式將擁有更高的優先權。舉例:包含 registry.terraform.io/hashicorp/* 但排除 registry.terraform.io/hashicorp/dns 將對所有 hashicorp 空間下的套件有效,但是 hashicorp/dns 除外。

和 Terraform 程式碼檔案中 Provider 的 source 屬性一樣的是,在 provider_installation 裡你也可以省略 registry.terraform.io/ 的前綴,甚至是使用萬用字元時也是如此。例如, registry.terraform.io/hashicorp/*hashicorp/* 是等價的; */*registry.terraform.io/*/* 的縮寫,而不是**** */*/* 的縮寫。

目前支援的安裝方式如下:

  • direct:要求直接從原始的 Registry 服務下載。此方法不需要額外參數。
  • filesystem_mirror:一個本地存有 Provider 套件拷貝的目錄。此方法需要一個額外的參數 path 來指定存有套件拷貝的目錄路徑。Terraform 期待給定路徑的目錄內透過路徑來描述套件的一些元資訊。支援一下兩種目錄結構:
    • 打包式佈局:HOSTNAME/NAMESPACE/TYPE/terraform-provider-TYPE_VERSION_TARGET.zip 的格式指定了一個從原始 Registry 獲取的包含套件的發行 版zip 文件
    • 解壓縮式佈局:HOSTNAME/NAMESPACE/TYPE/VERSION/TARGET 式一個包含有 Provider 套件發行版 zip 檔案解壓縮後內容物的目錄這兩種佈局下,VERSION 都是代表著套件版本的字串,例如 2.0.0TARGET 則指定了套件發行版對應的目標平台,例如 darwin_amd64linux_armwindows_amd64 等等。

如果使用解壓縮式佈局,Terraform 在安裝外掛程式時會嘗試建立一個到鏡像目錄的符號連接來避免拷貝資料夾。打包式佈局則不會這樣做,因為 Terraform 必須在安裝外掛程式時解壓縮發行版檔案。

你可以指定多個 filesystem_mirror 區塊來指定多個不同的目錄。

  • network_mirror:指定一個 HTTPS 服務位址提供 Provider 外掛程式的拷貝,不論這些外掛程式原先屬於哪些 Registry 服務。此方法需要一個額外參數 url 來指定鏡像服務的位址,url 位址必須使用 https: 作為前綴,以斜線結尾。Terraform 期待該位址指定的服務實現了 Provider網路鏡像協議,這是一種被設計用來託管套件拷貝的網站所需要實現的協議,在此我們不展開討論。

需要特別注意的是,請不要使用不可信的 network_mirror 地址。Terraform 會驗證鏡像網站的 TLS 憑證以確認身份,但一個擁有合法 TLS 憑證的鏡像站可能會提供包含惡意內容的套件檔案。

  • dev_overrides:指定使用本地的開發版本外掛程式。有時我們想要對 Provider 程式碼做一些修改,為了調試本地程式碼編譯後的套件,可以使用 dev_overrides 指定使用本地編譯的版本。

例如,我們想要調試本地修改過的 UCloud Provider 套件,我們可以從 github 上複製該專案原始碼,修改完程式碼後,編譯一個可執行版本(以 Mac OS 為例):

$ GOOS=darwin GOARCH=arm64 go build -o bin/terraform-provider-ucloud
$ chmod +x bin/terraform-provider-ucloud

然後寫出如下 provider_installation 配置:

provider_installation{
  dev_overrides {
    "ucloud/ucloud" = "PATH_TO_PROJECT/terraform-provider-ucloud/"
  }
}

當 Terraform 程式碼中要求了 sourceucloud/ucloud 的 Provider 時,執行 terraform init 仍然會報錯,抱怨找不到 ucloud/ucloud 這個 Provider,但執行 terraform plan 或是 terraform apply 等操作時可以順利執行,此時 Terraform 會使用路徑指定的本地 Provider 套件。這種方式比較適合用來調試本地 Provider 套件程式碼。

對於上述的幾種外掛安裝方式,Terraform 會嘗試透過 includeexclude 模式來搭配 Provider,遍歷相符的安裝方式,選擇符合 Terraform 程式碼中對外掛程式版本約束的最新版本。如果你擁有一個套件的特定版本的本機鏡像,並且你希望 Terraform 只使用這個本地鏡像,那麼你需要移除安裝方式 direct,或是在 direct 中透過 exclude 參數排除特定的 Provider。

1.6.1.1.5. 隱式的本地鏡像目錄

如果命令列設定檔中沒有包含 provider_installation 區塊,那麼 Terraform 會產生一個隱式的設定。此隱式配置包含了一個 filesystem_mirror 方法以及一個 direct 方法。

在不同的作業系統上,Terraform 會選擇不同的路徑作為隱式 filesystem_mirror 路徑:

  • Windows:%APPDATA%/terraform.d/plugins 以及 %APPDATA%/HashiCorp/Terraform/plugins
  • Mac OS X:$HOME/.terraform.d/plugins/~/Library/Application Support/io.terraform/plugins 以及 /Library/Application Support/io.terraform/plugins
  • Linux 以及其他 Unix 風格系統:$HOME/.terraform.d/plugins/,以及配置的 XDG 基礎目錄後接 terraform/plugins。如果沒有設定 XDG 環境變量,Terraform 會使用 ~/.local/share/terraform/plugins/usr/local/share/terraform/plugins,以及 /usr/share/terraform/plugins

Terraform 會在啟動時為上述路徑的每一個目錄建立一個隱式 filesystem_mirror 區塊。另外如果目前工作目錄下包含有 terraform.d/plugins 目錄,那麼也會為它建立一個隱式 filesystem_mirror 區塊。

相對於任意多個隱式 filesystem_mirror 區塊,Terraform 同時也會建立一個隱式 direct 區塊。Terraform 會掃描所有檔案系統鏡像目錄,對找到的 Provider 自動從 direct 區塊中排除出去(這種自動的 exclude 行為只對隱式 direct 區塊有效。如果你在 provider_installation 區塊中明確指定了 direct 區塊,那麼你需要自己明確定義 exclude 規則)。


原簡體中文教程連結: Introduction.《Terraform入門教程》


上一篇
Day18-【入門教程】設計新模組的模式
下一篇
Day20-【入門教程】環境變數及資源地址
系列文
Terraform 繁體中文25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言