Bước 4: EC2 Instance
Nội dung đang được chuẩn bị. Quay lại sớm nhé!
Sắp có trong bài này
Key Pair — SSH vào EC2
Tạo SSH key trên máy local trước:
ssh-keygen -t ed25519 -C "terraform-ec2" -f ~/.ssh/terraform-ec2
# Tạo ra: ~/.ssh/terraform-ec2 (private key) và ~/.ssh/terraform-ec2.pub (public key)
Khai báo trong Terraform:
# main.tf
resource "aws_key_pair" "web" {
key_name = "${local.name_prefix}-key"
public_key = file("~/.ssh/terraform-ec2.pub") # Chỉ upload PUBLIC key
}
Private key không commit lên Git
~/.ssh/terraform-ec2 là private key — không bao giờ commit lên Git.
Chỉ khai báo public_key trong Terraform.
IAM Role cho EC2 (SSM Access)
# IAM Role
resource "aws_iam_role" "ec2_role" {
name = "${local.name_prefix}-ec2-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = { Service = "ec2.amazonaws.com" }
}]
})
}
# Attach SSM policy — cho phép connect qua AWS Systems Manager (không cần SSH)
resource "aws_iam_role_policy_attachment" "ssm" {
role = aws_iam_role.ec2_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
# Instance Profile — wrap role để gán cho EC2
resource "aws_iam_instance_profile" "web" {
name = "${local.name_prefix}-instance-profile"
role = aws_iam_role.ec2_role.name
}
Data Source — lấy AMI mới nhất
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
}
EC2 Instance với User Data
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.web.id]
key_name = aws_key_pair.web.key_name
iam_instance_profile = aws_iam_instance_profile.web.name
# Script chạy khi instance khởi động lần đầu
user_data = <<-EOF
#!/bin/bash
yum update -y
yum install -y nginx
systemctl start nginx
systemctl enable nginx
echo "<h1>Hello from Terraform EC2 - ${var.environment}</h1>" > /usr/share/nginx/html/index.html
EOF
# Prevent replace khi user_data thay đổi nhỏ
user_data_replace_on_change = true
root_block_device {
volume_type = "gp3"
volume_size = 20
delete_on_termination = true
encrypted = true
}
tags = { Name = "${local.name_prefix}-web-server" }
}
outputs.tf
output "instance_public_ip" {
description = "Public IP của EC2 instance"
value = aws_instance.web.public_ip
}
output "instance_public_dns" {
description = "Public DNS của EC2 instance"
value = aws_instance.web.public_dns
}
output "ssh_command" {
description = "Lệnh SSH kết nối vào EC2"
value = "ssh -i ~/.ssh/terraform-ec2 ec2-user@${aws_instance.web.public_ip}"
}
output "web_url" {
description = "URL truy cập web server"
value = "http://${aws_instance.web.public_ip}"
}
Apply và kiểm tra
terraform plan
terraform apply
# Sau apply, kiểm tra output
terraform output ssh_command
terraform output web_url
# SSH vào EC2
ssh -i ~/.ssh/terraform-ec2 ec2-user@<IP>
# Kiểm tra Nginx
curl http://<IP>
Commit
git add main.tf outputs.tf
git commit -m "feat(ec2): thêm EC2 instance với Nginx và IAM role"