IaCInfrastructure as Codeterraformterraform import

Import Infrastructure có sẵn vào Terraform

Hướng dẫn đưa hạ tầng đã tồn tại vào Terraform một cách an toàn bằng terraform import và Import Blocks, tránh tạo lại resource và từng bước chuyển sang Infrastructure as Code.

22 thg 7, 20268 min readCập nhật 22 thg 7, 2026
Import Infrastructure có sẵn vào Terraform

Import Infrastructure có sẵn vào Terraform

Ở những bài trước, chúng ta luôn bắt đầu từ một project hoàn toàn mới.

terraform init
terraform plan
terraform apply

Terraform sẽ tạo ra toàn bộ infrastructure từ đầu.

Nhưng thực tế ở doanh nghiệp lại hoàn toàn khác.

Rất hiếm khi bạn được bắt đầu với một tài khoản AWS hay Azure trống.

Thông thường bạn sẽ gặp những hệ thống như:

  • Hàng trăm EC2 đã tồn tại
  • VPC được tạo từ nhiều năm trước
  • Database đang chạy production
  • Cloudflare DNS đã cấu hình
  • Vercel Project đang phục vụ hàng triệu request
  • S3 Bucket chứa dữ liệu nhiều TB

Những resource này đều đang hoạt động.

Bạn không thể xóa đi rồi tạo lại chỉ để dùng Terraform.

Vậy Terraform sẽ quản lý chúng như thế nào?

Đó chính là mục đích của Terraform Import.


Một câu hỏi rất phổ biến

Rất nhiều người mới học Terraform thường nghĩ như sau:

Muốn Terraform quản lý thì phải tạo resource bằng Terraform.

Điều này không đúng.

Terraform không quan tâm ai đã tạo resource.

Terraform chỉ quan tâm:

"Resource này đã được ghi vào State hay chưa?"

Nếu State biết resource tồn tại, Terraform sẽ quản lý được.

Nếu State không biết, Terraform sẽ nghĩ resource chưa tồn tại.

Đó là lý do Import ra đời.


Terraform Import là gì?

Hiểu đơn giản:

Import chỉ làm một việc duy nhất.

Nó nói với Terraform rằng:

"Resource ngoài đời này đã tồn tại rồi. Hãy ghi nó vào Terraform State."

Ví dụ:

Production đang có một EC2.

EC2

ID:
i-0123456789

Terraform hoàn toàn không biết điều này.

State:

(empty)

Khi chạy:

code
terraform import aws_instance.web i-0123456789

Terraform sẽ đọc thông tin resource từ AWS.

Sau đó ghi vào State.

Terraform State

↓

aws_instance.web

↓

ID = i-0123456789

Lưu ý.

Import không tạo resource mới.

Import cũng không sửa resource.

Nó chỉ cập nhật Terraform State.


Terraform Import không tạo Configuration

Đây là điểm khiến rất nhiều người bất ngờ.

Ví dụ sau khi import.

State đã có:

aws_instance.web

Nhưng project lại chưa có:

code
resource "aws_instance" "web" {
 
}

Nếu chạy:

code
terraform plan

Terraform sẽ báo lỗi.

Bởi vì State đã biết resource.

Nhưng Configuration lại không tồn tại.

Terraform luôn cần hai thứ:

Configuration

+

State

Nếu thiếu một trong hai.

Terraform sẽ không hoạt động đúng.


Hai thành phần luôn phải khớp nhau

Terraform luôn so sánh:

Configuration

↓

State

↓

Infrastructure

Ba thành phần này cần đồng nhất.

Nếu chỉ có State.

Terraform không biết resource nên có thuộc tính gì.

Nếu chỉ có Configuration.

Terraform không biết resource đã tồn tại hay chưa.

Chỉ khi cả hai cùng tồn tại.

Terraform mới có thể thực hiện Plan chính xác.


Ví dụ thực tế

AWS đã có Bucket:

company-production-assets

Bạn viết:

code
resource "aws_s3_bucket" "assets" {
  bucket = "company-production-assets"
}

Sau đó chạy:

code
terraform import aws_s3_bucket.assets company-production-assets

Kết quả:

Configuration
        ✓

State
        ✓

Infrastructure
        ✓

Từ thời điểm này.

Terraform chính thức quản lý Bucket đó.


Điều gì xảy ra nếu không Import?

Giả sử Bucket đã tồn tại.

Nhưng bạn lại viết:

code
resource "aws_s3_bucket" "assets" {
  bucket = "company-production-assets"
}

Rồi chạy:

code
terraform apply

Terraform sẽ nghĩ:

Bucket chưa tồn tại

Nó sẽ gửi API tạo mới.

AWS trả về:

BucketAlreadyExists

Hoặc:

BucketAlreadyOwnedByYou

Đây là lỗi rất phổ biến khi migrate sang Terraform.


Import không phải Migration hoàn chỉnh

Nhiều người nghĩ quy trình chỉ là:

terraform import

↓

Done

Thực tế không phải vậy.

Import mới chỉ là bước đầu.

Sau khi Import.

Bạn vẫn cần:

  • Viết Configuration đầy đủ
  • Đồng bộ thuộc tính
  • Kiểm tra Drift
  • Chạy Plan
  • Đảm bảo không có thay đổi ngoài ý muốn

Đó mới là quá trình migrate infrastructure sang Terraform.

Ở phần tiếp theo, chúng ta sẽ đi sâu vào toàn bộ workflow import trong production, tìm hiểu terraform import, import blocks của Terraform 1.5+, cách generate configuration và những lỗi phổ biến khi đưa hệ thống đang chạy vào Terraform.


# Workflow Import trong thực tế

Khi mới học Terraform, nhiều người thường nghĩ quy trình sẽ là:

Viết Configuration

Import

Done


Thực tế ở production, quy trình gần như ngược lại.

Xác định Resource

Viết Configuration

Import

Plan

Điều chỉnh Configuration

Plan = No changes

Commit


Mục tiêu cuối cùng luôn là:

> Terraform không tạo mới, không sửa gì ngoài ý muốn.

---

# Bước 1 - Xác định Resource cần Import

Đầu tiên, cần xác định chính xác resource muốn Terraform quản lý.

Ví dụ AWS có:

EC2 ID = i-0123456789


Hoặc

S3 Bucket company-assets


Hoặc

Cloudflare Zone

example.com


Điều quan trọng nhất là phải lấy đúng **ID** của resource.

Mỗi provider sẽ có cách định danh khác nhau.

Ví dụ:

AWS EC2

i-0123456789


AWS S3

company-assets


Cloudflare

zone_id


Vercel

project_id


Azure

Full Resource ID


Đọc tài liệu của provider luôn là bước đầu tiên.

---

# Bước 2 - Viết Terraform Configuration

Đây là điểm mà nhiều người làm sai.

Họ chạy Import trước.

Sau đó mới viết file `.tf`.

Điều này khiến project rất khó hiểu.

Thông thường nên tạo resource trước.

Ví dụ:

```hcl
resource "aws_s3_bucket" "assets" {
  bucket = "company-assets"
}

Hoặc:

code
resource "aws_instance" "web" {
 
}

Ban đầu có thể chưa đầy đủ.

Chỉ cần đúng tên resource.

Sau đó mới Import.


Bước 3 - Chạy terraform import

Ví dụ với EC2.

code
terraform import aws_instance.web i-0123456789

Ví dụ với S3.

code
terraform import aws_s3_bucket.assets company-assets

Terraform sẽ:

AWS API

↓

Read Resource

↓

Terraform State

Lưu ý.

Terraform không sửa gì trên AWS.

Nó chỉ ghi dữ liệu vào State.


Kiểm tra Terraform State

Sau khi Import.

Có thể xem State bằng:

code
terraform state list

Ví dụ:

aws_instance.web

aws_security_group.web

aws_s3_bucket.assets

Muốn xem chi tiết:

code
terraform state show aws_instance.web

Terraform sẽ hiển thị toàn bộ attribute.

Ví dụ:

instance_type = t3.micro

ami = ami-123456

availability_zone = ap-southeast-1a

private_ip = ...

...

Đây chính là thông tin Terraform đang lưu trong State.


Điều gì xảy ra khi chạy Plan?

Giả sử Configuration chỉ có:

code
resource "aws_instance" "web" {
 
}

Sau khi Import.

Chạy:

code
terraform plan

Terraform có thể hiển thị:

~ instance_type

~ ami

~ tags

~ monitoring

~ ebs_optimized

...

Rất nhiều thay đổi.

Không phải vì Import sai.

Mà vì Configuration còn thiếu.

Terraform đang so sánh:

Configuration

↓

State

↓

Infrastructure

Configuration chưa mô tả đầy đủ resource.

Terraform nghĩ cần sửa lại.


Bổ sung Configuration

Lúc này chúng ta cần cập nhật file Terraform.

Ví dụ:

code
resource "aws_instance" "web" {
  ami           = "ami-123456"
  instance_type = "t3.micro"
 
  tags = {
    Name = "production-web"
  }
}

Sau đó chạy:

code
terraform plan

Nếu vẫn còn thay đổi.

Tiếp tục bổ sung.

Lặp lại cho tới khi:

No changes.

Đây mới là trạng thái mong muốn.


Mục tiêu cuối cùng

Một quá trình Import thành công sẽ có kết quả:

Configuration

✓

State

✓

Infrastructure

✓

Ba thành phần hoàn toàn giống nhau.

Khi chạy:

code
terraform plan

Kết quả:

No changes.

Infrastructure is up-to-date.

Đây là thời điểm an toàn để commit source code.


Terraform 1.5 - Import Blocks

Trong nhiều năm.

Terraform chỉ hỗ trợ:

code
terraform import

Lệnh này hoạt động tốt.

Nhưng có một nhược điểm lớn.

Lịch sử Import không nằm trong source code.

Nếu đồng nghiệp clone project.

Họ sẽ không biết resource đã được Import như thế nào.

Terraform 1.5 giải quyết vấn đề này bằng Import Blocks.

Ví dụ:

code
import {
  to = aws_s3_bucket.assets
  id = "company-assets"
}

Sau đó chạy:

code
terraform plan

Terraform sẽ tự thực hiện Import.

Không cần chạy lệnh thủ công nữa.

Điều này giúp toàn bộ quá trình migrate infrastructure trở thành một phần của source code.


Generate Configuration tự động

Terraform còn hỗ trợ sinh Configuration từ resource đã tồn tại.

Ví dụ:

code
terraform plan \
  -generate-config-out=generated.tf

Terraform sẽ đọc resource.

Sau đó tạo file:

generated.tf

Trong file sẽ có:

code
resource "aws_s3_bucket" "assets" {
 
    ...
 
}

Đây là cách rất nhanh để bootstrap project Terraform từ hạ tầng hiện có.

Tuy nhiên.

Configuration được sinh ra thường khá dài.

Bao gồm rất nhiều giá trị mặc định.

Không nên commit trực tiếp.

Thay vào đó.

Hãy xem nó như một bản tham khảo.

Sau đó rút gọn lại thành style của team.


terraform import hay Import Blocks?

Hiện nay cả hai đều được hỗ trợ.

Nếu chỉ Import một vài resource.

Lệnh truyền thống vẫn rất nhanh.

terraform import

Nếu migrate cả một hệ thống lớn.

Import Blocks sẽ phù hợp hơn.

Bởi vì:

  • Có thể review qua Pull Request
  • Có lịch sử trong Git
  • Dễ lặp lại
  • Phù hợp CI/CD
  • Không cần nhớ các lệnh Import

Đây cũng là hướng HashiCorp khuyến khích sử dụng trong các phiên bản Terraform mới.

Những sai lầm phổ biến khi Import

Bản thân lệnh Import không quá phức tạp.

Điều khó nằm ở việc đồng bộ giữa Configuration, State và Infrastructure.

Đây cũng là nơi phần lớn lỗi xảy ra.


Sai lầm 1 - Import trước rồi mới viết Configuration

Đây là lỗi phổ biến nhất.

Ví dụ.

Chạy:

code
terraform import aws_instance.web i-0123456789

State sẽ có:

aws_instance.web

Nhưng project lại chưa có:

code
resource "aws_instance" "web" {
 
}

Sau vài tuần.

Một thành viên khác mở project.

Họ nhìn vào source code.

Không có EC2 nào cả.

Nhưng trong State lại tồn tại.

Điều này khiến project rất khó bảo trì.

Configuration luôn nên được viết trước.

Sau đó mới Import.


Sai lầm 2 - Import nhầm Resource Address

Ví dụ.

Configuration:

code
resource "aws_instance" "frontend" {
 
}

Nhưng lại chạy:

code
terraform import aws_instance.backend i-0123456789

Terraform sẽ báo lỗi.

Hoặc tệ hơn.

Import vào sai Resource Address.

Sau này rất khó hiểu resource nào đang đại diện cho infrastructure thực tế.

Resource Address phải khớp hoàn toàn với Configuration.


Sai lầm 3 - Chỉ Import một phần Infrastructure

Ví dụ.

Một EC2 thường đi kèm:

  • Security Group
  • IAM Role
  • Elastic IP
  • EBS Volume
  • Network Interface

Nhưng chỉ Import EC2.

EC2

✓ Imported

Security Group

✗

IAM Role

✗

Sau này.

Terraform sẽ cố tạo mới những resource còn thiếu.

Hoặc không thể resolve dependency.

Khi migrate.

Hãy xác định đầy đủ những resource liên quan.


Sai lầm 4 - Thấy Plan có thay đổi rồi Apply ngay

Sau khi Import.

Nhiều người chạy:

code
terraform plan

Terraform hiển thị:

~ instance_type

~ monitoring

~ tags

~ root_block_device

...

Thay vì tìm nguyên nhân.

Họ lại chạy:

code
terraform apply

Terraform sẽ bắt đầu sửa production.

Đây là một trong những lỗi nguy hiểm nhất.

Sau khi Import.

Mục tiêu luôn là:

terraform plan

↓

No changes

Nếu còn thay đổi.

Phải hiểu rõ lý do trước khi Apply.


Sai lầm 5 - Tin hoàn toàn vào generated.tf

Terraform có thể sinh Configuration.

Ví dụ:

code
terraform plan \
-generate-config-out=generated.tf

File được tạo thường rất dài.

Ví dụ:

code
resource "aws_instance" "web" {
 
  disable_api_stop = false
 
  monitoring = false
 
  ebs_optimized = false
 
  ...
 
}

Rất nhiều thuộc tính thực ra chỉ là giá trị mặc định.

Nếu commit toàn bộ.

Project sẽ trở nên khó đọc.

Configuration nên được tinh gọn.

Chỉ giữ những thuộc tính mà team thực sự muốn quản lý.


Sai lầm 6 - Import trực tiếp trên Production

Một số team làm như sau.

Production

↓

terraform import

↓

terraform apply

Nếu có sai sót.

Production sẽ bị ảnh hưởng ngay lập tức.

Quy trình tốt hơn là:

Clone Configuration

↓

Import

↓

Plan

↓

Review

↓

Commit

↓

CI/CD

↓

Production

Import cũng nên được review giống như code.


Workflow Production mà nhiều team sử dụng

Trong thực tế.

Việc migrate một hệ thống lớn thường diễn ra theo từng bước.

Inventory Resource

↓

Viết Terraform

↓

Import

↓

Plan

↓

Fix Configuration

↓

Plan = No Changes

↓

Pull Request

↓

Review

↓

Merge

↓

CI/CD

Điều đáng chú ý là.

Terraform chỉ được phép quản lý resource sau khi:

Plan

↓

No changes

Đây gần như là một quy tắc bất thành văn trong các team DevOps.


Khi nào nên Import?

Import phù hợp khi:

  • Bắt đầu áp dụng Terraform cho hệ thống cũ
  • Chuyển từ quản lý thủ công sang IaC
  • Tiếp quản hạ tầng từ team khác
  • Đưa resource được tạo bằng Console vào Terraform
  • Quản lý dịch vụ của bên thứ ba như Cloudflare, Vercel hoặc GitHub

Nếu toàn bộ infrastructure đều được tạo bằng Terraform ngay từ đầu.

Bạn gần như sẽ không cần Import.


Khi nào không nên Import?

Không phải resource nào cũng đáng để Import.

Ví dụ:

  • Resource tạm thời
  • Máy test
  • Sandbox
  • Hạ tầng chỉ tồn tại vài ngày
  • Resource được tạo tự động bởi dịch vụ khác

Việc Import những resource này chỉ khiến State trở nên phức tạp hơn.

Terraform nên quản lý những thành phần có vòng đời dài và thực sự cần được khai báo dưới dạng Infrastructure as Code.


Một góc nhìn thú vị

Terraform Import thường khiến nhiều người nghĩ rằng:

"Terraform đang học về Infrastructure."

Thực ra thì ngược lại.

Infrastructure không thay đổi.

Terraform chỉ đang cập nhật "trí nhớ" của mình.

Nếu ở bài về Terraform State chúng ta đã ví:

Configuration là ý định.

State là trí nhớ.

Thì Import chính là quá trình:

Đồng bộ trí nhớ của Terraform với thế giới thực.

Sau khi quá trình này hoàn tất.

Terraform mới có đủ thông tin để đưa ra Execution Plan chính xác.


Tổng kết

Import là một trong những tính năng quan trọng nhất của Terraform khi làm việc với hệ thống đã tồn tại.

Điều cần nhớ là:

  • Import không tạo resource mới
  • Import không chỉnh sửa infrastructure
  • Import chỉ ghi thông tin vào Terraform State
  • Configuration và State luôn phải đồng bộ
  • Chỉ Apply khi terraform plan trả về No changes
  • Với Terraform 1.5+, nên ưu tiên Import Blocks để toàn bộ quá trình Import được quản lý ngay trong source code

Khi hiểu đúng Import, bạn sẽ có thể từng bước chuyển đổi những hệ thống đang chạy ngoài thực tế sang Infrastructure as Code mà không cần xây dựng lại từ đầu.


Bài tiếp theo

Đến thời điểm này, chúng ta đã biết cách viết Terraform, tổ chức project, sử dụng Module và đưa hạ tầng hiện có vào Terraform.

Tuy nhiên, vẫn còn một vấn đề rất lớn.

Làm thế nào để nhiều người cùng làm việc trên một Terraform project mà không ghi đè State của nhau?

Làm sao để lưu Terraform State an toàn trên cloud, hỗ trợ locking và hoạt động tốt trong CI/CD?

Ở bài tiếp theo, chúng ta sẽ tìm hiểu về Remote State Backend, nền tảng không thể thiếu của bất kỳ dự án Terraform production nào.

Bình luận

0/2000

Đang tải bình luận…