Tryboy869

amazon-ec2

"[Applies to: **/*] This guide provides definitive best practices for deploying and managing Amazon EC2 instances, focusing on security, cost optimization, and operational excellence through Infrastructure as Code (IaC)."

Tryboy869 1 Updated 3mo ago

Resources

1
GitHub

Install

npx skillscat add tryboy869/dojutsu-for-ai/amazon-ec2

Install via the SkillsCat registry.

SKILL.md

amazon-ec2 Best Practices

Treat every EC2 instance as versioned, secured, and continuously optimized code. Adhere strictly to the AWS Well-Architected Framework and Foundational Security Best Practices (FSBP).

1. Code Organization and Structure

Always define EC2 resources using Infrastructure as Code (IaC). CloudFormation is the standard for AWS-native deployments. Break down templates into modular, reusable components.

1.1. Modular CloudFormation Templates

Organize your CloudFormation templates logically. Separate networking, IAM, and EC2 instance definitions into distinct, composable stacks or modules.

BAD: Monolithic Template

# all-in-one-stack.yaml
Resources:
  VPC: # ...
  Subnet: # ...
  SecurityGroup: # ...
  IAMRole: # ...
  EC2Instance: # ...

GOOD: Modular Stacks

# network-stack.yaml
Resources:
  VPC: # ...
  Subnet: # ...
Outputs: # Export VPC ID, Subnet IDs
# iam-stack.yaml
Resources:
  IAMRole: # ...
Outputs: # Export Role ARN
# ec2-instance-stack.yaml
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0abcdef1234567890
      InstanceType: !Ref InstanceTypeParam
      SecurityGroupIds: [!ImportValue MySecurityGroup]
      IamInstanceProfile: !ImportValue MyInstanceProfile
      # ...

1.2. Enforce Consistent Tagging

Implement a unified tagging strategy from your IaC templates. Tags are critical for cost allocation, resource discovery, and automation.

BAD: Missing or Inconsistent Tags

EC2Instance:
  Type: AWS::EC2::Instance
  Properties:
    # ... no tags or only a few

GOOD: Mandatory Tags via IaC

EC2Instance:
  Type: AWS::EC2::Instance
  Properties:
    # ...
    Tags:
      - Key: Environment
        Value: !Ref EnvironmentTag
      - Key: Project
        Value: !Ref ProjectTag
      - Key: Owner
        Value: !Ref OwnerTag
      - Key: CostCenter
        Value: !Ref CostCenterTag

2. Common Patterns and Anti-patterns

2.1. Right-Sizing Instances

Analyze workloads to select the optimal instance family and size. This is the single biggest driver for performance efficiency and cost optimization.

BAD: Defaulting to t2.micro or Over-provisioning

EC2Instance:
  Type: AWS::EC2::Instance
  Properties:
    InstanceType: t2.micro # For a production database!

GOOD: Workload-Specific Instance Types

EC2Instance:
  Type: AWS::EC2::Instance
  Properties:
    InstanceType: m5.large # General purpose, balanced CPU/memory
    # or c5.xlarge for compute-intensive, r5.large for memory-intensive

2.2. Least Privilege IAM Instance Profiles

Attach IAM roles to EC2 instances via Instance Profiles, granting only the minimum necessary permissions. Never embed AWS credentials directly on an instance.

BAD: Over-privileged IAM Role

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*"
    }
  ]
}

GOOD: Tightly Scoped IAM Role

# CloudFormation IAM Role for EC2
BastionHostRole:
  Type: AWS::IAM::Role
  Properties:
    AssumeRolePolicyDocument:
      Statement:
        - Effect: Allow
          Principal: { Service: [ 'ec2.amazonaws.com' ] }
          Action: [ 'sts:AssumeRole' ]
    ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM # For SSM access
    Policies:
      - PolicyName: S3ReadAccess
        PolicyDocument:
          Statement:
            - Effect: Allow
              Action: [ 's3:GetObject' ]
              Resource: !Sub 'arn:${AWS::Partition}:s3:::my-config-bucket/*'

2.3. Strict Security Group Rules

Security groups must enforce the principle of least privilege. Restrict inbound and outbound traffic to only what is absolutely required.

BAD: Open Ingress/Egress

SecurityGroupIngress:
  - IpProtocol: tcp
    FromPort: 22
    ToPort: 22
    CidrIp: 0.0.0.0/0 # SSH open to the world!

GOOD: Restricted Access

SecurityGroupIngress:
  - IpProtocol: tcp
    FromPort: 22
    ToPort: 22
    CidrIp: !Ref RemoteAccessCIDR # Parameter for specific IP range
  - IpProtocol: tcp
    FromPort: 80
    ToPort: 80
    SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup # Only allow from LB

2.4. Require IMDSv2

Always configure EC2 instances to require Instance Metadata Service Version 2 (IMDSv2). This prevents SSRF vulnerabilities.

BAD: Relying on IMDSv1

EC2Instance:
  Type: AWS::EC2::Instance
  Properties:
    # ... no MetadataOptions specified

GOOD: Enforce IMDSv2

EC2Instance:
  Type: AWS::EC2::Instance
  Properties:
    # ...
    MetadataOptions:
      HttpPutResponseHopLimit: 1
      HttpTokens: required

3. Performance Considerations

3.1. Leverage Launch Templates for Auto Scaling

Use EC2 Launch Templates with Auto Scaling Groups. This ensures consistent configuration, supports multiple instance types, and simplifies updates.

BAD: Launch Configurations (deprecated)

AutoScalingGroup:
  Type: AWS::AutoScaling::AutoScalingGroup
  Properties:
    LaunchConfigurationName: !Ref MyLaunchConfig # Avoid

GOOD: Launch Templates

AutoScalingGroup:
  Type: AWS::AutoScaling::AutoScalingGroup
  Properties:
    LaunchTemplate:
      LaunchTemplateId: !Ref MyLaunchTemplate
      Version: !GetAtt MyLaunchTemplate.LatestVersionNumber
    # ...

3.2. EBS Optimization and Encryption

Use EBS-optimized instances for I/O-intensive workloads and encrypt all EBS volumes by default.

BAD: Unencrypted Volumes, Non-EBS Optimized

BlockDeviceMappings:
  - DeviceName: /dev/sdh
    Ebs:
      VolumeSize: 100
      Encrypted: false # Never!

GOOD: Encrypted, EBS-Optimized

EC2Instance:
  Type: AWS::EC2::Instance
  Properties:
    InstanceType: m5.large # Often EBS-optimized by default or configurable
    BlockDeviceMappings:
      - DeviceName: /dev/sdh
        Ebs:
          VolumeSize: 100
          Encrypted: true # Always!
          KmsKeyId: !Ref MyEBSKMSKey # Use a customer-managed key

4. Common Pitfalls and Gotchas

4.1. Avoid Hardcoding Sensitive Information

Never hardcode secrets, ARNs, or environment-specific values. Use CloudFormation parameters, SSM Parameter Store, or AWS Secrets Manager.

BAD: Hardcoded S3 Bucket Name

#!/bin/bash
aws s3 cp /var/log/app.log s3://my-prod-bucket-123/logs/

GOOD: Parameterized Values

# CloudFormation UserData
UserData:
  Fn::Base64: !Sub |
    #!/bin/bash
    aws s3 cp /var/log/app.log s3://${LogBucketName}/logs/
Parameters:
  LogBucketName:
    Type: String
    Description: S3 bucket for application logs

4.2. Enable Termination Protection

Enable termination protection for critical EC2 instances. This prevents accidental deletion.

BAD: No Termination Protection

EC2Instance:
  Type: AWS::EC2::Instance
  Properties:
    # ... no DisableApiTermination

GOOD: Termination Protection Enabled

EC2Instance:
  Type: AWS::EC2::Instance
  Properties:
    # ...
    DisableApiTermination: true

5. Testing Approaches

5.1. IaC Linting and Validation

Integrate IaC linting and validation into your CI/CD pipeline. Catch policy violations and syntax errors before deployment.

BAD: Deploying without Pre-checks

aws cloudformation deploy --template-file my-ec2-stack.yaml --stack-name my-app

GOOD: CI/CD with CloudFormation Guard

# In CI/CD pipeline
cfn-guard validate --template my-ec2-stack.yaml --rules policies/ec2-rules.guard
aws cloudformation deploy --template-file my-ec2-stack.yaml --stack-name my-app

5.2. Automated Security Hub Compliance

Ensure your CI/CD pipeline includes checks against AWS Foundational Security Best Practices (FSBP) via AWS Security Hub.

BAD: Manual Security Audits Post-Deployment

# Hope for the best, check manually later

GOOD: Proactive Security Checks

# Example rule in CloudFormation Guard to enforce IMDSv2
rule imdsv2_required {
  EC2_Instance {
    Properties {
      MetadataOptions {
        HttpTokens == "required"
        HttpPutResponseHopLimit == 1
      }
    }
  }
}