Triển Khai Hệ Thống AWS ECS Với AWS CLI (Phần 2)
Tạo Relational Database Service
Tổng quan
Dịch vụ cơ sở dữ liệu quan hệ của Amazon (Amazon RDS) là một tập hợp các dịch vụ được quản lý giúp bạn dễ dàng thiết lập, vận hành và điều chỉnh quy mô cơ sở dữ liệu trên đám mây.
Trong phần này, chúng ta sẽ thiết lập Dịch vụ Cơ sở dữ liệu Quan hệ (RDS) trên AWS
Quy trình
-
Tạo RDS Subnet Group
Trong phần này, chúng ta tạo một RDS Subnet Group
rds_subnet_group_name=$project-subnet-group rds_subnet_group_descript="Subnet Group for Postgres RDS" rds_subnet1_id=$subnet_private_1 rds_subnet2_id=$subnet_private_2 # Create Subnet group aws rds create-db-subnet-group \ --db-subnet-group-name $rds_subnet_group_name \ --db-subnet-group-description "$rds_subnet_group_descript" \ --subnet-ids $rds_subnet1_id $rds_subnet2_id \ --tags "$tags"
Trong mã trên:
rds_subnet_group_name
: Đây là tên của Nhóm Subnet RDS, dựa trên biến$project
.aws rds create-db-subnet-group
: Dòng này tạo một Nhóm Subnet RDS với tên và mô tả được chỉ định, và liên kết nó với các subnet riêng tư.
-
Deploy RDS
Trong phần này, chúng ta triển khai Dịch vụ Cơ sở dữ liệu Quan hệ (RDS) bằng cách sử dụng Nhóm Subnet RDS đã tạo trước đó.
rds_name=$project-rds rds_db_name="workshop" rds_db_username="postgres" rds_db_password="postgres" # Create RDS aws rds create-db-instance \ --db-instance-identifier $rds_name \ --engine postgres \ --db-name $rds_db_name \ --db-instance-class db.t3.micro \ --allocated-storage 20 \ --master-username $rds_db_username \ --master-user-password $rds_db_password \ --storage-type gp2 \ --no-enable-performance-insights \ --availability-zone $az_01 \ --db-subnet-group-name $rds_subnet_group_name \ --vpc-security-group-ids $rds_sgr_id \ --backup-retention-period 0 \ --tags "$tags" aws rds wait db-instance-available \ --db-instance-identifier $rds_name # Get RDS information rds_address=$(aws rds describe-db-instances \ --db-instance-identifier $rds_name \ --query 'DBInstances[0].Endpoint.Address' \ --output text) echo rds_address=$rds_address
Trong đoạn code trên:
rds_instance_name
: Đây là tên của phiên bản RDS, dựa trên biến$project
.aws rds create-db-instance
: Dòng này triển khai một phiên bản RDS với cấu hình cụ thể, bao gồm lớp phiên bản, loại engine, kích thước lưu trữ, nhóm subnet, nhóm bảo mật, tên người dùng chính, và mật khẩu.aws rds describe-db-instances
để lấy thông tin chi tiết về một phiên bản RDS dựa trên định danh của nó (db-instance-identifier
) và sử dụng--query 'DBInstances[0].Endpoint.Address'
: để tìm ra địa chỉ của DB instance từ json mà lệnh trả về
Tạo SecretsManager
Tổng quan
AWS Secrets Manager giúp bạn mã hóa, lưu trữ và lấy thông tin đăng nhập một cách an toàn cho các cơ sở dữ liệu và dịch vụ khác của bạn. Thay vì cứ mã hóa trực tiếp thông tin đăng nhập trong ứng dụng của bạn, bạn có thể gọi tới Secrets Manager để lấy thông tin đăng nhập mỗi khi cần. Secrets Manager giúp bảo vệ quyền truy cập vào tài nguyên và dữ liệu IT của bạn bằng cách cho phép bạn xoay vòng và quản lý quyền truy cập vào các bí mật của mình.
Quy trình
Tạo Secret Manager
Để Tạo Secret Manager, chúng ta sử dụng lệnh aws secretsmanager create-secret
secret_name=$project-sm
secret_string=$(echo "{\"POSTGRES_HOST\":\"$rds_address\",\"POSTGRES_PORT\":\"5432\",\"POSTGRES_DB\":\"$rds_db_name\",\"POSTGRES_USERNAME\":\"$rds_db_username\",\"POSTGRES_PASSWORD\":\"$rds_db_password\"}")
# Create SecretManager
aws secretsmanager create-secret \
--name $secret_name \
--description "To save database information" \
--tags "$tags" \
--secret-string $secret_string
Tạo Application Load Balancing
Tổng quan
Application Load Balancer hoạt động ở tầng ứng dụng, là tầng thứ bảy của mô hình Open Systems Interconnection (OSI).
Sau khi ALB nhận yêu cầu, nó đánh giá các quy tắc trình nghe (listener rule) theo thứ tự ưu tiên để xác định quy tắc nào được áp dụng, sau đó chọn một mục tiêu từ Target Group để tiếp tục thực hiện.
Quy trình
-
Cấu hình biến
alb_name=$project-alb alb_tgr_name=$project-tgr alb_vpc_id=$vpc_id alb_subnet1_id=$subnet_public_1 alb_subnet2_id=$subnet_public_2
-
Tạo ALB
# Create ALB alb_arn=$(aws elbv2 create-load-balancer \ --name $alb_name \ --subnets $alb_subnet1_id $alb_subnet2_id \ --security-groups $alb_sgr_id \ --tags "$tags" \ --query 'LoadBalancers[0].LoadBalancerArn' \ --output text) echo alb_arn=$alb_arn
-
Tạo Target Group
alb_tgr_arn=$(aws elbv2 create-target-group \ --name $alb_tgr_name \ --protocol HTTP \ --target-type ip \ --health-check-path "/api/product" \ --port 8080 \ --vpc-id $alb_vpc_id \ --tags "$tags" \ --query 'TargetGroups[0].TargetGroupArn' \ --output text) echo alb_tgr_arn=$alb_tgr_arn
-
Tạo Listener
alb_listener_arn=$(aws elbv2 create-listener \ --load-balancer-arn $alb_arn \ --protocol HTTP \ --port 80 \ --default-actions Type=forward,TargetGroupArn=$alb_tgr_arn \ --query 'Listeners[0].ListenerArn' \ --output text) echo alb_listener_arn$alb_listener_arn
Tạo Elastic Container Service (ECS)
Tạo ECS Cluster
Tổng quan
ECS cluster là một nhóm về mặt logic của các ECS tasks hay services.
Ngoài các tasks and services, a cluster bao gồm các tài nguyên sau:
- Hạ tầng:
- Amazon EC2 instances trên AWS
- Serverless (AWS Fargate (Fargate)) trên AWS
- On-premises virtual machines (VM) hoặc servers
- Mạng (VPC and subnet).
- A namespace: được sử dụng cho giao tiếp từ dịch vụ này sang dịch vụ khác với Service Connect.
- A monitoring option: CloudWatch Container Insights tự động thu thập, tổng hợp và tóm tắt các số liệu và nhật ký của Amazon ECS.
Quy trình
Sử dụng lệnh sau để tạo một Cluster ECS.
ecs_cluster_name=$project-cluster
# Create ECS Cluster
aws ecs create-cluster \
--cluster-name $ecs_cluster_name \
--region $region \
--tags "$tags2"
# Check ECS Cluster created correctly
aws ecs list-clusters
Tạo ECS Capacity
Tổng quan
Amazon ECS capacity là cơ sở hạ tầng nơi mà các container của bạn chạy.
ECS capacity có 3 loại sau:
- Các instance Amazon EC2: Bạn chọn loại instance, số lượng instance và quản lý capacity.
- Serverless (AWS Fargate): Với Fargate, bạn không cần quản lý máy chủ, xử lý kế hoạch capacity, hoặc cách ly các công việc container để bảo mật.
- On-premise Máy ảo (VM) hoặc server: Amazon ECS Anywhere cung cấp hỗ trợ để đăng ký một instance bên ngoài như on-premises server hoặc virtual machine (VM), vào Amazon ECS cluster của bạn.
ECS cluster capacity providers với ECS capacity không phải là một.
ECS capacity đề cập đến khả năng cơ sở hạ tầng mà có sẵn để chạy các nhiệm vụ và dịch vụ trong một cluster ECS. Capacity này có thể được cung cấp bằng cách sử dụng các nhà cung cấp capacity.
Capacity provider strategy xác định cách các nhiệm vụ được phân phối đến các nguồn cơ sở hạ tầng khác nhau trong cluster. Điều này giúp tối ưu hóa việc sử dụng tài nguyên và chi phí dựa trên yêu cầu của task. Mỗi cluster có một hoặc nhiều nhà capacity provider và một cấu hình capacity provider strategy mặc định tùy chọn. Capacity provider stratergy xác định cách các task được phân phối qua các capacity provider. Khi chạy một task hoặc tạo một service, bạn có thể sử dụng capacity provider stragtegy mặc định của cluster hoặc chỉ định một capacity provider stragtegy thay thế.
Quy trình
-
Truy xuất ECS-optimized AMI
# Get ECS AMI ID ecs_instance_ami_id=$(aws ssm get-parameters \ --names /aws/service/ecs/optimized-ami/amazon-linux-2/recommended \ --region $region | jq -r '.Parameters[0].Value | fromjson.image_id')
Ở đây chúng ta sử dụng Amazon Linux 2 làm hệ điều hành cơ sở, đối với các hệ điều hành cơ sở khác, tìm hiểu thông tin tại Retrieving Amazon ECS-Optimized AMI metadata
-
Tạo Launch Template với Amazon ECS-optimized AMI
ECS agent là một công cụ containerization mà ECS sử dụng để quản lý instance. Để ECS agent biết rằng Instance này thuộc về ECS Cluster nào, bạn phải cấu hình như sau trong tệp /etc/ecs/ecs.config
ECS_CLUSTER=ecs_cluster_name
ecs_instance_type=t3.medium ecs_instance_subnet_id=$subnet_public_1 ecs_launch_template_name=$project-ecs-launch-template # Tạo Launch template file cat <<EOF | tee ecs-launch-template.json { "ImageId": "$ecs_instance_ami_id", "InstanceType": "$ecs_instance_type", "IamInstanceProfile": { "Arn": "$ecs_instance_profile_arn" }, "NetworkInterfaces": [{ "DeviceIndex": 0, "AssociatePublicIpAddress": true, "Groups": ["$ecs_instance_sgr_id"], "SubnetId": "$ecs_instance_subnet_id" }], "KeyName": "$ecs_instance_key_name", "TagSpecifications": [{ "ResourceType": "instance", "Tags": `echo '['$tagspec | sed 's/{/{"/g; s/}/"}/g; s/,/","/g; s/}","{/},{/g; s/=/":"/g'` }], "UserData": "`cat <<EOF | openssl base64 -A #!/bin/bash echo ECS_CLUSTER=$ecs_cluster_name >> /etc/ecs/ecs.config EOF`" } EOF # Tạo launch template sử dụng file launch template vừa tạo aws ec2 create-launch-template \ --launch-template-name $ecs_launch_template_name \ --launch-template-data file://ecs-launch-template.json
-
Tạo Auto Scaling Group sử dụng template vừa tạo
ecs_instance_name=$project-ecs-instance ecs_autoscaling_group_name=$project-ecs-autoscaling-group # create Autoscaling group aws autoscaling create-auto-scaling-group \ --auto-scaling-group-name $ecs_autoscaling_group_name \ --launch-template "$(echo "{\"LaunchTemplateName\":\"$ecs_launch_template_name\"}")" \ --min-size 1 \ --max-size 3 \ --desired-capacity 1 \ --tags "$(echo $tags | jq -c '. + [{"Key":"Name","Value":"'"$ecs_instance_name"'"}]')" ecs_autoscaling_group_arn=$(aws autoscaling describe-auto-scaling-groups \ --auto-scaling-group-names $ecs_autoscaling_group_name \ | jq .AutoScalingGroups[0].AutoScalingGroupARN)
-
List Container Instance
Kiểm tra các instance trong autoscaling group đã thuộc ECS quản lý chưa
aws ecs list-container-instances --cluster $ecs_cluster_name
-
Tạo Capacity Provider và sử dụng cho ECS Cluster
Thật ra trong bài lab này tạo ECS Capacity Provider không ý nghĩa lắm. Chủ yếu để biết và hiểu cách tạo ECS Capacity Provider. (Bỏ phần này Lab vẫn hoạt động 🥲)
ecs_capacity_provider=$project-capacity-provider # Tạo Capacity provider aws ecs create-capacity-provider \ --name $ecs_capacity_provider \ --auto-scaling-group-provider `echo "autoScalingGroupArn=$ecs_ec2_autoscaling_arn,managedScaling={status=ENABLED,targetCapacity=100},managedTerminationProtection=DISABLED"` \ --tags $tags2 aws ecs put-cluster-capacity-providers \ --cluster $ecs_cluster_name \ --capacity-providers $ecs_capacity_provider \ --default-capacity-provider-strategy capacityProvider=$ecs_capacity_provider,weight=1
Tạo ECS Task Definition
Tổng quan
Task Definition là một bản thiết kế cho ứng dụng của bạn. Đó là một tệp văn bản có định dạng JSON mô tả các tham số và một hoặc nhiều container tạo nên ứng dụng của bạn.
Quy trình
-
Tạo IAM Role cho Task Definition
-
Tạo IAM Role cho Task Definition với quyền được sử dụng bởi
ecs-tasks.amazonaws.com
# Lấy ARN của AWS secret manager secret_arn=$(aws secretsmanager describe-secret --secret-id $secret_name --query 'ARN' --output text) # Tạo IAM Role cho Task Definition ecs_task_role_name=$project-ecs-task-role ecs_task_policy_name=${project}_ecs_task_policy ecs_task_name=$project-task ecs_task_uri=$ecr_image_uri # Tạo IAM Role ecs_task_role_arn=$(aws iam create-role \ --role-name $ecs_task_role_name \ --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Service": "ecs-tasks.amazonaws.com" }, "Action": ["sts:AssumeRole"] }] }' \ --tags "$tags" \ --output text \ --query 'Role.Arn') echo ecs_task_role_arn=$ecs_task_role_arn
-
Gắn các chính sách vào IAM Role này
cat <<EOF | tee ecs-task-role.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:GetParameters", "secretsmanager:GetSecretValue" ], "Resource": [ "`echo $secret_arn`", "`echo $secret_arn`*" ] } ] } EOF aws iam put-role-policy \ --role-name $ecs_task_role_name \ --policy-name $ecs_task_policy_name \ --policy-document file://ecs-task-role.json aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly \ --role-name $ecs_task_role_name
-
-
Tạo Task Definition
-
Tạo tệp định nghĩa Task definition
Nội dung của SecretsManager tạo từ trước có dạng Json như sau
{ "POSTGRES_HOST":"test.rds.amazonaws.com", "POSTGRES_PORT":"5432", "POSTGRES_DB":"workshop", "POSTGRES_USERNAME":"postgres", "POSTGRES_PASSWORD":"postgres" }
# Nội dung của task-definition cat <<EOF | tee task-definition.json { "name": "$ecs_task_name", "image": "$ecs_task_uri", "portMappings": [ { "containerPort": 8080, "hostPort": 8080 } ], "secrets" : [ { "valueFrom" : "$secret_arn:POSTGRES_HOST::", "name" : "POSTGRES_HOST" }, { "valueFrom" : "$secret_arn:POSTGRES_DB::", "name" : "POSTGRES_DB" }, { "valueFrom" : "$secret_arn:POSTGRES_PASSWORD::", "name" : "POSTGRES_PASSWORD" } ] } EOF
-
Sử dụng file này để tạo Task Definition
# Tạo task-definition ecs_task_definition=$(aws ecs register-task-definition \ --family $ecs_task_name \ --network-mode awsvpc \ --requires-compatibilities EC2 \ --cpu "512" \ --memory "1024" \ --execution-role-arn "$ecs_task_role_arn" \ --tags "$tags2" \ --container-definitions "`jq -c . task-definition.json`" ) # Kiểm tra việc tạo ECS task definition aws ecs list-task-definitions ecs_task_arn=$(aws ecs describe-task-definition \ --task-definition $ecs_task_name \ --query "taskDefinition.taskDefinitionArn" \ --output text)
-
Tạo ECS Service
Tổng quan
Amazon ECS (Elastic Container Service) Service là một dịch vụ chạy và quản lý một số lượng xác định các phiên bản của một task definition đồng thời trong một cluster Amazon ECS.
Tạo ECS Service
Tạo ECS service dựa trên 1 task definition có sẵn bằng lệnh
ecs_service_name=$project-service
# Tạo Service
aws ecs create-service \
--cluster $ecs_cluster_name \
--service-name $ecs_service_name \
--task-definition $ecs_task_arn \
--desired-count 1 \
--network-configuration "awsvpcConfiguration={subnets=[$ecs_instance_subnet_id],securityGroups=[$ecs_instance_sgr_id]}"
aws ecs update-service --cluster $ecs_cluster_name \
--service $ecs_service_name \
--desired-count 1 \
--load-balancers targetGroupArn=$alb_tgr_arn,containerName=`echo $ecs_task_definition | jq -r '.taskDefinition.containerDefinitions[0].name'`,containerPort=8080
Kiểm tra kết quả
-
Kiểm tra Target Group (Check Healthy)
aws elbv2 describe-target-health --target-group-arn $alb_tgr_arn
-
Lấy giá trị ALB public DNS
aws elbv2 describe-load-balancers \ --load-balancer-arns $alb_arn \ --query 'LoadBalancers[0].DNSName' \ --output text
-
Kiểm tra ứng dụng bằng
api
Dọn dẹp
Xóa ALB và các thành phần liên quan
aws elbv2 delete-listener --listener-arn $alb_listener_arn
aws elbv2 delete-target-group --target-group-arn $alb_tgr_arn
aws elbv2 delete-load-balancer --load-balancer-arn $alb_arn
Xóa ECS Service
aws ecs delete-service --cluster $ecs_cluster_name \
--service $ecs_service_name --force
Xóa ECS Task Definition
task_definition_arns=$(aws ecs list-task-definitions \
--status ACTIVE \
--query 'taskDefinitionArns[]' --output text)
for arn in $task_definition_arns; do
aws ecs deregister-task-definition --task-definition $arn
done
task_definition_inactive_arns=$(aws ecs list-task-definitions \
--status INACTIVE \
--query 'taskDefinitionArns[]' --output text)
aws ecs delete-task-definitions \
--task-definitions $task_definition_inactive_arns
Xóa Task Role
aws iam delete-role-policy \
--role-name $ecs_task_role_name \
--policy-name $ecs_task_policy_name
aws iam detach-role-policy \
--policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly \
--role-name $ecs_task_role_name
aws iam delete-role --role-name $ecs_task_role_name
Xóa ECS instance và các thành phần liên quan
instance_ids=$(aws autoscaling describe-auto-scaling-groups \
--auto-scaling-group-names $ecs_autoscaling_group_name \
--query "AutoScalingGroups[].Instances[].InstanceId" \
--output text)
aws autoscaling delete-auto-scaling-group \
--auto-scaling-group-name $ecs_autoscaling_group_name \
--force-delete
aws ec2 terminate-instances --instance-ids $instance_ids
aws ec2 wait instance-terminated --instance-ids $instance_ids
aws ec2 delete-launch-template \
--launch-template-name $ecs_launch_template_name
Xóa ECS Cluster
aws ecs delete-cluster --cluster $ecs_cluster_name
Xóa ECS Capacity Provider
# aws ecs put-cluster-capacity-providers \
# --cluster $ecs_cluster_name \
# --capacity-providers $ecs_capacity_provider \
# --default-capacity-provider-strategy capacityProvider=$ecs_capacity_provider,weight=0,base=0
aws ecs delete-capacity-provider --capacity-provider $ecs_capacity_provider
Xóa Secrets Manager
aws secretsmanager delete-secret \
--secret-id $secret_name \
--force-delete-without-recovery
Xóa RDS
aws rds delete-db-instance \
--db-instance-identifier $rds_name \
--skip-final-snapshot
aws rds wait db-instance-deleted --db-instance-identifier $rds_name
aws rds delete-db-subnet-group --db-subnet-group-name $rds_subnet_group_name
Xóa Security Group
aws ec2 delete-security-group --group-id $alb_sgr_id
aws ec2 delete-security-group --group-id $rds_sgr_id
aws ec2 delete-security-group --group-id $ecs_instance_sgr_id
Xóa Network
aws ec2 delete-subnet --subnet-id $subnet_public_1
aws ec2 delete-subnet --subnet-id $subnet_public_2
aws ec2 delete-subnet --subnet-id $subnet_public_3
aws ec2 delete-subnet --subnet-id $subnet_private_1
aws ec2 delete-subnet --subnet-id $subnet_private_2
aws ec2 delete-subnet --subnet-id $subnet_private_3
aws ec2 delete-route-table --route-table-id $rtb_public_id
aws ec2 delete-route-table --route-table-id $rtb_private_id
aws ec2 detach-internet-gateway \
--internet-gateway-id $gateway_id \
--vpc-id $vpc_id
aws ec2 delete-internet-gateway --internet-gateway-id $gateway_id
aws ec2 delete-vpc --vpc-id $vpc_id
Xóa ECR
aws ecr batch-delete-image \
--repository-name $ecr_name \
--image-ids imageTag=latest \
--region $region
aws ecr delete-repository \
--repository-name $ecr_name \
--force \
--region $region
docker rmi $ecr_image_uri
docker rmi $ecr_name
# docker rmi $(docker image ls -aq)
Xóa Keypair
aws ec2 delete-key-pair --key-name $ecs_instance_key_name
rm -f $ecs_instance_key_name.pem
Xóa IAM Role
aws iam remove-role-from-instance-profile \
--instance-profile-name $ecs_instance_role_name \
--role-name $ecs_instance_role_name
aws iam delete-instance-profile \
--instance-profile-name $ecs_instance_role_name
aws iam detach-role-policy \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role \
--role-name $ecs_instance_role_name
aws iam detach-role-policy \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore \
--role-name $ecs_instance_role_name
aws iam delete-role --role-name $ecs_instance_role_name
Kết thúc
Vậy là bạn đã hoàn thành việc cài đặt ECS với công cụ AWS CLI. Hy vọng hướng dẫn này đã giúp bạn dễ dàng hơn trong việc thiết lập môi trường ECS. Nếu bạn có bất kỳ câu hỏi hay góp ý nào, hãy để lại bình luận bên dưới. Chúc bạn thành công!
All rights reserved