HCP Workspaces
Workspace ใน HCP ≠ CLI workspace! — แต่ละ HCP workspace = state + variables + runs + history แยกกัน
HCP Workspace vs CLI Workspace
⚠️ ต่างกัน!
| Aspect | CLI Workspace | HCP Workspace |
|---|---|---|
| What is it | Multiple state files in 1 directory | Full project (state + vars + runs) |
| Scope | Per terraform code | Per organization |
| Use case | Multi-env (dev/staging/prod) for SAME code | Each project + env combo |
| Variables | Shared .tf files | Workspace-specific vars |
| Runs history | Local | Centralized in HCP UI |
→ ใน HCP ห้ามใช้ CLI workspace — แต่ละ HCP workspace = 1 directory + 1 set of variables
Workspace Types
CLI-Driven
รัน Terraform จาก laptop:
terraform {
cloud {
organization = "my-org"
workspaces {
name = "prod-network"
}
}
}
terraform login
terraform init
terraform apply # runs in HCP, output streams to laptop
VCS-Driven
Connect to Git repo, auto plan/apply on push:
Workspace → Settings → Version Control
└── Repository: myorg/infra
Branch: main
Working directory: ./prod/network
Trigger patterns: prod/network/**
→ Push to main → auto plan + apply (or manual approve)
API-Driven
Programmatic create runs:
curl -X POST https://app.terraform.io/api/v2/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-d '{
"data": {
"type": "runs",
"attributes": {"is-destroy": false},
"relationships": {
"workspace": {"data": {"type": "workspaces", "id": "ws-xxx"}}
}
}
}'
Create Workspace
UI
HCP → Organization → New Workspace
└── Choose: CLI-Driven / VCS-Driven / API-Driven
Name: prod-network
Project: production
Tags: [prod, network]
Terraform (Self-Manage HCP with TF!)
provider "tfe" {
organization = "my-org"
}
resource "tfe_workspace" "prod_network" {
name = "prod-network"
organization = "my-org"
working_directory = "prod/network"
vcs_repo {
identifier = "myorg/infra"
branch = "main"
oauth_token_id = data.tfe_oauth_client.github.oauth_token_id
}
trigger_patterns = ["prod/network/**"]
tag_names = ["prod", "network"]
}
Workspace Variables
Terraform Variables
Workspace → Variables → Add
└── Key: region
Value: us-east-1
Category: Terraform variable
Sensitive: false
ใน code:
variable "region" { type = string }
provider "aws" {
region = var.region
}
Environment Variables
Key: AWS_ACCESS_KEY_ID
Value: AKIA...
Category: Environment variable
Sensitive: true
→ Set as env in run, accessible via provider
Variable Sets (Reusable)
Settings → Variable Sets → Create
└── Name: aws-credentials
Variables:
AWS_ACCESS_KEY_ID (env, sensitive)
AWS_SECRET_ACCESS_KEY (env, sensitive)
Apply to: All workspaces / Specific workspaces / By tag
→ Define once, apply to many workspaces
Variable Priority
(highest precedence wins)
- Workspace variables
- Variable sets (more specific tags first)
- Variable sets (less specific)
- Variable defaults in
.tf
Workspace Settings
General
- Name (immutable after create)
- Description
- Working directory (subdirectory in repo)
- Auto Apply (after plan: yes/no/require approval)
- Terraform version (specific version per workspace)
- Execution mode (remote / agent / local)
Notifications
Workspace → Settings → Notifications
└── Slack webhook
Triggers: applying, completed, errored, needs_attention
Run Triggers
Trigger this workspace when another workspace applies:
Workspace: prod-app
Run Trigger: Source = prod-network
→ When prod-network applies, prod-app queues a run
Project (Group Workspaces)
Organization → Projects → New Project
└── Name: production
Workspaces:
- prod-network
- prod-data
- prod-compute
→ Group + permission management
resource "tfe_project" "production" {
organization = "my-org"
name = "production"
}
resource "tfe_workspace" "prod_network" {
name = "prod-network"
project_id = tfe_project.production.id
}
Tags
Workspace → Settings → Tags
└── Tags: [prod, network, critical]
ใช้:
- Filter ใน UI
- Variable set targeting
- Bulk operations
Multi-Workspace ใน 1 Repo
infra/
├── prod/
│ ├── network/ # workspace: prod-network
│ ├── data/ # workspace: prod-data
│ └── compute/ # workspace: prod-compute
└── staging/
├── network/ # workspace: staging-network
└── ...
แต่ละ folder = workspace ตัวเอง
Workspace State
Read State
# In workspace B, read state from workspace A
data "tfe_outputs" "network" {
organization = "my-org"
workspace = "prod-network"
}
resource "aws_instance" "app" {
subnet_id = data.tfe_outputs.network.values.subnet_id
}
→ Cross-workspace state references (alternative to terraform_remote_state)
State Sharing
Workspace prod-network → Settings → State Sharing
└── Share with: prod-app, prod-monitoring
→ Other workspaces can read your outputs
Workspace Locking
Auto-lock during runs (prevent concurrent apply)
Manual lock:
Workspace → Lock
└── Reason: "Migration in progress"
→ No new runs until unlocked
Run History
ทุก plan/apply เก็บ:
- Plan output
- Apply output
- Triggered by (user/VCS)
- Duration
- Resources changed
- Cost estimation
→ Audit trail สมบูรณ์
Auto-Apply
Workspace → Settings → Auto Apply
└── ☑ Auto-apply successful plans
⚠️ ใช้เฉพาะ dev — prod ควร manual approve
Manual Apply (Approval)
Plan complete!
Plan: 5 to add, 0 to change, 0 to destroy.
[Click "Confirm & Apply"]
ผู้ที่มี Apply permission กดปุ่ม
Workspace Deletion
Settings → Destruction & Deletion
2 actions:
- Queue destroy plan — destroy resources first
- Delete workspace — delete metadata (resources still in cloud!)
Best practice:
- Queue destroy plan → apply → confirm 0 resources
- Delete workspace
Best Practices
✅ DO:
- 1 workspace = 1 logical scope (env + layer)
- Naming convention: <env>-<layer> (prod-network, staging-data)
- Use projects + tags
- Variable sets for shared credentials
- VCS-driven for production
- Auto-apply for dev only
❌ DON'T:
- ห้าม mix CLI workspace กับ HCP workspace
- ห้าม share workspace สำหรับ env ต่าง
- ห้าม delete workspace ก่อน destroy resources
- ห้ามใช้ auto-apply ใน prod
ตัวอย่าง: Mature Setup
Organization: my-company
├── Projects:
│ ├── shared
│ │ ├── workspace: shared-dns
│ │ └── workspace: shared-iam
│ ├── production
│ │ ├── workspace: prod-network
│ │ ├── workspace: prod-data
│ │ ├── workspace: prod-compute
│ │ └── workspace: prod-apps
│ ├── staging
│ │ └── workspace: staging-*
│ └── development
│ └── workspace: dev-*
├── Variable Sets:
│ ├── aws-credentials → all workspaces (sensitive env vars)
│ ├── prod-config → tag:prod (production-specific)
│ └── shared-tags → all (default tags)
└── Teams:
├── platform-eng → admin all workspaces
├── dev-team → write dev/staging workspaces
└── viewers → read all
สรุป
- HCP Workspace = state + vars + runs + history (ต่างจาก CLI workspace)
- 3 modes: CLI-driven, VCS-driven, API-driven
- Variables + Variable Sets สำหรับ config
- Projects + Tags จัดกลุ่ม
- Run Triggers สำหรับ chain workspaces
- VCS-driven for prod, auto-apply for dev
ต่อไป → VCS Integration