python boto实现自动部署AWS
最近接到一家游戏公司有些游戏业务需要在海外上线,需要使用aws来部署服务器,
考虑前期在海外自建机房很不合适,因此aws就是我们的不二之选了。要在aws租用服务器,那么就一定了解amazon提供的基本服务,例如VPC,EC2,S3,ELB
随着公司海外业务的扩大,服务器的需求也越来越大,之前我们都是在aws提供的web console上点点拽拽生成各种服务与网络环境,机器少的时候还好说,多起来连点击都费劲,那么aws也友好地提供了各种API,供各路程序猿实现自动化部署自己的业务,这里选取了AWS python boto来部署。
1. 工欲善其事,必先有其网络–VPC
AWS提供了virtual private cloud 与一个传统网络结构相似的虚拟网络,那么再从ec2上生成一个实例放进创建好的vpc里,我们就可以在云上创建属于自己的网络环境而不受外界影响
在web console上很容易就可以生成一个vpc,那么在python里是如何生成呢,
import boto
import boto.vpc
region = 'us-west-1' #此region 为大湾区
vpc_name = 'haowan123'
vpc_cidr = '10.100.0.0/24' #即将创建vpc的网段!
Connections = namedtuple('Connections', ['ec2', 'vpc'])
def connect():
vpc_conn = boto.vpc.connect_to_region(region)
ec2_conn = boto.ec2.connect_to_region(region)
return Connections(ec2_conn, vpc_conn)
def create_vpc(conn, vpc_name, vpc_cidr):
datacenters = conn.vpc.get_all_vpcs(filters=[("cidrBlock", vpc_cidr)])
if not len(datacenters): #判断之前是否已经创建了此vpc
datacenter = conn.vpc.create_vpc(cidr_block=vpc_cidr)
make_tag(datacenter, vpc_name) #给创建完的vpc打上标签
print "have created a vpc which name is %s and cidr is %s" %(datacenter.tags['Name'], datacenter.cidr_block)
print "----------------------------------"
else: datacenter = datacenters.pop(0)
print "the vpc you requested is already exists"
print "----------------------------------"
return datacenter
conn = connect()
create_vpc(conn, vpc_name, vpc_cidr)
2. 没网关怎么谈上网呢–internet gateway
有了属于自己的那片私密网络空间,那么如何才能访问互联网精彩的世界呢,这就需要internet gateway帮你忙了。要注意的就是创建这个internet gateway的时候要指定刚刚生成的那个vpc
def create_internet_gateway(conn, vpc, intgw_name):
i_gws = conn.vpc.get_all_internet_gateways(filters=[('tag:Name', intgw_name)])
if not len(i_gws): #根据internet gw name判断之前有没创建
i_gw = conn.vpc.create_internet_gateway()
make_tag(i_gw, intgw_name)
conn.vpc.attach_internet_gateway(i_gw.id, vpc.id)
print "have created a internet gw attaching to the vpc which created before "
print "-----------------------------------"
else: i_gw = i_gws.pop(0)
print "the internet gw u requested is already exists"
print "-----------------------------------"
return i_gw
vpc = create_vpc(conn, vpc_name, vpc_cidr)
3. 有了网关出口没有路由表如何出口–route table
上述已经为这个vpc创建好了Internet gateway,我们还要做的是创建好一个路由表然后把需要出口的流量指向internet gateway,然后下述的subnet再关联到此路由表,就能完成通往外面的世界了。
def create_route_table(conn, vpc, route_name, i_gw):
route_tables = conn.vpc.get_all_route_tables(filters=[("tag:Name", route_name)])
if not len(route_tables):
route_table = conn.vpc.create_route_table(vpc.id)
make_tag(route_table, route_name)
conn.vpc.create_route(route_table.id, ANYWHERE, i_gw.id)
print "have created a route table for the vpc which created before"
print "-----------------------------------"
else:
route_table = route_tables.pop(0)
print "the route table is exists already"
print "-----------------------------------"
return route_table
4. 子网–subnet
在第一部分我们划好的vpc掩码为10.100.0.0/24。那么这个vpc下可以创建255个instance,但是业务逻辑需要划分出三个 子网,一个作为public subnet,另外两个为private subnet。所有就要利用boto来帮我创建好这些子网的环境。
要注意的是aws vpc里还有个概念叫available zone。在一个region里面至少都会有两个az,一般不同az都是部署在不同的物理机房内。我们创建subnet的时候因此也需要指定放在哪个az内。
def create_subnet(conn,
vpc,
route_table,
subnet_name,
sub_cidr,
availability_zone):
subnets = conn.vpc.get_all_subnets(filters=[("cidrBlock", sub_cidr)])
if not len(subnets):
subnet = conn.vpc.create_subnet(vpc.id, sub_cidr, availability_zone)
make_tag(subnet, subnet_name)
conn.vpc.associate_route_table(route_table.id, subnet.id)
print "have created a subnet"
print "-----------------------------------"
else:
subnet = subnets.pop(0)
print "the subnet u requested is already exists"
print "-----------------------------------"
return subnet
5.主菜上桌–instance
其实还需要创建一堆东西,例如security group, ebs, public_key,因为篇幅有限这里就不提供如何利用boto来创建了,如果有不清楚或者感兴趣的再找我私聊。
基本的网络都搭建好了,那么就要创建intance放到我们刚刚创建好的subnet里面,这样基本上instance就可以批量创建喽。
parser = SafeConfigParser()
parser.read('/home/raingolee/aws.cfg')#我把要创建的instance信息都存在一个配置文件里
def create_instance( conn, vpc, pub_subnet, pri_subnet, public_key, security_group):
with open('~/aws/user-data', 'r') as file:
user_data = file.read()
for ins in parser.sections(): #我把要创建的instance信息都存在一个配置文件里
if ins.startswith('instance'):
ami_id = parser.get(ins, 'ami_id')
ami_type = parser.get(ins, 'ami_type')
subnet = parser.get(ins, 'subnet')
if subnet == 'public':
subnet = pub_subnet
elif subnet == 'private':
subnet = pri_subnet
subnet_ip = parser.get(ins, 'subnet_ip')
instance_name = parser.get(ins, 'instance_name')
reservations = conn.ec2.get_all_instances(filters=[("tag:Name", instance_name)])
if not len(reservations):
bdm = create_ebs(conn)
reservation = conn.ec2.run_instances(ami_id,
instance_type=ami_type,
security_group_ids=[security_group.id],
key_name=public_key.name,
subnet_id=subnet.id,
private_ip_address=subnet_ip,
block_device_map=bdm,
user_data=user_data)
instance = reservation.instances[0]
instance.add_tag("Name", instance_name)
print "have created a instance named is %s" % (instance_name)
print '-----------------------------------------