Lỗi Gặp Phải
Ứng dụng của bạn đang chạy trong một private VPC subnet. Nó gọi đến AWS Secrets Manager — và nhận ngay lỗi này:
EndpointConnectionError: Could not connect to the endpoint URL: https://secretsmanager.us-east-1.amazonaws.com
ConnectionError: HTTPSConnectionPool(host='secretsmanager.us-east-1.amazonaws.com', port=443): Max retries exceeded with url: / (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known'))
Lỗi này xuất hiện trong logs của Lambda, trên EC2 instance trong private subnet, bên trong ECS task — bất kỳ nơi nào không có đường ra internet công cộng.
Nguyên Nhân
AWS SDK mặc định trỏ đến secretsmanager.<region>.amazonaws.com — một endpoint công khai. Các private subnet không có NAT Gateway hay Internet Gateway sẽ không có tuyến đường nào đến đó. DNS hoặc là không thể phân giải tên miền, hoặc quá trình bắt tay TCP đơn giản là không bao giờ hoàn thành.
Giải pháp: tạo một VPC Interface Endpoint (AWS PrivateLink) cho Secrets Manager. Nó sẽ đưa một địa chỉ IP private — ví dụ như 10.0.1.45 — vào DNS của VPC. Sau đó, secretsmanager.us-east-1.amazonaws.com sẽ phân giải thành một địa chỉ nằm bên trong VPC của bạn. Không cần qua internet nữa.
Hướng Dẫn Sửa Lỗi
Bước 1 — Xác nhận nguyên nhân gốc rễ
SSH vào instance bị ảnh hưởng (hoặc dùng ECS Exec / Lambda test) và thử kết nối trực tiếp đến endpoint:
# Kiểm tra có kết nối được đến public endpoint không?
curl -v https://secretsmanager.us-east-1.amazonaws.com
# Kiểm tra phân giải DNS
nslookup secretsmanager.us-east-1.amazonaws.com
Nếu thấy Could not resolve host hoặc kết nối bị treo — đã xác nhận: VPC không có tuyến đường đến AWS APIs và bạn cần tạo private endpoint.
Bước 2 — Tạo VPC Interface Endpoint
Trong AWS Console:
- Vào VPC → Endpoints → Create Endpoint
- Service category: AWS services
- Tìm
secretsmanager, chọncom.amazonaws.<region>.secretsmanager - Chọn VPC của bạn
- Chọn tất cả private subnet nơi workload của bạn chạy
- Gắn một Security Group cho phép inbound HTTPS (port 443) từ security group của workload
- Bật Private DNS — đây là phần quan trọng nhất
Muốn dùng CLI? Chạy lệnh sau:
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0abc123def456 \
--vpc-endpoint-type Interface \
--service-name com.amazonaws.us-east-1.secretsmanager \
--subnet-ids subnet-0aaa111 subnet-0bbb222 \
--security-group-ids sg-0xxxxxx \
--private-dns-enabled \
--region us-east-1
Đừng bỏ qua --private-dns-enabled. Nếu không có flag này, SDK vẫn sẽ cố kết nối đến public endpoint và bạn lại quay về điểm ban đầu.
Bước 3 — Bật DNS hostnames trên VPC
Private DNS chỉ hoạt động khi VPC đã bật cả DNS hostnames lẫn DNS resolution. Các VPC cũ đôi khi bị tắt những tùy chọn này. Kiểm tra trước:
# Kiểm tra cài đặt hiện tại
aws ec2 describe-vpc-attribute \
--vpc-id vpc-0abc123def456 \
--attribute enableDnsHostnames
aws ec2 describe-vpc-attribute \
--vpc-id vpc-0abc123def456 \
--attribute enableDnsSupport
# Bật nếu đang tắt
aws ec2 modify-vpc-attribute \
--vpc-id vpc-0abc123def456 \
--enable-dns-hostnames
aws ec2 modify-vpc-attribute \
--vpc-id vpc-0abc123def456 \
--enable-dns-support
Bước 4 — Cập nhật Security Group của endpoint
Interface endpoint là một network interface thực sự — nó có security group riêng. Port 443 phải được mở inbound từ các workload Lambda, EC2 hoặc ECS của bạn:
aws ec2 authorize-security-group-ingress \
--group-id sg-0endpoint-sg \
--protocol tcp \
--port 443 \
--source-group sg-0your-workload-sg \
--region us-east-1
Thiếu security group rule là một trong những nguyên nhân phổ biến nhất khiến endpoint đã tạo nhưng kết nối vẫn thất bại.
Bước 5 — Gắn Endpoint Policy (tùy chọn nhưng nên làm)
Mặc định, endpoint cấp quyền truy cập Secrets Manager đầy đủ cho mọi principal trong tài khoản của bạn. Hãy giới hạn lại đúng với những gì ứng dụng cần:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/MyAppRole"
},
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:MyApp/*"
}
]
}
Áp dụng qua Console (Endpoint → tab Policy) hoặc CLI:
aws ec2 modify-vpc-endpoint \
--vpc-endpoint-id vpce-0xxxxxxxxx \
--policy-document file://endpoint-policy.json
Kiểm Tra Kết Quả
Endpoint mất khoảng 1–2 phút để đạt trạng thái Available. Sau khi sẵn sàng, kiểm tra từ bên trong private subnet:
# DNS giờ sẽ phân giải thành IP private (10.x.x.x hoặc 172.x.x.x)
nslookup secretsmanager.us-east-1.amazonaws.com
# Lấy một secret — phải trả về kết quả ngay lập tức
aws secretsmanager get-secret-value \
--secret-id MyApp/prod/database \
--region us-east-1
# Hoặc dùng boto3
python3 -c "
import boto3
client = boto3.client('secretsmanager', region_name='us-east-1')
resp = client.get_secret_value(SecretId='MyApp/prod/database')
print(resp['SecretString'][:50])
"
Nếu nslookup trả về IP nằm trong dải VPC của bạn — ví dụ 10.0.1.45 thay vì IP công khai của AWS — và giá trị secret trả về bình thường, bạn đã xử lý xong.
Một Số Lưu Ý
Các endpoint khác bạn có thể cần thêm
Secrets Manager hiếm khi là dịch vụ AWS duy nhất mà workload trong private subnet gọi đến. Mỗi dịch vụ cần một VPC endpoint riêng — nếu không bạn lại phải dùng NAT Gateway. Các endpoint thường gặp:
com.amazonaws.<region>.kms— khi secret dùng customer-managed keycom.amazonaws.<region>.sts— để assume IAM rolecom.amazonaws.<region>.ssm— cho Parameter Store
Lập kế hoạch CIDR cho subnet
Trước khi gắn endpoint qua nhiều AZ, hãy kiểm tra kỹ các subnet CIDR đã được kích thước đúng và không bị chồng lấp. Công cụ Subnet Calculator trên ToolCraft chạy ngay trên trình duyệt rất tiện để xác minh nhanh các dải địa chỉ và đếm số IP khả dụng mà không cần tính toán nhị phân thủ công.
Chi phí cần cân nhắc
Interface endpoint không miễn phí: khoảng $0.01/giờ cho mỗi AZ, cộng thêm phí truyền dữ liệu. Trải đều trên ba AZ, mỗi endpoint tốn khoảng ~$21/tháng. Nếu bạn đang chạy hàng chục dịch vụ trong private subnet, một NAT Gateway duy nhất với chi phí cố định $32/tháng đôi khi lại rẻ hơn. Hãy tính toán dựa trên lưu lượng thực tế trước khi tạo endpoint riêng cho từng dịch vụ.
Snippet Terraform
Quản lý hạ tầng này dưới dạng code:
resource "aws_vpc_endpoint" "secretsmanager" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${var.region}.secretsmanager"
vpc_endpoint_type = "Interface"
subnet_ids = aws_subnet.private[*].id
security_group_ids = [aws_security_group.vpc_endpoint.id]
private_dns_enabled = true
tags = {
Name = "secretsmanager-endpoint"
}
}

