I am trying to select two Security Groups, one is from parameters and other is a new one.
But getting below errors. How can I solve this?
AWSTemplateFormatVersion : 2010-09-09
Description: "simple web layer"
Parameters:
ImageId:
Description: 'web Layer'
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
AllowedPattern: "^[a-zA-Z][-a-zA-Z0-9]*$"
Default: ami-244333
Vpc:
Description: enter vpc
Type: List<AWS::EC2::VPC::Id>
Securitycab:
Type: String
Default: 0.0.0.0/0
Description: enter vpc ip range
Subnets:
Description: enter subnet
Type: List<AWS::EC2::Subnet::Id>
Default: subnet-384736383838
Securitygroup:
Description: enter sc
Type: List<AWS::EC2::SecurityGroup::Id>
Default: sg-237377383773873
Resources:
Lpsecurity:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: vpc-1a2b3c4d
GroupDescription: Sample target security group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: !Ref Securitycab
MyEC2Instance1:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: !Ref ImageId
InstanceType: t2.large
VpcId: !Ref Vpc
SubnetId: !Select [ 0, !Ref Subnets ]
SecurityGroupIds:
- !Ref Securitygroup
!Ref Lpsecurity
Error : Unsolved Resource dependence [Securitygroup !Ref Lpsecurity] in the resource block of the template.
A list should have dashes before every element.
Here is the suggested code from your other I have a problem in cloud formation. Error when using Fn::Join with a parameter question:
SecurityGroupIds:
- !GetAtt Securitygroup.GroupId
- !GetAtt Lpsecurity.GroupId
Alternatively, you could possibly use:
SecurityGroupIds:
- !Ref Securitygroup
- !Ref Lpsecurity
Related
i am pretty new to CloudFormation templates. I have already created a VPC with 2 public and 4 private subnets. Now, i want to create an EC2 instance in 2 of the private subnets, which is then load balanced using ELB created on a public subnet. Below is the CFT template for the same.
Parameters:
SecurityGroupDescription:
Description: Security Group Description
Type: String
KeyName:
Description: Key Pair for EC2
Type: 'AWS::EC2::KeyPair::KeyName'
VPC:
Description: Select VPC.
Type: AWS::EC2::VPC::Id
Subnet1:
Description: Private Subnet to Deploy Docker MFA.
Type: AWS::EC2::Subnet::Id
Subnet2:
Description: Private Subnet to Deploy Docker MFA.
Type: AWS::EC2::Subnet::Id
Mappings:
RegionMap:
us-west-2:
AMI: ami-0c54e4ec017b92f04
Resources:
EC2InstanceMule1:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId:
Fn::FindInMap:
- RegionMap
- Ref: AWS::Region
- AMI
SubnetId:
Ref: Subnet1
SecurityGroups:
- !GetAtt EC2SecurityGroup.GroupId
KeyName: !Ref KeyName
EC2InstanceMule2:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId:
Fn::FindInMap:
- RegionMap
- Ref: AWS::Region
- AMI
SubnetId:
Ref: Subnet2
SecurityGroups:
- !GetAtt EC2SecurityGroup.GroupId
KeyName: !Ref KeyName
# security group
ELBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: ELB Security Group
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Ref SecurityGroupDescription
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId:
Fn::GetAtt:
- ELBSecurityGroup
- GroupId
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
# Load Balancer for EC2
LoadBalancerforEC2:
Type: AWS::ElasticLoadBalancing::LoadBalancer
Properties:
Instances:
- !Ref EC2InstanceMule1
- !Ref EC2InstanceMule2
Listeners:
- LoadBalancerPort: '80'
InstancePort: '80'
Protocol: HTTP
HealthCheck:
Target: HTTP:80/
HealthyThreshold: '3'
UnhealthyThreshold: '5'
Interval: '30'
Timeout: '5'
SecurityGroups:
- !GetAtt ELBSecurityGroup.GroupId
I am getting the following error :
The parameter groupName cannot be used with the parameter subnet (Service: AmazonEC2; Status Code: 400; Error Code: InvalidParameterCombination
I have gone through the previous question of the same error and used the security group ID that is being created. Still the error persists. Also, any other modifications required would be appreciated.
You should be using SecurityGroupIds, rather then SecurityGroups.
I am trying to EC2 instance (new), Security group (new) and VPC(existing). Here is my cloudformation template.
When I run the template in Stack, I got error as *"Value () for parameter groupId is invalid. The value cannot be empty"*. How to solve this?
Template:
Parameters:
VPCID:
Description: Name of an existing VPC
Type: AWS::EC2::VPC::Id
KeyName:
Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription: must be the name of an existing EC2 KeyPair.
InstanceType:
Description: EC2 instance type
Type: String
Default: t2.medium
AllowedValues:
- t2.medium
- t2.large
AccessLocation:
Description: The IP address range that can be used to access to the EC2 instances
Type: String
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref 'InstanceType'
SecurityGroups:
- !Ref 'InstanceSecurityGroup'
KeyName: !Ref 'KeyName'
ImageId: !Ref 'ImageId'
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPCID
GroupDescription: Enable SSH
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: !Ref 'AccessLocation'
SecurityGroups can only be used for default VPC. Since you are explicitly assigning VPCID to InstanceSecurityGroup, this will be considered as non-default, resulting in failed deployment.
You must use SecurityGroupIds (not SecurityGroups) in your case as your VPC use will be considered as non-default:
SecurityGroupIds:
- !GetAtt 'InstanceSecurityGroup.GroupId'
The error in EC2Instance resource in SecurityGroups attribute. SecurityGroups needs an array of GroupId but when you use !Ref InstanceSecurityGroup this returns ResourceId. So you need to use GetAtt instead to get GroupId.
Parameters:
VPCID:
Description: Name of an existing VPC
Type: AWS::EC2::VPC::Id
KeyName:
Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription: must be the name of an existing EC2 KeyPair.
InstanceType:
Description: EC2 instance type
Type: String
Default: t2.medium
AllowedValues:
- t2.medium
- t2.large
AccessLocation:
Description: The IP address range that can be used to access to the EC2 instances
Type: String
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref 'InstanceType'
SecurityGroups:
- !GetAtt InstanceSecurityGroup.GroupId
KeyName: !Ref 'KeyName'
ImageId: !Ref 'ImageId'
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPCID
GroupDescription: Enable SSH
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: !Ref 'AccessLocation'
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html
I have created this nested stack. I want to implement the same stack with {prod, dev, qa} environment. Like I want to up the same stack but it doesn't have any name conflicts with each other. I want to deploy the same stack in three different environment, What changes do I have to make to achieve it
Root:
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
bucketname:
Type: String
Description: Path to the bucket
Default: webserver
bucketpath:
Type: String
Description: Path to the bucket
Default: /env #/mysql
Env:
Type: String
Description: Select the appropriate environment
AllowedValues:
- dev
- test
- uat
- prod
Cidr:
Type: String
Description: Cidr for vpc
Publicsubnet1:
Type: String
Description: public subnet 1
Publicsubnet2:
Type: String
Description: public subnet 2
Privatesubnet1:
Type: String
Description: Private subnet 1
Privatesubnet2:
Type: String
Description: Private subnet 2
Resources:
Vpcstack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Sub "https://${bucketname}.s3.us-east-2.amazonaws.com${bucketpath}/vpc.yml"
Parameters:
Env: Ref: Env
Cidr: !Ref Cidr
Publicsubnet1: !Ref Publicsubnet1
Publicsubnet2: !Ref Publicsubnet2
Privatesubnet1: !Ref Privatesubnet1
Privatesubnet2: !Ref Privatesubnet2
Vpc:
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
Cidr:
Type: String
Description: Cidr for vpc
Publicsubnet1:
Type: String
Description: public subnet 1
Publicsubnet2:
Type: String
Description: public subnet 2
Privatesubnet1:
Type: String
Description: Private subnet 1
Privatesubnet2:
Type: String
Description: Private subnet 2
Env:
Type: String
Description: Select the appropriate environment
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref Cidr
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: !Ref Publicsubnet1
MapPublicIpOnLaunch: true
SubnetB:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2b
VpcId: !Ref VPC
CidrBlock: !Ref Publicsubnet2
MapPublicIpOnLaunch: true
SubnetC:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2a
VpcId: !Ref VPC
CidrBlock: !Ref Privatesubnet1
MapPublicIpOnLaunch: false
SubnetD:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2b
VpcId: !Ref VPC
CidrBlock: !Ref Privatesubnet2
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: !Sub "nat-${Env}"
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: "VpcID"
SubnetA:
Description: public subnet
Value: !Ref SubnetA
Export:
Name: "SubnetA"
SubnetB:
Description: public subnet 2
Value: !Ref SubnetB
Export:
Name: "SubnetB"
SubnetC:
Description: priavte subnet
Value: !Ref SubnetC
Export:
Name: "SubnetC"
SubnetD:
Description: private subnet 2
Value: !Ref SubnetD
Export:
Name: "SubnetD"
You can specify different names for your top-level stacks by adding the environment to the top-level stack name. You do this at the time of stack creation, via the console or programmatically.
Then when each top-level environment-specific stack runs it will create the necessary nested stacks without name conflicts. You won't be able to control the stack names for the nested stacks, but you can get the name using outputs.
See the following:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html
You can add output values from a nested stack within the containing
template. You use the GetAtt function with the nested stack's logical
name and the name of the output value in the nested stack in the
format Outputs.NestedStackOutputName.
CloudFormation nested stack name
If you need to use different resource values for the different environments, then you can use mappings to specify the settings that correspond to the selected environment. Here is an example of mappings:
Mappings:
EnvTypeMap:
prod:
vpc: vpc-a6842gb0
subnet: subnet-hjk23553
dev:
vpc: vpc-b7742gb0
subnet: subnet-abc23553
qa:
vpc: vpc-c2542gb0
subnet: subnet-uio23553
Then to reference one of these mapping values you would do so like this:
VpcId:
Fn::FindInMap:
- EnvTypeMap
- Ref: Env
- vpc
CF stack is identified by a stack-name. All you have to do is to specify this stack-name when you are deploying the CF template.
aws cloudformation deploy --stack-name <value> --template-file <value> ...
If you specify the name of an existing stack, that stack will be updated. If you specify a new name, you will create a new stack from a given template.
You can create as many stacks as you want from a singe template by choosing new stack name each time. You do not need to worry about naming conflicts because each resource's name in a given stack is uniquely identified based on the stack name which will be different.
aws cloudformation deploy --stack-name dev --template-file the-same-template.yaml ...
aws cloudformation deploy --stack-name test --template-file the-same-template.yaml ...
aws cloudformation deploy --stack-name uat --template-file the-same-template.yaml ...
aws cloudformation deploy --stack-name prod --template-file the-same-template.yaml ...
This will create 4 separate stacks (dev, test, uat, prod).
Note that since you are hardcoding IP address ranges, resources in these stacks will not be able to communicate between each other because of overlapping networks (which probably is what you want anyway) but if for some reason you need these to communicate, you will need to create Parameters for CIDR blocks (VPC, subnets) as well.
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.
How can I create a CloudFormation template that launches three of the same EC2 instances in three different AZs in the same region, without using Auto Scaling?
For example:
Instance one in eu-west-1a
Instance two in eu-west-1b
Instance three in eu-west-1c
Here is my template:
AWSTemplateFormatVersion : 2010-09-09
Description: "simple web layer"
Parameters:
ImageId:
Description: 'web Layer'
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
AllowedPattern: "^[a-zA-Z][-a-zA-Z0-9]*$"
Default: ami-244333
Webservercapacity:
Default: '3'
Description: number
Type: Number
MinValue: '1'
MaxValue: '4'
Securitycab:
Type: String
Default: 0.0.0.0/0
Description: enter vpc ip range
Subnets:
Description: enter subnet
Type: List<AWS::EC2::Subnet::Id>
Default: subnet-384736383838
Securitygroup:
Description: enter sc
Type: List<AWS::EC2::SecurityGroup::Id>
Default: sg-237377383773873
Vpc:
Description: enter vpc
Type: List<AWS::EC2::VPC::Id>
Resources:
MyEC2Instance:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: !Ref ImageId
InstanceType: t2.large
VpcId: !Ref Vpc
SubnetId: !Ref Subnets
SecurityGroupIds:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: vpc-1a2b3c4d
GroupDescription: Sample target security group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: !Ref Securitycab
The template should launch three separate instances. Within the properties for each instance, specify the subnet by referring to your Subnets parameter (of type List<AWS::EC2::Subnet::Id>).
You can use !Select to choose the subnet:
SubnetId: !Select [ 0, Subnets ]
or
SubnetId: !Select [ 1, Subnets ]
or
SubnetId: !Select [ 2, Subnets ]
So it would look like:
Instance1:
Type: 'AWS::EC2::Instance'
Properties:
SubnetId: !Select [ 0, Subnets ]
...
Instance2:
Type: 'AWS::EC2::Instance'
Properties:
SubnetId: !Select [ 1, Subnets ]
...
Also, rather than defining a security group within the instance properties, define a single Security Group, then have each instance refer to it by reference.