2016-09-03 4 views
1

Я хочу использовать экземпляры Spot Spot для тренировки Neural Networks. Чтобы предотвратить потерю модели при завершении спот-экземпляра, я планирую создать снимок тома EBS, создать новый том и прикрепить его к зарезервированному экземпляру. Как смонтировать или сделать доступный объем EBS с помощью python & boto3.python - Объем тома EBS с помощью boto3

Это шаги, используемые для make the volume available в Linux, но я хочу автоматизировать процесс, чтобы каждый раз, когда мне не требовалось SSH в экземпляр. Вот код, который я использую для присоединения к тому -

import boto3 
ec2 = boto3.resource('ec2') 

spot = ec2.Instance('i-9a8f5082') 
res = ec2.Instance('i-86e65a13') 

snapshot = ec2.create_snapshot(VolumeId="vol-5315f7db", Description="testing spot instances") 
volume = ec2.create_volume(SnapshotId=snapshot.id, AvailabilityZone='us-west-2a') 
res.attach_volume(VolumeId="vol-5315f7db", Device='/dev/sdy') 
snapshot.delete() 

ответ

0

Необходимо выполнить команду монтирования по экземпляру. 2 пути для него. Одна из них - команда отправки с подключением ssh, например, @mootmoot. Другой - команда отправки с помощью службы AWS SSM, например, @Mark B. Вот подробный пример решения SSM, вы можете игнорировать ненужные части для вас: команда

Отправить Баш к экземплярам с помощью AWS SSM:

# Amazon EC2 Systems Manager requires 
# 1. An IAM role for EC2 instances that will process commands. There should be a system manager role and the instance should use this role ! (Did it while creation instance) 
# 2. And a separate role for users executing commands. Aws IAM user that has access and secret keys should have ssm permission. (i.e. AmazonSSMFullAccess) 
# http://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-configuring-access-policies.html 
def execute_commands_on_linux_instances(commands, instance_ids): 
    client = boto3.client('ssm', **conn_args) # Need your credentials here 

    all_ssm_enabled_instances, ssm_enabled_instances, not_worked_instances = [],[],[] 
    not_worked_instances = instance_ids.copy() 
    all_ssm_enabled_instances = list() 
    outputs = list({}) 
    not_executed = list() 

    # Select only the Instances that have an active ssm agent. 
    if len(client.describe_instance_information()['InstanceInformationList']) > 0: 
     resp = client.describe_instance_information(MaxResults=20)['InstanceInformationList'] 
     for ins in resp: 
      all_ssm_enabled_instances.append(ins['InstanceId']) 
     ssm_enabled_instances = list(set(all_ssm_enabled_instances).intersection(instance_ids)) 
     not_worked_instances = list(set(instance_ids).difference(all_ssm_enabled_instances)) 


     # Now, send the command ! 
     resp = client.send_command(
     DocumentName="AWS-RunShellScript", 
     Parameters={'commands': [commands]}, 
     InstanceIds=ssm_enabled_instances, 
     ) 

     # get the command id generated by the send_command 
     com_id = resp['Command']['CommandId'] 

     # Wait until all the commands status are out of Pending and InProgress 
     list_comm = client.list_commands(CommandId=com_id) 
     while True: 
      list_comm = client.list_commands(CommandId=com_id) 
      if (list_comm['Commands'][0]['Status'] == 'Pending'or list_comm['Commands'][0]['Status'] == 'InProgress'): 
       continue 
      else: 
       # Commands on all Instances were executed 
       break 

     # Get the responses the instances gave to this command. (stdoutput and stderror) 
     # Althoug the command could arrive to instance, if it couldn't be executed by the instance (response -1) it will ignore. 
     for i in ssm_enabled_instances: 
      resp2 = client.get_command_invocation(CommandId=com_id, InstanceId=i) 
      if resp2['ResponseCode'] == -1: 
       not_executed.append(i) 
      else: 
       outputs.append({'ins_id': i, 'stdout': resp2['StandardOutputContent'], 
          'stderr': resp2['StandardErrorContent']}) 

     # Remove the instance that couldn't execute the command ever, add it to not_worked_instances 
     ssm_enabled_instances = list(set(ssm_enabled_instances).difference(not_executed)) 
     not_worked_instances.extend(not_executed) 

     return ssm_enabled_instances, not_worked_instances, outputs 
    else: 
     print("There is no any available instance that has a worked SSM service!") 
     return ssm_enabled_instances, not_worked_instances, outputs 

Создание экземпляров с требуемым профилем IAM Instance, которая требуется роль, которая требуемой политика. В результате создания этого экземпляра в экземплярах работают агенты SSM:

def create_ec2_instance(node_type): 
    # define userdata to be run at instance launch 

    userdata = """#cloud-config 

    runcmd: 
    - cd /tmp 
    - sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm 
    """ 

    ec2_r = boto3.resource('ec2', **conn_args) 

    rolename = "amazonec2ssmrole" 
    i_pro_name = "ins_pro_for_ssm" 

    # Create an iam instance profile and add required role to this instance profile. 
    # Create a role and attach a policy to it if not exist. 
    # Instances will have this role to build ssm (ec2 systems manager) connection. 
    iam = boto3.resource('iam', **conn_args) 

    try: 
     response= iam.meta.client.get_instance_profile(InstanceProfileName=i_pro_name) 
    except: 
     iam.create_instance_profile(InstanceProfileName=i_pro_name) 
    try: 
     response = iam.meta.client.get_role(RoleName=rolename) 
    except: 
     iam.create_role(
        AssumeRolePolicyDocument='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":["ec2.amazonaws.com"]},"Action":["sts:AssumeRole"]}]}', 
        RoleName=rolename) 
     role = iam.Role(rolename) 
     role.attach_policy(PolicyArn='arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM') 
     iam.meta.client.add_role_to_instance_profile(InstanceProfileName=i_pro_name, RoleName=rolename) 

    iam_ins_profile = {'Name': i_pro_name} 

    if node_type == "Medium": 
     instance = ec2_r.create_instances(
      ImageId='ami-aa5ebdd2', 
      MinCount=1, 
      MaxCount=1, 
      UserData=userdata, 
      InstanceType='t2.medium', 
      KeyName=key_pair_name, 
      IamInstanceProfile=iam_ins_profile, 
      BlockDeviceMappings=[{"DeviceName": "/dev/xvda", "Ebs": {"VolumeSize": 20}}]) 
    elif node_type == "Micro": 
     instance = ec2_r.create_instances(
      ImageId='ami-aa5ebdd2', 
      MinCount=1, 
      MaxCount=1, 
      UserData=userdata, 
      InstanceType='t2.micro', 
      KeyName=key_pair_name, 
      IamInstanceProfile=iam_ins_profile, 
      BlockDeviceMappings=[{"DeviceName": "/dev/xvda", "Ebs": {"VolumeSize": 10}}]) 
    else: 
     print("Node Type Error") 
     return -1 

    # Wait for the instance state, default --> one wait is 15 seconds, 40 attempts 
    print('Waiting for instance {0} to switch to running state'.format(instance[0].id)) 
    waiter = ec2_r.meta.client.get_waiter('instance_running') 
    waiter.wait(InstanceIds=[instance[0].id]) 
    instance[0].reload() 
    print('Instance is running, public IP: {0}'.format(instance[0].public_ip_address)) 

    return instance[0].id 

Не забывайте давать разрешение ssm. (т. е. AmazonSSMFullAccess) пользователю Aws IAM, имеющему доступ и секретные ключи.

Кстати, conn_args может быть определена следующим образом:

conn_args = { 
     'aws_access_key_id': Your_Access_Key, 
     'aws_secret_access_key': Your_Secret_Key, 
     'region_name': 'us-west-2' 
    } 
1

Необходимо выполнить эти шаги в операционной системе. Вы не можете выполнить эти шаги через API AWS (Boto3). Лучше всего называть эти шаги, а затем запускать сценарий каким-то образом через Boto3, возможно, используя сервис AWS SSM.

1

Что случилось с отправкой и выполнением сценария ssh удаленно? Предположим, вы используете Ubuntu, то есть

ssh -i your.pem [email protected]_name_or_ip 'sudo bash -s' < mount_script.sh 

Если присоединить тег к этим ресурсам, вы можете позже использовать boto3 к запрошенному ресурсы универсальным именем тега, а не привязанной к конкретному статическому ид.

Смежные вопросы