Last active
October 12, 2023 13:12
-
-
Save sebsto/ebb66807ac8c6f9148c7580e2da5803d to your computer and use it in GitHub Desktop.
CDK Create EC2 instace in private subnet. Install Nginx.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ec2 = require('@aws-cdk/aws-ec2'); | |
import cdk = require('@aws-cdk/core'); | |
import { Fn, Tag, Resource } from '@aws-cdk/core'; | |
import { AmazonLinuxImage, UserData, InstanceType } from '@aws-cdk/aws-ec2'; | |
import { Role, ServicePrincipal, ManagedPolicy, CfnInstanceProfile } from '@aws-cdk/aws-iam' | |
/** | |
* Create my own Ec2 resource and Ec2 props as these are not yet defined in CDK | |
* These classes abstract low level details from CloudFormation | |
*/ | |
class Ec2InstanceProps { | |
readonly image : ec2.IMachineImage; | |
readonly instanceType : ec2.InstanceType; | |
readonly userData : UserData; | |
readonly subnet : ec2.ISubnet; | |
readonly role : Role; | |
} | |
class Ec2 extends Resource { | |
constructor(scope: cdk.Construct, id: string, props? : Ec2InstanceProps) { | |
super(scope, id); | |
if (props) { | |
//create a profile to attch the role to the instance | |
const profile = new CfnInstanceProfile(this, `${id}Profile`, { | |
roles: [ props.role.roleName ] | |
}); | |
// create the instance | |
const instance = new ec2.CfnInstance(this, id, { | |
imageId: props.image.getImage(this).imageId, | |
instanceType: props.instanceType.toString(), | |
networkInterfaces: [ | |
{ | |
deviceIndex: "0", | |
subnetId: props.subnet.subnetId | |
} | |
] | |
,userData: Fn.base64(props.userData.render()) | |
,iamInstanceProfile: profile.ref | |
}); | |
// tag the instance | |
Tag.add(instance, 'Name', `${CodeStack.name}/${id}`); | |
} | |
} | |
} | |
export class CodeStack extends cdk.Stack { | |
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { | |
super(scope, id, props); | |
// create VPC w/ public and private subnets in 1 AZ | |
// this also creates a NAT Gateway | |
// I am using 1 AZ because it's a demo. In real life always use >=2 | |
const vpc = new ec2.Vpc(this, 'NewsBlogVPC', { | |
maxAzs : 1 | |
}); | |
const privateSubnet0 = vpc.privateSubnets[0]; | |
// define the IAM role that will allow the EC2 instance to communicate with SSM | |
const role = new Role(this, 'NewsBlogRole', { | |
assumedBy: new ServicePrincipal('ec2.amazonaws.com') | |
}); | |
// arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore | |
role.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore')); | |
// define a user data script to install & launch our web server | |
const ssmaUserData = UserData.forLinux(); | |
// make sure the latest SSM Agent is installed. | |
const SSM_AGENT_RPM='https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm'; | |
ssmaUserData.addCommands(`sudo yum install -y ${SSM_AGENT_RPM}`, 'restart amazon-ssm-agent'); | |
// install and start Nginx | |
ssmaUserData.addCommands('yum install -y nginx', 'chkconfig nginx on', 'service nginx start'); | |
// launch an EC2 instance in the private subnet | |
const instance = new Ec2(this, 'NewsBlogInstance', { | |
image: new AmazonLinuxImage(), | |
instanceType : ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MICRO), | |
subnet : privateSubnet0, | |
role: role, | |
userData : ssmaUserData | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment