Sau khi hoàn tất bài thực hành, chúng ta tiến hành dọn dẹp toàn bộ tài nguyên đã được tạo ra.
Hãy đọc phần này kỹ trước khi bắt đầu. Việc xoá các CloudFormation Stack là chưa đủ. Có hai nhóm tài nguyên vẫn sót lại và tiếp tục phát sinh chi phí:
pattern3-pipeline sẽ thất bại ở trạng thái DELETE_FAILED nếu bạn chưa dọn bucket.Các Stack phụ thuộc lẫn nhau thông qua Export và Fn::ImportValue, nên bắt buộc phải xoá theo đúng thứ tự ngược lại với lúc tạo. Nếu xoá pattern3-base trước, CloudFormation sẽ từ chối vì các giá trị Export vẫn đang được Stack khác sử dụng.
| Thứ tự | Stack | Ghi chú |
|---|---|---|
| 1 | pattern3-automate | Xoá được ngay |
| 2 | (không phải Stack) | Xoá AMI và EBS Snapshot do Image Builder tạo |
| 3 | pattern3-pipeline | Phải dọn rỗng S3 bucket trước |
| 4 | pattern3-app | Mất khoảng 5 đến 10 phút |
| 5 | pattern3-base | Xoá NAT Gateway, Elastic IP, VPC |
Từ CloudFormation Console, xoá Stack pattern3-automate. Hoặc dùng CLI:
aws cloudformation delete-stack --stack-name pattern3-automate --region ap-southeast-2
aws cloudformation wait stack-delete-complete --stack-name pattern3-automate --region ap-southeast-2
Đây là bước quan trọng nhất về mặt chi phí. Mỗi lần pipeline chạy thành công đều sinh ra một AMI kèm một EBS Snapshot, và snapshot vẫn bị tính phí lưu trữ vô thời hạn cho đến khi bạn xoá.
Liệt kê các AMI do bạn sở hữu để xác định AMI cần xoá:
aws ec2 describe-images --owners self --region ap-southeast-2 --query "Images[].{Id:ImageId,Name:Name,Created:CreationDate}" --output table
Với mỗi AMI, thu thập ID của các snapshot đi kèm rồi hủy đăng ký AMI:
AMI_ID=ami-xxxxxxxxxxxxxxxxx
SNAPSHOTS=$(aws ec2 describe-images --image-ids "$AMI_ID" --region ap-southeast-2 --query "Images[0].BlockDeviceMappings[].Ebs.SnapshotId" --output text)
aws ec2 deregister-image --image-id "$AMI_ID" --region ap-southeast-2
for SNAP in $SNAPSHOTS; do
aws ec2 delete-snapshot --snapshot-id "$SNAP" --region ap-southeast-2
done
$AMI_ID = 'ami-xxxxxxxxxxxxxxxxx'
$SNAPSHOTS = (aws ec2 describe-images --image-ids $AMI_ID --region ap-southeast-2 --query "Images[0].BlockDeviceMappings[].Ebs.SnapshotId" --output text) -split '\s+'
aws ec2 deregister-image --image-id $AMI_ID --region ap-southeast-2
foreach ($SNAP in $SNAPSHOTS) {
if ($SNAP) { aws ec2 delete-snapshot --snapshot-id $SNAP --region ap-southeast-2 }
}
Hãy hủy đăng ký AMI trước, rồi mới xoá snapshot. Làm ngược lại sẽ để lại một AMI hỏng không thể khởi chạy.
Ngoài ra, --owners self chỉ trả về AMI do chính bạn tạo, nên lệnh trên sẽ không ảnh hưởng đến các AMI công khai của Amazon. Tuy vậy, nếu tài khoản này còn AMI của công việc khác, hãy đối chiếu cột Name để chỉ xoá đúng AMI của bài thực hành.
Image Builder có hai loại ARN khác nhau, rất dễ nhầm.
| Loại | Dạng ARN | Lệnh trả về |
|---|---|---|
| Image version | .../image/<ten-recipe>/1.0.0 | list-images |
| Image build version | .../image/<ten-recipe>/1.0.0/2 | list-image-build-versions |
1.0.0 là phiên bản của recipe, còn số cuối là lần build thứ mấy của phiên bản đó. Chạy pipeline 3 lần sẽ tạo ra 1.0.0/1, 1.0.0/2, 1.0.0/3.
Lệnh delete-image chỉ nhận image build version ARN, tức là dạng có số build ở cuối. Nếu bạn truyền ARN lấy từ list-images thì sẽ gặp lỗi:
An error occurred (InvalidParameterValueException) when calling the DeleteImage operation:
The value supplied for parameter 'imageBuildVersionArn' is not valid.
The supplied Arn is not a valid Image Builder Image Build Version Arn.
Vì vậy phải qua hai bước: lấy image version ARN trước, rồi từ đó liệt kê các build version.
# Buoc 1: lay danh sach image version ARN
aws imagebuilder list-images --owner Self --region ap-southeast-2 --query "imageVersionList[].arn" --output text
# Buoc 2: voi moi image version, liet ke cac build version roi xoa tat ca
for VER in $(aws imagebuilder list-images --owner Self --region ap-southeast-2 --query "imageVersionList[].arn" --output text); do
for BUILD in $(aws imagebuilder list-image-build-versions --image-version-arn "$VER" --region ap-southeast-2 --query "imageSummaryList[].arn" --output text); do
echo "Dang xoa $BUILD"
aws imagebuilder delete-image --image-build-version-arn "$BUILD" --region ap-southeast-2
done
done
# Buoc 1: lay danh sach image version ARN
$VERSIONS = (aws imagebuilder list-images --owner Self --region ap-southeast-2 --query "imageVersionList[].arn" --output text) -split '\s+'
# Buoc 2: voi moi image version, liet ke cac build version roi xoa tat ca
foreach ($VER in $VERSIONS) {
if (-not $VER) { continue }
$BUILDS = (aws imagebuilder list-image-build-versions --image-version-arn $VER --region ap-southeast-2 --query "imageSummaryList[].arn" --output text) -split '\s+'
foreach ($BUILD in $BUILDS) {
if (-not $BUILD) { continue }
Write-Output "Dang xoa $BUILD"
aws imagebuilder delete-image --image-build-version-arn $BUILD --region ap-southeast-2
}
}
DELETE_FAILED:BUCKET=$(aws cloudformation describe-stacks --stack-name pattern3-pipeline --region ap-southeast-2 --query "Stacks[0].Outputs[?OutputKey=='Pattern3LoggingBucketName'].OutputValue" --output text)
echo "Logging bucket: $BUCKET"
aws s3 rm "s3://${BUCKET}" --recursive --region ap-southeast-2
$BUCKET = aws cloudformation describe-stacks --stack-name pattern3-pipeline --region ap-southeast-2 --query "Stacks[0].Outputs[?OutputKey=='Pattern3LoggingBucketName'].OutputValue" --output text
Write-Output "Logging bucket: $BUCKET"
aws s3 rm "s3://$BUCKET" --recursive --region ap-southeast-2
aws cloudformation delete-stack --stack-name pattern3-pipeline --region ap-southeast-2
aws cloudformation wait stack-delete-complete --stack-name pattern3-pipeline --region ap-southeast-2
Nếu bạn làm phần 4 và phần 5 thủ công từ Console, hãy xoá các tài nguyên đó ở đây, trước khi sang Bước 5. CloudFormation không quản lý chúng nên xoá Stack sẽ không dọn được.
| Tài nguyên | Lệnh xoá |
|---|---|
| Image pipeline | aws imagebuilder delete-image-pipeline --image-pipeline-arn <ARN> |
| Image recipe | aws imagebuilder delete-image-recipe --image-recipe-arn <ARN> |
| Component | aws imagebuilder delete-component --component-build-version-arn <ARN> |
| Infrastructure configuration | aws imagebuilder delete-infrastructure-configuration --infrastructure-configuration-arn <ARN> |
| SSM Automation document | aws ssm delete-document --name pattern3-automate-CreateImage |
| S3 bucket | aws s3 rb s3://<TEN_BUCKET> --force |
| Security group | aws ec2 delete-security-group --group-id <SG_ID> |
| IAM role | Xoá instance profile, detach policy, xoá inline policy, rồi mới xoá role |
Security group là cái quan trọng nhất phải xoá trước Bước 5. Nó nằm trong VPC của pattern3-base, và AWS không cho xoá một VPC nào còn security group không phải default bên trong. Bỏ sót nó thì Stack pattern3-base sẽ dừng ở DELETE_FAILED.
Xoá IAM Role bằng bốn lệnh theo đúng thứ tự:
ROLE=pattern3-recipe-instance-role
aws iam remove-role-from-instance-profile --instance-profile-name $ROLE --role-name $ROLE
aws iam delete-instance-profile --instance-profile-name $ROLE
aws iam detach-role-policy --role-name $ROLE --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
aws iam detach-role-policy --role-name $ROLE --policy-arn arn:aws:iam::aws:policy/EC2InstanceProfileForImageBuilder
aws iam delete-role-policy --role-name $ROLE --policy-name pattern3-recipe-instance-policy
aws iam delete-role --role-name $ROLE
Bước này sẽ xoá Application Load Balancer, Auto Scaling Group, Launch Template, các EC2 instance và IAM Role đi kèm.
aws cloudformation delete-stack --stack-name pattern3-app --region ap-southeast-2
aws cloudformation wait stack-delete-complete --stack-name pattern3-app --region ap-southeast-2
Quá trình mất khoảng 5 đến 10 phút vì phải chờ Auto Scaling Group hạ số lượng instance về 0 và Load Balancer hủy đăng ký các target.
Bước cuối cùng sẽ xoá NAT Gateway, Elastic IP, Internet Gateway, Subnets và VPC.
aws cloudformation delete-stack --stack-name pattern3-base --region ap-southeast-2
aws cloudformation wait stack-delete-complete --stack-name pattern3-base --region ap-southeast-2
NAT Gateway là tài nguyên tốn phí nhiều nhất của bài thực hành này, tính theo giờ kể cả khi không có lưu lượng đi qua. Hãy chắc chắn Stack pattern3-base đã ở trạng thái DELETE_COMPLETE.
Chạy các lệnh sau, tất cả đều phải trả về kết quả rỗng:
# Khong con Stack nao cua bai thuc hanh
aws cloudformation describe-stacks --region ap-southeast-2 --query "Stacks[?starts_with(StackName, 'pattern3')].{Name:StackName,Status:StackStatus}" --output table
# Khong con AMI nao do minh so huu
aws ec2 describe-images --owners self --region ap-southeast-2 --query "Images[].ImageId" --output text
# Khong con EBS Snapshot nao do minh so huu
aws ec2 describe-snapshots --owner-ids self --region ap-southeast-2 --query "Snapshots[].SnapshotId" --output text
# Khong con NAT Gateway nao dang hoat dong
aws ec2 describe-nat-gateways --region ap-southeast-2 --filter "Name=state,Values=available,pending" --query "NatGateways[].NatGatewayId" --output text
# Khong con Elastic IP nao chua duoc gan
aws ec2 describe-addresses --region ap-southeast-2 --query "Addresses[?AssociationId==null].PublicIp" --output text
Sau khi dọn xong, bạn nên kiểm tra lại AWS Cost Explorer hoặc Billing Dashboard sau 24 giờ để chắc chắn không còn tài nguyên nào phát sinh chi phí.
Chúc mừng bạn đã hoàn thành bài thực hành.