I have been following this guide to create a Kubernetes cluster via CloudFormation, but the NodeGroup never joins the cluster, and I never get an error or explanation about why is not joining.
I can see the autoscaling group and the EC2 machines are created, but EKS reports that there is not node groups.
If I create a new node group manually through the web admin tool, it works, but it assigns different security groups. It has a launch template instead of a launch configuration.
Same AMI, same IAM role, same machine type...
I am very new in both CloudFormation and EKS, and I don't know how to proceed now to find out what the problem is.
Here is the template:
Description: >
Kubernetes cluster
Parameters:
EnvironmentName:
Description: An environment name that will be prefixed to resource names
Type: String
KeyName:
Description: The EC2 Key Pair to allow SSH access to the instances
Type: AWS::EC2::KeyPair::KeyName
VpcBlock:
Type: String
Default: 192.168.0.0/16
Description: The CIDR range for the VPC. This should be a valid private (RFC 1918) CIDR range.
Subnet01Block:
Type: String
Default: 192.168.64.0/18
Description: CidrBlock for subnet 01 within the VPC
Subnet02Block:
Type: String
Default: 192.168.128.0/18
Description: CidrBlock for subnet 02 within the VPC
Subnet03Block:
Type: String
Default: 192.168.192.0/18
Description: CidrBlock for subnet 03 within the VPC. This is used only if the region has more than 2 AZs.
NodeInstanceType:
Description: EC2 instance type for the node instances
Type: String
NodeImageId:
Type: AWS::EC2::Image::Id
Description: AMI id for the node instances.
NodeAutoScalingGroupMinSize:
Type: Number
Description: Minimum size of Node Group ASG.
Default: 1
NodeAutoScalingGroupMaxSize:
Type: Number
Description: Maximum size of Node Group ASG. Set to at least 1 greater than NodeAutoScalingGroupDesiredCapacity.
Default: 3
NodeAutoScalingGroupDesiredCapacity:
Type: Number
Description: Desired capacity of Node Group ASG.
Default: 3
BootstrapArguments:
Description: Arguments to pass to the bootstrap script. See files/bootstrap.sh in https://github.com/awslabs/amazon-eks-ami
Default: ""
Type: String
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcBlock
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Environment
Value: !Ref EnvironmentName
InternetGateway:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
- Key: Environment
Value: !Ref EnvironmentName
VPCGatewayAttachment:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Environment
Value: !Ref EnvironmentName
Route:
DependsOn: VPCGatewayAttachment
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
Subnet01:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [ 0, !GetAZs '' ]
CidrBlock: !Ref Subnet01Block
VpcId: !Ref VPC
MapPublicIpOnLaunch: true
Tags:
- Key: Environment
Value: !Ref EnvironmentName
Subnet02:
Type: AWS::EC2::Subnet
Metadata:
Comment: Subnet 02
Properties:
AvailabilityZone: !Select [ 1, !GetAZs '' ]
CidrBlock: !Ref Subnet02Block
VpcId: !Ref VPC
MapPublicIpOnLaunch: true
Tags:
- Key: Environment
Value: !Ref EnvironmentName
Subnet03:
Type: AWS::EC2::Subnet
Metadata:
Comment: Subnet 03
Properties:
AvailabilityZone: !Select [ 2, !GetAZs '' ]
CidrBlock: !Ref Subnet03Block
VpcId: !Ref VPC
MapPublicIpOnLaunch: true
Tags:
- Key: Environment
Value: !Ref EnvironmentName
Subnet01RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref Subnet01
RouteTableId: !Ref RouteTable
Subnet02RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref Subnet02
RouteTableId: !Ref RouteTable
Subnet03RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref Subnet03
RouteTableId: !Ref RouteTable
ControlPlaneSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Cluster communication with worker nodes
VpcId: !Ref VPC
ClusterRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${EnvironmentName}KubernetesClusterRole
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: eks.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonEKSServicePolicy
- arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
Tags:
- Key: Environment
Value: !Ref EnvironmentName
Cluster:
Type: AWS::EKS::Cluster
Properties:
Name: !Sub ${EnvironmentName}KubernetesCluster
RoleArn: !GetAtt ClusterRole.Arn
ResourcesVpcConfig:
SecurityGroupIds:
- !Ref ControlPlaneSecurityGroup
SubnetIds:
- !Ref Subnet01
- !Ref Subnet02
- !Ref Subnet03
NodeRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${EnvironmentName}KubernetesNodeRole
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
- arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
- arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
Path: /
Tags:
- Key: Environment
Value: !Ref EnvironmentName
NodeInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: "/"
Roles:
- !Ref NodeRole
NodeSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for all nodes in the cluster
VpcId: !Ref VPC
Tags:
- Key: !Sub "kubernetes.io/cluster/${EnvironmentName}KubernetesCluster"
Value: 'owned'
- Key: Environment
Value: !Ref EnvironmentName
NodeSecurityGroupIngress:
Type: AWS::EC2::SecurityGroupIngress
DependsOn: NodeSecurityGroup
Properties:
Description: Allow node to communicate with each other
GroupId: !Ref NodeSecurityGroup
SourceSecurityGroupId: !Ref NodeSecurityGroup
IpProtocol: '-1'
FromPort: 0
ToPort: 65535
NodeSecurityGroupFromControlPlaneIngress:
Type: AWS::EC2::SecurityGroupIngress
DependsOn: NodeSecurityGroup
Properties:
Description: Allow worker Kubelets and pods to receive communication from the cluster control plane
GroupId: !Ref NodeSecurityGroup
SourceSecurityGroupId: !Ref ControlPlaneSecurityGroup
IpProtocol: tcp
FromPort: 1025
ToPort: 65535
ControlPlaneEgressToNodeSecurityGroup:
Type: AWS::EC2::SecurityGroupEgress
DependsOn: NodeSecurityGroup
Properties:
Description: Allow the cluster control plane to communicate with worker Kubelet and pods
GroupId: !Ref ControlPlaneSecurityGroup
DestinationSecurityGroupId: !Ref NodeSecurityGroup
IpProtocol: tcp
FromPort: 1025
ToPort: 65535
NodeSecurityGroupFromControlPlaneOn443Ingress:
Type: AWS::EC2::SecurityGroupIngress
DependsOn: NodeSecurityGroup
Properties:
Description: Allow pods running extension API servers on port 443 to receive communication from cluster control plane
GroupId: !Ref NodeSecurityGroup
SourceSecurityGroupId: !Ref ControlPlaneSecurityGroup
IpProtocol: tcp
FromPort: 443
ToPort: 443
ControlPlaneEgressToNodeSecurityGroupOn443:
Type: AWS::EC2::SecurityGroupEgress
DependsOn: NodeSecurityGroup
Properties:
Description: Allow the cluster control plane to communicate with pods running extension API servers on port 443
GroupId: !Ref ControlPlaneSecurityGroup
DestinationSecurityGroupId: !Ref NodeSecurityGroup
IpProtocol: tcp
FromPort: 443
ToPort: 443
ClusterControlPlaneSecurityGroupIngress:
Type: AWS::EC2::SecurityGroupIngress
DependsOn: NodeSecurityGroup
Properties:
Description: Allow pods to communicate with the cluster API Server
GroupId: !Ref ControlPlaneSecurityGroup
SourceSecurityGroupId: !Ref NodeSecurityGroup
IpProtocol: tcp
ToPort: 443
FromPort: 443
NodeGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
DesiredCapacity: !Ref NodeAutoScalingGroupDesiredCapacity
LaunchConfigurationName: !Ref NodeLaunchConfig
MinSize: !Ref NodeAutoScalingGroupMinSize
MaxSize: !Ref NodeAutoScalingGroupMaxSize
VPCZoneIdentifier:
- !Ref Subnet01
- !Ref Subnet02
- !Ref Subnet03
Tags:
- Key: Name
Value: !Sub "${EnvironmentName}KubernetesCluster-Node"
PropagateAtLaunch: 'true'
- Key: !Sub 'kubernetes.io/cluster/${EnvironmentName}KubernetesCluster'
Value: 'owned'
PropagateAtLaunch: 'true'
UpdatePolicy:
AutoScalingRollingUpdate:
MaxBatchSize: '1'
MinInstancesInService: !Ref NodeAutoScalingGroupDesiredCapacity
PauseTime: 'PT5M'
NodeLaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
AssociatePublicIpAddress: 'true'
IamInstanceProfile: !Ref NodeInstanceProfile
ImageId: !Ref NodeImageId
InstanceType: !Ref NodeInstanceType
KeyName: !Ref KeyName
SecurityGroups:
- !Ref NodeSecurityGroup
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeSize: 20
VolumeType: gp2
DeleteOnTermination: true
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
set -o xtrace
/etc/eks/bootstrap.sh ${EnvironmentName}KubernetesCluster ${BootstrapArguments}
/opt/aws/bin/cfn-signal --exit-code $? \
--stack ${AWS::StackName} \
--resource NodeGroup \
--region ${AWS::Region}
Outputs:
KubernetesClusterName:
Description: Cluster name
Value: !Ref Cluster
Export:
Name: KubernetesClusterName
KubernetesClusterEndpoint:
Description: Cluster endpoint
Value: !GetAtt Cluster.Endpoint
Export:
Name: KubernetesClusterEndpoint
KubernetesNodeInstanceProfile:
Description: The name of the IAM profile for K8
Value: !GetAtt NodeInstanceProfile.Arn
Export:
Name: KubernetesNodeInstanceProfileArn
There are two ways of adding Worker nodes to your EKS cluster:
Launch and register workers on your own (https://docs.aws.amazon.com/eks/latest/userguide/launch-workers.html)
Use managed node groups (https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)
As I can see from your template, you are using the first approach by now. Important when doing this is, that you need to wait until the EKS Cluster is ready and in state active, before launching the worker nodes. You can achieve this by using the DependsOn Attribute. If this does not resolve your issues, have a look at the cloud init logs (/var/log/cloud-init-output.log) to check what is happening while joining the cluster.
If you would like to use Managed Node Groups, just remove the AutoScaling Group and LaunchConfiguration and use this type instead: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-nodegroup.html
The benefit is, that AWS takes care of creating the required resources (AutoScaling Group and LaunchTemplate) in your account for you and you can see the Node Group in the AWS Console.
I approached with managed node groups (https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) option. It was working. But how to define the autoscaling policy. It just allows giving max and min node counts not even name.
Related
I am trying to launch a containerized grpc application on aws fargate. I've tested the image locally, and have pushed it to ecr. I've created a task with a role that has permission to reach ecr, yet I am still getting an error pulling the container (error message shown below). I even tried launching the container in a public subnet with internet gateway/route table association that auto assigns public ips and the security group allows all outbound traffic.
The full cloudformation template is given below:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
TicketingAppTaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
ContainerDefinitions:
- Essential: true
Image: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/ticketing-app:latest"
Name: ticketing-app
PortMappings:
- ContainerPort: 8080
Cpu: "1 vCPU"
ExecutionRoleArn: !Ref ExecutionRole
Memory: "2 GB" #this is smallest for 1 vcpu .... could maybe decrease
NetworkMode: awsvpc
RuntimePlatform:
CpuArchitecture: X86_64
OperatingSystemFamily: LINUX
ExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: [ sts:AssumeRole ]
Effect: Allow
Principal:
Service: [ ecs-tasks.amazonaws.com ]
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
TicketingEcsService:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref TicketingEcsCluster
LaunchType: FARGATE
#TODO I think we eventually need to specify load balancers here
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED #TODO remove this when done, just seeing if this let's us grab image from ecr?
SecurityGroups: [ !GetAtt TicketingServiceSecurityGroup.GroupId ]
Subnets:
- !Ref TicketingServicePrivateSubnet01
- !Ref TicketingServicePrivateSubnet02
TaskDefinition: !Ref TicketingAppTaskDefinition
TicketingEcsCluster:
Type: AWS::ECS::Cluster
TicketingServiceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "A security group used for the ticketing app"
VpcId: !Ref TicketingServiceVpc
TicketingServiceVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
TicketingServicePrivateSubnet01:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Sub "${AWS::Region}a"
VpcId: !Ref TicketingServiceVpc
CidrBlock: 10.0.0.0/18
TicketingServicePrivateSubnet02:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Sub "${AWS::Region}b"
VpcId: !Ref TicketingServiceVpc
CidrBlock: 10.0.64.0/18
#TODO public subnets and NAT gateway?
TicketingSecurityGroupHttpIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
#TODO I would probably use load balancer security group name here once we make one instead of opening up to any ip
GroupId: !GetAtt TicketingServiceSecurityGroup.GroupId
CidrIpv6: "::/0"
FromPort: 8080
IpProtocol: tcp
ToPort: 8080
TicketingSecurityGroupAllTrafficEgress:
Type: AWS::EC2::SecurityGroupEgress
Properties:
GroupId: !GetAtt TicketingServiceSecurityGroup.GroupId
IpProtocol: "-1" #-1 indicates all -- like a wildcard
CidrIp: "0.0.0.0/0"
TicketingServiceInternetGateway:
Type: AWS::EC2::InternetGateway
DependsOn: TicketingServiceVpc
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref TicketingServiceVpc
InternetGatewayId: !Ref TicketingServiceInternetGateway
TicketingAppRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref TicketingServiceVpc
TicketingVPCRouteAllTrafficToInternetGateway:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref TicketingAppRouteTable
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref TicketingServiceInternetGateway
Would anyone be able to point out a simple way to get this working (even if it uses not best practices, such as public subnet instead of private subnet and nat gateway) -- it is just for a poc.
Thanks
I had pushed my image to ecr in a different region..... changed the region and it worked (face palm).
So check your region if anyone else is in the same spot as me.
I'm experiencing a very annoying problem. I created a CI/CD pipelines using AWS CodePipeline and CloudFormation.
This is the template.yml used by CloudFormation to create a ScheduledTask on ECS.
AWSTemplateFormatVersion: "2010-09-09"
Description: Template for deploying a ECR image on ECS
Resources:
VPC:
Type: "AWS::EC2::VPC"
Properties:
CidrBlock: "10.0.0.0/16"
EnableDnsSupport: true
EnableDnsHostnames: true
InstanceTenancy: default
Subnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !Sub "10.0.0.0/20"
MapPublicIpOnLaunch: true
Subnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [1, !GetAZs ""]
CidrBlock: !Sub "10.0.32.0/20"
MapPublicIpOnLaunch: true
InternetGateway:
Type: "AWS::EC2::InternetGateway"
VPCGatewayAttachment:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
RouteTable:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref VPC
RouteTableAssociation1:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref Subnet1
RouteTableId: !Ref RouteTable
RouteTableAssociation2:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref Subnet2
RouteTableId: !Ref RouteTable
InternetRoute:
Type: "AWS::EC2::Route"
DependsOn: VPCGatewayAttachment
Properties:
GatewayId: !Ref InternetGateway
RouteTableId: !Ref RouteTable
DestinationCidrBlock: "0.0.0.0/0"
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: "SLAComputation"
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: ecs-services
Subnets:
- !Ref "Subnet1"
- !Ref "Subnet2"
SecurityGroups:
- !Ref LoadBalancerSecurityGroup
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref LoadBalancer
Protocol: HTTP
Port: 80
DefaultActions:
- Type: forward
TargetGroupArn: !Ref DefaultTargetGroup
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for loadbalancer to services on ECS
VpcId: !Ref "VPC"
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
DefaultTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: default
VpcId: !Ref "VPC"
Protocol: "HTTP"
Port: "80"
CloudWatchLogsGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: "sla_computation"
RetentionInDays: 1
ContainerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref "VPC"
GroupDescription: for ecs containers
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref "LoadBalancerSecurityGroup"
IpProtocol: -1
Task:
Type: AWS::ECS::TaskDefinition
Properties:
Family: apis
Cpu: 1024
Memory: 2048
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ExecutionRoleArn: !Ref ECSTaskExecutionRole
ContainerDefinitions:
- Name: ass001
Image: !Sub 649905970782.dkr.ecr.eu-west-1.amazonaws.com/ass001:latest
Cpu: 1024
Memory: 2048
HealthCheck:
Command: [ "CMD-SHELL", "exit 0" ]
Interval: 30
Retries: 5
Timeout: 10
StartPeriod: 30
PortMappings:
- ContainerPort: 8080
Protocol: tcp
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: "sla_computation"
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: "ass001"
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: employee-tg
VpcId: !Ref VPC
Port: 80
Protocol: HTTP
Matcher:
HttpCode: 200-299
TargetType: ip
ListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
ListenerArn: !Ref LoadBalancerListener
Priority: 2
Conditions:
- Field: path-pattern
Values:
- /*
Actions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs-tasks.amazonaws.com]
Action: ["sts:AssumeRole"]
Path: /
Policies:
- PolicyName: AmazonECSTaskExecutionRolePolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
# ECS Tasks to download images from ECR
- "ecr:GetAuthorizationToken"
- "ecr:BatchCheckLayerAvailability"
- "ecr:GetDownloadUrlForLayer"
- "ecr:BatchGetImage"
# ECS tasks to upload logs to CloudWatch
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Resource: "*"
TaskSchedule:
Type: AWS::Events::Rule
Properties:
Description: SLA rule ass001
Name: ass001
ScheduleExpression: cron(0/5 * * * ? *)
State: ENABLED
Targets:
- Arn:
!GetAtt ECSCluster.Arn
Id: dump-data-ecs-task
RoleArn:
!GetAtt ECSTaskExecutionRole.Arn
EcsParameters:
TaskDefinitionArn:
!Ref Task
TaskCount: 1
LaunchType: FARGATE
PlatformVersion: LATEST
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- sg-07db5ae6616a8c5fc
Subnets:
- subnet-031d0787ad492c1c4
TaskSchedule:
Type: AWS::Events::Rule
Properties:
Description: SLA rule ass002
Name: ass002
ScheduleExpression: cron(0/5 * * * ? *)
State: ENABLED
Targets:
- Arn:
!GetAtt ECSCluster.Arn
Id: dump-data-ecs-task
RoleArn:
!GetAtt ECSTaskExecutionRole.Arn
EcsParameters:
TaskDefinitionArn:
!Ref Task
TaskCount: 1
LaunchType: FARGATE
PlatformVersion: LATEST
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- sg-07db5ae6616a8c5fc
Subnets:
- subnet-031d0787ad492c1c4
Outputs:
ApiEndpoint:
Description: Employee API Endpoint
Value: !Join ["", ["http://", !GetAtt LoadBalancer.DNSName, "/employees"]]
Export:
Name: "EmployeeApiEndpoint"
The ScheduledTask is created successfully but it is not running actually. Very strange. But the strangest thing is that the ScheduledTask starts working when I click on "Edit" from the AWS console and (without making any change) I save.
The main issue I see is that you are using wrong role for your scheduled rule. It can't be !GetAtt ECSTaskExecutionRole.Arn. Instead you should create new role (or edit existing one) which has AmazonEC2ContainerServiceEventsRole AWS Managed policy.
It works after you edit in console, because AWS console will probably create the correct role in the background and use it instead of yours.
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.
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)
I am trying to create an internet facing elb. I have created vpc in ohio region (us-east-2). I have created 4 subnet. 2 public subnets and 2 private subnets.
Public subent: SubnetA (us-east-2a), SubnetB (us-east-2b)
Private subnet: SubnetC (us-east-2a) , SubnetD (us-east-2b)
When I give the availability zone to the load balancer it shows the following error Security group does not belong to VPC
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
SourceStackName:
Description: "Source stack name"
Type: String
AllowedPattern: "^[a-zA-Z][-a-zA-Z0-9]*$"
Default: "wahaj-vpc"
Resources:
wahajelb:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: wahaj-elb
VpcId:
Fn::ImportValue:
Fn::Sub: "${SourceStackName}-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
MyLoadBalancer:
Type: AWS::ElasticLoadBalancing::LoadBalancer
Properties:
Listeners:
- LoadBalancerPort: "80"
InstancePort: "80"
Protocol: HTTP
SecurityGroups:
- !Ref wahajelb
LoadBalancerName: wahajelb
Subnets:
- Fn::ImportValue: !Sub "${SourceStackName}-SubnetC"
- Fn::ImportValue: !Sub "${SourceStackName}-SubnetD"
HealthCheck:
Target: HTTP:80/SamplePage.php
HealthyThreshold: "3"
UnhealthyThreshold: "5"
Interval: "30"
Timeout: "5"
I am new to this so please if any changes is required to the template do tell me I might have made some mistakes.
Vpc template
---
AWSTemplateFormatVersion: 2010-09-09
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 11.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
InstanceTenancy: default
InternetGateway:
Type: AWS::EC2::InternetGateway
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
SubnetA:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2a
VpcId: !Ref VPC
CidrBlock: 11.0.0.0/24
MapPublicIpOnLaunch: true
SubnetB:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2b
VpcId: !Ref VPC
CidrBlock: 11.0.1.0/24
MapPublicIpOnLaunch: true
SubnetC:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2a
VpcId: !Ref VPC
CidrBlock: 11.0.2.0/24
MapPublicIpOnLaunch: false
SubnetD:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2b
VpcId: !Ref VPC
CidrBlock: 11.0.3.0/24
MapPublicIpOnLaunch: false
RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
RouteTable2:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
InternetRoute:
Type: AWS::EC2::Route
DependsOn: VPCGatewayAttachment
Properties:
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
RouteTableId: !Ref RouteTable
SubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref SubnetA
SubnetBRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref SubnetB
SubnetCRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable2
SubnetId: !Ref SubnetC
SubnetDRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable2
SubnetId: !Ref SubnetD
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: "Internet Group"
GroupDescription: "SSH traffic in, all traffic out."
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: "22"
ToPort: "22"
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
NAT:
Type: AWS::EC2::NatGateway
Properties:
AllocationId:
Fn::GetAtt:
- EIP
- AllocationId
SubnetId:
Ref: SubnetA
Tags:
- Key: Name
Value: wahaj-nat
EIP:
DependsOn: VPCGatewayAttachment
Type: AWS::EC2::EIP
Properties:
Domain: VPC
Route:
Type: AWS::EC2::Route
Properties:
RouteTableId:
Ref: RouteTable2
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId:
Ref: NAT
Outputs:
vpcID:
Description: VPC id
Value: !Ref VPC
Export:
Name:
Fn::Sub: "${AWS::StackName}-VpcID"
SubnetA:
Description: public subnet
Value: !Ref SubnetA
Export:
Name:
Fn::Sub: "${AWS::StackName}-SubnetA"
SubnetB:
Description: public subnet 2
Value: !Ref SubnetB
Export:
Name:
Fn::Sub: "${AWS::StackName}-SubnetB"
SubnetC:
Description: priavte subnet
Value: !Ref SubnetC
Export:
Name:
Fn::Sub: "${AWS::StackName}-SubnetC"
SubnetD:
Description: private subnet 2
Value: !Ref SubnetD
Export:
Name:
Fn::Sub: "${AWS::StackName}-SubnetD"
Autoscaling template
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
SourceStackName:
Description: "Source stack name"
Type: String
AllowedPattern: "^[a-zA-Z][-a-zA-Z0-9]*$"
Default: "wahaj-vpc"
elb:
Description: "elb"
Type: String
AllowedPattern: "^[a-zA-Z][-a-zA-Z0-9]*$"
Default: "wahaj-elb"
bastion:
Description: "bastion host"
Type: String
AllowedPattern: "^[a-zA-Z][-a-zA-Z0-9]*$"
Default: "wahaj-bastion"
Resources:
wahajwebserver:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: wahaj-webserver
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId:
Fn::ImportValue: !Sub "${bastion}-bsgId"
Description: For traffic from Internet
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId:
Fn::ImportValue: !Sub "${elb}-lgsg"
Description: For traffic from Internet
GroupDescription: Security Group for demo server
VpcId:
Fn::ImportValue:
Fn::Sub: "${SourceStackName}-VpcID"
ec2instance:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
DeleteOnTermination: "true"
VolumeSize: "8"
VolumeType: gp2
ImageId: ami-0bdcc6c05dec346bf
InstanceType: t2.micro
IamInstanceProfile: !Ref ListS3BucketsInstanceProfile
KeyName: wahaj(webserver)
SecurityGroups:
- Ref: wahajwebserver
ListS3BucketsInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: "/"
Roles:
- Ref: S3FullAccess
ListS3BucketsPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: ListS3BucketsPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- s3:List*
Resource: "*"
Roles:
- Ref: S3FullAccess
S3FullAccess:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
myASG:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AvailabilityZones:
- "us-east-2a"
- "us-east-2b"
AutoScalingGroupName: myASG
LoadBalancerNames:
- Fn::ImportValue: !Sub "${elb}-MyLoadBalancer"
MinSize: "2"
MaxSize: "2"
DesiredCapacity: "2"
HealthCheckGracePeriod: 300
LaunchConfigurationName:
Ref: ec2instance
VPCZoneIdentifier:
- Fn::ImportValue: !Sub "${SourceStackName}-SubnetC"
- Fn::ImportValue: !Sub "${SourceStackName}-SubnetD"
Outputs:
Autoscaling:
Description: autoscaling
Value: !Ref myASG
Export:
Name:
Fn::Sub: "${AWS::StackName}-myASG"
ec2instance:
Description: ec2instances
Value: !Ref ec2instance
Export:
Name:
Fn::Sub: "${AWS::StackName}-ec2instance"
sg:
Description: ec2instances securitygroup
Value: !GetAtt wahajwebserver.GroupId
Export:
Name:
Fn::Sub: "${AWS::StackName}-sg"
This is because the ELB and the security group reside within separate VPCs.
Your template has commented out the subnets which result in the load balancer being created in the default VPC of that region, however your security group explicitly sets a VPC ID. Therefore they are in separate VPCs.
It is always good practice to ensure that you define the VPC ID/subnet ID of resources that support it, for some resources such as EC2 without this property they will always replace when you make a change (such as changing a tag) via CloudFormation.
I built a VPC with a few AWS resources inside of it. I can get Internet access if I'm in the VPC and resources inside the VPC can communicate with each other. For instance, I have a Lambda function that can communicate to the Internet and also reach an RDS instance inside the VPC. However, the issue comes in when I am trying to connect to the RDS instance from my local machine.
I've tried updating the VPCSecurityGroup to allow all incoming traffic, but still won't work. The only thing that seems to work is if I switch all of the Route Tables to use an IGW as opposed to a NAT, but I'd prefer if that wasn't the case. Also, I'm not even sure I'd be allowed to do that because I'm pretty sure lambda functions have to exist in private subnets.
vpc.yml
AWSTemplateFormatVersion: 2010-09-09
Description: VPC Stack
Resources:
Vpc:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
InstanceTenancy: default
InternetGateway:
Type: 'AWS::EC2::InternetGateway'
VpcGatewayAttachment:
Type: 'AWS::EC2::VPCGatewayAttachment'
Properties:
VpcId: !Ref Vpc
InternetGatewayId: !Ref InternetGateway
ElasticIP:
Type: 'AWS::EC2::EIP'
Properties:
Domain: vpc
NatGateway:
Type: 'AWS::EC2::NatGateway'
DependsOn:
- VpcGatewayAttachment
Properties:
AllocationId: !GetAtt
- ElasticIP
- AllocationId
SubnetId: !Ref SubnetAPublic
SubnetAPublic:
Type: 'AWS::EC2::Subnet'
Properties:
AvailabilityZone: !Select
- '0'
- !GetAZs ''
CidrBlock: 10.0.0.0/19
MapPublicIpOnLaunch: true
VpcId: !Ref Vpc
SubnetBPublic:
Type: 'AWS::EC2::Subnet'
Properties:
AvailabilityZone: !Select
- '1'
- !GetAZs ''
CidrBlock: 10.0.32.0/19
MapPublicIpOnLaunch: true
VpcId: !Ref Vpc
SubnetAPrivate:
Type: 'AWS::EC2::Subnet'
Properties:
AvailabilityZone: !Select
- '0'
- !GetAZs ''
CidrBlock: 10.0.64.0/19
VpcId: !Ref Vpc
SubnetBPrivate:
Type: 'AWS::EC2::Subnet'
Properties:
AvailabilityZone: !Select
- '1'
- !GetAZs ''
CidrBlock: 10.0.96.0/19
VpcId: !Ref Vpc
RouteTableAPublic:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref Vpc
RouteTableBPublic:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref Vpc
RouteTableAPrivate:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref Vpc
RouteTableBPrivate:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref Vpc
RouteTableAssociationAPublic:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref SubnetAPublic
RouteTableId: !Ref RouteTableAPublic
RouteTableAssociationBPublic:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref SubnetBPublic
RouteTableId: !Ref RouteTableBPublic
RouteTableAssociationAPrivate:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref SubnetAPrivate
RouteTableId: !Ref RouteTableAPrivate
RouteTableAssociationBPrivate:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref SubnetBPrivate
RouteTableId: !Ref RouteTableBPrivate
RouteTableAPrivateInternetRoute:
Type: 'AWS::EC2::Route'
DependsOn:
- VpcGatewayAttachment
Properties:
RouteTableId: !Ref RouteTableAPrivate
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway
RouteTableBPrivateInternetRoute:
Type: 'AWS::EC2::Route'
DependsOn:
- VpcGatewayAttachment
Properties:
RouteTableId: !Ref RouteTableBPrivate
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway
RouteTableAPublicInternetRoute:
Type: 'AWS::EC2::Route'
Properties:
RouteTableId: !Ref RouteTableAPublic
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
RouteTableBPublicInternetRoute:
Type: 'AWS::EC2::Route'
Properties:
RouteTableId: !Ref RouteTableBPublic
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
NetworkAclPublic:
Type: 'AWS::EC2::NetworkAcl'
Properties:
VpcId: !Ref Vpc
NetworkAclPrivate:
Type: 'AWS::EC2::NetworkAcl'
Properties:
VpcId: !Ref Vpc
SubnetNetworkAclAssociationAPublic:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref SubnetAPublic
NetworkAclId: !Ref NetworkAclPublic
SubnetNetworkAclAssociationBPublic:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref SubnetBPublic
NetworkAclId: !Ref NetworkAclPublic
SubnetNetworkAclAssociationAPrivate:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref SubnetAPrivate
NetworkAclId: !Ref NetworkAclPrivate
SubnetNetworkAclAssociationBPrivate:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref SubnetBPrivate
NetworkAclId: !Ref NetworkAclPrivate
NetworkAclEntryInPublicAllowAll:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAclPublic
RuleNumber: 99
Protocol: -1
RuleAction: allow
Egress: false
CidrBlock: 0.0.0.0/0
NetworkAclEntryOutPublicAllowAll:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAclPublic
RuleNumber: 99
Protocol: -1
RuleAction: allow
Egress: true
CidrBlock: 0.0.0.0/0
NetworkAclEntryInPrivateAllowVpc:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAclPrivate
RuleNumber: 99
Protocol: -1
RuleAction: allow
Egress: false
CidrBlock: 0.0.0.0/0
NetworkAclEntryOutPrivateAllowVpc:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAclPrivate
RuleNumber: 99
Protocol: -1
RuleAction: allow
Egress: true
CidrBlock: 0.0.0.0/0
LambdaSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: Lambdas security group
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
IpProtocol: '-1'
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: '-1'
VpcId: !Ref Vpc
Outputs:
VpcId:
Description: VPC ID
Value: !Ref Vpc
Export:
Name: !Sub "Portal-VpcId"
SubnetAPrivate:
Description: Subnet A Private
Value: !Ref SubnetAPrivate
Export:
Name: !Sub "SubnetAPrivate"
SubnetBPrivate:
Description: Subnet B Private
Value: !Ref SubnetBPrivate
Export:
Name: !Sub "SubnetBPrivate"
SubnetAPublic:
Description: Subnet A Public
Value: !Ref SubnetAPublic
Export:
Name: !Sub "SubnetAPublic"
SubnetBPublic:
Description: Subnet B Public
Value: !Ref SubnetBPublic
Export:
Name: !Sub "SubnetBPublic"
LambdaSecurityGroup:
Description: Access to Lambda functions
Value: !Ref LambdaSecurityGroup
Export:
Name: !Sub "LambdaSecurityGroup"
rds.yml
DBSubnetGroup:
Type: 'AWS::RDS::DBSubnetGroup'
Properties:
DBSubnetGroupDescription: Subnets available for the RDS DB Instance
SubnetIds:
- !Ref SubnetAPublic
- !Ref SubnetBPublic
VPCSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: Security group for RDS DB Instance.
VpcId: !Ref VpcId
SecurityGroupIngress:
-
IpProtocol: "tcp"
FromPort: "3306"
ToPort: "3306"
CidrIp: "[my IP]"
-
IpProtocol: "tcp"
FromPort: "3306"
ToPort: "3306"
CidrIp: "10.0.64.0/19"
-
IpProtocol: "tcp"
FromPort: "3306"
ToPort: "3306"
CidrIp: "10.0.96.0/19"
DBInstance:
Type: 'AWS::RDS::DBInstance'
Properties:
DBName: !Join
- ''
- - portal
- !Ref Environment
AllocatedStorage: !Ref DBAllocatedStorage
DBInstanceClass: !Ref DBClass
Engine: MariaDB
EngineVersion: '10.1.23'
MasterUsername: !Ref DBUsername
MasterUserPassword: !Ref DBPassword
DBSubnetGroupName: !Ref DBSubnetGroup
StorageEncrypted: true
PubliclyAccessible: true
VPCSecurityGroups:
- !Ref VPCSecurityGroup
DatabaseDnsRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneName: !Join
- ''
- - !Ref HostedZoneName
- .
Name: !Join
- ''
- - portal
- !Ref Environment
- 'db'
- .
- !Ref HostedZoneName
- .
Type: CNAME
TTL: '60'
ResourceRecords:
- !GetAtt
- DBInstance
- Endpoint.Address
DependsOn: DBInstance
Your problem is this
The only thing that seems to work is if I switch all of the Route
Tables to use an IGW as opposed to a NAT
Your instances are located in private subnets which are not accessible from the public Internet (your home PC). You have three (or more) solutions:
1) Move your instances to a public subnet. NOT RECOMMENDED.
2) Convert your private subnet into a public subnet (switch from NAT to IGW). NOT RECOMMENDED.
3) Create a VPN from your home network to a new EC2 instance located in your public subnet that routes your traffic to the instances in the private subnet. RECOMMENDED.
OpenVPN is a very cool solution. You can build this yourself or just launch an OpenVPN instance from Amazon Marketplace for free (I think the free is limited to 2 users). OpenVPN Access Server
There will be EC2 instance charges while the OpenVPN access server is running. What I do is shutdown that instance when I don't need it and start it back up when I do using the AWS CLI commands stored in batch files.