How do I specify an ECS-optimized AMI in CDK? - amazon-web-services

I'm attempting to specify an EC2 launch template using CDK.
So far my template declaration looks like this:
let launch_template = new ec2.LaunchTemplate(
this,
'MyLaunchTemplate',
{
instanceType: params.instanceType,
machineImage: ec2.MachineImage.latestAmazonLinux(),
}
);
But the MachineImage.latestAmazonLinux method does not appear to give an ECS-optimized AMI.
I will need to create two launch templates: one which is ECS-optimized, and another which is ECS-optimized with GPU support.
The AMI's I am currently using are:
ami-00eb0dc604a8124fd
ami-03d0d75de9d82f509
Is there any way in CDK to specify that an ECS optimized AMI is required, and that an AMI with GPU support is required?
And if not, how can I specify a specific AMI in CDK when creating a launch template?

You can use the EcsOptimizedImage construct ecs.EcsOptimizedImage.amazonLinux2(ecs.AmiHardwareType.GPU)
let launch_template = new ec2.LaunchTemplate(
this,
'MyLaunchTemplate',
{
instanceType: params.instanceType,
machineImage: ecs.EcsOptimizedImage.amazonLinux2(ecs.AmiHardwareType.GPU)
}
);
Also in order to pick the exact AMI you can give the region ami map
machineImage: ec2.MachineImage.genericLinux({
'us-east-1': 'ami-xxxxxxxxxx',
})

Related

CDK cloud9 - How to attach preconstructed instance profile to Cloud9 instance iam role in cdk?

I created cloud9 instance and vpc environment via cdk. Also with role permissions and instance profile, how do i attach that at the end via cdk too?
Currently there seem to be no in built parameters about setting iam role in Ec2Environment
Can't achieve this automatically too if i use CloudFormation, so i am thinking this is not available yet?
I know i can use custom resource or create a lambda to achieve that, but was thinking it's just a bit too much to just to use to attach an instance profile
My code:
const c9IamRole = new iam.Role(this, 'C9IamRole', {
roleName: 'cloud9-admin-access-role',
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'),
]
});
const c9InstanceProfile = new iam.CfnInstanceProfile(this, 'C9InstanceProfile', {
roles: [c9IamRole.roleName],
});
// create a cloud9 ec2 environment in a new VPC
const vpc = new ec2.Vpc(this, 'VPC', { maxAzs: 3 });
const c9Env = new cloud9.Ec2Environment(this, 'Cloud9Env', {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO),
});
IAM role that i want to attach the instance profile (at the created cloud9 ec2 instance page)
Anything using a Cfn prefixed method is an L1 construct. They do not have the hooks necessary to automatically apply them to other constructs (l2 and l3 - the higher level objects) - they are bare bones, just basically a translation from your code to cfn template snippet.
if iam.CfnInstanceProfile does not have a l2 or l3 version (as of this answer it does not seem to, but the CDK team is always updating) then you'll have to manually attach it using other cfn methods.
Also, the cloud9 library is (as of this writing) still Experimental, which is a good indication that it wont have all the things it needs - It does not seem to have any property for attaching a role. You might be able to manually (again using cfn escape hatch methods) attach a role.
You might try instead applying the roles to a User/Group and giving them permission to access the cloud9, rather than attaching the role to cloud9 and give allowance to various Identities - it may be easier with current CDK constructs.

Why EKS cluster creates a clone of the launch template?

Our EKS cluster is terraform managed and was specified with EC2 Launch Template as terraform resource. Our aws_eks_node_group includes Launch template section as shown below.
resource "aws_eks_node_group" eks_node_group" {
.........................
..........................
launch_template {
id = aws_launch_template.eksnode_template.id
version = aws_launch_template.eksnode_template.default_version
name = aws_launch_template.eksnode_template.name
}
}
However, after a while, EKS self-deployed the new Launch Template and linked it to the relevant auto-scaling group.
Why this has happened at the first place and how to avoid it in the future?
How can we link the customer managed Launch Template to EKS Autoscaling Group via terraform again? I tried changing the name or version of the launch template, but it is still using one created by EKS (self-managed)
The Amazon EKS API creates this launch template either by copying one you provide or by creating one automatically with default values in your account.
We don't recommend that you modify auto-generated launch templates.
(source)

Attach IAM role to existing EC2 instance using terraform

I am trying to attach an IAM role to EC2 instance using terraform. But after looking out on some web pages.. I found that the attaching can be done at the time of creating ec2 instance.
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
iam_instance_profile = "${aws_iam_instance_profile.ec2_profile.name}"
tags = {
Name = "HelloWorld"
}
}
As in the above part , it can be clearly seen that, AMI is being passed which will create a new instance.
Is it somehow possible that instead of using AMI id, we can provide instance it, so that it can attach role to that instance?
I found out one link from terraform community pointing out that this feature is not yet released.
https://github.com/hashicorp/terraform/issues/11852
Please provide inputs on how to accomplish this task.
Thanks in advance
As you pointed out this is not supported. But if you really want to use terraform for that you could consider two options:
Use local-exec which would use AWS CLI associate-iam-instance-profile to attach the role to an existing instance.
Use aws_lambda_invocation. This way you could invoke a custom lambda function from your terraform which would use AWS SDK to associate profile with the instance. For example, for boto3 the method is associate_iam_instance_profile.

How to create Elastic IP association with an EC2 instance using AWS CDK?

In AWS CDK, I have an EC2 instance and Elastic IP created as follows:
// EC2 Instance
let ec2Instance = new ec2.Instance(this, "EC2Instance", {
instanceType: ec2.InstanceType.of(InstanceClass.T2, InstanceSize.MICRO),
vpc: vpc,
securityGroup: securityGroupEc2,
keyName: Config.keyPairName,
machineImage: new ec2.GenericLinuxImage({"eu-west-1": Config.ec2ImageAmi}),
blockDevices: [{deviceName: "/dev/sda1", volume: ec2.BlockDeviceVolume.ebs(30)}]
});
// Elastic IP
let eip = new ec2.CfnEIP(this, "Ip");
I have difficulties to understand how I can declare an association between these, as I can not perceive using AWS CDK documentation how to declare that. Seems that I need AWS::EC2::EIPAssociation.EIP: string to supply and I am missing as to how to get it from the eip object.
It wasn't explained very well, but the solution is:
// EC2 Instance <> EIP
let ec2Assoc = new ec2.CfnEIPAssociation(this, "Ec2Association", {
eip: eip.ref,
instanceId: ec2Instance.instanceId
});
For Cfn* CDK resources, I find that the CloudFormation docs are much more informative than the CDK API.
The CloudFormation docs for AWS::EC2::EIP show that there is an instanceId property that can be used when creating the EIP, which I believe should avoid the need to create a CfnEIPAssociation separately.

Can the EC2 instance be created with the latest Image-id of the region when cloudformation template execute

I am having a template where I am creating a Ubuntu EC2 instance based on the region and the associated image id mapped in the template.Is there anyway through which the the latest Ubuntu image id will get selected based on the region.This will happen during template execution.It would be helpful to get any sample template for the same.
There are few ways you can achieve this:
A) You can use the Mappings section of the template to specify an AMI for each region. You would then use Fn::FindInMap to retrieve the value of the AMI according to the evaluation of the pseudo parameter AWS::Region.
See:
Mappings - AWS CloudFormation
Fn::FindInMap - AWS CloudFormation
Pseudo Parameters Reference - AWS CloudFormation
B) You can use a lambda backed custom resource to retrieve the latest ubuntu AMI during stack creation. There is a getting started guide for the same, you can use it as a starting point.
See: Walkthrough: Looking Up Amazon Machine Image IDs - AWS CloudFormation
C) If you can migrate to an Amazon Linux AMI, based on RHEL, you can reference public systems manager parameters for the latest AMI id for that region. I have an example template in github you can use as a reference.
See: CloudFormationExamples/highlyavailable-asg-lamp-server-alb at master ยท smith-b/CloudFormationExamples