預(yù)置器是由Terraform所提供的另一組插件,每種預(yù)置器可以在資源對象創(chuàng)建后執(zhí)行不同類型的操作。
使用預(yù)置器需要節(jié)制,因?yàn)樗麄儾扇〉牟僮鞑⒎荰erraform聲明式的風(fēng)格,所以Terraform無法對他們執(zhí)行的變更進(jìn)行建模和保存。
預(yù)置器也可以聲明為資源銷毀前執(zhí)行,但會有一些限制。
作為元參數(shù),provisioner和connection可以聲明在任意類型的resource塊內(nèi)。
舉一個(gè)例子:
resource "aws_instance" "web" {
# ...
provisioner "file" {
source = "conf/myapp.conf"
destination = "/etc/myapp.conf"
connection {
type = "ssh"
user = "root"
password = var.root_password
host = self.public_ip
}
}
}
我們在aws_instance中定義了類型為file的預(yù)置器,該預(yù)置器可以本機(jī)文件或文件夾拷貝到目標(biāo)機(jī)器的指定路徑下。我們在預(yù)置器內(nèi)部定義了connection塊,類型是ssh。我們對connection的host賦值self.public_ip,在這里self代表預(yù)置器所在的母塊,也就是aws_instance.web,所以self.public_ip代表著aws_instance.web.public_ip,也就是創(chuàng)建出來的主機(jī)的公網(wǎng)ip。
file類型預(yù)置器支持ssh和winrm兩種類型的connection。
預(yù)置器根據(jù)運(yùn)行的時(shí)機(jī)分為兩種類型,創(chuàng)建時(shí)預(yù)置器以及銷毀時(shí)預(yù)置器。
創(chuàng)建時(shí)預(yù)置器
默認(rèn)情況下,資源對象被創(chuàng)建時(shí)會運(yùn)行預(yù)置器,在對象更新、銷毀時(shí)則不會運(yùn)行。預(yù)置器的默認(rèn)行為時(shí)為了引導(dǎo)一個(gè)系統(tǒng)。
如果創(chuàng)建時(shí)預(yù)置器失敗了,那么資源對象會被標(biāo)記污點(diǎn)(我們將在介紹terraform taint命令時(shí)詳細(xì)介紹)。一個(gè)被標(biāo)記污點(diǎn)的資源在下次執(zhí)行terraform apply命令時(shí)會被銷毀并重建。Terrform的這種設(shè)計(jì)是因?yàn)楫?dāng)預(yù)置器運(yùn)行失敗時(shí)標(biāo)志著資源處于半就緒的狀態(tài)。由于Terraform無法衡量預(yù)置器的行為,所以唯一能夠完全確保資源被正確初始化的方式就是刪除重建。
我們可以通過設(shè)置on_failure參數(shù)來改變這種行為。
銷毀時(shí)預(yù)置器
如果我們設(shè)置預(yù)置器的when參數(shù)為destroy,那么預(yù)置器會在資源被銷毀時(shí)執(zhí)行:
resource "aws_instance" "web" {
# ...
provisioner "local-exec" {
when = destroy
command = "echo 'Destroy-time provisioner'"
}
}
銷毀時(shí)預(yù)置器在資源被實(shí)際銷毀前運(yùn)行。如果運(yùn)行失敗,Terraform會報(bào)錯,并在下次運(yùn)行terraform apply操作時(shí)重新執(zhí)行預(yù)置器。在這種情況下,需要仔細(xì)關(guān)注銷毀時(shí)預(yù)置器以使之能夠安全地反復(fù)執(zhí)行。
銷毀時(shí)預(yù)置器只有在存在于代碼中的情況下才會在銷毀時(shí)被執(zhí)行。如果一個(gè)resource塊連帶內(nèi)部的銷毀時(shí)預(yù)置器塊一起被從代碼中刪除,那么被刪除的預(yù)置器在資源被銷毀時(shí)不會被執(zhí)行。要解決這個(gè)問題,我們需要使用多個(gè)步驟來繞過這個(gè)限制:
修改資源聲明代碼,添加count = 0參數(shù)
執(zhí)行terraform apply,運(yùn)行刪除時(shí)預(yù)置器,然后刪除資源實(shí)例
刪除resource塊
重新執(zhí)行terraform apply,此時(shí)應(yīng)該不會有任何變更需要執(zhí)行
該限制在未來將會得到解決,但目前來說我們必須節(jié)制使用銷毀時(shí)預(yù)置器。
預(yù)置器失敗行為
默認(rèn)情況下,預(yù)置器運(yùn)行失敗會導(dǎo)致terraform apply執(zhí)行失敗。可以通過設(shè)置on_failure參數(shù)來改變這一行為??梢栽O(shè)置的值為:
continue:忽視錯誤,繼續(xù)執(zhí)行創(chuàng)建或是銷毀
fail:報(bào)錯并終止執(zhí)行變更(這是默認(rèn)行為)。如果這是一個(gè)創(chuàng)建時(shí)預(yù)置器,則在對應(yīng)資源對象上標(biāo)記污點(diǎn)
樣例:
resource "aws_instance" "web" {
# ...
provisioner "local-exec" {
command = "echo The server's IP address is ${self.private_ip}"
on_failure = continue
}
}
本地資源
雖然大部分資源類型都對應(yīng)的是通過遠(yuǎn)程基礎(chǔ)設(shè)施API控制的一個(gè)資源對象,但也有一些資源對象他們只存在于Terraform進(jìn)程自身內(nèi)部,用來計(jì)算生成某些結(jié)果,并將這些結(jié)果保存在狀態(tài)中以備日后使用。
比如說,我們可以用tls_private_key生成公私鑰,用tls_self_signed_cert生成自簽名證書,或者是用random_id生成隨機(jī)id。雖不像其他“真實(shí)”基礎(chǔ)設(shè)施對象那般重要,但這些本地資源也可以成為連接其他資源有用的黏合劑。
本地資源的行為與其他類型資源是一致的,但是他們的結(jié)果數(shù)據(jù)僅存在于Terraform狀態(tài)文件中。“銷毀”這種資源只是將結(jié)果數(shù)據(jù)從狀態(tài)中刪除。
操作超時(shí)設(shè)置
有些資源類型提供了特殊的timeouts內(nèi)嵌塊參數(shù),它允許我們配置我們允許操作持續(xù)多長時(shí)間,超時(shí)將被認(rèn)定為失敗。比如說,aws_db_instance資源允許我們分別為create,update,delete操作設(shè)置超時(shí)時(shí)間。
超時(shí)完全由資源對應(yīng)的Provider來處理,但支持超時(shí)設(shè)置的Provider一般都遵循相同的傳統(tǒng),那就是由一個(gè)名為timeouts的嵌入塊參數(shù)定義超時(shí)設(shè)置,timeouts塊內(nèi)可以分別設(shè)置不同操作的超時(shí)時(shí)間。超時(shí)時(shí)間由string描述,比如"60m"代表60分鐘,"10s"代表10秒,"2h"代表2小時(shí)。
esource "aws_db_instance" "example" {
# ...
timeouts {
create = "60m"
delete = "2h"
}
}
可配置超時(shí)的操作類別由每種支持超時(shí)設(shè)定的資源類型自行決定。大部分資源類型不支持設(shè)置超時(shí)。使用超時(shí)前請先查閱相關(guān)文檔。