How to get/set AWS ECS container instance role - amazon-web-services

When creating an EC2 based ECS cluster in the AWS console you can specify the container instance role:
However, after the cluster has been created, I don't see any way to view which role was attached to the cluster.
In addition, I don't see any way to specify the container instance role when creating a cluster using the cli or in Cloudformation (or, by extension, the CDK).
My question is two-fold:
Can this property be specified in the API/Cloudformation
Is there any way to view this property on an existing cluster either in the console or using the API/CLI

The console leads you to believe it's an ECS property but in fact it's simply an EC2 property known as "IAM Instance Profile". You have to specify this role by setting the IamInstanceProfile property on a AWS::EC2::Instance or even better on a AWS::EC2::LaunchTemplate resource that can be used inside an AutoScaling group. Small caveat, you won't be able to directly add the role to that property just yet, you will need to create a AWS::IAM::InstanceProfile first like so:
EcsInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- ecsInstanceRole
For the sake of completeness, here's how you would then set the property inside a launch template:
LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
IamInstanceProfile:
Arn: !GetAtt EcsInstanceProfile.Arn
...

Related

AWS ECS EC2 Capacity Provider not listed

I'm trying to create a new Capacity Provider
I deployed the following CloudFormation snippet:
myECSCapacityProvider:
Type: AWS::ECS::CapacityProvider
Properties:
Name: my-project-asg-cp
AutoScalingGroupProvider:
AutoScalingGroupArn: !Ref myAutoScalingGroup
ManagedScaling:
MaximumScalingStepSize: 10
MinimumScalingStepSize: 1
Status: ENABLED
TargetCapacity: 100
ManagedTerminationProtection: DISABLED
I have the resource ASG (myAutoScalingGroup) created.
When I go to the ECS console and then to the Capacity Providers tab it is blank, no CPs are listed.
If I try to create the same CP through the console, using the name my-project-asg-cp I see the following error:
There was an error creating the capacity provider.
Fix the following error and try again.
The specified Auto Scaling group ARN is already being used by another capacity provider.
Specify a unique Auto Scaling group ARN and try again.
So it seems somehow the CP was created but it is not listed.
And of course, I don't have any error in CloudFormation.
If I check the resources tab I can see the resource created:
myECSCapacityProvider my-project-asg-cp AWS::ECS::CapacityProvider CREATE_COMPLETE
Also, the cli doesn't show it either.
Does anyone has faced this error?
Associate the capacity provided with the cluster:
ECSCluster:
Type: 'AWS::ECS::Cluster'
Properties:
ClusterName: <your-ecs-cluster>
CapacityProviders:
- !Ref myECSCapacityProvider

Why does ECS CloudFormation template create an EC2 Spot Fleet

I created a cluster in ECS with basic settings, nothing specific about the configuration except that I am using 1 On Demand t2.micro EC2 instance for the cluster.
I wanted to see what exactly was created and took a look at the CloudFormation template the cluster created.
I noticed in the template it has a configuration for EcsSpotFleet
EcsSpotFleet:
Condition: CreateWithSpot
Type: AWS::EC2::SpotFleet
Properties:
SpotFleetRequestConfigData:
AllocationStrategy: !Ref SpotAllocationStrategy
IamFleetRole: !Ref IamSpotFleetRoleArn
TargetCapacity: !Ref AsgMaxSize
SpotPrice: !If [ CreateWithSpotPrice, !Ref SpotPrice, !Ref 'AWS::NoValue' ]
TerminateInstancesWithExpiration: true
LaunchSpecifications:
....
I am wondering why is this created? Because I know the Cluster instances are created with ASG + LC. My only explanation is this fleet is used for running the CloudFormation stack. I cannot find an explanation to this in the documentation, not even sure if instances are needed for CloudFormation stack run.
p.s. I am very new to AWS, also have very little knowledge on CloudFormation.
Not all code in CloudFormation will be executed. It still depends on the "Condition" flag.
AWS usually create a template that covers most of the user cases and enables/disable parts of the template using the "Condition"
You can read more about Condition in AWS documentation here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html

AWS Cloudformation: Outputs ServiceName for Unnamed ECS Service

I create ECS stack via cloudformation. Everything works fine.
Due to a certain reason, I do not specify ServiceName for ECS service (Name: Service) in definition.
However, I want to have it in outputs, after Cloudformation creates the stack.
So for this purpose, I defined outputs like this:
Outputs:
ECSServiceName:
Description: Service Name I want to see
Value: !GetAtt Service.ServiceName
When I run update CF Stack, I receive an error from AWS:
Requested attribute ServiceName must be a readonly property in schema for AWS::ECS::Service
Does this mean that I cannot receive it in outputs, if it wasn't strictly specified before? Or I made a mistake somewhere in Outputs definition?
You have to export ECSServiceName from your template. Also the correct way to get ECS service name is !GetAtt Service.Name:
Outputs:
ECSServiceName:
Description: Service Name I want to see
Value: !GetAtt Service.Name
Export:
Name: ECSServiceName
Then, in other templates, you can use ImportValue to reference the exported output:
!ImportValue ECSClusterName

How to attach AmazonEC2RoleforSSM to ec2 instance in a CloudFormation script

I am trying to bring up multiple ec2 instances cloudformation script. I am using a shell script to loop the aws cloudformation create-stack command and successfully bringing up multiple instances.
Now I need to bring these instance up with the SSM Role attached. However I don't see any way of using an existing role in the script. I need to re-create the role inside the script thus:
AWSTemplateFormatVersion: 2010-09-09
Description: Compact template for creating an ec2 instance for SPT
Resources:
IAMRole:
Type: AWS::IAM::Role
Properties:
RoleName: SPTvacmRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
Path: "/"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
InstanceProfile1:
Type: AWS::IAM::InstanceProfile
Properties:
Path: "/"
Roles:
- Ref: IAMRole
ec2instance1:
Type: AWS::EC2::Instance
Properties:
SubnetId: subnet-0da86f65478f3d30a
KeyName: spt-lab
ImageId: ami-00344ae218e7aae62
InstanceType: t2.nano
IamInstanceProfile: !Ref InstanceProfile1
SecurityGroupIds:
- sg-0d3fae6860ce71c91
This can be executed only once, because by the time the loop executes the command for a second time, the role SPTvacmRole already exists and the stack fails.
I've already created a role from the console manually, using the AmazonEC2RoleForSSM Policy and named it EC2RoleForSSM, however when I try to reference that role by its name -Ref: EC2RoleForSSM in InstanceProfile1 without creating IAMRole, it gives an error saying Template format error: Unresolved resource dependencies [EC2RoleForSSM] in the Resources block of the template
How can I use the pre-existing role EC2RoleForSSM in the script, without having to create it again?
You should not include a Ref function as this is used for retrieving values from parameters or resources.
Instead just use the string EC2RoleForSSM like below.
InstanceProfile1:
Type: AWS::IAM::InstanceProfile
Properties:
Path: "/"
Roles:
- EC2RoleForSSM
However I don't see any way of using an existing role in the script. I need to re-create the role inside the script
How can I use the pre-existing role EC2RoleForSSM in the script, without having to create it again?
If the role exists, you can't create the same role in CloudFormation. Instead, you should import it:
Bringing existing resources into CloudFormation management
AWS::IAM::Role is one of the resources that can be imported into CloudFormation.
If you just want to reference it in the templates, #ChrisWilliams already explained how to do it.

Is it possible to execute commands and then update security groups in a CloudFormation template?

I would like to perform the following operations in order with CloudFormation.
Start up an EC2 instance.
Give it privileges to access the full internet using security group A.
Download particular versions of Java and Python
Remove its internet privileges by removing security group A and adding a security group B.
I observe that there is a DependsOn attribute for specifying the order in which to create resources, but I was unable to find a feature that would allow me to update the security groups on the same EC2 instance twice over the course of creating a stack.
Is this possible with CloudFormation?
Not in CloudFormation natively, but you could launch the EC2 instance with a configured userdata script that itself downloads Java/Python and the awscli, as necessary, and then uses the awscli to switch security groups for the current EC2 instance.
However, if all you need is Java and Python pre-loaded then why not simply create an AMI with them already installed and launch from that AMI?
The best way out is to utilise a Cloudformation custom resource here. You can create a lambda function that does exactly what you need. This lambda function can then be called as a custom resource function in the cloud formation template.
You can pass your new security group ID and instance ID to the lambda function and code the lambda function to use AWS SDK and do the modifications that you need.
I have leveraged it to post an update to my web server about the progress of the cloud formation template. Below is the sample code of the template.
EC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles: [!Ref 'EC2Role']
MarkInstanceProfileComplete:
Type: 'Custom::EC2InstanceProfileDone'
Version: '1.0'
DependsOn: EC2InstanceProfile
Properties:
ServiceToken: !Ref CustomResourceArn
HostURL: !Ref Host
LoginType: !Ref LoginType
SecretId: !Ref SecretId
WorkspaceId: !Ref WorkspaceId
Event: 2
Total: 3
Here the resource MarkInstanceProfileComplete is a custom resource that calls a Lambda function. It takes the event count and total count as input and processes them to calculate percentage progress. Based on that it sends out a request to my web server. For all we care, this Lambda function can do potentially anything you want it to do.