How to create a LAMP stack in AWS using Python Boto3
Hello Everyone
Welcome to CloudAffaire and this is Debjeet.
In the last blog post, we have discussed boto3 clients.
https://cloudaffaire.com/boto3-clients/
In this blog post, we will discuss how to create a LAMP stack in AWS using Python Boto3. In this demo, we are going to install Apache webserver with PHP and MySQL support on your Amazon Linux instance (sometimes called a LAMP web server or LAMP stack). You can use this server to host a static website or deploy a dynamic PHP application that reads and writes information to a database. We will create a custom VPC, one public subnet and one private subnet, one internet gateway, custom route tables for the public and private subnets, custom security groups, Key Pair and one EC2 Amazon Linux 2 server with LAMP configuration using user data.
Prerequisites for this demo:
- One EC2 AWS Linux 2 instance with boto3 installed and configured.
Demo:
Step 1: Create a file deploy_lamp.py to define your LAMP stack.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
## Login to your EC2 instance ## Create a file named deploy_lamp.py vi deploy_lamp.py --------------------------- #!/usr/bin/env python # Create a LAMP stack # import python packages import boto3 import os from operator import itemgetter # variables aws_region = "ap-south-1" aws_az1 = "ap-south-1a" aws_az2 = "ap-south-1b" vpc_cidr = "10.0.0.0/16" public_subnet_cidr = "10.0.1.0/24" private_subnet_cidr = "10.0.2.0/24" source_cidr = '0.0.0.0/0' user_data_content = """#!/bin/bash sudo yum update -y sudo amazon-linux-extras install -y lamp-mariadb10.2-php7.2 php7.2 sudo yum install -y httpd mariadb-server sudo systemctl start httpd sudo systemctl is-enabled httpd""" # initialize boto3 ec2 client and resource ec2_resource = boto3.resource('ec2', aws_region) ec2_client = boto3.client('ec2', aws_region) # create a vpc vpc = ec2_resource.create_vpc(CidrBlock=vpc_cidr) vpc.wait_until_available() print('VPC created successfully with VPC ID: ' + vpc.id) # modify vpc to enable dns hostname vpc.modify_attribute(EnableDnsHostnames={'Value':True}) # create public subnet public_subnet = vpc.create_subnet(AvailabilityZone=aws_az1,CidrBlock=public_subnet_cidr) ec2_client.modify_subnet_attribute(MapPublicIpOnLaunch={'Value': True},SubnetId=public_subnet.id) print('Public Subnet created successfully with SUBNET ID: ' + public_subnet.id) # create a private subnet private_subnet = vpc.create_subnet(AvailabilityZone=aws_az2,CidrBlock=private_subnet_cidr) print('Private Subnet created successfully with SUBNET ID: ' + private_subnet.id) # create an internet gateway and attach to the vpc internet_gateway = ec2_resource.create_internet_gateway() internet_gateway.attach_to_vpc(VpcId=vpc.id) print('Internet Gateway created successfully with GATEWAY ID: ' + internet_gateway.id) # create a public route table and assosiate to public subnet public_route_table = ec2_resource.create_route_table(VpcId=vpc.id) public_route_table.associate_with_subnet(SubnetId=public_subnet.id ) # create route to Internet Gateway in public route table public_route = ec2_client.create_route(RouteTableId=public_route_table.id,DestinationCidrBlock=source_cidr,GatewayId=internet_gateway.id) print('Public Route Table with ID ' + public_route_table.id + ' created successfully') # create a private route table and assosiate to private subnet private_route_table = ec2_resource.create_route_table(VpcId=vpc.id) private_route_table.associate_with_subnet(SubnetId=private_subnet.id) print('Private Route Table with ID ' + private_route_table.id + ' created successfully') # create a security group security_group = ec2_resource.create_security_group(GroupName='myvpc_security_group',Description='Used by LAMP',VpcId= vpc.id) # create ssh and http ingress rules ec2_client.authorize_security_group_ingress(GroupId=security_group.id,IpProtocol='tcp',FromPort=22,ToPort=22,CidrIp=source_cidr) ec2_client.authorize_security_group_ingress(GroupId=security_group.id,IpProtocol='tcp',FromPort=80,ToPort=80,CidrIp=source_cidr) print('Security Group with ID ' + security_group.id + ' created successfully') # get the latest AMI ID for Amazon Linux 2 ec2_ami_ids = ec2_client.describe_images( Filters=[{'Name':'name','Values':['amzn2-ami-hvm-2.0.????????-x86_64-gp2']},{'Name':'state','Values':['available']}], Owners=['amazon'] ) image_details = sorted(ec2_ami_ids['Images'],key=itemgetter('CreationDate'),reverse=True) ec2_ami_id = image_details[0]['ImageId'] # create a key pair outfile = open('my_keypair.pem','w') keypair = ec2_client.create_key_pair(KeyName='my_keypair') keyval = keypair['KeyMaterial'] outfile.write(keyval) outfile.close() os.chmod('my_keypair.pem', 400) print('Key Pair my_keypair created successfully') # create an ec2 instance ec2_instance = ec2_resource.create_instances( ImageId=ec2_ami_id, InstanceType='t2.micro', KeyName='my_keypair', Monitoring={'Enabled':False}, SecurityGroupIds=[security_group.id], SubnetId=public_subnet.id, UserData=user_data_content, MaxCount=1, MinCount=1, PrivateIpAddress='10.0.1.10' ) ec2_instance_id = ec2_instance[0].id print('Creating EC2 instance') #wait untill the ec2 is running waiter = ec2_client.get_waiter('instance_running') waiter.wait(InstanceIds=[ec2_instance_id]) print('EC2 Instance created successfully with ID: ' + ec2_instance_id) # create tags vpc.create_tags(Tags=[{"Key": "Name", "Value": "myvpc"}]) public_subnet.create_tags(Tags=[{"Key": "Name", "Value": "myvpc_public_subnet"}]) private_subnet.create_tags(Tags=[{"Key": "Name", "Value": "myvpc_private_subnet"}]) internet_gateway.create_tags(Tags=[{"Key": "Name", "Value": "myvpc_internet_gateway"}]) public_route_table.create_tags(Tags=[{"Key": "Name", "Value": "myvpc_public_route_table"}]) private_route_table.create_tags(Tags=[{"Key": "Name", "Value": "myvpc_private_route_table"}]) security_group.create_tags(Tags=[{"Key": "Name", "Value": "myvpc_security_group"}]) create_tag = ec2_client.create_tags(Resources=[ec2_instance_id], Tags=[{'Key': 'Name','Value': 'myvpc_ec2_instance'}]) # print webserver dns name ec2_instance = ec2_client.describe_instances( Filters=[{'Name': 'tag:Name','Values': ['myvpc_ec2_instance']}, {'Name': 'instance-state-name','Values': ['running']}] ) ec2_public_dns_name = ec2_instance["Reservations"][0]["Instances"][0]["PublicDnsName"] print('Webserver URL: ' + ec2_public_dns_name) --------------------------- :wq |
Step 2: Execute the deploy_lamp.py to create your LAMP stack.
1 2 |
# deploy your lamp stack python deploy_lamp.py |
Our LAMP stack created successfully.
Once the instance ‘Status Checks’ is completed, open the Webserver URL in your favorite browser.
Step 3: Create a file delete_lamp.py to delete your LAMP stack.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
vi delete_lamp.py --------------------------- #!/usr/bin/env python # Delete the LAMP stack # import python packages import boto3 import os # variables aws_region = "ap-south-1" # initialize boto3 ec2 client and resource ec2_resource = boto3.resource('ec2', aws_region) ec2_client = boto3.client('ec2', aws_region) # get vpc id for myvpc myvpc = ec2_client.describe_vpcs( Filters=[{'Name': 'tag:Name','Values': ['myvpc']}] ) vpc_id = myvpc["Vpcs"][0]["VpcId"] vpc = ec2_resource.Vpc(vpc_id) # delete ec2 instance ec2_instance = ec2_client.describe_instances( Filters=[{'Name': 'tag:Name','Values': ['myvpc_ec2_instance']} ,{'Name': 'instance-state-name','Values': ['running']}] ) ec2_instance_id = ec2_instance["Reservations"][0]["Instances"][0]["InstanceId"] ec2_client.terminate_instances(InstanceIds=[ec2_instance_id]) print('Terminating EC2 instance') #wait untill the ec2 is terminated waiter = ec2_client.get_waiter('instance_terminated') waiter.wait(InstanceIds=[ec2_instance_id]) print('EC2 instance with ID ' + ec2_instance_id + ' deleted successfully') # delete key pair ec2_client.delete_key_pair(KeyName='my_keypair') os.remove("my_keypair.pem") print('Key Pair my_keypair deleted successfully') # delete custom security group security_group = ec2_client.describe_security_groups( Filters=[{'Name': 'tag:Name','Values': ['myvpc_security_group']}] ) security_group_id = security_group["SecurityGroups"][0]["GroupId"] ec2_client.delete_security_group(GroupId=security_group_id) print('Security Group myvpc_security_group deleted successfully') # delete internet gateway internet_gateways = vpc.internet_gateways.filter(Filters=[{'Name': 'tag:Name','Values': ['myvpc_internet_gateway']}]) for igw in internet_gateways: internet_gateway_id = igw.id internet_gateway = ec2_resource.InternetGateway(internet_gateway_id) internet_gateway.detach_from_vpc(VpcId=vpc_id) internet_gateway.delete() print('Internet Gateway with ID ' + internet_gateway_id + ' delete successfully') # delete route tables public_route_tables = vpc.route_tables.filter(Filters=[{'Name': 'tag:Name','Values': ['myvpc_public_route_table']}]) for rutablpub in public_route_tables: public_route_table_id = rutablpub.id public_route_table = ec2_resource.RouteTable(public_route_table_id) pubrutablassoid = public_route_table.associations_attribute for pubassosiation in pubrutablassoid: public_route_table_association_id = pubassosiation['RouteTableAssociationId'] public_route_table_association = ec2_resource.RouteTableAssociation(public_route_table_association_id) public_route_table_association.delete() public_route_table.delete() print('Public Route Table with ID ' + public_route_table_id + ' delete successfully') private_route_tables = vpc.route_tables.filter(Filters=[{'Name': 'tag:Name','Values': ['myvpc_private_route_table']}]) for rutablpvt in private_route_tables: private_route_table_id = rutablpvt.id private_route_table = ec2_resource.RouteTable(private_route_table_id) pvtrutablassoid = private_route_table.associations_attribute for pvtassosiation in pvtrutablassoid: private_route_table_association_id = pvtassosiation['RouteTableAssociationId'] private_route_table_association = ec2_resource.RouteTableAssociation(private_route_table_association_id) private_route_table_association.delete() private_route_table.delete() print('Private Route Table with ID ' + private_route_table_id + ' delete successfully') # delete subnets public_subnets = vpc.subnets.filter(Filters=[{'Name': 'tag:Name','Values': ['myvpc_public_subnet']}]) for public_subnet in public_subnets: public_subnet_id = public_subnet.id public_subnet = ec2_resource.Subnet(public_subnet_id) public_subnet.delete() print('Public Subnet with ID ' + public_subnet_id + ' delete successfully') private_subnets = vpc.subnets.filter(Filters=[{'Name': 'tag:Name','Values': ['myvpc_private_subnet']}]) for private_subnet in private_subnets: private_subnet_id = private_subnet.id private_subnet = ec2_resource.Subnet(private_subnet_id) private_subnet.delete() print('Private Subnet with ID ' + private_subnet_id + ' delete successfully') # delete vpc vpc.delete() print('VPC with ID ' + vpc_id + ' delete successfully') --------------------------- :wq |
Step 4: Delete your LAMP stack
1 2 |
# Delete your LAMP stack python delete_lamp.py |
Note: We have used both Boto3 resources and clients in this demo. You can try to optimize the code if you want.
Hope your understanding in boto3 is clear now. You can try to interact with other services using boto3 by referring below Boto3 official documentation.
https://boto3.amazonaws.com/v1/documentation/api/latest/index.html
Wow… awesome, I was looking for these type of resource.