【问题标题】:Using boto3 to create and attach an EBS volume to an EC2 instance使用 boto3 创建 EBS 卷并将其附加到 EC2 实例
【发布时间】:2025-12-11 06:05:01
【问题描述】:

我有一个现有的 EC2 实例,其中附加了两个 EBS 卷。我想使用 boto3 向这个 EC2 实例添加第三个 EBS 卷。

这是我的想法:

或者有更简单的方法吗? boto3 中是否有可用于向现有 EC2 实例添加新 EBS 卷的函数?

【问题讨论】:

  • AFAIK,这是使用 boto3 创建和附加卷的唯一方法。不过,使用 ansible 可以做得更短。

标签: python amazon-web-services amazon-ec2 boto3 amazon-ebs


【解决方案1】:

没有将这两种操作结合​​在一起的“单一 API 调用”。

创建一个卷然后附加它是正确的。

【讨论】:

    【解决方案2】:

    试试这个...

     '''
     Creation State:
     'State': 'creating'|'available'|'in-use'|'deleting'|'deleted'|'error'
    
     Attachment State:
     'State': 'attaching'|'attached'|'detaching'|'detached'
     '''
    
     #create_and_attach_volume
    def create_and_attach_volume(ec2_client, availability_zone, DryRunFlag, device, 
    instance_id):
    try:
        response= ec2_client.create_volume(
            AvailabilityZone=availability_zone,
            Encrypted=False,
            #Iops=100,
            #KmsKeyId='string',
            Size=10,
            #SnapshotId='string',
            VolumeType='gp2',    #standard'|'io1'|'gp2'|'sc1'|'st1',
            DryRun=DryRunFlag
            )
        #pprint(response)
    
        if response['ResponseMetadata']['HTTPStatusCode']== 200:
            volume_id= response['VolumeId']
            print('***volume:', volume_id)
    
            ec2_client.get_waiter('volume_available').wait(
                VolumeIds=[volume_id],
                DryRun=DryRunFlag
                )
            print('***Success!! volume:', volume_id, 'created...')
    
    except Exception as e:
            print('***Failed to create the volume...')
            print(type(e), ':', e)
    
    #botocore.exceptions.ClientError:
    #An error occurred (InvalidParameterCombination) when calling the CreateVolume 
    operation: The parameter iops is not supported for gp2 volumes.
    if volume_id:
        try:
            print('***attaching volume:', volume_id, 'to:', instance_id)
            response= ec2_client.attach_volume(
                Device=device,
                InstanceId=instance_id,
                VolumeId=volume_id,
                DryRun=DryRunFlag
                )
            #pprint(response)
    
            if response['ResponseMetadata']['HTTPStatusCode']== 200:
                ec2_client.get_waiter('volume_in_use').wait(
                    VolumeIds=[volume_id],
                    DryRun=False
                    )
                print('***Success!! volume:', volume_id, 'is attached to instance:', 
      instance_id)
    
        except Exception as e:
            print('***Error - Failed to attach volume:', volume_id, 'to the instance:', instance_id)
            print(type(e), ':', e)
    
    #botocore.exceptions.ClientError:
    #An error occurred (IncorrectState) when calling the AttachVolume operation: vol- 
    0fcc7c3319a885513 is not 'available'.
    #An error occurred (InvalidParameterValue) when calling the AttachVolume operation: 
    Invalid value '/dev/sdc' for unixDevice. Attachment point /dev/sdc is already in use
    
    #__main__
    session= boto3.session.Session()
    region_name= session.region_name
    #region_name='ap-south-1'
    availability_zone='ap-south-1a'
    bdm='/dev/sdc'
    instance_id='i-08364669ada3804d3'
    
    start= -perf_counter()
    ec2_client= boto3.client('ec2', region_name=region_name)
    create_and_attach_volume(ec2_client, availability_zone, DryRunFlag=False, bdm, 
    instance_id)
    print('***duration:', (start+ perf_counter()), 'secs')
    

    【讨论】:

      【解决方案3】:

      试试这个....

      import time
      
      import boto3
      
      ec2 = boto3.client('ec2')
      response = ec2.describe_instances()
      instance_dict = {}
      count = 1
      print('  {0:3}    {1:30s}  {2:15s}     {3:15s}   {4:15s}   {5:10s}'.format("S No. ", "NAME", "INSTANCE ID", "IP ADDRESS",'AvailabilityZone', "STATE"))
      print('----------------------------------------------------------------------------------------------------------------- \n')
      for reservation in response["Reservations"]:
          for instance in reservation["Instances"]:
              if instance['State']['Name'] == "running":
                  if instance.__contains__("Tags"):
                      print('  {0:3}    {1:30s}  {2:15s}   {3:15s}   {4:15s}   {5:10s}'.format(
                          count, instance["Tags"][0]["Value"], instance["InstanceId"],
                          instance["PublicIpAddress"], instance['Placement']['AvailabilityZone'], "RUNNING"))
                      instance_dict[count] = instance["InstanceId"],instance['Placement']['AvailabilityZone']
                      count += 1
                  else:
                      print('  {0:3}    {1:30s}  {2:15s}   {3:15s}   {4:15s}   {5:10s}'.format(
                          count, "No Name", instance["InstanceId"], instance["PublicIpAddress"],instance['Placement']['AvailabilityZone'], "RUNNING"))
                      instance_dict[count] = instance["InstanceId"],instance['Placement']['AvailabilityZone']
                      count += 1
              elif instance['State']['Name'] == "stopped":
                  if instance.__contains__("Tags"):
                      print('  {0:3}    {1:30s}  {2:15s}   {3:15s}   {4:15s}   {5:10s}'.format(
                          count, instance["Tags"][0]["Value"], instance["InstanceId"], "No IP ADDRESS", instance['Placement']['AvailabilityZone'],
                          "STOPPED"))
                      instance_dict[count] = instance["InstanceId"],instance['Placement']['AvailabilityZone']
                      count += 1
                  else:
                      print('  {0:3}    {1:30s}  {2:15s}   {3:15s}   {4:15s}   {5:10s}'.format(
                          count, "No Name", instance["InstanceId"], "No IP ADDRESS", instance['Placement']['AvailabilityZone'], "STOPPED"))
                      instance_dict[count] = instance["InstanceId"],instance['Placement']['AvailabilityZone']
                      count += 1
      print()
      iId = int(input('On which instance you want to add Volume : '))
      
      az = instance_dict[iId][1]
      
      size = input("Enter Size of Volume (default: 10): ")
      
      response= ec2.create_volume(
                  AvailabilityZone=az,
                  Encrypted=False,
                  #Iops=100,
                  #KmsKeyId='string',
                  Size=int(size),
                  #SnapshotId='string',
                  VolumeType='gp2',    #standard'|'io1'|'gp2'|'sc1'|'st1',
                  DryRun=False)
      print("Volume ID : ", response['VolumeId'])
      time.sleep(10)
      response= ec2.attach_volume(Device="/dev/sdc", InstanceId=instance_dict[iId][0], VolumeId=response['VolumeId'])
      print("State : ",response['State'])
      

      【讨论】:

      • 纯代码答案往往不是很有用,因为它们没有解释为什么。考虑添加一些上下文和理由。