雲生態下的基礎架構資源管理利器Terraform

子優發表於2017-09-25

About Terraform

Terraform (https://www.terraform.io/) 是HashiCorp旗下的一款開源(Go語言開發)的DevOps 基礎架構資源管理運維工具,可以看下對應的DevOps工具鏈:
image.png

Terraform可以安全高效的構建、更改和合並多個雲廠商的各種服務資源,當前支援有阿里雲、AWS、微軟Azure、Vmware、Google Cloud Platform等多個雲廠商雲產品的資源建立。
image.png

Write, Plan, and Create Infrastructure as Code

Terraform通過模板配置檔案定義所有資源型別(有如主機,OS,儲存型別,中介軟體,網路VPC,SLB,DB,Cache等)和資源的數量、規格型別、資源建立依賴關係,基於資源廠商的OpenAPI快速建立一鍵建立定義的資源列表,同時也支援資源的一鍵銷燬。

通過模板配置化的方式,我們可以得知整個資源關係,也可以做相應的資源版本化管理,甚至可以把該資源模板直接複製建立多可用區的服務,包括資源的彈性伸縮,可以說在提高運維自動化生產力上是一個絕好的利器。

這裡引用@簫竹 一次分享中提供的一個建立阿里雲資源的Terraform產品介紹圖 :
image.png
最左邊欄通過一個main.tf檔案(只需要是.tf 檔案)定義了ECS(映象、例項型別)、VPC(CIDR、VPC Name)、OSS資源(ACL、例項Name)資訊,通過Terraform 對資源配置引數做解析,呼叫阿里cloud OpenAPI 進行資源校驗於建立,同時把整個資源建立狀態化到一個.tf.state檔案中,基於該檔案則可以得知資源建立的所有資訊,包括資源數量調整,規格調整,例項變更都依賴這種非常重要的檔案。 具體後續綜合一些案例,比如Terraform 實現WordPress的一鍵自動化搭建,可以更好的理解該產品的執行過程。

下面先講述下Terraform的安裝,模板配置檔案的編寫,後續再專門寫幾個案例作為分享。

Install Terraform

Terraform 可以隨意部署在任意的C端上,只要可以連通公網即可(Initializing provider plugins and Call Cloud OpenAPI)
通過 https://www.terraform.io/downloads.html 下載對應平臺的可執行二進位制包,解壓出來Executable Binary 放指定目錄,配置好相應的PATH則可使用terraform 指令。

wangzhipengs-MacBook-Pro:~ wangzhipeng$ which terraform
/usr/local/bin/terraform
wangzhipengs-MacBook-Pro:~ wangzhipeng$ 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
    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
    push               Upload this Terraform module to Atlas to run
    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:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

這裡需要特別說明一下的是目前Terraform官網的版本只支援阿里cloud比較有效的幾個大產品的resource,因此如果要建立阿里cloud多個resource需要引入阿里cloud的provider:
https://github.com/alibaba/terraform-provider/releases
通過下載alicloud的provider binary (bin/terraform-provider-alicloud) 放置到Terraform的安裝目錄下。

Build Infrastructure

整個架構資源建立的過程,可以分成如下四部分:
image.png
通過一個*.tf 字尾的模板檔案,描述指定廠商的所有資源配置資訊,比如說建立一個alicloud ECS的模板配置:

# Configure the Alicloud Provider
provider "alicloud" {
  access_key = "${var.access_key}"
  secret_key = "${var.secret_key}"
  region     = "${var.region}"
}

# Create a web server
resource "alicloud_instance" "web" {
  # cn-beijing
  provider          = "alicloud"
  availability_zone = "cn-beijing-a"
  image_id          = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"

  internet_charge_type  = "PayByBandwidth"

  instance_type        = "ecs.n1.medium"
  io_optimized         = "optimized"
  system_disk_category = "cloud_efficiency"
  security_groups      = ["${alicloud_security_group.default.id}"]
  instance_name        = "web"
}

# Create security group
resource "alicloud_security_group" "default" {
  name        = "default"
  provider    = "alicloud"
  description = "default"
}

# Output message
output "ecs instance name" {
  value = "${alicloud_instance.web.instance_name}"
}

output "ecs private ip" {
  value = "${alicloud_instance.web.private_ip}"
}

如上access_key,secret_key 填寫建立資源賬號的AK,該Config File涵蓋了Region,可用區,ECS映象,頻寬計費方式,例項規格,IO型別,儲存型別,安全組,例項名稱多個資訊。
完成如上配置資訊後,需要通過terraform init 做cloud provider plugins的初始化操作:

wangzhipengs-MacBook-Pro:terraform_dir wangzhipeng$ terraform init

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "alicloud" (0.1.0)...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.alicloud: version = "~> 0.1"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

此時會在當前目錄下建立一個.terraform目錄,儲存有該平臺下的provider可執行檔案。
上面資訊也做了提示,我們可以running “terraform plan” 檢視將要建立的資源資訊:

wangzhipengs-MacBook-Pro:terraform_dir wangzhipeng$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + alicloud_instance.web
      id:                   <computed>
      allocate_public_ip:   "false"
      availability_zone:    "cn-beijing-a"
      host_name:            <computed>
      image_id:             "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
      instance_name:        "web"
      instance_type:        "ecs.n1.medium"
      internet_charge_type: "PayByBandwidth"
      io_optimized:         "optimized"
      private_ip:           <computed>
      public_ip:            <computed>
      security_groups.#:    <computed>
      status:               <computed>
      subnet_id:            <computed>
      system_disk_category: "cloud_efficiency"
      system_disk_size:     <computed>

  + alicloud_security_group.default
      id:                   <computed>
      description:          "default"
      name:                 "default"


Plan: 2 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn`t specify an "-out" parameter to save this plan, so Terraform
can`t guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

通過apply可以預覽模板對應建立2個資源,已經對應的屬性資訊:

  • alicloud_instance.web
  • alicloud_security_group.default (該安全組暫時未設定自定義放行規則)
    其中computed標識為暫時無法得知最終建立出來的資訊,所以也可以理解成系統預設分配。

接下通過指令terraform apply執行資源建立:

wangzhipengs-MacBook-Pro:terraform_dir wangzhipeng$ terraform apply
alicloud_security_group.default: Creating...
  description: "" => "default"
  name:        "" => "default"
alicloud_security_group.default: Creation complete after 1s (ID: sg-2zec9v8aq2hgb244qrqf)
alicloud_instance.web: Creating...
  allocate_public_ip:         "" => "false"
  availability_zone:          "" => "cn-beijing-a"
  host_name:                  "" => "<computed>"
  image_id:                   "" => "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
  instance_name:              "" => "web"
  instance_type:              "" => "ecs.n1.medium"
  internet_charge_type:       "" => "PayByBandwidth"
  io_optimized:               "" => "optimized"
  private_ip:                 "" => "<computed>"
  public_ip:                  "" => "<computed>"
  security_groups.#:          "" => "1"
  security_groups.2344301974: "" => "sg-2zec9v8aq2hgb244qrqf"
  status:                     "" => "<computed>"
  subnet_id:                  "" => "<computed>"
  system_disk_category:       "" => "cloud_efficiency"
  system_disk_size:           "" => "<computed>"
alicloud_instance.web: Still creating... (10s elapsed)
alicloud_instance.web: Still creating... (20s elapsed)
alicloud_instance.web: Still creating... (30s elapsed)
alicloud_instance.web: Still creating... (40s elapsed)
alicloud_instance.web: Still creating... (50s elapsed)
alicloud_instance.web: Creation complete after 51s (ID: i-2zedvfowy4m39sg1xdig)

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

ecs instance name = web
ecs private ip = 10.31.28.93

分鐘級功夫該ECS就建立好了
image.png

Input/Output Variables

回顧上面通過Terraform 建立資源的過程,最關鍵的還是如何描述模板配置資訊,這裡主要說明一下引數配置2個輸入輸出的變數實現。

# Configure the Alicloud Provider
provider "alicloud" {
  access_key = "${var.access_key}"
  secret_key = "${var.secret_key}"
  region     = "${var.region}"
}

我們可以在當前檔案,但最好另建立一個*.tf字尾結尾檔案,存放對應的ak和region資訊,這樣我們就可以把一些變數資訊提取出來避免硬編碼,這對整個配置檔案具備更好的可維護性:

wangzhipengs-MacBook-Pro:terraform_dir wangzhipeng$ cat variable.tf
variable "access_key" {
  default = "xxx"
}
variable "secret_key" {
  default = "xxx"
}
variable "region" {
  default = "cn-beijing"
}

此外,如上配置指定了output的變數資訊,本身如果不指定output的內容也不影響整個資源建立的過程,但通過輸出output的資訊可以徹底脫離控制檯,對於如下的output變數資訊也可以存放在另一個*.tf字尾檔案,對於resource的輸出變數可以參閱每個provider resource的attribute資訊。

# Output message
output "ecs instance name" {
  value = "${alicloud_instance.web.instance_name}"
}

output "ecs private ip" {
  value = "${alicloud_instance.web.private_ip}"
}

Destroy Infrastructure

資源使用後如果想要釋放,以往通過控制檯,往往需要存在資源依賴,導致資源釋放的時候需要先釋放被依賴的資源,所以整個資源釋放的過程還是比較繁瑣的,甚至可能存在忘記釋放個別資源造成資源浪費,Terraform通過指令terraform destroy 可以一鍵釋放資源:

wangzhipengs-MacBook-Pro:terraform_dir wangzhipeng$ terraform destroy
alicloud_security_group.default: Refreshing state... (ID: sg-2zec9v8aq2hgb244qrqf)
alicloud_instance.web: Refreshing state... (ID: i-2zedvfowy4m39sg1xdig)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - alicloud_instance.web

  - alicloud_security_group.default


Plan: 0 to add, 0 to change, 2 to destroy.

Do you really want to destroy?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only `yes` will be accepted to confirm.

  Enter a value: yes

alicloud_instance.web: Destroying... (ID: i-2zedvfowy4m39sg1xdig)
alicloud_instance.web: Still destroying... (ID: i-2zedvfowy4m39sg1xdig, 10s elapsed)
alicloud_instance.web: Destruction complete after 11s
alicloud_security_group.default: Destroying... (ID: sg-2zec9v8aq2hgb244qrqf)
alicloud_security_group.default: Destruction complete after 1s

Destroy complete! Resources: 2 destroyed.


相關文章