《Terraform 101 從入門到實踐》這本小冊在南瓜慢說官方網站和GitHub兩個地方同步更新,書中的示例代碼也是放在GitHub上,方便大家參考查看,
介紹了Terraform一些比較基礎的概念后,我們可以先了解一下Terraform的語法,也就是HCL的語法,
變數Variables
變數是實作代碼復用的一種方式,同樣的代碼不同的變數往往會有不同的效果,而在Terraform里,有一個概念非常重要,就是變數都是從屬于模塊的,變數無法跨模塊參考,即在模塊A定義的變數X,無法在模塊B中直接參考,但父模塊的變數,可以作為子模塊的入參;而子模塊的輸出變數可以被父模塊獲取,
變數型別
從語言角度
跟任何編程語言一樣,變數都是有型別的,Terraform的變數型別從語言的角度可分為兩大類:基本型別和組合型別,具體如下:
基本型別:
- 字串string,如
"pkslow.com" - 數字number,如
319或5.11 - 布林值bool,如
true
組合型別:
- 串列list(
),如 ["dev", "uat", "prod"] - 集合set(
),如 set(...) - 映射map(
),如 {name="Larry", age="18"} - 物件object({name1=T1, name2=T2})
- 元組tuple([T1,T2,T3...])
如果不想指定某個型別,可以用any來表示任意型別;或者不指定,默認為任意型別,
從功能角度
從功能角度來看,變數可以分為輸入變數、輸出變數和本地變數,
輸入變數是模塊接收外部變數的方式,它定義在variable塊中,如下:
variable "image_id" {
type = string
}
variable "availability_zone_names" {
type = list(string)
default = ["us-west-1a"]
}
variable "docker_ports" {
type = list(object({
internal = number
external = number
protocol = string
}))
default = [
{
internal = 8300
external = 8300
protocol = "tcp"
}
]
}
輸出變數定義了一個模塊對外回傳的變數,通過output塊來定義,如下:
output "instance_ip_addr" {
value = https://www.cnblogs.com/larrydpk/archive/2023/02/11/aws_instance.server.private_ip
}
本地變數是模塊內定義且可參考的臨時變數,在locals塊中定義,如下:
locals {
service_name = "forum"
owner = "Community Team"
}
輸入變數Input Variable
輸入變數是定義在variable塊中的,它就像是函式的入參,
定義輸入變數
定義variable有很多可選屬性:
- 型別type:指定變數是什么型別;如果沒有指定,則可以是任意型別;
- 默認值default:變數的默認值,定義后可以不用提供變數的值,注意它的值的型別要與type對應上;
- 說明description:說明這個變數的作用和用途;
- 校驗validation:提供校驗邏輯來判斷輸入的變數是否合法;
- 敏感性sensitive:定義變數是否敏感,如果是則不會顯示;默認為
false; - 可空nullable:如果為true則可以為空,否則不能,默認為
true,
所有屬性都顯性指定如下面例子所示:
variable "env" {
type = string
default = "dev"
description = "environment name"
sensitive = false
nullable = false
validation {
condition = contains(["dev", "uat", "prod"], var.env)
error_message = "The env must be one of dev/uat/prod."
}
}
這個變數名為env,表示環境名,默認值為dev,這個值必須為dev、uat和prod中的其中一個,如果輸出一個非法的值,會報錯:
$ terraform plan -var="env=sit"
?
│ Error: Invalid value for variable
│
│ on input.tf line 1:
│ 1: variable "env" {
│
│ The env must be one of dev/uat/prod.
使用輸入變數
只有定義了變數才可以使用,使用的方式是var.name,比如這里定義了兩個變數env和random_string_length:
variable "env" {
type = string
default = "dev"
}
variable "random_string_length" {
type = number
default = 10
}
則使用如下:
resource "random_string" "random" {
length = var.random_string_length
lower = true
special = false
}
locals {
instance_name = "${var.env}-${random_string.random.result}"
}
output "instance_name" {
value = https://www.cnblogs.com/larrydpk/archive/2023/02/11/local.instance_name
}
傳入變數到根模塊
要從外部傳入變數到根模塊,有多種方式,常見的有以下幾種,按優先級從低到高:
-
環境變數
export TF_VAR_image_id=ami-abc123 -
terraform.tfvars檔案; -
terraform.tfvars.json檔案; -
*.auto.tfvars或*.auto.tfvars.json檔案; -
命令列引數
-var傳入一個變數;命令列引數-var-file傳入一個變數的集合檔案;
在實踐中,最常用的還是通過命令列來傳入引數,因為一般需要指定不同環境的特定變數,所以會把變數放到檔案中,然后通過命令列指定特定環境的主檔案:
$ terraform apply -var="env=uat"
$ terraform apply -var-file="prod.tfvars"
而prod.tfvars的內容如下:
env = "prod"
random_string_length = 12
我們可以定義dev.tfvars、uat.tfvars和prod.tfvars等,要使用不同環境的變數就直接改變檔案名即可,
輸出變數Output Variable
有輸入就有輸出,輸出變數就像是模塊的回傳值,比如我們呼叫一個模塊去創建一臺服務,那就要獲取服務的IP,這個IP事先是不知道,它是服務器創建完后的結果之一,輸出變數有以下作用:
- 子模塊的輸出變數可以暴露一些資源的屬性;
- 根模塊的輸出變數可以在apply后輸出到控制臺;
- 根模塊的輸出變數可以通過
remote state的方式共享給其它Terraform配置,作為資料源,
定義輸出變數
輸出變數需要定義在output塊中,如下:
output "instance_ip_addr" {
value = https://www.cnblogs.com/larrydpk/archive/2023/02/11/aws_instance.server.private_ip
}
這個value可以是reource的屬性,也可以是各種變數計算后的結果,只要在執行apply的時候才會去計算輸出變數,像plan是不會執行計算的,
還可以定義輸出變數的一些屬性:
description:輸出變數的描述,說明清楚這個變數是干嘛的;sensitive:如果是true,就不會在控制臺列印出來;depends_on:顯性地定義依賴關系,
完整的定義如下:
output "instance_ip_addr" {
value = https://www.cnblogs.com/larrydpk/archive/2023/02/11/aws_instance.server.private_ip
description ="The private IP address of the main server instance."
sensitive = false
depends_on = [
# Security group rule must be created before this IP address could
# actually be used, otherwise the services will be unreachable.
aws_security_group_rule.local_access,
]
}
參考輸出變數
參考輸出變數很容易,運算式為module.<module name>.<output name>,如果前面的輸出變數定義在模塊pkslow_server中,則參考為:module.pkslow_server.instance_ip_addr,
本地變數Local Variable
本地變數有點類似于其它語言代碼中的區域變數,在Terraform模塊中,它的一個重要作用是避免重復計算一個值,
locals {
instance_name = "${var.env}-${random_string.random.result}-${var.suffix}"
}
這里定義了一個本地變數instance_name,它的值是一個復雜的運算式,這時我們可以通過local.xxx的形式參考,而不用再寫復雜的運算式了,如下:
output "instance_name" {
value = https://www.cnblogs.com/larrydpk/archive/2023/02/11/local.instance_name
}
這里要特別注意:定義本地變數的關鍵字是locals塊,里面可以有多個變數;而參考的關鍵字是local,并沒有s,
一般我們是建議需要重復參考的復雜的運算式才使用本地變數,不然太多本地變數就會影響可讀性,
對變數的參考
定義了變數就需要對其進行參考,前面的講解其實已經講過了部分變數的參考,這些把所有列出來,
| 型別 | 參考方式 |
|---|---|
| 資源Resources | <Resource Type>.<Name> |
| 輸入變數Input Variables | var.<NAME> |
| 本地變數Local Values | local.<NAME> |
| 子模塊的輸出 | module.<Module Name>.<output Name> |
| 資料源Data Sources | data.<Data Type>.<Name> |
| 路徑和Terraform相關 | path.module:模塊所在路徑path.root:根模塊的路徑path.cwd:一般與根模塊相同,其它高級用法除外terraform.workspace:作業區名字 |
| 塊中的本地變數 | count.index:count回圈的下標;each.key/each.value:for each回圈的鍵值;self:在provisioner的參考; |
上面都是單值的參考,如果是List或Map這種復雜型別,就要使用中括號[]來參考,
aws_instance.example[0].id:參考其中一個元素;
aws_instance.example[*].id:參考串列的所有id值;
aws_instance.example["a"].id:參考key為a的元素;
[for value in aws_instance.example: value.id]:回傳所有id為串列;
運算子
與其它語言一樣,Terraform也有運算子可以用,主要是用于數值計算和邏輯計算,以下運算子按優先級從高到低如下:
!取反,-取負*乘號,/除號,%取余+加號,-減號>,>=,<,<=:比較符號==等于,!=不等于&&與門||或門
當然,用小括號可以改變這些優秀級,如(1 + 2) * 3,
注意:對于結構化的資料比較需要注意型別是否一致,比如var.list == []按理說應該回傳true,而list為空時,當[]實際表示是元組tuple([]),所以它們不匹配,可以使用length(var.list) == 0的方式,
條件運算式
條件運算式的作用是在兩個值之間選一個,條件為真則選第一個,條件為假則選第二個,形式如下:
condition ? true_value : false_value
示例如下:
env = var.env !="" ? var.env : "dev"
意思是給env賦值,如果var.env不為空就把輸入變數var.env的值賦給它,如果為空則賦默認值dev,
for運算式
使用for運算式可以創建一些復雜的值,而且可以使用一些轉換和計算對值計算再回傳,如將字串串列轉化成大寫:
> [for s in ["larry", "Nanhua", "Deng"] : upper(s)]
[
"LARRY",
"NANHUA",
"DENG",
]
可以獲取下標和值:
> [for i,v in ["larry", "Nanhua", "Deng"] : "${i}.${v}"]
[
"0.larry",
"1.Nanhua",
"2.Deng",
]
對于Map的for運算式:
> [for k,v in {name: "Larry Deng", age: 18, webSite: "www.pkslow.com"} : "${k}: ${v}"]
[
"age: 18",
"name: Larry Deng",
"webSite: www.pkslow.com",
]
通過條件過濾資料:
> [for i in range(1, 10) : i*3 if i%2==0]
[
6,
12,
18,
24,
]
動態塊Dynamic Block
動態塊的作用是根據變數重復某一塊配置,這在Terraform是會遇見的,
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
name = "tf-test-name"
application = "${aws_elastic_beanstalk_application.tftest.name}"
solution_stack_name = "64bit Amazon Linux 2018.03 v2.11.4 running Go 1.12.6"
dynamic "setting" {
for_each = var.settings
content {
namespace = setting.value["namespace"]
name = setting.value["name"]
value = https://www.cnblogs.com/larrydpk/archive/2023/02/11/setting.value["value"]
}
}
}
比如這里的例子,就會重復setting塊,重復的次數取決于for_each后面跟的變數,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543604.html
標籤:其他
