Search code examples
amazon-web-servicesamazon-ec2amazon-ecsautoscalingaws-application-load-balancer

Unable to create Ec2 instance with autoscaling and register them to ECS cluster


Hi I am trying to create a cluster with service and task. I have a python app in Ecr that connects to redis container. The issue is I am unable to create ec2 instance with autoscaling. Myservice in Cluster and Autoscaling doesn't builds.

Cluster:

---
AWSTemplateFormatVersion: 2010-09-09 
Parameters:
    Alb:
      Type: String
    DefaultTargetGroup:
      Type: String
    ECSServiceRole:
      Type: String
    Task:
      Type: String
Resources:
    MyCluster:
        Type: AWS::ECS::Cluster
        Properties: 
            ClusterName: Flask-redis
    Myservice:
        Type: AWS::ECS::Service
        Properties: 
            Cluster: !Ref MyCluster        
            DeploymentController:   
                Type: ECS
            DesiredCount: 2
            LaunchType: EC2
            LoadBalancers: 
                - ContainerName: python
                  ContainerPort: 5000
                  TargetGroupArn: !Ref DefaultTargetGroup
            Role: !Ref ECSServiceRole
            SchedulingStrategy: REPLICA
            ServiceName: Python-service
            TaskDefinition: !Ref Task

Autoscaling:

---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  SubnetA:
    Type: String
  SubnetB:
    Type: String
  VpcID:
    Type: String
  Albsg:
    Type: String
  Alb:
    Type: String
  ECSServiceRole:
    Type: String

Resources:
  wahajwebserver:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: wahaj-webserver
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          SourceSecurityGroupId: !Ref Albsg
          Description: For traffic from Internet
      GroupDescription: Security Group for demo server
      VpcId: !Ref VpcID
  ec2instance:
    Type: AWS::AutoScaling::LaunchConfiguration
    Properties:
    #   UserData:
    #     Fn::Base64: !Sub |
    #     #!/bin/bash -xe
    #     echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
    #     yum install -y aws-cfn-bootstrap
    #     /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}
        BlockDeviceMappings:
          - DeviceName: /dev/xvda
            Ebs:
                DeleteOnTermination: "true"
                VolumeSize: "8"
                VolumeType: gp2
        ImageId: ami-0bdcc6c05dec346bf
        InstanceType: t2.small
        IamInstanceProfile: !Ref ECSServiceRole
        KeyName: wahaj(webserver)
        SecurityGroups:
            - Ref: wahajwebserver
  myASG:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
        AvailabilityZones:
            - "us-east-2a"
            - "us-east-2b"
        AutoScalingGroupName: myASG
        LoadBalancerNames:
            - Ref: Alb
        MinSize: "2"
        MaxSize: "2"
        DesiredCapacity: "2"
        HealthCheckGracePeriod: 300
        LaunchConfigurationName:
            Ref: ec2instance
        VPCZoneIdentifier:
            - Ref: "SubnetA"
            - Ref: "SubnetB"

Task:

---
AWSTemplateFormatVersion: 2010-09-09 
Parameters:
    ExRole:
        Type: String
Resources:
    Task:
        Type: AWS::ECS::TaskDefinition
        Properties:
            Family: redis-python 
            Cpu: 1 vCPU
            ExecutionRoleArn: !Ref ExRole
            Memory: 1 GB
            NetworkMode: bridge
            RequiresCompatibilities:
                - EC2
            TaskRoleArn: !Ref ExRole
            ContainerDefinitions: 
              - Essential: true
                Image: redis:latest
                Name: redis 
              - Essential: true
                Image: 021146125185.dkr.ecr.us-east-2.amazonaws.com/python-app:latest
                Name: python
                PortMappings:  
                  - ContainerPort: 5000
                    HostPort: 0
                    Protocol: tcp
                DependsOn:
                   - Condition: START  
                     ContainerName: redis
                Links: 
                   - redis            
Outputs:
  Task:
    Description: Contains all the task specifications
    Value: !Ref Task
    Export:
      Name: "Task"

Application Load balancer:

---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
    SubnetA:
      Type: String
    SubnetB:
      Type: String
    VpcID:
      Type: String
Resources:
    Albsg:
        Type: AWS::EC2::SecurityGroup
        Properties:
            GroupName: alb-sg
            VpcId: !Ref VpcID
            SecurityGroupIngress:
                - IpProtocol: tcp
                  FromPort: 22
                  ToPort: 22
                  CidrIp: 0.0.0.0/0
                  Description: For traffic from Internet
                - IpProtocol: tcp
                  FromPort: 80
                  ToPort: 80
                  CidrIp: 0.0.0.0/0
                  Description: For traffic from Internet
            GroupDescription: Security Group for demo server
    Alb:
        Type: AWS::ElasticLoadBalancingV2::LoadBalancer
        Properties: 
            IpAddressType: ipv4
            Name: Alb
            Scheme: internet-facing
            SecurityGroups: 
                - !Ref Albsg
            Subnets:
                - Ref: "SubnetA"
                - Ref: "SubnetB"
            Type: application
    DefaultTargetGroup:
        Type: AWS::ElasticLoadBalancingV2::TargetGroup
        DependsOn: Alb
        Properties:
            Name: alb-tg
            VpcId: !Ref VpcID
            Port: 80
            Protocol: HTTP
    LoadBalancerListener:
        Type: AWS::ElasticLoadBalancingV2::Listener
        Properties:
            LoadBalancerArn: !Ref Alb
            Port: 80
            Protocol: HTTP
            DefaultActions:
                - Type: forward
                  TargetGroupArn: !Ref DefaultTargetGroup
Outputs:
  Albsg:
    Description: security group for application load balancer
    Value: !Ref Albsg
    Export:
        Name: "Albsg"
  Alb:
    Description: application load balancer
    Value: !Ref Alb
    Export:
      Name: "Alb"
  DefaultTargetGroup:
    Description: Default Target Group
    Value: !Ref DefaultTargetGroup
    Export:
      Name: "DefaultTargetGroup"

role:

---
AWSTemplateFormatVersion: 2010-09-09 
Resources:
    ECSServiceRole:
        Type: AWS::IAM::Role
        Properties:
          AssumeRolePolicyDocument:
            Statement:
            - Effect: Allow
              Principal:
                Service: [ecs.amazonaws.com]
              Action: ['sts:AssumeRole']
          Path: /
          Policies:
          - PolicyName: ecs-service
            PolicyDocument:
              Statement:
              - Effect: Allow
                Action: ['elasticloadbalancing:DeregisterInstancesFromLoadBalancer', 'elasticloadbalancing:DeregisterTargets',
                  'elasticloadbalancing:Describe*', 'elasticloadbalancing:RegisterInstancesWithLoadBalancer',
                  'elasticloadbalancing:RegisterTargets', 'ec2:Describe*', 'ec2:AuthorizeSecurityGroupIngress']
                Resource: '*'
    ExRole:
        Type: 'AWS::IAM::Role'
        Properties:
          AssumeRolePolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Principal:
                  Service:
                    - ecs-tasks.amazonaws.com
                Action:
                  - 'sts:AssumeRole'
          Path: /
          ManagedPolicyArns:
            - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
          Policies: 
            - PolicyName: AccessECR
              PolicyDocument:
                Version: '2012-10-17'
                Statement:
                  - Effect: Allow
                    Action: 
                      - ecr:BatchGetImage
                      - ecr:GetAuthorizationToken
                      - ecr:GetDownloadUrlForLayer 
                    Resource: '*'
Outputs:
  ExRole:
    Description: Task excution role
    Value: !Ref ExRole
    Export:
        Name: "ExRole"
  ECSServiceRole:
    Description: application load balancer
    Value: !Ref ECSServiceRole
    Export:
      Name: "ECSServiceRole"

I am unable to create Ec2 instance with autoscaling and register them to ECS cluster. Any help would be appreciated.


Solution

  • Since you haven't provided any error messages, the initial look at Autoscaling template shows several issues.

    LoadBalancerNames

            LoadBalancerNames:
                - Ref: Alb
    

    This is only for CLB, but you are using ALB. For ALB you should be using TargetGroupARNs parameter.

    UserData

    You commented out the UserData. Not sure why? It should be there as you should register the instance with the cluster. I guess due to mistakes? see below.

    cfn-signal

    In the UserData, you are using --resource ECSAutoScalingGroup. But it should be --resource myASG

    ASG and creation policy

    cfn-signal has no effect as your ASG is missing CreationPolicy.

    ECSCluster

    Again in the UserData: reference to ECSCluster is not defined.

    ImageId

    Just by looking at ami-0bdcc6c05dec346bf I'm not sure if this is ECS optimized AMI. This have to be checked.

    ECSServiceRole

    Its form is not shown. Could be incorrect or even fully missing.

    Update and fixed template

    Upon further examination many more issues were found. Just to name few:

    • missing instance profile
    • missing/wrong container instance role
    • incorrect security groups
    • Not using ImportValue
    • Missing some output exports

    The fixed and modified templates was tested in us-east-1 and default VPC. It will not work in any other region unless AMI is adjusted. Also due to lack of your ECR image, I had to create my own with my own ports, so I also had to modify this as well to even attempt a verification.

    roles

    ---
    AWSTemplateFormatVersion: 2010-09-09 
    Resources:
    
      ExRole:
          Type: 'AWS::IAM::Role'
          Properties:
            AssumeRolePolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Principal:
                    Service:
                      - ecs-tasks.amazonaws.com
                  Action:
                    - 'sts:AssumeRole'
            Path: /
            ManagedPolicyArns:
              - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
            Policies: 
              - PolicyName: AccessECR
                PolicyDocument:
                  Version: '2012-10-17'
                  Statement:
                    - Effect: Allow
                      Action: 
                        - ecr:BatchGetImage
                        - ecr:GetAuthorizationToken
                        - ecr:GetDownloadUrlForLayer 
                      Resource: '*'
    
      ContainerInstanceRole:
        Type: AWS::IAM::Role
        Properties:
          AssumeRolePolicyDocument:
            Version: '2012-10-17'               
            Statement:
              - Effect: Allow
                Principal: {'Service': ['ec2.amazonaws.com']}
                Action: ['sts:AssumeRole']
          ManagedPolicyArns:
            - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
          Path: '/'
    
      InstanceProfile:
        Type: AWS::IAM::InstanceProfile
        Properties: 
          Roles: 
            - !Ref ContainerInstanceRole      
    
    Outputs:
      
      ExRole:
        Description: Task excution role
        Value: !Ref ExRole
        Export:
            Name: "ExRole"
    
    
      InstanceProfile:
        Description: profile for container instances
        Value: !Ref InstanceProfile
        Export:
            Name: "InstanceProfile"            
    

    alb

    ---
    AWSTemplateFormatVersion: 2010-09-09
    Parameters:
        SubnetA:
          Type: AWS::EC2::Subnet::Id
        SubnetB:
          Type: AWS::EC2::Subnet::Id
        VpcID:
          Type: AWS::EC2::VPC::Id
    Resources:
        Albsg:
            Type: AWS::EC2::SecurityGroup
            Properties:
                GroupName: alb-sg
                VpcId: !Ref VpcID
                SecurityGroupIngress:
                    - IpProtocol: tcp
                      FromPort: 80
                      ToPort: 80
                      CidrIp: 0.0.0.0/0
                      Description: For traffic from Internet
                GroupDescription: Security Group for demo server
        Alb:
            Type: AWS::ElasticLoadBalancingV2::LoadBalancer
            Properties: 
                IpAddressType: ipv4
                Name: Alb
                Scheme: internet-facing
                SecurityGroups: 
                    - !Ref Albsg
                Subnets:
                    - Ref: "SubnetA"
                    - Ref: "SubnetB"
                Type: application
        DefaultTargetGroup:
            Type: AWS::ElasticLoadBalancingV2::TargetGroup
            DependsOn: Alb
            Properties:
                Name: alb-tg
                VpcId: !Ref VpcID
                Port: 8080
                Protocol: HTTP
        LoadBalancerListener:
            Type: AWS::ElasticLoadBalancingV2::Listener
            Properties:
                LoadBalancerArn: !Ref Alb
                Port: 80
                Protocol: HTTP
                DefaultActions:
                    - Type: forward
                      TargetGroupArn: !Ref DefaultTargetGroup
    Outputs:
      Albsg:
        Description: security group for application load balancer
        Value: !Ref Albsg
        Export:
            Name: "Albsg"
      Alb:
        Description: application load balancer
        Value: !Ref Alb
        Export:
          Name: "Alb"
      DefaultTargetGroup:
        Description: Default Target Group
        Value: !Ref DefaultTargetGroup
        Export:
          Name: "DefaultTargetGroup"
    
      SubnetA:
        Value: !Ref SubnetA
        Export:
            Name: "SubnetA"
      SubnetB:
        Value: !Ref SubnetB
        Export:
            Name: "SubnetB"
      VpcID:
        Value: !Ref VpcID
        Export:
            Name: "VpcID"           
    

    task

    ---
    AWSTemplateFormatVersion: 2010-09-09 
    
    Resources:
        Task:
            Type: AWS::ECS::TaskDefinition
            Properties:
                Family: redis-python 
                Cpu: 1 vCPU
                ExecutionRoleArn: !ImportValue ExRole
                Memory: 1 GB
                NetworkMode: bridge
                RequiresCompatibilities:
                    - EC2
                TaskRoleArn: !ImportValue ExRole
                ContainerDefinitions: 
                  - Essential: true
                    Image: redis:latest
                    Name: redis 
                  - Essential: true
                    Image: xxxxxx.dkr.ecr.us-east-1.amazonaws.com/xxxxxx:latest
                    Name: python
                    PortMappings:  
                      - ContainerPort: 8080
                        #HostPort: 0
                        Protocol: tcp
                    DependsOn:
                       - Condition: START  
                         ContainerName: redis
                    Links: 
                       - redis            
    Outputs:
      Task:
        Description: Contains all the task specifications
        Value: !Ref Task
        Export:
          Name: "Task"
    

    service_and_asg

    ---
    AWSTemplateFormatVersion: 2010-09-09
    
    Parameters:
    
      KeyName:
        Type: AWS::EC2::KeyPair::KeyName
        Default: wahajwebserver
    
      DesiredCapacity:
        Type: Number
        Default: 2
    
      MinSize:
        Type: Number
        Default: 1
    
      MaxSize:
        Type: Number
        Default: 4  
    
    
    Resources:
    
      MyCluster:
          Type: AWS::ECS::Cluster
          Properties: {}
    
      wahajwebserver:
        Type: AWS::EC2::SecurityGroup
        Properties:
          #GroupName: wahaj-webserver
          SecurityGroupIngress:
            - IpProtocol: tcp
              FromPort: 22
              ToPort: 22
              CidrIp: 0.0.0.0/0
            - IpProtocol: tcp
              FromPort: 0
              ToPort: 65535
              SourceSecurityGroupId: !ImportValue Albsg
              Description: For traffic from Internet
          GroupDescription: Security Group for demo server
          VpcId: !ImportValue VpcID
    
      Myservice:
          Type: AWS::ECS::Service
          Properties: 
              Cluster: !Ref MyCluster        
              DeploymentController:   
                  Type: ECS
              DesiredCount: 2
              LaunchType: EC2
              LoadBalancers: 
                  - ContainerName: python
                    ContainerPort: 8080
                    TargetGroupArn: !ImportValue DefaultTargetGroup
              #Role: !Ref ECSServiceRole
              SchedulingStrategy: REPLICA
              #ServiceName: Python-service
              TaskDefinition: !ImportValue Task
    
      ec2instance:
        Type: AWS::AutoScaling::LaunchConfiguration
        Properties:
          UserData:
            Fn::Base64: !Sub |
              #!/bin/bash -xe
    
              yum update -y && yum install -y aws-cfn-bootstrap 
    
              echo ECS_CLUSTER=${MyCluster} >> /etc/ecs/ecs.config
              echo ECS_BACKEND_HOST= >> /etc/ecs/ecs.config           
    
              /opt/aws/bin/cfn-signal -e $? \
                    --stack ${AWS::StackName} \
                    --resource myASG \
                    --region ${AWS::Region}
    
          BlockDeviceMappings:
            - DeviceName: /dev/xvda
              Ebs:
                DeleteOnTermination: "true"
                VolumeSize: 30
                VolumeType: gp2
          ImageId: ami-07a63940735aebd38 # before ami-0bdcc6c05dec346bf
          InstanceType: t2.small
          IamInstanceProfile: !ImportValue InstanceProfile
          KeyName: !Ref KeyName
          SecurityGroups:
              - Ref: wahajwebserver
    
      myASG:
        Type: AWS::AutoScaling::AutoScalingGroup
        CreationPolicy:
          ResourceSignal:
            Timeout: PT5M
            Count: !Ref DesiredCapacity
        Properties:
          #AutoScalingGroupName: myASG
          MinSize: !Ref MinSize
          MaxSize: !Ref MaxSize
          DesiredCapacity: !Ref DesiredCapacity
          HealthCheckGracePeriod: 300
          LaunchConfigurationName:
            Ref: ec2instance
          VPCZoneIdentifier:
            - !ImportValue SubnetA
            - !ImportValue SubnetB
          TargetGroupARNs:
            - !ImportValue DefaultTargetGroup
    

    Screenshots showing an ECS cluster with two tasks and 2 tasks (1 task on each instance)

    enter image description here