iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0
自我挑戰組

Terraform 繁體中文系列 第 22

Day22-【入門教程】graph, import, init, output, plan

  • 分享至 

  • xImage
  •  

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


1.6.10.1. graph

terraform graph 指令可以用來產生程式碼描述的基礎架構或是執行計畫的視覺化圖形。它的輸出是 DOT 格式,可以使用 GraphViz 來產生圖片,也有許多網路服務可以讀取這種格式。

1.6.10.1.1. 用法

terraform graph [options] [DIR]

此指令產生 DIR 路徑下的程式碼鎖定所描述的 Terraform 資源的可視化依賴圖(如果 DIR 參數缺省則使用目前工作目錄)

-type 參數被用來指定輸出的圖表的類型。Terraform 為不同的操作創建不同的圖形。對於代碼文件,預設類型為 "plan",對於變更計劃文件,預設類型為 "apply"。

參數:

  • -draw-cycles:用彩色的邊高亮圖中的環,這可以幫助我們分析程式碼中的環錯誤(Terraform 禁止環狀依賴)
  • -type=plan:產生圖表的類型。可以是:planplan-destroyapplyvalidateinputrefresh

1.6.10.1.2. 建立圖片文件

terraform graph 指令輸出的是 DOT 格式的數據,可以輕鬆使用 GraphViz 轉換為圖形檔:

$ terraform graph | dot -Tsvg > graph.svg

輸出的圖片大概是這樣的:
產生的依賴圖
圖1.6.10/1 - 產生的依賴圖

1.6.10.1.3. 如何安裝GraphViz

安裝 GraphViz 也很簡單,對於 Ubuntu:

$ sudo apt install graphviz

對於 CentOS:

$ sudo yum install graphviz

對於 Windows,也可以使用 choco:

> choco install graphviz
> 

針對 Mac 用戶:

$ brew install graphviz

1.6.11.1. import

terraform import 指令用來將已經存在的資源物件匯入 Terraform。

我們並不總是那麼幸運,能夠在專案一開始就使用 Terraform 來建置和管理我們的基礎設施;有時我們有一組已經運行的基礎設施資源,然後我們為它們編寫了相應的 Terraform 程式碼,我們進行了測試,確認了這組程式碼描述的基礎設施與目前正在使用的基礎設施是等價的;但是我們仍然無法直接使用這套程式碼來管理現有的基礎設施,因為我們缺乏了相應的狀態文件。這時我們需要使用 terraform import 將資源物件「匯入」到 Terraform 狀態檔案中去。

1.6.11.1.1. 用法

terraform import [options] ADDRESS ID

terraform import 會根據資源 ID 找到對應資源,並將其資訊匯入狀態檔案中 ADDRESS 對應的資源。ADDRESS 必須符合我們在資源位址中所描述的合法資源位址格式,這樣 terraform import 不但可以把資源匯入到根模組中,也可以匯入到子模組中。

ID 取決於被匯入的資源物件的類型。舉例來說,AWS 主機的 ID 格式類似 i-abcd1234,而 AWS Route53 Zone 的 ID 類似 Z12ABC4UGMOZ2N,請參考相關 Provider 文件來取得有關 ID 的詳細資訊。如果不確信的話,可以隨便嘗試任意 ID。如果 ID 不合法,你會收到一個報錯。

需要特別注意的是,Terraform 設想的是每個資源對像都僅對應一個獨一無二的實際基礎設施對象,通常來說如果我們完全使用 Terraform 創建並管理基礎設施時這一點不是問題;但如果你是通過導入的方式把基礎設施物件匯入到 Terraform 裡,要絕對避免將同一個物件匯入到兩個以及更多不同的位址上,這會導致 Terraform 產生不可預測的行為。

此指令有以下參數可以使用:

  • -backup=path:產生狀態備份檔案的位址,預設為 -state-out 路徑加上 ".backup" 後綴名。設定為 "-" 可以關閉備份(不建議)
  • -config=path:包含含有導入目標的 Terraform 程式碼的資料夾路徑。預設為目前工作目錄
  • -input=true:是否允許提示輸入 Provider 設定訊息
  • -lock=true:如果 Backend 支持,是否鎖定狀態文件
  • -lock-timeout=0s:重試取得狀態鎖定的間隔
  • -no-color:如果指定,則不會輸出彩色訊息
  • -parallelism=n:限制 Terraform 遍歷圖的最大並行度,預設值為 10(又是考點)
  • -state=path:要讀取的狀態檔案的位址。預設為配置的Backend儲存位址,或是 "terraform.tfstate" 文件
  • -state-out=path:指定修改後的狀態檔案的儲存路徑,預設會覆寫來源狀態檔案。使用此參數可以產生新的狀態文件,避免破壞現有狀態文件
  • -var 'foo=bar':透過命令列設定輸入變數值,類似 apply 指令中的介紹
  • -var-file=foo:類似 apply 指令中的介紹

1.6.11.1.2. Provider配置

Terraform 會嘗試讀取要匯入的資源對應的 Provider 的設定資訊。如果找不到相關 Provider 的配置,那麼 Terraform 會提示你輸入相關的存取憑證。你也可以透過環境變數來設定存取憑證。

Terraform 在讀取 Provider 配置時唯一的限制是不能依賴"非輸入變數"的輸入。舉例來說,Provider 配置不能依賴資料來源的輸出。

舉一個例子,如果你想要導入 AWS 資源而你有這樣的一份程式碼文件,那麼 Terraform 會使用這兩個輸入變數來配置 AWS Provier:

variable "access_key" {}
variable "secret_key" {}

provider "aws" {
  access_key = var.access_key
  secret_key = var.secret_key
}

1.6.11.1.3. 例子

$ terraform import aws_instance.foo i-abcd1234
$ terraform import module.foo.aws_instance.bar i-abcd1234
$ terraform import 'aws_instance.baz[0]' i-abcd1234
$ terraform import 'aws_instance.baz["example"]' i-abcd1234

上面這條指令如果是在 PowerShell 下:

$ terraform import 'aws_instance.baz[\"example\"]' i-abcd1234

如果是cmd:

$ terraform import aws_instance.baz[\"example\"] i-abcd1234

1.6.12.1. init

terraform init 指令被用來初始化一個包含 Terraform 程式碼的工作目錄。在編寫了一些 Terraform 程式碼或克隆了一個 Terraform 專案後應先執行該指令。重複執行該指令是安全的(考點)。

1.6.12.1.1. 用法

terraform init [options] [DIR]

此指令為初始化工作目錄執行了多個不同的步驟。詳細說明可以見下文,整體來說用戶不需要擔心這些步驟。即使某些步驟可能會遭遇錯誤,但該指令絕對不會刪除你的基礎架構資源或是狀態檔。

如果不傳入任何參數,那麼命令會初始化目前工作目錄。我們推薦不使用 DIR 參數,直接在根模組的目錄下執行該指令。

1.6.12.1.2. 常用參數

  • -input=true:是否在取不到輸入變數值時提示使用者輸入
  • -lock=false:是否在執行時鎖定狀態文件
  • -lock-timeout=\:嘗試取得狀態檔案鎖定時的逾時時間,預設為 0,意為一旦發現鎖定已被其他進程取得立即報錯
  • -no-color:禁止輸出包含顏色
  • -upgrade:是否升級模組程式碼以及插件

1.6.12.1.3. 從模組源拷貝模組

預設情況下,terraform init 會認為工作目錄下已經包含了 Terraform 程式碼檔案。

init 配合 -from-module=MODULE-SOURCE 參數在一個空目錄下執行,這將會在運行其他任何步驟之前先把相關模組複製到目標資料夾下。

這種特殊的使用方式有兩種場景:

  • 對於 source 對應的版本控制系統,我們可以用這種方法簽出指定版本程式碼並為它初始化工作目錄
  • 如果模組來源指向的是一個範例項目,那麼這種方式可以把範例程式碼拷貝到本地目錄以便我們後續基於範例編寫新的程式碼

如果是常規運作操作我們建議用獨立的步驟從版本控制系統簽出程式碼,使用版本控制系統所屬的工具。

1.6.12.1.4. Backend 初始化

在執行 init 時,會分析根模組程式碼以尋找 Backend 配置,然後使用給定的配置設定初始化 Backend 儲存。

在已經初始化 Backend 後重複執行 init 指令會更新工作目錄以使用新的 Backend 設定。取決於改變的內容,init 可能會提示使用者是否確認進行狀態遷移(我們在狀態管理章節中有所介紹)。-force-copy 參數跳過了提示,直接確認遷移狀態。-reconfigure 參數則使得 init 不理會任何現有配置,防止任何狀態遷移。

要跳過 Backend 配置,可以使用 -backend=false。注意某些其他 init 步驟需要已經被初始化的 Backend,所以建議只在已經初始化過 Backend 後才使用該參數。

-backend-config 參數可以用來動態指定 Backend 配置,我們在狀態管理章節中介紹「部分配置」時已經提過,在此不再贅述。

1.6.12.1.5. 初始化子模組

init 會搜尋 module 塊,然後透過 source 參數取回模組程式碼。

模組安裝之後重新執行 init 指令會繼續安裝那些自從上次 init 之後新增的模組,但不會修改已被安裝的模組。使用 -upgrade 可以改變這種行為,將所有模組升級到最新版本的程式碼。

若要跳過子模組安裝步驟,可以使用 -get=false 參數。要注意其他一些 init 步驟需要模組樹完整,所以建議只在成功安裝過模組以後使用該參數。

1.6.12.1.6. 插件安裝

我們在 Provider 章節中介紹了插件安裝,所以在此不再贅述,我們值介紹一下參數:

  • -upgrade:將先前所有已安裝的插件升級到符合 version 約束的最新版本。此參數對手動安裝的插件無效
  • -get-plugins=false:跳過插件安裝。Terraform 會使用已安裝在目前工作目錄下方或是外掛程式快取路徑中的外掛程式。如果這些插件不足以覆蓋需求,那麼 init 會失敗
  • -plugin-dir=PATH:跳過插件安裝,只從指定目錄載入插件。此參數會跳過使用者插件目錄以及所有目前工作目錄下的插件。若要在使用過此參數後恢復預設行為,請使用 -plugin-dir="" 參數重新執行 init。
  • -verify-plugins=false:在下載外掛後跳過驗證簽章(不建議)。官方外掛都會經 HashiCorp 簽名,Terraform 會驗證這些簽名。可以使用此參數跳過簽章驗證(Terraform 不會驗證手動安裝的插件的簽章)

1.6.13.1. output

terraform output 指令被用來提取狀態檔案中輸出值的值。

1.6.13.1.1. 用法

terraform output [options] [NAME]

如果不新增參數,output 指令會展示根模組內定義的所有輸出值。如果指定了 NAME,只會輸出相關輸出值。

可以使用以下參數:

  • -json:使用此參數後 Terraform 會使用 JSON 格式輸出。如果指定了 NAME,只會輸出相關輸出值。此參數搭配 jq 使用可以建構複雜的管線
  • -no-color:不輸出顏色
  • -state=path:狀態檔案的路徑,預設為 "terraform.tfstate"。啟用遠端 Backend 時此參數無效

1.6.13.1.2. 範例

假設有以下輸出值代碼:

output "lb_address" {
  value = aws_alb.web.public_dns
}

output "instance_ips" {
  value = [aws_instance.web[*].public_ip]
}

output "password" {
  sensitive = true
  value = [var.secret_password]
}

列出所有輸出值:

$ terraform output

注意 password 輸出值定義了 sensitive = true,所以它的值在輸出時會被隱藏:

$ terraform output password
password = <sensitive>

若要查詢負載平衡的 DNS 位址:

$ terraform output lb_address
my-app-alb-1657023003.us-east-1.elb.amazonaws.com

查詢所有主機的 IP:

$ terraform output instance_ips
test = [
    54.43.114.12,
    52.122.13.4,
    52.4.116.53
]

使用 -json 和jq 查詢指定主機的 ip:

$ terraform output -json instance_ips | jq '.value[0]'

1.6.14.1. plan

terraform plan 指令被用來創建變更計畫。Terraform 會先執行一次 refresh(我們後面的章節會介紹,該行為也可以被明確關閉),然後決定要執行哪些變更使得現有狀態遷移到程式碼描述的期待狀態。

該命令可以方便地審查狀態遷移的所有細節而不會實際更改現有資源以及狀態文件。例如,在將程式碼提交到版本控制系統前可以先執行 terraform plan,確認變更行為如預期般。

可選參數 -out 可以將變更計畫保存在一個檔案中,以便日後使用 terraform apply 指令來執行該計畫。

如果 Terraform 偵測不到任何變更,那麼 terraform plan 會提示沒有任何需要執行的變更。

1.6.14.1.1. 用法

terraform plan [options] [dir]

預設情況下,plan 指令不需要參數,使用目前工作目錄下的程式碼和狀態檔執行 refresh

有如下參數可以使用:

  • -compact-warnings:如果 Terraform 產生了一些警告訊息而沒有伴隨的錯誤訊息,那麼以只顯示訊息總結的精簡形式展示警告
  • -destroy:產生銷毀所有資源的計劃
  • -detailed-exitcode:當指令退出時回傳一個詳細的回傳碼。如果有該參數,那麼返回碼將會包含更詳細的含義:
    • 0 = 成功的空計畫(沒有變更)
    • 1 = 錯誤
    • 2 = 成功的非空計畫(有變更)
  • -input=true:在取不到值的情況下是否提示使用者給定輸入變數值
  • -lock=true:與 apply 類似,不再贅述
  • -lock-timeout=0s:與 apply 類似,不再贅述
  • -no-color:關閉彩色輸出
  • -out=path:將變更計劃儲存到指定路徑下的檔案中,隨後我們可以使用 terraform apply 執行該計劃
  • -parallelism-n:限制 Terraform 遍歷圖的最大並行度,預設值為 10
  • -refresh=true:計算變更前先執行 refresh
  • -state=path:狀態檔案的位置,預設為 "terraform.tfstate"。如果啟用了遠端 Backend 則該參數設定無效
  • -target=resource:目標資源的位址,此參數可重複聲明,以對基礎設施進行部分更新
  • `-var 'foo=bar':與 apply 類似,不再贅述
  • -var-file=foo:與 apply 類似,不再贅述

1.6.14.1.2. 部分更新

使用 -target 參數可以使得 Terraform 專注於一部分的資源。可以使用資源位址來標記這個集合。資源地址依下列規則解釋:

  • 如果給定位址能夠定位到一個資源,那麼只該資源會被標記;如果該資源使用了 count 參數而沒有給定具體存取下標,該資源所有實例都會被標記
  • 如果給定位址定位到的不是資源而是一個模組,那麼該模組內所有資源及其內嵌模組資源都會被標記

這種標記部分資源併計算更新計劃的能力是為了一些比較罕見的場景設計的,例如從先前的錯誤中恢復或是繞過某些 Terraform 的設計限制。對於常規操作不建議使用 -target 參數,因為它會造成無法檢測的配置漂移以及使人無法從程式碼推導出當前真實的狀態。

1.6.14.1.3. 安全警告

被儲存的變更計畫檔案(使用 -out 參數)內部可能含有敏感訊息,Terraform 本身並不會加密計畫檔案。如果你要移動或是儲存該文件一段時間,強烈建議你自行加密該文件。

Terraform 未來打算增強計畫文件的安全性。


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


上一篇
Day21-【入門教程】apply, console, destroy, fmt, force-unlock, get
下一篇
Day23-【入門教程】providers, refresh, show
系列文
Terraform 繁體中文25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言