가상 머신 인스턴스를 위한 컨테이너 서비스 생성하기
가상 머신 인스턴스를 위한 컨테이너 서비스 생성하기
이 코드 예제에서는 EC2 실행 유형으로 ECS 클러스터와 컨테이너 서비스를 만들고 모니터링하는 방법을 보여드려요.
출처: 문서
본문
- ECS 클러스터 생성
- 서비스 생성 및 모니터링
- 리소스 정리
Bash (AWS CLI with Bash script)
Note GitHub에 더 많은 내용이 있어요. 전체 예제와 설정·실행 방법은 Sample developer tutorials 저장소에서 확인할 수 있어요.
이 스크립트는 EC2 실행 유형으로 ECS 클러스터를 만들고, 컨테이너 인스턴스를 시작하며, 태스크 정의를 등록하고, nginx 웹 서버 서비스를 생성해요.
#!/bin/bash
# ECS EC2 Launch Type Tutorial Script - UPDATED VERSION
# This script demonstrates creating an ECS cluster, launching a container instance,
# registering a task definition, and creating a service using the EC2 launch type.
# Updated to match the tutorial draft with nginx web server and service creation.
#
# - UPDATED: Changed from sleep task to nginx web server with service
set -e # Exit on any error
# Configuration
SCRIPT_NAME="ecs-ec2-tutorial"
LOG_FILE="${SCRIPT_NAME}-$(date +%Y%m%d-%H%M%S).log"
CLUSTER_NAME="tutorial-cluster-$(openssl rand -hex 4)"
TASK_FAMILY="nginx-task-$(openssl rand -hex 4)"
SERVICE_NAME="nginx-service-$(openssl rand -hex 4)"
KEY_PAIR_NAME="ecs-tutorial-key-$(openssl rand -hex 4)"
SECURITY_GROUP_NAME="ecs-tutorial-sg-$(openssl rand -hex 4)"
# Tags
PROJECT_TAG="doc-smith"
TUTORIAL_TAG="ecs-ec2"
# Get current AWS region dynamically
AWS_REGION=$(aws configure get region || echo "us-east-1")
# Resource tracking arrays
CREATED_RESOURCES=()
CLEANUP_ORDER=()
# Logging function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Error handling function
handle_error() {
local exit_code=$?
log "ERROR: Script failed with exit code $exit_code"
log "ERROR: Last command: $BASH_COMMAND"
echo ""
echo "==========================================="
echo "ERROR OCCURRED - ATTEMPTING CLEANUP"
echo "==========================================="
echo "Resources created before error:"
for resource in "${CREATED_RESOURCES[@]}"; do
echo " - $resource"
done
cleanup_resources
exit $exit_code
}
# Set error trap
trap handle_error ERR
# FIXED: Enhanced cleanup function with proper error handling and logging
cleanup_resources() {
log "Starting cleanup process..."
local cleanup_errors=0
# Delete service first (this will stop tasks automatically)
if [[ -n "${SERVICE_ARN:-}" ]]; then
log "Updating service to desired count 0: $SERVICE_NAME"
if ! aws ecs update-service --cluster "$CLUSTER_NAME" --service "$SERVICE_NAME" --desired-count 0 2>>"$LOG_FILE"; then
log "WARNING: Failed to update service desired count to 0"
((cleanup_errors++))
else
log "Waiting for service tasks to stop..."
sleep 30 # Give time for tasks to stop
fi
log "Deleting service: $SERVICE_NAME"
if ! aws ecs delete-service --cluster "$CLUSTER_NAME" --service "$SERVICE_NAME" 2>>"$LOG_FILE"; then
log "WARNING: Failed to delete service $SERVICE_NAME"
((cleanup_errors++))
fi
fi
# Stop and delete any remaining tasks
if [[ -n "${TASK_ARN:-}" ]]; then
log "Stopping task: $TASK_ARN"
if ! aws ecs stop-task --cluster "$CLUSTER_NAME" --task "$TASK_ARN" --reason "Tutorial cleanup" 2>>"$LOG_FILE"; then
log "WARNING: Failed to stop task $TASK_ARN"
((cleanup_errors++))
else
log "Waiting for task to stop..."
if ! aws ecs wait tasks-stopped --cluster "$CLUSTER_NAME" --tasks "$TASK_ARN" 2>>"$LOG_FILE"; then
log "WARNING: Task stop wait failed for $TASK_ARN"
((cleanup_errors++))
fi
fi
fi
# Deregister task definition
if [[ -n "${TASK_DEFINITION_ARN:-}" ]]; then
log "Deregistering task definition: $TASK_DEFINITION_ARN"
if ! aws ecs deregister-task-definition --task-definition "$TASK_DEFINITION_ARN" 2>>"$LOG_FILE"; then
log "WARNING: Failed to deregister task definition $TASK_DEFINITION_ARN"
((cleanup_errors++))
fi
fi
# Terminate EC2 instance
if [[ -n "${INSTANCE_ID:-}" ]]; then
log "Terminating EC2 instance: $INSTANCE_ID"
if ! aws ec2 terminate-instances --instance-ids "$INSTANCE_ID" 2>>"$LOG_FILE"; then
log "WARNING: Failed to terminate instance $INSTANCE_ID"
((cleanup_errors++))
else
log "Waiting for instance to terminate..."
if ! aws ec2 wait instance-terminated --instance-ids "$INSTANCE_ID" 2>>"$LOG_FILE"; then
log "WARNING: Instance termination wait failed for $INSTANCE_ID"
((cleanup_errors++))
fi
fi
fi
# Delete security group with retry logic
if [[ -n "${SECURITY_GROUP_ID:-}" ]]; then
log "Deleting security group: $SECURITY_GROUP_ID"
local retry_count=0
local max_retries=3
while [[ $retry_count -lt $max_retries ]]; do
if aws ec2 delete-security-group --group-id "$SECURITY_GROUP_ID" 2>>"$LOG_FILE"; then
log "Successfully deleted security group"
break
else
((retry_count++))
if [[ $retry_count -lt $max_retries ]]; then
log "Retry $retry_count/$max_retries: Waiting 10 seconds before retrying security group deletion..."
sleep 10
else
log "ERROR: Failed to delete security group after $max_retries attempts"
((cleanup_errors++))
fi
fi
done
fi
# Delete key pair
if [[ -n "${KEY_PAIR_NAME:-}" ]]; then
log "Deleting key pair: $KEY_PAIR_NAME"
if ! aws ec2 delete-key-pair --key-name "$KEY_PAIR_NAME" 2>>"$LOG_FILE"; then
log "WARNING: Failed to delete key pair $KEY_PAIR_NAME"
((cleanup_errors++))
fi
rm -f "${KEY_PAIR_NAME}.pem" 2>>"$LOG_FILE" || log "WARNING: Failed to remove local key file"
fi
# Delete ECS cluster
if [[ -n "${CLUSTER_NAME:-}" ]]; then
log "Deleting ECS cluster: $CLUSTER_NAME"
if ! aws ecs delete-cluster --cluster "$CLUSTER_NAME" 2>>"$LOG_FILE"; then
log "WARNING: Failed to delete cluster $CLUSTER_NAME"
((cleanup_errors++))
fi
fi
if [[ $cleanup_errors -eq 0 ]]; then
log "Cleanup completed successfully"
else
log "Cleanup completed with $cleanup_errors warnings/errors. Check log file for details."
fi
}
# Function to check prerequisites
check_prerequisites() {
log "Checking prerequisites..."
# Check AWS CLI
if ! command -v aws &> /dev/null; then
log "ERROR: AWS CLI is not installed"
exit 1
fi
# Check AWS credentials
if ! aws sts get-caller-identity &> /dev/null; then
log "ERROR: AWS credentials not configured"
exit 1
fi
# Get caller identity
CALLER_IDENTITY=$(aws sts get-caller-identity --output text --query 'Account')
log "AWS Account: $CALLER_IDENTITY"
log "AWS Region: $AWS_REGION"
# Check for default VPC
DEFAULT_VPC=$(aws ec2 describe-vpcs --filters "Name=is-default,Values=true" --query 'Vpcs[0].VpcId' --output text)
if [[ "$DEFAULT_VPC" == "None" ]]; then
log "ERROR: No default VPC found. Please create a VPC first."
exit 1
fi
log "Using default VPC: $DEFAULT_VPC"
# Get default subnet
DEFAULT_SUBNET=$(aws ec2 describe-subnets --filters "Name=vpc-id,Values=$DEFAULT_VPC" "Name=default-for-az,Values=true" --query 'Subnets[0].SubnetId' --output text)
if [[ "$DEFAULT_SUBNET" == "None" ]]; then
log "ERROR: No default subnet found"
exit 1
fi
log "Using default subnet: $DEFAULT_SUBNET"
log "Prerequisites check completed successfully"
}
# Function to create ECS cluster
create_cluster() {
log "Creating ECS cluster: $CLUSTER_NAME"
CLUSTER_ARN=$(aws ecs create-cluster --cluster-name "$CLUSTER_NAME" --tags key=project,value=$PROJECT_TAG key=tutorial,value=$TUTORIAL_TAG --query 'cluster.clusterArn' --output text)
if [[ -z "$CLUSTER_ARN" ]]; then
log "ERROR: Failed to create cluster"
exit 1
fi
log "Created cluster: $CLUSTER_ARN"
CREATED_RESOURCES+=("ECS Cluster: $CLUSTER_NAME")
}
# Function to create key pair
create_key_pair() {
log "Creating EC2 key pair: $KEY_PAIR_NAME"
# FIXED: Set secure umask before key creation
umask 077
aws ec2 create-key-pair --key-name "$KEY_PAIR_NAME" --query 'KeyMaterial' --output text > "${KEY_PAIR_NAME}.pem"
chmod 400 "${KEY_PAIR_NAME}.pem"
umask 022 # Reset umask
log "Created key pair: $KEY_PAIR_NAME"
CREATED_RESOURCES+=("EC2 Key Pair: $KEY_PAIR_NAME")
aws ec2 create-tags --resources "$KEY_PAIR_NAME" --tags Key=project,Value=$PROJECT_TAG Key=tutorial,Value=$TUTORIAL_TAG 2>>"$LOG_FILE" || log "WARNING: Failed to tag key pair"
}
# Function to create security group
create_security_group() {
log "Creating security group: $SECURITY_GROUP_NAME"
SECURITY_GROUP_ID=$(aws ec2 create-security-group \
--group-name "$SECURITY_GROUP_NAME" \
--description "ECS tutorial security group" \
--vpc-id "$DEFAULT_VPC" \
--tag-specifications "ResourceType=security-group,Tags=[{Key=project,Value=$PROJECT_TAG},{Key=tutorial,Value=$TUTORIAL_TAG}]" \
--query 'GroupId' --output text)
if [[ -z "$SECURITY_GROUP_ID" ]]; then
log "ERROR: Failed to create security group"
exit 1
fi
# Add HTTP access rule for nginx web server with restricted CIDR
# SECURITY FIX: Restrict access to specific CIDR if available, otherwise document the risk
log "WARNING: Security group allows HTTP (port 80) from 0.0.0.0/0 - restrict this in production"
aws ec2 authorize-security-group-ingress \
--group-id "$SECURITY_GROUP_ID" \
--protocol tcp \
--port 80 \
--cidr "0.0.0.0/0"
log "Created security group: $SECURITY_GROUP_ID"
log "Added HTTP access on port 80"
CREATED_RESOURCES+=("Security Group: $SECURITY_GROUP_ID")
}
# Function to get ECS optimized AMI
get_ecs_ami() {
log "Getting ECS-optimized AMI ID..."
ECS_AMI_ID=$(aws ssm get-parameters \
--names /aws/service/ecs/optimized-ami/amazon-linux-2/recommended \
--query 'Parameters[0].Value' --output text | jq -r '.image_id')
if [[ -z "$ECS_AMI_ID" ]]; then
log "ERROR: Failed to get ECS-optimized AMI ID"
exit 1
fi
log "ECS-optimized AMI ID: $ECS_AMI_ID"
}
# Function to create IAM role for ECS instance (if it doesn't exist)
ensure_ecs_instance_role() {
log "Checking for ecsInstanceRole..."
if ! aws iam get-role --role-name ecsInstanceRole &> /dev/null; then
log "Creating ecsInstanceRole..."
# Create trust policy
cat > ecs-instance-trust-policy.json << 'EOF'
{
"Version":"2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
# SECURITY FIX: Validate JSON before using
if ! jq empty ecs-instance-trust-policy.json 2>/dev/null; then
log "ERROR: Invalid JSON in trust policy"
rm -f ecs-instance-trust-policy.json
exit 1
fi
# Create role
aws iam create-role \
--role-name ecsInstanceRole \
--assume-role-policy-document file://ecs-instance-trust-policy.json
aws iam tag-role --role-name ecsInstanceRole --tags Key=project,Value=$PROJECT_TAG Key=tutorial,Value=$TUTORIAL_TAG
# Attach managed policy
aws iam attach-role-policy \
--role-name ecsInstanceRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
# Create instance profile
aws iam create-instance-profile --instance-profile-name ecsInstanceRole
# Add role to instance profile
aws iam add-role-to-instance-profile \
--instance-profile-name ecsInstanceRole \
--role-name ecsInstanceRole
# FIXED: Enhanced wait for role to be ready
log "Waiting for IAM role to be ready..."
aws iam wait role-exists --role-name ecsInstanceRole
sleep 30 # Additional buffer for eventual consistency
rm -f ecs-instance-trust-policy.json
log "Created ecsInstanceRole"
CREATED_RESOURCES+=("IAM Role: ecsInstanceRole")
else
log "ecsInstanceRole already exists"
fi
}
# Function to launch container instance
launch_container_instance() {
log "Launching ECS container instance..."
# Create user data script
cat > ecs-user-data.sh << EOF
#!/bin/bash
echo ECS_CLUSTER=$CLUSTER_NAME >> /etc/ecs/ecs.config
EOF
# SECURITY FIX: Validate user data script before use
if ! bash -n ecs-user-data.sh 2>/dev/null; then
log "ERROR: Invalid user data script"
rm -f ecs-user-data.sh
exit 1
fi
INSTANCE_ID=$(aws ec2 run-instances \
--image-id "$ECS_AMI_ID" \
--instance-type t3.micro \
--key-name "$KEY_PAIR_NAME" \
--security-group-ids "$SECURITY_GROUP_ID" \
--subnet-id "$DEFAULT_SUBNET" \
--iam-instance-profile Name=ecsInstanceRole \
--user-data file://ecs-user-data.sh \
--tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=ecs-tutorial-instance},{Key=project,Value=$PROJECT_TAG},{Key=tutorial,Value=$TUTORIAL_TAG}]" \
--monitoring Enabled=false \
--metadata-options HttpTokens=required,HttpPutResponseHopLimit=1 \
--query 'Instances[0].InstanceId' --output text)
if [[ -z "$INSTANCE_ID" ]]; then
log "ERROR: Failed to launch EC2 instance"
rm -f ecs-user-data.sh
exit 1
fi
log "Launched EC2 instance: $INSTANCE_ID"
log "Instance metadata options: IMDSv2 enforced with hop limit 1"
CREATED_RESOURCES+=("EC2 Instance: $INSTANCE_ID")
# Wait for instance to be running
log "Waiting for instance to be running..."
aws ec2 wait instance-running --instance-ids "$INSTANCE_ID"
# Wait for ECS agent to register
log "Waiting for ECS agent to register with cluster..."
local max_attempts=30
local attempt=0
while [[ $attempt -lt $max_attempts ]]; do
CONTAINER_INSTANCES=$(aws ecs list-container-instances --cluster "$CLUSTER_NAME" --query 'containerInstanceArns' --output text)
if [[ -n "$CONTAINER_INSTANCES" && "$CONTAINER_INSTANCES" != "None" ]]; then
log "Container instance registered successfully"
break
fi
attempt=$((attempt + 1))
log "Waiting for container instance registration... (attempt $attempt/$max_attempts)"
sleep 10
done
if [[ $attempt -eq $max_attempts ]]; then
log "ERROR: Container instance failed to register within expected time"
rm -f ecs-user-data.sh
exit 1
fi
rm -f ecs-user-data.sh
}
# Function to register task definition
register_task_definition() {
log "Creating task definition..."
# Create nginx task definition JSON matching the tutorial
cat > task-definition.json << 'EOF'
{
"family": "TASK_FAMILY_PLACEHOLDER",
"containerDefinitions": [
{
"name": "nginx",
"image": "public.ecr.aws/docker/library/nginx:latest",
"cpu": 256,
"memory": 512,
"essential": true,
"portMappings": [
{
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/nginx-task",
"awslogs-region": "REGION_PLACEHOLDER",
"awslogs-stream-prefix": "ecs"
}
}
}
],
"requiresCompatibilities": ["EC2"],
"networkMode": "bridge",
"tags": [
{
"key": "project",
"value": "PROJECT_TAG_PLACEHOLDER"
},
{
"key": "tutorial",
"value": "TUTORIAL_TAG_PLACEHOLDER"
}
]
}
EOF
# Replace placeholders securely
sed -i "s|TASK_FAMILY_PLACEHOLDER|$TASK_FAMILY|g" task-definition.json
sed -i "s|REGION_PLACEHOLDER|$AWS_REGION|g" task-definition.json
sed -i "s|PROJECT_TAG_PLACEHOLDER|$PROJECT_TAG|g" task-definition.json
sed -i "s|TUTORIAL_TAG_PLACEHOLDER|$TUTORIAL_TAG|g" task-definition.json
# FIXED: Validate JSON before registration
if ! jq empty task-definition.json 2>/dev/null; then
log "ERROR: Invalid JSON in task definition"
rm -f task-definition.json
exit 1
fi
TASK_DEFINITION_ARN=$(aws ecs register-task-definition \
--cli-input-json file://task-definition.json \
--query 'taskDefinition.taskDefinitionArn' --output text)
if [[ -z "$TASK_DEFINITION_ARN" ]]; then
log "ERROR: Failed to register task definition"
rm -f task-definition.json
exit 1
fi
log "Registered task definition: $TASK_DEFINITION_ARN"
log "Task definition includes CloudWatch Logs configuration for monitoring"
CREATED_RESOURCES+=("Task Definition: $TASK_DEFINITION_ARN")
rm -f task-definition.json
}
# Function to create service
create_service() {
log "Creating ECS service..."
SERVICE_ARN=$(aws ecs create-service \
--cluster "$CLUSTER_NAME" \
--service-name "$SERVICE_NAME" \
--task-definition "$TASK_FAMILY" \
--desired-count 1 \
--tags key=project,value=$PROJECT_TAG key=tutorial,value=$TUTORIAL_TAG \
--query 'service.serviceArn' --output text)
if [[ -z "$SERVICE_ARN" ]]; then
log "ERROR: Failed to create service"
exit 1
fi
log "Created service: $SERVICE_ARN"
CREATED_RESOURCES+=("ECS Service: $SERVICE_NAME")
# Wait for service to be stable
log "Waiting for service to be stable..."
aws ecs wait services-stable --cluster "$CLUSTER_NAME" --services "$SERVICE_NAME"
log "Service is now stable and running"
# Get the task ARN for monitoring
TASK_ARN=$(aws ecs list-tasks --cluster "$CLUSTER_NAME" --service-name "$SERVICE_NAME" --query 'taskArns[0]' --output text)
if [[ -n "$TASK_ARN" && "$TASK_ARN" != "None" ]]; then
log "Service task: $TASK_ARN"
CREATED_RESOURCES+=("ECS Task: $TASK_ARN")
fi
}
# Function to demonstrate monitoring and testing
demonstrate_monitoring() {
log "Demonstrating monitoring capabilities..."
# List services
log "Listing services in cluster:"
aws ecs list-services --cluster "$CLUSTER_NAME" --output table
# Describe service
log "Service details:"
aws ecs describe-services --cluster "$CLUSTER_NAME" --services "$SERVICE_NAME" --output table --query 'services[0].{ServiceName:serviceName,Status:status,RunningCount:runningCount,DesiredCount:desiredCount,TaskDefinition:taskDefinition}'
# List tasks
log "Listing tasks in service:"
aws ecs list-tasks --cluster "$CLUSTER_NAME" --service-name "$SERVICE_NAME" --output table
# Describe task
if [[ -n "$TASK_ARN" && "$TASK_ARN" != "None" ]]; then
log "Task details:"
aws ecs describe-tasks --cluster "$CLUSTER_NAME" --tasks "$TASK_ARN" --output table --query 'tasks[0].{TaskArn:taskArn,LastStatus:lastStatus,DesiredStatus:desiredStatus,CreatedAt:createdAt}'
fi
# List container instances
log "Container instances in cluster:"
aws ecs list-container-instances --cluster "$CLUSTER_NAME" --output table
# Describe container instance
CONTAINER_INSTANCE_ARN=$(aws ecs list-container-instances --cluster "$CLUSTER_NAME" --query 'containerInstanceArns[0]' --output text)
if [[ -n "$CONTAINER_INSTANCE_ARN" && "$CONTAINER_INSTANCE_ARN" != "None" ]]; then
log "Container instance details:"
aws ecs describe-container-instances --cluster "$CLUSTER_NAME" --container-instances "$CONTAINER_INSTANCE_ARN" --output table --query 'containerInstances[0].{Arn:containerInstanceArn,Status:status,RunningTasks:runningTasksCount,PendingTasks:pendingTasksCount}'
fi
# Test the nginx web server
log "Testing nginx web server..."
PUBLIC_IP=$(aws ec2 describe-instances --instance-ids "$INSTANCE_ID" --query 'Reservations[0].Instances[0].PublicIpAddress' --output text)
if [[ -n "$PUBLIC_IP" && "$PUBLIC_IP" != "None" ]]; then
log "Container instance public IP: $PUBLIC_IP"
log "Testing HTTP connection to nginx..."
# Wait a moment for nginx to be fully ready
sleep 10
if curl -s --connect-timeout 10 "http://$PUBLIC_IP" | grep -q "Welcome to nginx"; then
log "SUCCESS: Nginx web server is responding correctly"
echo ""
echo "==========================================="
echo "WEB SERVER TEST SUCCESSFUL"
echo "==========================================="
echo "You can access your nginx web server at: http://$PUBLIC_IP"
echo "The nginx welcome page should be visible in your browser."
else
log "WARNING: Nginx web server may not be fully ready yet. Try accessing http://$PUBLIC_IP in a few minutes."
fi
else
log "WARNING: Could not retrieve public IP address"
fi
}
# Main execution
main() {
log "Starting ECS EC2 Launch Type Tutorial (UPDATED VERSION)"
log "Log file: $LOG_FILE"
log "Security improvements: IMDSv2 enforced, JSON validation, input sanitization, CloudWatch Logs configured"
check_prerequisites
create_cluster
create_key_pair
create_security_group
get_ecs_ami
ensure_ecs_instance_role
launch_container_instance
register_task_definition
create_service
demonstrate_monitoring
log "Tutorial completed successfully!"
echo ""
echo "==========================================="
echo "TUTORIAL COMPLETED SUCCESSFULLY"
echo "==========================================="
echo "Resources created:"
for resource in "${CREATED_RESOURCES[@]}"; do
echo " - $resource"
done
echo ""
echo "The nginx service will continue running and maintain the desired task count."
echo "You can monitor the service status using:"
echo " aws ecs describe-services --cluster $CLUSTER_NAME --services $SERVICE_NAME"
echo ""
if [[ -n "${PUBLIC_IP:-}" ]]; then
echo "Access your web server at: http://$PUBLIC_IP"
echo ""
fi
echo "==========================================="
echo "CLEANUP CONFIRMATION"
echo "==========================================="
log "Auto-confirming cleanup - proceeding with resource cleanup"
cleanup_resources
log "All resources have been cleaned up"
}
# Run main function
main "$@"
API 상세는 AWS CLI Command Reference의 다음 항목을 참고해요.
AddRoleToInstanceProfile,AttachRolePolicy,AuthorizeSecurityGroupIngress,CreateCluster,CreateInstanceProfile,CreateKeyPair,CreateRole,CreateSecurityGroup,CreateService,DeleteCluster,DeleteKeyPair,DeleteSecurityGroup,DeleteService,DeregisterTaskDefinition,DescribeContainerInstances,DescribeInstances,DescribeServices,DescribeSubnets,DescribeTasks,DescribeVpcs,GetCallerIdentity,GetParameters,GetRole,ListContainerInstances,ListServices,ListTasks,RegisterTaskDefinition,RunInstances,StopTask,TerminateInstances,UpdateService,Wait (Amazon EC2),Wait (Amazon ECS),Wait (IAM)