Sửa lỗi Terraform 'no matching EC2 instances found' khi Data Source Filter không trả về kết quả

intermediate🏗️ Terraform2026-06-27| Terraform 1.x, AWS Provider 4.x / 5.x, Linux / macOS / Windows

Error Message

Error: no matching EC2 instances found With the criteria passed, no matching EC2 instances were found. Please change your search criteria and try again.
#terraform#data-source#aws#filter

Tình Huống

Bạn chạy terraform plan và nó chết ngay lập tức:

Error: no matching EC2 instances found

With the criteria passed, no matching EC2 instances were found. Please change your search criteria and try again.

Instance vẫn đang hiển thị trên AWS Console. Bạn nhìn thấy nó. Terraform thì không. Lúc này là 2 giờ sáng và quá trình deploy đang bị chặn.

Chuyện Gì Đang Xảy Ra

data "aws_instance" của Terraform — cùng với các data source tương tự như aws_ami, aws_subnet, aws_security_group — chuyển đổi các filter block của bạn thành một lời gọi AWS API. Khi không có resource nào khớp đồng thời tất cả các điều kiện, Terraform dừng hoàn toàn. Không có fallback. Không có cảnh báo. Chỉ là chết.

Một block có thể kích hoạt lỗi này:

data "aws_instance" "app_server" {
  filter {
    name   = "tag:Name"
    values = ["my-app-server"]
  }

  filter {
    name   = "instance-state-name"
    values = ["running"]
  }
}

Mỗi filter block là một điều kiện AND. Chỉ cần một filter sai — tag viết sai hoa thường, instance đã dừng, sai region — là bạn nhận về kết quả rỗng.

Bước 1: Xác Minh Resource Tồn Tại Với Đúng Tiêu Chí

Trước khi động vào Terraform, hãy tái hiện lại query bằng AWS CLI. Cách này cho bạn biết ngay lập tức Terraform có bị lỗi không, hay hạ tầng của bạn đơn giản là không khớp với những gì bạn nghĩ:

aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=my-app-server" \
            "Name=instance-state-name,Values=running" \
  --query "Reservations[*].Instances[*].{ID:InstanceId,State:State.Name,Tags:Tags}" \
  --output table

Không có kết quả trả về? Terraform đúng — resource không khớp với tiêu chí của bạn trên AWS lúc này. Hãy kiểm tra trạng thái instance:

aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=my-app-server" \
  --query "Reservations[*].Instances[*].{ID:InstanceId,State:State.Name}" \
  --output table

Nếu hiển thị stopped hoặc terminated, đó là câu trả lời — filter instance-state-name đang loại bỏ nó. Hãy khởi động lại instance hoặc xóa filter đó đi.

Bước 2: Kiểm Tra Region

Nhầm lẫn region xảy ra với nhiều người hơn bạn nghĩ. Instance nằm ở us-west-2 nhưng provider hoặc môi trường shell đang trỏ tới us-east-1. Kết quả rỗng, không có thông báo lỗi hữu ích.

aws ec2 describe-instances \
  --region us-west-2 \
  --filters "Name=tag:Name,Values=my-app-server" \
  --output table

Xác nhận region của provider trong Terraform khớp với nơi resource thực sự tồn tại:

provider "aws" {
  region = "us-west-2"  # must match the resource's actual region
}

Cần tham chiếu resource ở region khác với provider mặc định? Bạn cần dùng aliased provider:

provider "aws" {
  alias  = "us_west"
  region = "us-west-2"
}

data "aws_instance" "app_server" {
  provider = aws.us_west

  filter {
    name   = "tag:Name"
    values = ["my-app-server"]
  }
}

Các Lỗi Filter Thường Gặp

Giá Trị Tag Phân Biệt Hoa Thường

Giá trị tag trong AWS phân biệt chữ hoa và chữ thường. my-app-serverMy-App-Server là hai tag khác nhau theo API. Hãy lấy giá trị thực tế từ tài khoản của bạn để chắc chắn:

aws ec2 describe-instances \
  --query "Reservations[*].Instances[*].Tags[?Key=='Name'].Value" \
  --output text | sort

Sao chép giá trị chính xác từ output. Đừng gõ lại bằng tay.

Sai Cú Pháp Tên Filter Cho Tag

Filter tag yêu cầu tiền tố tag: — không thể bỏ qua:

# SAI — "Name" là EC2 filter cho tên resource, không phải tag
filter {
  name   = "Name"
  values = ["my-server"]
}

# ĐÚNG
filter {
  name   = "tag:Name"
  values = ["my-server"]
}

Nhiều Giá Trị Là OR, Nhiều Block Là AND

Nhiều giá trị trong một filter block = OR. Nhiều filter block = AND. Nhầm lẫn hai cái này khiến filter của bạn âm thầm hoạt động khác với ý định:

# OR: tìm instance tên "server-a" HOẶC "server-b"
filter {
  name   = "tag:Name"
  values = ["server-a", "server-b"]
}

# AND: tìm instance có đúng tên VÀ đang ở us-west-2a
filter {
  name   = "tag:Name"
  values = ["my-app-server"]
}
filter {
  name   = "availability-zone"
  values = ["us-west-2a"]
}

AMI: Quá Nhiều Kết Quả Cũng Là Lỗi

Data source aws_ami lại gặp vấn đề ngược lại: filter khớp nhiều AMI cũng sẽ báo lỗi. Hãy giới hạn bằng most_recent = true:

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }
}

Sửa Nhanh: Cô Lập Filter Bị Lỗi

Comment từng filter một cho đến khi data source giải quyết được. Bắt đầu với filter cụ thể nhất:

data "aws_instance" "app_server" {
  filter {
    name   = "tag:Name"
    values = ["my-app-server"]
  }

  # Tạm thời vô hiệu hóa để cô lập vấn đề
  # filter {
  #   name   = "instance-state-name"
  #   values = ["running"]
  # }
}

Khi terraform plan chạy thành công, thêm từng filter trở lại một lần. Filter nào làm nó lỗi lại chính là thủ phạm.

Sửa Lâu Dài: Dùng Data Source Số Nhiều

Hạ tầng có điều kiện, triển khai blue/green, instance bị dừng định kỳ — với những pattern như vậy, data source số ít sẽ tiếp tục gây lỗi. Hãy chuyển sang aws_instances (số nhiều). Danh sách rỗng, không có lỗi:

data "aws_instances" "app_servers" {
  filter {
    name   = "tag:Name"
    values = ["my-app-server"]
  }

  filter {
    name   = "instance-state-name"
    values = ["running"]
  }
}

locals {
  app_server_id = length(data.aws_instances.app_servers.ids) > 0 ? data.aws_instances.app_servers.ids[0] : null
}

Terraform plan chạy sạch. Xử lý trường hợp null một cách rõ ràng ở các bước tiếp theo — ít nhất pipeline không còn bị chặn nữa.

Các data source bắt buộc — shared VPC, base AMI, security group được khóa chặt — xứng đáng được thêm comment. Khi chúng lỗi lúc nửa đêm, comment đó là ranh giới giữa sửa trong 5 phút và mò mẫm 45 phút:

data "aws_instance" "app_server" {
  # Yêu cầu: EC2 instance được gắn tag Name=my-app-server ở trạng thái running.
  # Thuộc infra-base workspace — khởi động instance ở đó nếu lệnh này thất bại.
  filter {
    name   = "tag:Name"
    values = ["my-app-server"]
  }

  filter {
    name   = "instance-state-name"
    values = ["running"]
  }
}

Xác Nhận Bản Sửa

Chỉ target data source để xác nhận nó giải quyết được trước khi chạy full plan:

terraform plan -target='data.aws_instance.app_server'

Thêm debug output để kiểm tra kết quả tìm được:

output "debug_instance_id" {
  value = data.aws_instance.app_server.id
}

Chạy terraform output debug_instance_id sau khi apply. Một instance ID hợp lệ như i-0abc123def456 xác nhận data source đang giải quyết đúng. Xóa output này trước khi commit — nó làm lộ infrastructure ID vào state file một cách không cần thiết.

Related Error Notes