+86 13541016684Mon. - Fri. 10:00-22:00

python boto实现自动部署AWS

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 '-----------------------------------------