Terraform 工作區與環境管理

前言

在使用 Terraform 管理基礎設施時,我們經常需要針對不同環境(如開發、測試、正式環境)部署相同的基礎設施配置。Terraform Workspace 提供了一個優雅的解決方案,讓我們能夠在單一配置下管理多個環境的狀態。

Workspace 概念

什麼是 Workspace?

Terraform Workspace 是一種狀態隔離機制,允許你在同一個工作目錄中維護多組獨立的狀態檔案。每個 workspace 都有自己的 terraform.tfstate 檔案,這意味著你可以使用相同的 Terraform 配置來管理多個環境,而不會產生狀態衝突。

預設 Workspace

當你初始化 Terraform 專案時,會自動建立一個名為 default 的 workspace。如果你沒有明確建立或切換 workspace,所有操作都會在這個預設 workspace 中進行。

1
2
3
# 查看目前所在的 workspace
terraform workspace show
# 輸出: default

建立與切換 Workspace

基本操作指令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 列出所有 workspace
terraform workspace list

# 建立新的 workspace
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod

# 切換到指定的 workspace
terraform workspace select dev

# 刪除 workspace(需先切換到其他 workspace)
terraform workspace delete staging

實際操作範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 建立開發環境的 workspace
$ terraform workspace new dev
Created and switched to workspace "dev"!

# 確認目前的 workspace
$ terraform workspace show
dev

# 列出所有 workspace
$ terraform workspace list
  default
* dev

# 星號表示目前所在的 workspace

多環境管理

使用 terraform.workspace 變數

在 Terraform 配置中,你可以使用 terraform.workspace 變數來取得目前的 workspace 名稱,並根據不同環境設定不同的資源配置。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# main.tf
resource "aws_instance" "web" {
  ami           = var.ami_id
  instance_type = terraform.workspace == "prod" ? "t3.large" : "t3.micro"

  tags = {
    Name        = "web-server-${terraform.workspace}"
    Environment = terraform.workspace
  }
}

條件式資源部署

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 只在正式環境部署額外的監控資源
resource "aws_cloudwatch_metric_alarm" "high_cpu" {
  count = terraform.workspace == "prod" ? 1 : 0

  alarm_name          = "high-cpu-utilization"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "AWS/EC2"
  period              = "120"
  statistic           = "Average"
  threshold           = "80"
}

變數區分

使用 Map 變數區分環境配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# variables.tf
variable "instance_type" {
  type = map(string)
  default = {
    dev     = "t3.micro"
    staging = "t3.small"
    prod    = "t3.large"
  }
}

variable "instance_count" {
  type = map(number)
  default = {
    dev     = 1
    staging = 2
    prod    = 3
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# main.tf
resource "aws_instance" "web" {
  count         = var.instance_count[terraform.workspace]
  ami           = var.ami_id
  instance_type = var.instance_type[terraform.workspace]

  tags = {
    Name = "web-server-${terraform.workspace}-${count.index + 1}"
  }
}

使用獨立的變數檔案

另一種方式是為每個環境建立獨立的變數檔案:

1
2
3
4
5
6
7
8
# 目錄結構
.
├── main.tf
├── variables.tf
├── outputs.tf
├── dev.tfvars
├── staging.tfvars
└── prod.tfvars
1
2
3
4
# dev.tfvars
instance_type  = "t3.micro"
instance_count = 1
enable_monitoring = false
1
2
3
4
# prod.tfvars
instance_type  = "t3.large"
instance_count = 3
enable_monitoring = true
1
2
3
4
5
6
# 套用特定環境的變數
terraform workspace select dev
terraform apply -var-file="dev.tfvars"

terraform workspace select prod
terraform apply -var-file="prod.tfvars"

最佳實務

1. 命名規範

為 workspace 建立一致的命名規範,便於識別和管理:

1
2
3
4
5
6
7
8
9
# 建議的命名方式
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod

# 或加上專案前綴
terraform workspace new myapp-dev
terraform workspace new myapp-staging
terraform workspace new myapp-prod

2. 狀態管理

使用遠端後端(Remote Backend)來儲存狀態,確保團隊協作時的狀態一致性:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# backend.tf
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "project/terraform.tfstate"
    region         = "ap-northeast-1"
    encrypt        = true
    dynamodb_table = "terraform-lock"
  }
}

使用 S3 後端時,不同 workspace 的狀態會自動存放在不同的路徑下:

1
2
3
4
s3://my-terraform-state/
├── env:/dev/project/terraform.tfstate
├── env:/staging/project/terraform.tfstate
└── env:/prod/project/terraform.tfstate

3. 環境隔離策略

根據專案需求選擇適合的隔離策略:

策略適用場景優點缺點
單一 Workspace小型專案、單一環境簡單直接無法管理多環境
多 Workspace中型專案、環境配置相似配置共用、易於維護環境差異大時不適用
多目錄大型專案、環境差異大完全隔離、彈性高配置重複、維護成本高

4. CI/CD 整合

在 CI/CD 流程中整合 workspace 操作:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# GitLab CI 範例
stages:
  - plan
  - apply

variables:
  TF_WORKSPACE: ${CI_ENVIRONMENT_NAME}

plan:
  stage: plan
  script:
    - terraform init
    - terraform workspace select ${TF_WORKSPACE} || terraform workspace new ${TF_WORKSPACE}
    - terraform plan -var-file="${TF_WORKSPACE}.tfvars" -out=tfplan
  artifacts:
    paths:
      - tfplan

apply:
  stage: apply
  script:
    - terraform init
    - terraform workspace select ${TF_WORKSPACE}
    - terraform apply tfplan
  when: manual
  only:
    - main

5. 安全注意事項

  • 避免在 workspace 名稱中包含敏感資訊
  • 確保正式環境的狀態檔案有適當的存取控制
  • 使用 terraform plan 確認變更內容後再執行 apply
  • 對正式環境的操作加入審核流程
1
2
3
4
5
6
7
8
# 防止意外刪除正式環境資源
resource "aws_instance" "web" {
  # ... 其他配置

  lifecycle {
    prevent_destroy = terraform.workspace == "prod" ? true : false
  }
}

總結

Terraform Workspace 是管理多環境基礎設施的強大工具。透過適當的規劃和最佳實務,你可以:

  • 簡化配置管理:使用單一配置管理多個環境
  • 降低維護成本:避免重複的配置檔案
  • 提高部署效率:快速切換和部署不同環境
  • 確保環境一致性:所有環境使用相同的基礎配置

選擇適合你專案的環境管理策略,並結合 CI/CD 流程,將能大幅提升基礎設施管理的效率和可靠性。

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy