in python/ec2-cloudwatch/ec2_cloudwatch/ec2_cloudwatch_stack.py [0:0]
def __init__(self, scope: Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
# The code from zhxinyua to create VPC, s3_endpoint, bastion, EC2, EBS, Cloudwatch event rule stop EC2, Backup for EC2
# create a new VPC
vpc_new = aws_ec2.Vpc(self, "VpcFromCDK", cidr="10.0.0.0/16")
vpc_new.add_gateway_endpoint("S3Endpoint",
service=aws_ec2.GatewayVpcEndpointAwsService.S3,
# Add only to ISOLATED subnets
subnets=[aws_ec2.SubnetSelection(subnet_type=aws_ec2.SubnetType.PUBLIC)
]
)
# only allow a specific rang of IP to conncet bastion
# BastionHostLinux support two way to connect, one is SSM, second is EC2 Instance Connect
# EC2 Instance Connect are not supportd in CN
host_bastion = aws_ec2.BastionHostLinux(self, "BastionHost",
vpc=vpc_new,
subnet_selection=aws_ec2.SubnetSelection(subnet_type=aws_ec2.SubnetType.PUBLIC)
)
# write your own IP rang to access this bastion instead of 1.2.3.4/32
host_bastion.allow_ssh_access_from(aws_ec2.Peer.ipv4("1.2.3.4/32"))
# use amazon linux as OS
amzn_linux = aws_ec2.MachineImage.latest_amazon_linux(generation=aws_ec2.AmazonLinuxGeneration.AMAZON_LINUX,
edition=aws_ec2.AmazonLinuxEdition.STANDARD,
virtualization=aws_ec2.AmazonLinuxVirt.HVM,
storage=aws_ec2.AmazonLinuxStorage.GENERAL_PURPOSE)
# secure group
my_security_group = aws_ec2.SecurityGroup(self, "SecurityGroup",
vpc=vpc_new,
description="SecurityGroup from CDK",
security_group_name="CDK SecurityGroup",
allow_all_outbound=True,
)
my_security_group.add_ingress_rule(aws_ec2.Peer.ipv4('10.0.0.0/16'), aws_ec2.Port.tcp(22), "allow ssh access from the VPC")
# set up an web instance in public subnet
work_server = aws_ec2.Instance(self, "WebInstance",
instance_type=aws_ec2.InstanceType("Write a EC2 instance type"),
machine_image=amzn_linux,
vpc=vpc_new,
vpc_subnets=aws_ec2.SubnetSelection(subnet_type=aws_ec2.SubnetType.PUBLIC),
security_group=my_security_group,
key_name="Your SSH key pair name")
# allow web connect
work_server.connections.allow_from_any_ipv4(aws_ec2.Port.tcp(80), "allow http from world")
work_server.connections.allow_from_any_ipv4(aws_ec2.Port.tcp(443), "allow https from world")
# set a second ebs to web instance
work_server.instance.add_property_override("BlockDeviceMappings", [{
"DeviceName": "/dev/sdb",
"Ebs": {"VolumeSize": "30",
"VolumeType": "gp2",
"DeleteOnTermination": "true"}
}])
# Cloudwatch event rule to stop instances every day in 15:00 UTC
# they only use javascript SDK to call AWS API
# https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_events_targets/AwsApi.html
stop_EC2 = AwsApi(service="EC2",
action="stopInstances",
parameters={"InstanceIds": [work_server.instance_id, host_bastion.instance_id]})
Rule(self, "ScheduleRule", schedule=Schedule.cron(minute="0", hour="15"), targets=[stop_EC2])
# AWS backup part
# create a BackupVault
vault = backup.BackupVault(self, "BackupVault", backup_vault_name="CDK_Backup_Vault")
# create a BackupPlan
plan = backup.BackupPlan(self, "AWS-Backup-Plan", backup_plan_name="CDK_Backup")
# add buackup resources with two way for two resources
plan.add_selection("Selection", resources=[
backup.BackupResource.from_ec2_instance(work_server),
backup.BackupResource.from_tag("Name", "BastionHost")
])
# details with backup rules
plan.add_rule(backup.BackupPlanRule(backup_vault=vault,
rule_name="CDK_Backup_Rule",
schedule_expression=Schedule.cron(minute="0", hour="16", day="1", month="1-12"),
delete_after=Duration.days(130),
move_to_cold_storage_after=Duration.days(10)))
# output information after deploy
output = CfnOutput(self, "BastionHost_information",
value=host_bastion.instance_public_ip,
description="BastionHost's Public IP")
output = CfnOutput(self, "WebHost_information",
value=work_server.instance_public_ip,
description="Web server's Public IP")