EC2 `UserData` execution hangs on `Checking init scripts...` - amazon-ec2

I have a YAML Cloudformation script which launches a single EC2 instance and runs some UserData upon startup.
I am using ami-0727f3c2d4b0226d5, a standard Ubuntu 18:04 LTS server.
Everything works fine provided the UserData is simple, eg -
UserData:
Fn::Base64:
!Sub |
#!/bin/bash -ex
echo "Hello World EC2!"
which gives me the following in the EC2 system log -
[[0;32m OK [0m] Started Apply the settings specified in cloud-config.
Starting Execute cloud user/final scripts...
[ 21.827930] cloud-init[1307]: + echo 'Hello World EC2!'
[ 21.832906] cloud-init[1307]: Hello World EC2!
but if I extend the UserData for some fairly normal- looking Ubuntu commands -
UserData:
Fn::Base64:
!Sub |
#!/bin/bash -ex
apt-get update
apt-get install -y ruby
echo "Hello World EC2!"
then (having torn down the original machine and restarted a new instance from scratch) the UserData process seems to hang with the following messages in the system log -
[ 29.606055] cloud-init[1304]: + apt-get install -y ruby
[ 29.675005] cloud-init[1304]: Reading package lists...
[ 29.828430] cloud-init[1304]: Building dependency tree...
[ 29.836236] cloud-init[1304]: Reading state information...
[ ... ]
[ ... ]
[ ... ]
[ 34.233706] cloud-init[1304]: Checking for services that may need to be restarted...done.
[ 34.254767] cloud-init[1304]: Checking for services that may need to be restarted...done.
[ 34.262182] cloud-init[1304]: Checking init scripts...
ie Checking init scripts ... never returns. Any thoughts on how to debug this situation / find out what is going wrong ?
TIA
[full YAML CF included]
---
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
AppName:
Type: String
InstanceType:
Type: String
Default: t2.micro
ImageId:
Type: String
Default: ami-0727f3c2d4b0226d5 # 18.04 LTS eu-west-1
KeyName:
Type: String
Outputs:
MyDNSName:
Value:
Fn::GetAtt:
- AppEC2Instance
- PublicDnsName
Description: "EC2 public DNS name"
MyIPAddress:
Value:
Fn::GetAtt:
- AppEC2Instance
- PublicIp
Description: "EC2 public IP address"
MyInstanceId:
Value:
Ref: AppEC2Instance
Description: "EC2 instance id"
Resources:
AppEC2Instance:
Properties:
IamInstanceProfile:
Ref: AppInstanceProfile
ImageId:
Ref: ImageId
InstanceType:
Ref: InstanceType
KeyName:
Ref: KeyName
SecurityGroupIds:
- Fn::GetAtt:
- AppSecurityGroup
- GroupId
SubnetId:
Ref: AppSubnet
Tags:
- Key: Name
Value:
Ref: AppName
UserData:
Fn::Base64:
!Sub |
#!/bin/bash -ex
apt-get update
apt-get install -y ruby
echo "Hello World EC2!"
Type: AWS::EC2::Instance
AppInstanceProfile:
Properties:
Path: /
Roles:
- Ref: AppInstanceRole
Type: AWS::IAM::InstanceProfile
AppInstanceRole:
Properties:
AssumeRolePolicyDocument:
Statement:
- Action:
- sts:AssumeRole
Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Version: '2012-10-17'
Path: /
Policies:
- PolicyDocument:
Statement:
- Action:
- ec2:DescribeTags # allow codedeploy to find machine
Effect: Allow
Resource: '*'
- Action: s3:* # allow machine to access deployables
Effect: Allow
Resource: '*'
- Action: logs:*
Effect: Allow
Resource: '*'
Version: '2012-10-17'
PolicyName: # required
Fn::Join:
- '-'
- - Ref: AppName
- ec2
Type: AWS::IAM::Role
AppSecurityGroup:
Properties:
GroupDescription:
Ref: AppName
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
FromPort: '3000'
IpProtocol: tcp
ToPort: '3000'
VpcId:
Ref: AppVPC
Type: AWS::EC2::SecurityGroup
AppInternetGateway:
Type: AWS::EC2::InternetGateway
AppRoute:
DependsOn: AppInternetGateway
Properties:
DestinationCidrBlock: 0.0.0.0/0
GatewayId:
Ref: AppInternetGateway
RouteTableId:
Ref: AppRouteTable
Type: AWS::EC2::Route
AppRouteTable:
Properties:
VpcId:
Ref: AppVPC
Type: AWS::EC2::RouteTable
AppSubnet:
Properties:
CidrBlock: 172.31.0.0/20
MapPublicIpOnLaunch: true
VpcId:
Ref: AppVPC
Type: AWS::EC2::Subnet
AppSubnetRouteTableAssociation:
Properties:
RouteTableId:
Ref: AppRouteTable
SubnetId:
Ref: AppSubnet
Type: AWS::EC2::SubnetRouteTableAssociation
AppVPC:
Properties:
CidrBlock: 172.31.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
InstanceTenancy: default
Type: AWS::EC2::VPC
AppVPCGatewayAttachment:
Properties:
InternetGatewayId:
Ref: AppInternetGateway
VpcId:
Ref: AppVPC
Type: AWS::EC2::VPCGatewayAttachment
AppCodeDeployApp:
Properties:
ApplicationName:
Ref: AppName
Type: AWS::CodeDeploy::Application
AppCodeDeployGroup:
Properties:
ApplicationName:
Ref: AppCodeDeployApp
DeploymentConfigName: CodeDeployDefault.AllAtOnce
DeploymentGroupName:
Ref: AppName
Ec2TagFilters: # lookup ec2 machine for deployment
- Key: Name
Type: KEY_AND_VALUE
Value:
Ref: AppName
ServiceRoleArn:
Fn::GetAtt:
- AppCodeDeployRole
- Arn
Type: AWS::CodeDeploy::DeploymentGroup
AppCodeDeployRole:
Properties:
AssumeRolePolicyDocument:
Statement:
- Action:
- sts:AssumeRole
Effect: Allow
Principal:
Service:
- codedeploy.amazonaws.com
Version: '2012-10-17'
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole
Path: /
Type: AWS::IAM::Role

Related

Not able to join EKS Nodegroup into the existing EKScluster in AWS CloudFormation

In this template we are creating node groups that are to be deployed in the existing EKS cluster and VPC. The stack gets deployed successfully but I don't see the node groups inside my existing EKS cluster.
AWSTemplateFormatVersion: "2010-09-09"
Description: Amazon EKS - Node Group
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: EKS Cluster
Parameters:
- ClusterName
- ClusterControlPlaneSecurityGroup
- Label:
default: Worker Node Configuration
Parameters:
- NodeGroupName
- NodeAutoScalingGroupMinSize
- NodeAutoScalingGroupDesiredCapacity
- NodeAutoScalingGroupMaxSize
- NodeInstanceType
- NodeImageIdSSMParam
- NodeImageId
- NodeVolumeSize
- KeyName
- BootstrapArguments
- Label:
default: Worker Network Configuration
Parameters:
- VpcId
- Subnets
Parameters:
BootstrapArguments:
Type: String
Default: ""
Description: "Arguments to pass to the bootstrap script. See files/bootstrap.sh in https://github.com/awslabs/amazon-eks-ami"
ClusterControlPlaneSecurityGroup:
Type: "AWS::EC2::SecurityGroup::Id"
Description: The security group of the cluster control plane.
ClusterName:
Type: String
Description: The cluster name provided when the cluster was created. If it is incorrect, nodes will not be able to join the cluster.
KeyName:
Type: "AWS::EC2::KeyPair::KeyName"
Description: The EC2 Key Pair to allow SSH access to the instances
NodeAutoScalingGroupDesiredCapacity:
Type: Number
Default: 3
Description: Desired capacity of Node Group ASG.
NodeAutoScalingGroupMaxSize:
Type: Number
Default: 4
Description: Maximum size of Node Group ASG. Set to at least 1 greater than NodeAutoScalingGroupDesiredCapacity.
NodeAutoScalingGroupMinSize:
Type: Number
Default: 1
Description: Minimum size of Node Group ASG.
NodeGroupName:
Type: String
Description: Unique identifier for the Node Group.
NodeImageId:
Type: String
Default: ""
Description: (Optional) Specify your own custom image ID. This value overrides any AWS Systems Manager Parameter Store value specified above.
NodeImageIdSSMParam:
Type: "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
Default: /aws/service/eks/optimized-ami/1.14/amazon-linux-2/recommended/image_id
Description: AWS Systems Manager Parameter Store parameter of the AMI ID for the worker node instances.
NodeInstanceType:
Type: String
Default: t3.medium
AllowedValues:
- a1.medium
- a1.large
- a1.xlarge
- a1.2xlarge
- a1.4xlarge
- c1.medium
- c1.xlarge
- c3.large
- c3.xlarge
- c3.2xlarge
- c3.4xlarge
- c3.8xlarge
- c4.large
- c4.xlarge
- c4.2xlarge
- c4.4xlarge
- c4.8xlarge
- c5.large
- c5.xlarge
- c5.2xlarge
- c5.4xlarge
- c5.9xlarge
- c5.12xlarge
- c5.18xlarge
- c5.24xlarge
- c5.metal
- c5d.large
- c5d.xlarge
- c5d.2xlarge
- c5d.4xlarge
- c5d.9xlarge
- c5d.18xlarge
- c5n.large
- c5n.xlarge
- c5n.2xlarge
- c5n.4xlarge
- c5n.9xlarge
- c5n.18xlarge
- cc2.8xlarge
- cr1.8xlarge
- d2.xlarge
- d2.2xlarge
- d2.4xlarge
- d2.8xlarge
- f1.2xlarge
- f1.4xlarge
- f1.16xlarge
- g2.2xlarge
- g2.8xlarge
- g3s.xlarge
- g3.4xlarge
- g3.8xlarge
- g3.16xlarge
- h1.2xlarge
- h1.4xlarge
- h1.8xlarge
- h1.16xlarge
- hs1.8xlarge
- i2.xlarge
- i2.2xlarge
- i2.4xlarge
- i2.8xlarge
- i3.large
- i3.xlarge
- i3.2xlarge
- i3.4xlarge
- i3.8xlarge
- i3.16xlarge
- i3.metal
- i3en.large
- i3en.xlarge
- i3en.2xlarge
- i3en.3xlarge
- i3en.6xlarge
- i3en.12xlarge
- i3en.24xlarge
- m1.small
- m1.medium
- m1.large
- m1.xlarge
- m2.xlarge
- m2.2xlarge
- m2.4xlarge
- m3.medium
- m3.large
- m3.xlarge
- m3.2xlarge
- m4.large
- m4.xlarge
- m4.2xlarge
- m4.4xlarge
- m4.10xlarge
- m4.16xlarge
- m5.large
- m5.xlarge
- m5.2xlarge
- m5.4xlarge
- m5.8xlarge
- m5.12xlarge
- m5.16xlarge
- m5.24xlarge
- m5.metal
- m5a.large
- m5a.xlarge
- m5a.2xlarge
- m5a.4xlarge
- m5a.8xlarge
- m5a.12xlarge
- m5a.16xlarge
- m5a.24xlarge
- m5ad.large
- m5ad.xlarge
- m5ad.2xlarge
- m5ad.4xlarge
- m5ad.12xlarge
- m5ad.24xlarge
- m5d.large
- m5d.xlarge
- m5d.2xlarge
- m5d.4xlarge
- m5d.8xlarge
- m5d.12xlarge
- m5d.16xlarge
- m5d.24xlarge
- m5d.metal
- p2.xlarge
- p2.8xlarge
- p2.16xlarge
- p3.2xlarge
- p3.8xlarge
- p3.16xlarge
- p3dn.24xlarge
- g4dn.xlarge
- g4dn.2xlarge
- g4dn.4xlarge
- g4dn.8xlarge
- g4dn.12xlarge
- g4dn.16xlarge
- g4dn.metal
- r3.large
- r3.xlarge
- r3.2xlarge
- r3.4xlarge
- r3.8xlarge
- r4.large
- r4.xlarge
- r4.2xlarge
- r4.4xlarge
- r4.8xlarge
- r4.16xlarge
- r5.large
- r5.xlarge
- r5.2xlarge
- r5.4xlarge
- r5.8xlarge
- r5.12xlarge
- r5.16xlarge
- r5.24xlarge
- r5.metal
- r5a.large
- r5a.xlarge
- r5a.2xlarge
- r5a.4xlarge
- r5a.8xlarge
- r5a.12xlarge
- r5a.16xlarge
- r5a.24xlarge
- r5ad.large
- r5ad.xlarge
- r5ad.2xlarge
- r5ad.4xlarge
- r5ad.12xlarge
- r5ad.24xlarge
- r5d.large
- r5d.xlarge
- r5d.2xlarge
- r5d.4xlarge
- r5d.8xlarge
- r5d.12xlarge
- r5d.16xlarge
- r5d.24xlarge
- r5d.metal
- t1.micro
- t2.nano
- t2.micro
- t2.small
- t2.medium
- t2.large
- t2.xlarge
- t2.2xlarge
- t3.nano
- t3.micro
- t3.small
- t3.medium
- t3.large
- t3.xlarge
- t3.2xlarge
- t3a.nano
- t3a.micro
- t3a.small
- t3a.medium
- t3a.large
- t3a.xlarge
- t3a.2xlarge
- u-6tb1.metal
- u-9tb1.metal
- u-12tb1.metal
- x1.16xlarge
- x1.32xlarge
- x1e.xlarge
- x1e.2xlarge
- x1e.4xlarge
- x1e.8xlarge
- x1e.16xlarge
- x1e.32xlarge
- z1d.large
- z1d.xlarge
- z1d.2xlarge
- z1d.3xlarge
- z1d.6xlarge
- z1d.12xlarge
- z1d.metal
ConstraintDescription: Must be a valid EC2 instance type
Description: EC2 instance type for the node instances
NodeVolumeSize:
Type: Number
Default: 20
Description: Node volume size
Subnets:
Type: "List<AWS::EC2::Subnet::Id>"
Description: The subnets where workers can be created.
VpcId:
Type: "AWS::EC2::VPC::Id"
Description: The VPC of the worker instances
Conditions:
HasNodeImageId: !Not
- "Fn::Equals":
- Ref: NodeImageId
- ""
Resources:
NodeInstanceRole:
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/AmazonEKSWorkerNodePolicy"
- "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
- "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
Path: /
NodeInstanceProfile:
Type: "AWS::IAM::InstanceProfile"
Properties:
Path: /
Roles:
- Ref: NodeInstanceRole
NodeSecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: Security group for all nodes in the cluster
Tags:
- Key: !Sub kubernetes.io/cluster/${ClusterName}
Value: owned
VpcId: !Ref VpcId
NodeSecurityGroupIngress:
Type: "AWS::EC2::SecurityGroupIngress"
DependsOn: NodeSecurityGroup
Properties:
Description: Allow node to communicate with each other
FromPort: 0
GroupId: !Ref NodeSecurityGroup
IpProtocol: "-1"
SourceSecurityGroupId: !Ref NodeSecurityGroup
ToPort: 65535
ClusterControlPlaneSecurityGroupIngress:
Type: "AWS::EC2::SecurityGroupIngress"
DependsOn: NodeSecurityGroup
Properties:
Description: Allow pods to communicate with the cluster API Server
FromPort: 443
GroupId: !Ref ClusterControlPlaneSecurityGroup
IpProtocol: tcp
SourceSecurityGroupId: !Ref NodeSecurityGroup
ToPort: 443
ControlPlaneEgressToNodeSecurityGroup:
Type: "AWS::EC2::SecurityGroupEgress"
DependsOn: NodeSecurityGroup
Properties:
Description: Allow the cluster control plane to communicate with worker Kubelet and pods
DestinationSecurityGroupId: !Ref NodeSecurityGroup
FromPort: 1025
GroupId: !Ref ClusterControlPlaneSecurityGroup
IpProtocol: tcp
ToPort: 65535
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
DestinationSecurityGroupId: !Ref NodeSecurityGroup
FromPort: 443
GroupId: !Ref ClusterControlPlaneSecurityGroup
IpProtocol: tcp
ToPort: 443
NodeSecurityGroupFromControlPlaneIngress:
Type: "AWS::EC2::SecurityGroupIngress"
DependsOn: NodeSecurityGroup
Properties:
Description: Allow worker Kubelets and pods to receive communication from the cluster control plane
FromPort: 1025
GroupId: !Ref NodeSecurityGroup
IpProtocol: tcp
SourceSecurityGroupId: !Ref ClusterControlPlaneSecurityGroup
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
FromPort: 443
GroupId: !Ref NodeSecurityGroup
IpProtocol: tcp
SourceSecurityGroupId: !Ref ClusterControlPlaneSecurityGroup
ToPort: 443
Problem seems to be over here
NodeLaunchConfig:
Type: "AWS::AutoScaling::LaunchConfiguration"
Properties:
AssociatePublicIpAddress: "true"
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
DeleteOnTermination: true
VolumeSize: !Ref NodeVolumeSize
VolumeType: gp2
IamInstanceProfile: !Ref NodeInstanceProfile
ImageId: !If
- HasNodeImageId
- Ref: NodeImageId
- Ref: NodeImageIdSSMParam
InstanceType: !Ref NodeInstanceType
KeyName: !Ref KeyName
SecurityGroups:
- Ref: NodeSecurityGroup
UserData: !Base64
"Fn::Sub": |
#!/bin/bash
set -o xtrace
/etc/eks/bootstrap.sh ${ClusterName} ${BootstrapArguments}
/opt/aws/bin/cfn-signal --exit-code $? \
--stack ${AWS::StackName} \
--resource NodeGroup \
--region ${AWS::Region}
May be over here
NodeGroup:
Type: "AWS::AutoScaling::AutoScalingGroup"
Properties:
DesiredCapacity: !Ref NodeAutoScalingGroupDesiredCapacity
LaunchConfigurationName: !Ref NodeLaunchConfig
MaxSize: !Ref NodeAutoScalingGroupMaxSize
MinSize: !Ref NodeAutoScalingGroupMinSize
Tags:
- Key: Name
PropagateAtLaunch: "true"
Value: !Sub ${ClusterName}-${NodeGroupName}-Node
- Key: !Sub kubernetes.io/cluster/${ClusterName}
PropagateAtLaunch: "true"
Value: owned
VPCZoneIdentifier: !Ref Subnets
UpdatePolicy:
AutoScalingRollingUpdate:
MaxBatchSize: "1"
MinInstancesInService: !Ref NodeAutoScalingGroupDesiredCapacity
PauseTime: PT5M
Outputs:
NodeInstanceRole:
Description: The node instance role
Value: !GetAtt NodeInstanceRole.Arn
NodeSecurityGroup:
Description: The security group for the node group
Value: !Ref NodeSecurityGroup
Well, though the template is getting deployed but the nodegroups aren't visible in my EKS Cluster. Please do let me know if there are any updations to be made so that the nodegroups get deployed in the cluster.
Okay, I was going through the same problem. The problem is with the type which you chosen for the nodegroup. It should be of AWS::EKS::Nodegroup. You have chosen the wrong type. Change it and your nodegroup will be visible in the cluster.
Here is the link for the same:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-nodegroup.html

!GetAtt InternalLB.DNSName

I am trying to fetch the dns of internal classic load balancer and pass it in the launch configuration of ec2 instance as a user data. Creating a db in ec2 instance and in the config file trying to get the dns of the internal classic load balancer but I am unable to get it. !GetAtt InternalLB.DNSName I have used this in the user data but the db is not connected but when I manually pass the dns it works.I need to fetch the dns on its on using this userdata script.
ec2instance:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
# AvailabilityZone: us-east-2a
UserData:
Fn::Base64: !Sub |
#!/bin/bash
cd /var/www
mkdir inc
cd inc
sudo echo "<?php
define('DB_SERVER', '!GetAtt InternalLB.DNSName');
define('DB_USERNAME', 'db');
define('DB_PASSWORD', 'db');
define('DB_DATABASE', 'db');
?>" > dbinfo.inc
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
DeleteOnTermination: "true"
VolumeSize: "8"
VolumeType: gp2
ImageId: ami-0bdcc6c05dec346bf
InstanceType: t2.micro
KeyName: wahaj(webserver)
SecurityGroups:
- Ref: wahajwebserver
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"
internalelbsg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: internal-elb
VpcId:
Fn::ImportValue:
Fn::Sub: "${SourceStackName}-VpcID"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !GetAtt wahajwebserver.GroupId
Description: For traffic from Internet
GroupDescription: Security Group for demo server
InternalLB:
Type: AWS::ElasticLoadBalancing::LoadBalancer
Properties:
Scheme: internal
Listeners:
- LoadBalancerPort: "80"
InstancePort: "80"
Protocol: HTTP
- LoadBalancerPort: "3306"
InstancePort: "3306"
Protocol: TCP
SecurityGroups:
- !Ref internalelbsg
LoadBalancerName: internalelbsg
Subnets:
- Fn::ImportValue: !Sub "${SourceStackName}-SubnetC"
- Fn::ImportValue: !Sub "${SourceStackName}-SubnetD"
HealthCheck:
Target: HTTP:80/index.html
HealthyThreshold: "3"
UnhealthyThreshold: "5"
Interval: "30"
Timeout: "5"
The main issue is in define('DB_SERVER', '!GetAtt InternalLB.DNSName'); this line I am not fetching the dns in the right way. Please help
To use GetAtt inside of Sub, you have to use the VarName: VarValue syntax as described in the Fn::Sub documentation page. Additionally, you have to wrap VarName with ${}, i.e. ${VarName}.
I believe this syntax should work:
UserData:
Fn::Base64: !Sub
- |
#!/bin/bash
cd /var/www
mkdir inc
cd inc
sudo echo "<?php
define('DB_SERVER', '${InternalLBDNSName}');
define('DB_USERNAME', 'db');
define('DB_PASSWORD', 'db');
define('DB_DATABASE', 'db');
?>" > dbinfo.inc
- InternalLBDNSName: !GetAtt InternalLB.DNSName

EC2 cloudformation template using conditions to add ebs volume

I am trying to add EBS Volume to my EC2 resource based on a condition of EBS volume required or not. How can I make the condition work?
Here is the snippet of code:
Conditions:
EbsVolumeTrue: !Equals [!Ref EBS, true]
Resources:
Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-xxxxxx
!If [EbsVolumeTrue, !Ref BlockDeviceMappings, !Ref "AWS::NoValue"]
BlockDeviceMappings:
- DeviceName: !Ref VolumeName
Ebs:
VolumeType: !Ref VolumeType
DeleteOnTermination: false
VolumeSize: !Ref VolumeSize
This is the way to go with multiple lines in Conditions:
Conditions:
EbsVolumeTrue: !Equals [!Ref EBS, true]
Resources:
Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-xxxxxx
Fn::If:
- EbsVolumeTrue
-
BlockDeviceMappings:
- DeviceName: !Ref VolumeName
Ebs:
VolumeType: !Ref VolumeType
DeleteOnTermination: false
VolumeSize: !Ref VolumeSize
- Ref: AWS::NoValue

validated cloudformation yaml template

I have a Cloudformation template which when I validate it it appears it appears to be valid I get no errors using the linter tool in Atom and I have also use an online yaml validate tool which confirms it is correct but when I go to deploy the template in CFN it fails with error
Template validation error: Template format error: Unresolved resource dependencies [AgentserviceSNSTopic] in the Resources block of the template
I can't see any errors (am not sure how the formatting will be but the template is below )
AWSTemplateFormatVersion: '2010-09-09'
Description: AgentService Web infra
Outputs:
AgentServiceFQDN:
Value:
'Fn::GetAtt':
- AgentServiceELB
- DNSName
Parameters:
AZ:
Default: 'ap-southeast-2a, ap-southeast-2b'
Description: >-
Comma delimited list of AvailabilityZones where the instances will be
created
Type: CommaDelimitedList
InstanceProfile:
Default: >-
arn:aws:iam::112888586165:instance-profile/AdvanceCodeDeployInstanceProfile
Description: >-
Use the full ARN for SimpleCodeDeployInstanceProfile or
AdvancedCodeDeployInstanceProfile
Type: String
InstanceType:
ConstraintDescription: 'Must be a valid EC2 instance type, such as t2.medium'
Default: t2.medium
Description: Provide InstanceType to be used
Type: String
KeyName:
ConstraintDescription: The name of an existing EC2 KeyPair.
Default: LMBRtraining
Description: Name of an existing EC2 KeyPair to enable SSH access to the instances
Type: 'AWS::EC2::KeyPair::KeyName'
PublicSubnets:
Default: 'subnet-bb0a3ade,subnet-fedd8389'
Description: Comma delimited list of public subnets
Type: CommaDelimitedList
VPCID:
Default: vpc-a18eccc4
Description: VPC ID
Type: String
WindowsAMIID:
Default: ami-5a989d39
Description: Windows AMI ID with IIS
Type: String
myIP:
Default: 0.0.0.0/0
Description: 'Enter your IP address in CIDR notation, e.g. 100.150.200.225/32'
Type: String
Resources:
AgentServiceASG:
Properties:
AvailabilityZones:
Ref: AZ
DesiredCapacity: '2'
HealthCheckGracePeriod: '600'
HealthCheckType: ELB
LaunchConfigurationName:
Ref: AgentServiceLaunchConfig
LoadBalancerNames:
- Ref: AgentServiceELB
MaxSize: '2'
MinSize: '2'
NotificationConfiguration:
NotificationTypes:
- 'autoscaling:EC2_INSTANCE_LAUNCH'
- 'autoscaling:EC2_INSTANCE_LAUNCH_ERROR'
- 'autoscaling:EC2_INSTANCE_TERMINATE'
- 'autoscaling:EC2_INSTANCE_TERMINATE_ERROR'
TopicARN:
Ref: AgentServiceSNSTopic
Tags:
- Key: Name
PropagateAtLaunch: 'true'
Value: AgentServiceServer
VPCZoneIdentifier:
Ref: PublicSubnets
Type: 'AWS::AutoScaling::AutoScalingGroup'
AgentServiceAutoscaleDownPolicy:
Properties:
AdjustmentType: ChangeInCapacity
AutoScalingGroupName:
Ref: AgentServiceASG
Cooldown: '300'
ScalingAdjustment: '-1'
Type: 'AWS::AutoScaling::ScalingPolicy'
AgentServiceAutoscaleUpPolicy:
Properties:
AdjustmentType: ChangeInCapacity
AutoScalingGroupName:
Ref: AgentServiceASG
Cooldown: '300'
ScalingAdjustment: '1'
Type: 'AWS::AutoScaling::ScalingPolicy'
AgentServiceCloudWatchCPUAlarmHigh:
Properties:
AlarmActions:
- Ref: AgentServiceAutoscaleUpPolicy
- Ref: AgentServiceSNSTopic
AlarmDescription: SNS Notification and scale up if CPU Util is Higher than 90% for 10 mins
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: AutoScalingGroupName
Value:
Ref: AgentServiceASG
EvaluationPeriods: '2'
MetricName: CPUUtilization
Namespace: AWS/EC2
Period: '300'
Statistic: Average
Threshold: '90'
Type: 'AWS::CloudWatch::Alarm'
AgentServiceCloudWatchCPUAlarmLow:
Properties:
AlarmActions:
- Ref: AgentServiceAutoscaleDownPolicy
- Ref: AgentserviceSNSTopic
AlarmDescription: SNS Notification and scale down if CPU Util is less than 70% for 10 mins
ComparisonOperator: LessThanThreshold
Dimensions:
- Name: AutoScalingGroupName
Value:
Ref: AgentServiceASG
EvaluationPeriods: '2'
MetricName: CPUUtilization
Namespace: AWS/EC2
Period: '300'
Statistic: Average
Threshold: '70'
Type: 'AWS::CloudWatch::Alarm'
AgentServiceELB:
Properties:
ConnectionDrainingPolicy:
Enabled: 'true'
Timeout: '60'
CrossZone: true
HealthCheck:
HealthyThreshold: '3'
Interval: '15'
Target: 'HTTP:80/index.html'
Timeout: '5'
UnhealthyThreshold: '3'
Listeners:
- InstancePort: '80'
InstanceProtocol: HTTP
LoadBalancerPort: '80'
Protocol: HTTP
LoadBalancerName: AgentServiceELB
Scheme: internet-facing
SecurityGroups:
- Ref: AgentServiceSecurityGroup
Subnets:
Ref: PublicSubnets
Tags:
- Key: Network
Value: public
Type: 'AWS::ElasticLoadBalancing::LoadBalancer'
AgentServiceLaunchConfig:
Properties:
AssociatePublicIpAddress: 'true'
IamInstanceProfile:
Ref: InstanceProfile
ImageId:
Ref: WindowsAMIID
InstanceType:
Ref: InstanceType
KeyName:
Ref: KeyName
SecurityGroups:
- Ref: AgentServiceSecurityGroup
UserData:
'Fn::Base64':
'Fn::Join':
- ''
- - |
<script>
- |
echo hello world > c:\\inetpub\\wwwroot\\index.html
- |
hostname >> c:\\inetpub\\wwwroot\\index.html
- "if not exist \\"c:\\temp\\" mkdir c:\\temp\\n"
- >
powershell.exe -Command Read-S3Object -BucketName
aws-codedeploy-us-east-1/latest -Key codedeploy-agent.msi -File
c:\\temp\\codedeploy-agent.msi
- >
c:\\temp\\codedeploy-agent.msi /quiet /l
c:\\temp\\host-agent-install-log.txt
- |
powershell.exe -Command Get-Service -Name codedeployagent
- |
</script>
Type: 'AWS::AutoScaling::LaunchConfiguration'
AgentServiceSNSTopic:
Type: 'AWS::SNS::Topic'
AgentServiceSecurityGroup:
Properties:
GroupDescription: AgentServiceSecurityGroup
InstanceAccessHTTPS:
Properties:
CidrIp: 0.0.0.0/0
FromPort: '443'
GroupId: AgentServiceSecurityGroup
IpProtocol: tcp
ToPort: '443'
Type: 'AWS::EC2::SecurityGroupIngress'
InstanceAccessPSremote:
Properties:
CidrIp: 198.18.0.0/24
FromPort: '5985'
GroupId: AgentServiceSecurityGroup
IpProtocol: tcp
ToPort: '5985'
Type: 'AWS::EC2::SecurityGroupIngress'
InstanceAccessRDP:
Properties:
CidrIp: 0.0.0.0/0
FromPort: '3389'
GroupId: AgentServiceSecurityGroup
IpProtocol: tcp
ToPort: '3389'
Type: 'AWS::EC2::SecurityGroupIngress'
InstanceAccessSMB:
Properties:
CidrIp: 198.18.0.0/24
FromPort: '445'
GroupId: AgentServiceSecurityGroup
IpProtocol: tcp
ToPort: '445'
Type: 'AWS::EC2::SecurityGroupIngress'
VpcId:
Ref: VPCID
Type: 'AWS::EC2::SecurityGroup'
It would be interesting to know which online validator accepted your "valid YAML".
The Online YAML Parser and YAML Lint both complain when you use your YAML as input. After changing the line these YAML parsers indicate as problematic:
- "if not exist \\"c:\\temp\\" mkdir c:\\temp\\n"
which is a quoted scalar "if not exist \\"c:\\temp\\" followed by more mkdir ... into:
- "if not exist \"c:\\temp\" mkdir c:\\temp\n"
in which the quotes are escaped, or to the better readable:
- |
if not exist "c:\temp" mkdir c:\temp
The Code Beautify YAML Validator complain that your YAML has problems, but as usual cannot deal with the corrected YAML either, so don't use that.

Fn::GetAZs + Fn::Select not co-operating

So I have this CloudFormation resource in my networking template:
Resources:
...
PubSubnetAz2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
CidrBlock: !FindInMap [VpcCidrs, !Ref "AWS::Region", pubsubnet2]
AvailabilityZone: !Select
- 1
- Fn::GetAZs: !Ref "AWS::Region"
I'm getting this error when I try to create this stack:
17:40:06 UTC-0700 CREATE_FAILED AWS::EC2::Subnet PubSubnetAz2 Template error: Fn::Select cannot select nonexistent value at index 1
The template validates, I have a PubSubnetAz1 block which is identical and passes, (it selects index=0 though).
Am I using Fn::GetAZs wrong?
PS. I am using us-west-2 region, as far as I can tell that has > 1 AZs.
The following template successfully deployed a VPC across multiple subnets in us-west-2:
---
AWSTemplateFormatVersion: '2010-09-09'
Resources:
vpc1:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
InstanceTenancy: default
EnableDnsSupport: true
EnableDnsHostnames: false
Tags:
- Key: Name
Value: My-VPC
subnet1:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone:
Fn::Select:
- 0
- Fn::GetAZs: ''
CidrBlock: 10.0.0.0/24
VpcId:
Ref: vpc1
Tags:
- Key: Name
Value: Subnet-A
subnet2:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone:
Fn::Select:
- 1
- Fn::GetAZs: ''
CidrBlock: 10.0.1.0/24
VpcId:
Ref: vpc1
Tags:
- Key: Name
Value: Subnet-B
I created the VPC manually, used Hava to convert it to a JSON CloudFormation template, manually inserted the Select statements, then converted to YAML using json2yaml.com.
I was getting a similar error while doing AWS Mysfits sample demo, for a second time. I found I needed to list the AZ I wished to use and the stack created successfully.
PrivateSubnetTwo:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2b
VpcId: !Ref 'VPC'
CidrBlock: !FindInMap ['SubnetConfig', 'PrivateTwo', 'CIDR']
The Fn::GetAZs documentation shows examples like:
mySubnet:
Type: "AWS::EC2::Subnet"
Properties:
VpcId:
!Ref VPC
CidrBlock: 10.0.0.0/24
AvailabilityZone:
Fn::Select:
- 0
- Fn::GetAZs: ""
It has an empty Region, which apparently is equivalent to specifying AWS::Region.
It also shows an example using the full format as:
"Fn::GetAZs": ""
"Fn::GetAZs": { Ref: "AWS::Region" }
"Fn::GetAZs": "us-east-1"
Try some of those formats to see whether they work.

Resources