EC2 Instance
- CloudFormation template: yaml
AWSTemplateFormatVersion: 2010-09-09 Description: An EC2 Instance.
Prerequisets
- ../network/public.html deployed with the same
DeploymentName
- An EC2 KeyPair in this region
Overview
This CloudFormation template creates a single EC2 instance.
Parameters
Parameters:
DeploymentName
DeploymentName: Type: String Description: A name for this deployment
A deployment is a deployed application, potentially comprised of many
CloudFormation stacks. This is sometimes called an "environment", but that is an
overloaded and confusing term. Use the DeploymentName
to indicate which
logical deployment a stack belongs to.
If a deployment is completely specified by exactly one CloudFormation template,
the DeploymentName
and the AWS::StackName refer to the same things. In that
case, consider not using a DeploymentName
parameter.
KeyName
KeyName: Type: AWS::EC2::KeyPair::KeyName Description: The name of an EC2 KeyPair Default: test
AWS does not provide a CloudFormation type for EC2 KeyPairs. This is a deliberate choice: a KeyPair consists of a public and private key, and AWS does not want to expose the private key in CloudFormation outputs.
This is one example where Terraform has an advantage: since Terraform runs locally, it can create a KeyPair and save the private key locally.
In CloudFormation, you have two options:
- Create the KeyPair beforehand, then provide the
KeyName
to your CloudFormation template as a parameter. - Create the KeyPair using a CloudFormation Custom Resource (i.e. a Lambda Function) defined in your CloudFormation template. The Custom Resource must save the private key somewhere (like SecretsManager or SSM Parameter Store).
Mappings
Mappings:
Instance mapping
RegionMap: us-east-1: AMI: ami-0aeeebd8d2ab47354 us-east-2: AMI: ami-0d8d212151031f51c
Resources
Resources:
IAM
An EC2 instance isn't required to have an IAM instance profile. However, an instance profile is a good idea if the instance will talk to any other AWS service. The only alternative would be to copy AWS credentials onto the instance somehow.
Role
InstanceRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${DeploymentName}-InstanceRole" Description: Allows EC2 instances to call AWS services AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: ec2.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - !Ref InstancePolicy
Instance Profile
InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: InstanceProfileName: !Sub "${DeploymentName}-InstanceProfile" Roles: - !Ref InstanceRole
Policy
InstancePolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: Allow logging to CloudWatch ManagedPolicyName: !Sub "${DeploymentName}-InstancePolicy" PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:DescribeLogStreams Resource: "*"
Security Group
SecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Allow HTTP and SSH GroupName: !Sub "${DeploymentName}" VpcId: {Fn::ImportValue: !Sub "${DeploymentName}-VpcId"} SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 0.0.0.0/0 Tags: - Key: Name Value: !Sub "${DeploymentName}-instance"
Instance
Instance: Type: AWS::EC2::Instance Properties: IamInstanceProfile: !Sub "${DeploymentName}-InstanceProfile" ImageId: Fn::FindInMap [RegionMap, !Ref AWS::Region, AMI] InstanceType: t2.nano KeyName: !Ref KeyName SecurityGroupIds: - !Ref SecurityGroup SubnetId: {Fn::ImportValue: !Sub "${DeploymentName}-PublicSubnet1"} Tags: - Key: Name Value: !Sub "${DeploymentName}-instance"