Chạy Script Tự Động Khi EC2 Khởi Động: Hướng Dẫn User Data Thực Tế
Bạn vừa launch một EC2 instance mới và muốn Nginx được cài đặt sẵn ngay khi máy chủ khởi động lần đầu — không cần SSH vào tay, không cần chạy lệnh thủ công. Đây là bài toán cực kỳ phổ biến trong production, và EC2 User Data chính là cơ chế giải quyết nó một cách sạch sẽ nhất.
TL;DR — Tóm Tắt Nhanh
| Bước | Hành động | Lưu ý quan trọng |
|---|---|---|
| 1 | Soạn shell script cài Nginx | Dòng đầu phải là #!/bin/bash |
| 2 | Dán vào ô 'User Data' khi launch instance | EC2 Console → Advanced Details → User Data |
| 3 | Script chạy một lần duy nhất lúc first boot | Chạy với quyền root, không cần sudo |
| 4 | Kiểm tra log tại /var/log/cloud-init-output.log | Đây là nơi debug khi script không chạy đúng |
EC2 User Data Hoạt Động Như Thế Nào
Trước khi paste script vào console, cần hiểu đúng cơ chế để tránh những lỗi ngớ ngẩn mà ai cũng từng gặp ít nhất một lần.
Khi một EC2 instance khởi động, dịch vụ cloud-init chạy rất sớm trong quá trình boot — trước khi bạn có thể SSH vào. Cloud-init đọc User Data từ Instance Metadata Service (IMDS) tại địa chỉ http://169.254.169.254/latest/user-data, sau đó thực thi nội dung đó.
Mặc định, User Data script chỉ chạy một lần duy nhất trong lần boot đầu tiên sau khi instance được tạo. Nếu bạn stop rồi start lại instance, script sẽ không chạy lại — trừ khi bạn cấu hình cloud-init để làm vậy.
- EC2 Launch: AWS tạo instance, gắn User Data vào metadata của instance.
- cloud-init khởi động: Dịch vụ này chạy trong quá trình boot, truy vấn IMDS để lấy User Data.
- Script thực thi: Shell script chạy với quyền root. Output được ghi vào
/var/log/cloud-init-output.log. - Instance sẵn sàng: Sau khi script hoàn thành, instance chuyển sang trạng thái running bình thường.
- Stop/Start lại: Script không tự chạy lại — đây là hành vi mặc định của cloud-init.
Viết User Data Script Cài Nginx
Script dưới đây cài Nginx trên Amazon Linux 2 hoặc Amazon Linux 2023. Lưu ý rằng package manager và tên service có thể khác nhau tùy AMI — ví dụ Ubuntu dùng apt-get thay vì dnf hay yum.
Cho Amazon Linux 2023 / Amazon Linux 2:
#!/bin/bash
# Cập nhật package list
dnf update -y
# Cài đặt Nginx
dnf install -y nginx
# Khởi động Nginx ngay lập tức
systemctl start nginx
# Bật Nginx tự khởi động cùng hệ thống
systemctl enable nginx
Cho Ubuntu 22.04 / 24.04:
#!/bin/bash
# Cập nhật package list
apt-get update -y
# Cài đặt Nginx
apt-get install -y nginx
# Khởi động Nginx ngay lập tức
systemctl start nginx
# Bật Nginx tự khởi động cùng hệ thống
systemctl enable nginx
Dòng #!/bin/bash (shebang) là bắt buộc — nếu thiếu dòng này, cloud-init sẽ không biết dùng interpreter nào để chạy script và có thể bỏ qua hoàn toàn.
Dán User Data Vào EC2 Console — Từng Bước
Đây là phần mà nhiều người mất thời gian tìm vì AWS Console thay đổi giao diện khá thường xuyên. Ô User Data nằm khá sâu trong wizard launch instance.
- Vào EC2 Console → chọn Launch Instances.
- Điền tên, chọn AMI và instance type như bình thường.
- Cuộn xuống phần Advanced Details — click để mở rộng.
- Tìm ô User Data ở gần cuối phần Advanced Details.
- Đảm bảo radio button 'As text' được chọn (không phải 'As file').
- Paste toàn bộ script vào ô đó, bao gồm cả dòng
#!/bin/bash. - Hoàn tất các cấu hình còn lại (Security Group, Key Pair, v.v.) rồi launch.
- Launch Instances: Điểm bắt đầu trong EC2 Console.
- Advanced Details: Section cần mở rộng để thấy ô User Data.
- User Data field: Paste script vào đây, chọn 'As text'.
- Launch: Instance được tạo với User Data đã gắn kèm.
Cài Nginx Qua AWS CLI Với User Data
Nếu bạn cần tự động hóa việc launch instance trong CI/CD pipeline hoặc Infrastructure as Code, dùng AWS CLI sẽ tiện hơn nhiều so với console.
aws ec2 run-instances \
--image-id ami-0c02fb55956c7d316 \
--instance-type t3.micro \
--key-name my-key-pair \
--security-group-ids sg-0123456789abcdef0 \
--subnet-id subnet-0123456789abcdef0 \
--user-data file://nginx-install.sh \
--region us-east-1
Trong đó nginx-install.sh là file chứa shell script ở trên. Tham số --user-data file:// cho phép truyền nội dung file trực tiếp — AWS CLI sẽ tự động encode Base64 trước khi gửi lên API.
Nghĩ về User Data như một tờ giấy ghi chú bạn nhét vào tay nhân viên mới trước ca làm việc đầu tiên. Họ đọc và làm theo đúng một lần — sau đó tờ giấy không còn tác dụng nữa, dù họ có nghỉ rồi đi làm lại.
Kiểm Tra Và Debug Khi Script Không Chạy Đúng
Script chạy trong background lúc boot, không có terminal để xem output trực tiếp. File log duy nhất bạn cần quan tâm là /var/log/cloud-init-output.log.
SSH vào instance sau khi nó chuyển sang trạng thái running, rồi chạy:
# Xem toàn bộ output của User Data script
cat /var/log/cloud-init-output.log
# Xem trạng thái cloud-init
cloud-init status
# Kiểm tra Nginx đã chạy chưa
systemctl status nginx
Nếu cloud-init status trả về done nhưng Nginx không chạy, lỗi thường nằm trong script — sai tên package, thiếu quyền, hoặc network chưa sẵn sàng khi script chạy. Đọc log từ trên xuống để tìm dòng lỗi đầu tiên.
Một lỗi hay gặp khác: bạn thấy instance đã running nhưng log vẫn trống. Điều này thường xảy ra khi Security Group chặn outbound traffic, khiến dnf install không kết nối được đến repository — script bị treo hoặc fail ngay bước cài package mà không có thông báo rõ ràng.
Kinh Nghiệm Thực Tế: Sai Lầm Phổ Biến Và Cách Sửa
Triệu chứng: Instance running, SSH được, nhưng Nginx không có mặt. Log cloud-init-output.log cho thấy script bắt đầu chạy nhưng dừng đột ngột ở bước dnf install.
Chẩn đoán ban đầu (sai): Nhiều người nghĩ ngay đến AMI không tương thích hoặc script có lỗi cú pháp. Họ sửa script, launch lại instance nhiều lần — vẫn thất bại.
Nguyên nhân thực sự: Security Group của instance không có outbound rule cho HTTPS (port 443) hoặc HTTP (port 80). Lệnh dnf install nginx cần kết nối ra ngoài để tải package từ AWS repository. Khi outbound bị chặn, lệnh timeout sau vài phút và script dừng lại — không có error message rõ ràng trong log.
Cách fix: Kiểm tra Security Group outbound rules. Đảm bảo có rule cho phép 0.0.0.0/0 trên port 443 và 80, hoặc ít nhất là đến các IP của AWS package repository. Sau đó terminate instance cũ và launch lại với script không thay đổi.
# Kiểm tra outbound rules của Security Group
aws ec2 describe-security-groups \
--group-ids sg-0123456789abcdef0 \
--query 'SecurityGroups[*].IpPermissionsEgress' \
--region us-east-1
Script không lỗi — môi trường mới là vấn đề. Đây là lý do tại sao debug User Data luôn phải bắt đầu từ network, không phải từ script.
Xem Lại User Data Của Instance Đang Chạy
Nếu bạn cần kiểm tra User Data đã được gắn vào instance nào đó, có hai cách:
Từ bên trong instance (truy vấn IMDS):
# IMDSv2 — cách được khuyến nghị hiện tại
TOKEN=$(curl -s -X PUT 'http://169.254.169.254/latest/api/token' \
-H 'X-aws-ec2-metadata-token-ttl-seconds: 21600')
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/user-data
Từ AWS CLI bên ngoài:
aws ec2 describe-instance-attribute \
--instance-id i-0123456789abcdef0 \
--attribute userData \
--query 'UserData.Value' \
--output text \
--region us-east-1 | base64 --decode
User Data được lưu dưới dạng Base64 encoded — lệnh base64 --decode ở cuối giải mã về dạng text đọc được.
Cập Nhật User Data Sau Khi Instance Đã Tạo
Bạn có thể sửa User Data của một instance đã tồn tại, nhưng instance phải ở trạng thái stopped. Script mới sẽ không tự chạy lại khi start lại — đây là hành vi mặc định của cloud-init.
# Bước 1: Stop instance trước
aws ec2 stop-instances \
--instance-ids i-0123456789abcdef0 \
--region us-east-1
# Bước 2: Cập nhật User Data (truyền nội dung mới dưới dạng Base64)
aws ec2 modify-instance-attribute \
--instance-id i-0123456789abcdef0 \
--user-data file://new-script.sh \
--region us-east-1
Nếu bạn cần script chạy lại trong mỗi lần boot (ví dụ để cập nhật config), đó là trường hợp dùng cloud-init directives hoặc cơ chế khác như AWS Systems Manager Run Command — User Data đơn thuần không phải công cụ phù hợp cho use case đó.
Chạy Script EC2 Startup Đúng Cách — Tổng Kết Và Bước Tiếp Theo
EC2 User Data là cách đơn giản và hiệu quả nhất để tự động hóa việc cài đặt phần mềm khi instance khởi động lần đầu. Với Nginx hay bất kỳ package nào khác, quy trình đều giống nhau: viết shell script với shebang, paste vào ô User Data trong Advanced Details, kiểm tra log tại /var/log/cloud-init-output.log khi cần debug.
Khi hệ thống phức tạp hơn — nhiều instance, nhiều môi trường — hãy xem xét chuyển sang AWS Systems Manager State Manager hoặc tích hợp User Data với AWS CloudFormation cfn-init để có khả năng quản lý cấu hình tốt hơn. Tài liệu tham khảo chính thức: AWS EC2 User Guide — Run commands on your Linux instance at launch.
Glossary — Các Thuật Ngữ Quan Trọng
| Thuật ngữ | Giải thích |
|---|---|
| User Data | Script hoặc dữ liệu được truyền vào EC2 instance khi launch, thực thi bởi cloud-init trong lần boot đầu tiên. |
| cloud-init | Công cụ khởi tạo instance tiêu chuẩn trên Linux, chịu trách nhiệm đọc và thực thi User Data. |
| IMDS (Instance Metadata Service) | Endpoint nội bộ tại 169.254.169.254 cung cấp metadata và User Data cho instance. |
Shebang (#!/bin/bash) | Dòng đầu tiên của shell script, chỉ định interpreter sẽ được dùng để thực thi script. |
| IMDSv2 | Phiên bản bảo mật hơn của IMDS, yêu cầu session token trước khi truy vấn metadata. |
Nhận xét
Đăng nhận xét