天天看點

Terraform 文法 module子產品 簡介/封裝/實踐

Terraform 文法 module子產品 簡介/封裝/實踐

之前所有的基礎設施的代碼都放在一個目錄下面來進行管理的,後面寫代碼的方式通過子產品來組合。

随着基礎設施是不斷在變更的,在一個目錄下面管理全部的資源會随着基礎設施的擴充管理起來的複雜度就越來越高了,這樣就需要将資源抽象成子產品,然後引入子產品。

将所有的資源封裝為子產品,然後實作資源的複用。

Terraform 文法 module子產品 簡介/封裝/實踐

這裡的子產品和程式設計語言當中的子產品是一樣的概念。之前寫代碼是在整個檔案裡面寫我們的函數和方法,甚至一些邏輯都寫到檔案裡面去了。

但是後期發現一個檔案管理起來是十分複雜的,這個時候就可以建立包和子產品,然後單獨的去維護那塊功能就行了,後面就直接導入這個子產品就行了。

在tf裡面也是一樣的。

在子產品裡面定義的還是基礎設施及代碼,後期使用哪些資源導入這個子產品就行了,不需要重複去定義這些資源了。

如果全部放在一起,那麼建立3個ecs就需要複制三行代碼,這是不推薦的做法。有了子產品就可以直接使用子產品,減少代碼編寫同時代碼可以複用。

resource "alicloud_instance" "instance" {
  # cn-beijing
  availability_zone = "${var.region}-b"
  security_groups   = alicloud_security_group.group.*.id

  # series III
  instance_type           = "ecs.n1.tiny"
  system_disk_category    = "cloud_efficiency"
  system_disk_name        = "test_foo_system_disk_name"
  system_disk_description = "test_foo_system_disk_description"
  // image_id                   = "ubuntu_18_04_64_20G_alibase_20190624.vhd"
  image_id                   = data.alicloud_images.images_ds.images[0].id
  instance_name              = local.instance_name
  vswitch_id                 = alicloud_vswitch.vsw.id
  internet_max_bandwidth_out = 10
  internet_charge_type       = "PayByTraffic"
  password                   = "root@123"
}      

module 簡介

Terraform 文法 module子產品 簡介/封裝/實踐

一個目錄下就是一個子產品,隻不過它叫做根子產品。在生産環境代碼下都是根子產品下面有很多子子產品,甚至子子產品裡面還有子子產品。(之前所有檔案在一起,其實就已經是一個子產品了,之前是大子產品,裡面沒有子子產品,現在需要做的就是添加子子產品)

建議就是根子產品和子子產品,不易套太深,套太深那麼可讀性和維護性都會變的很差了,到時候不友善去管理。

一個目錄下所有.tf檔案組成的就是一個子產品。這些子產品寫的資源的文法都是一緻的。

如果你是json文法,那麼會有很多.json結尾的檔案組成子產品。

子產品結構如上所示:有個主檔案,main.tf,主程式的入口,有些子產品的輸出變量outputs.tf(主要适用于子產品之間的調用),子產品的說明,最後子產品的變量。

上面是常見子產品裡面所包含的内容。

文法

Terraform 文法 module子產品 簡介/封裝/實踐

随意建立一個目錄,然後在這個目錄下存放所有的資源子產品,然後在子產品下建立ecs,那麼下面全部存放的都是ecs資源。

Terraform 文法 module子產品 簡介/封裝/實踐

上面就是常見子產品的組成。這個主配置檔案裡面還是寫我們的ecs。如果後面要建立VPC 安全組,那麼在子產品下再建立目錄。

我們将這些資源以子產品方式加進去(其實就是将資源改為子產品的方式),最後導入進來。

在建立ecs的時候,肯定會使用到vpc的屬性的。

vswitch_id                 = alicloud_vswitch.vsw.id      

 那麼就需要在vpc子產品outputs.tf裡面使用output輸出變量了。

output "vswitch_id" {
  value = alicloud_vswitch.vsw.id
}      
Terraform 文法 module子產品 簡介/封裝/實踐

vpc是一個子產品,ecs是一個子產品,ecs肯定是要使用到vpc子產品當中vswitch_id參數的。

Terraform 文法 module子產品 簡介/封裝/實踐

 那麼現在就可以在ecs當中改了

vswitch_id                 = var.vswitch_id      

帶寬先不需要關心,後面可能會建立eip的資源,然後挂上去就行了,當你指定完帶寬之後,它會給你自動的配置設定公網的IP。

然後使用locals定義局部變量,locals非常适合在子產品當中定義變量。

因為ecs涉及到vpc,上面建立好了vpc,還差安全組,現在搞安全組。

這裡需要關聯vpc,那麼将其變為變量。因為安全組和安全組規則在同一個子產品,是以可以通過資源名稱引用。因為ecs和安全組不是一個子產品,那麼安全組需要在outputs加一個輸出,這個輸出其實就是安全組。

output "security_group_id" {
  value = alicloud_security_group.group.*.id
}      

因為傳回的是list類型,那麼在ecs裡面定義的便利也是list類型

variable "security_group_id" {
  type = list(string)
}      

最後同理dns也一樣,引用了子產品ecs的public ip,那麼ecs的要使用output

output "instance_public_ip" {
  value = alicloud_instance.instance.public_ip
}      
Terraform 文法 module子產品 簡介/封裝/實踐

整體結構如上面。子產品定義好了,資源定義好了,要釋出了,就要去引用資源了。

現在在根目錄下建立一個目錄env,再建立一個檔案夾dev。dev環境肯定需要引入這些資源。

versions裡面其實就是版本,main是項目的主配置檔案。

上面就是按照步驟,建立好了各個資源,相當于将資源都分開了,之前是在一個目錄下,現在是按照每個資源一個子產品目錄的方式去劃分的。

現在比如要建立dev環境,那麼肯定要引入這裡的資源,接下來就是子產品的引用。

Terraform 文法 module子產品 簡介/封裝/實踐

引用的話也是按照語句塊這種格式去寫的,用的關鍵字module, 然後是子產品的名稱,這個是可以自己去定義的。

後面就是source源,就是子產品在哪,可以是在git上面,也可能在你的本地,也可能在其他的HTTP伺服器上面。

這個在實際環境當中,用的最多的就是git了,在git上面存儲我們的子產品,加載的時候從gitlab上面去拿,更新就是更新到gitlab上面去。

現在是使用本地的方式去加載,唯一的差別就是儲存到本地了,還有一個就是上傳到版本控制系統遠端的,source裡面位址會發生變化。

version是版本,這個可以按照自己的定義去寫。

最後就是變量和參數了。調用子產品的時候需要傳遞什麼樣的參數。

在調用子產品的時候,裡面的形參數是子產品裡面通過variable定義的參數,實參可以來自于local。而調用其他子產品當中參數,就在子產品當中使用output參數即可。

比如ecs子產品需要用的vpc子產品當中的輸出變量,module.哪個子產品的名稱.output輸出變量

vswitch_id = module.terraform_vpc.vswitch_id      

1.如果全部資源清單檔案在一起,那麼可以直接通過data資料源和資源resource拿到想要的值,如果是不同子產品,那麼要通過variables聲明變量,然後通過子產品當中的參數

value = alicloud_security_group.group.*.id      

*.id這就代表是list類型

variable "security_group_id" {
  type = list(string)
}      

或者這裡類型不限制

Terraform 文法 module子產品 簡介/封裝/實踐
Terraform 文法 module子產品 簡介/封裝/實踐

 最後整個結構如下,env是環境,下面有test測試環境,dev生産環境,現在我們去dev環境操作

Terraform 文法 module子產品 簡介/封裝/實踐

兩個目錄,一個目錄是環境(開發,測試環境)一個目錄子產品環境(放各個資源子產品) 

這裡注意在引用子產品的時候,相對路徑不要寫錯了。

上面就是子產品的文法,非常的簡單,重點還是source這塊,将路徑寫對,下面就是一些參數了。

Terraform 文法 module子產品 簡介/封裝/實踐

子產品source可以寫遠端的子產品,也可以寫本地的子產品。

所有的遠端的子產品都是放在git存儲庫上面,那麼在執行init或者get的時候,他就會将其下載下傳到.terraform目錄下面,這裡多了modules這個目錄。

Terraform 文法 module子產品 簡介/封裝/實踐
{
    "Modules": [
        {
            "Key": "terraform_dns",
            "Source": "../../modules/dns",
            "Dir": "../../modules/dns"
        },
        {
            "Key": "terraform_ecs",
            "Source": "../../modules/ecs",
            "Dir": "../../modules/ecs"
        },
        {
            "Key": "terraform_security_group",
            "Source": "../../modules/security_group",
            "Dir": "../../modules/security_group"
        },
        {
            "Key": "terraform_vpc",
            "Source": "../../modules/vpc",
            "Dir": "../../modules/vpc"
        },
        {
            "Key": "",
            "Source": "",
            "Dir": "."
        }
    ]
}      

key是子產品的名稱,子產品的位置在哪,然後目錄。在執行init的時候就會在terraform目錄下建立。

但是本地子產品就比較簡單,不會把子產品複制到這裡面去,而是直接做了引用,相當于軟連結的引用,你改了本地子產品之後理論上是不需要重新init的。

init是包含get下載下傳子產品這個步驟,另外還加了初始化後端存儲,就是terraform.tfstate這個檔案。

Terraform 文法 module子產品 簡介/封裝/實踐

是以init功能比get功能要多一些,而get是專門去下載下傳子產品的。當子產品較多的時候,可以通過graph圖表的方式檢視子產品。

root下面有很多子產品,和我們現在結構一樣。

Terraform 文法 module子產品 簡介/封裝/實踐
Terraform 文法 module子產品 簡介/封裝/實踐

子產品調用,就是source這塊,可以是本地的目錄,也可以是一個公共的terraform regestri上面的公共的子產品,現在子產品比較成熟,可以直接拿來使用。

GitHub上面支援HTTP ssh,無非就改一下連結。

s3 bucket裡面也可以去拿。

還有通用的一些git。

上面都是子產品的調用方式。

Terraform 文法 module子產品 簡介/封裝/實踐

ecs這裡其實引用了vpc子產品裡面的交換機的id,那麼這個id我們這定義了一個變量,通過variable裡面定義了輸入的變量。

在建立好交換機之後,是要将變量輸出一下,将交換機的id放在output裡面了。

主子產品在調用建立ecs的時候交換機的id通過子產品輸出拿到。 

這裡的輸入輸出就是對應我們在:

輸入變量:variables裡面定義的是輸入變量,這些變量放在了子產品定義裡面。

Terraform 文法 module子產品 簡介/封裝/實踐

輸出變量就放在output裡面。

Terraform 文法 module子產品 簡介/封裝/實踐

子產品執行個體化就是引入這個子產品,練習就是單獨的子產品,上面就是一個子產品的多次執行個體化。 

記住一點dev相當于是root子產品,在裡面有stat檔案,那麼dev環境變更的時候都要進入到這個目錄下面,在其他目錄下執行,就加載不到這個狀态檔案,最後有可能就失敗的。