无法将卷附加到 EC2 实例,grantAttachVolumeByResourceTag 的用法不清楚

Unable to attach Volumes to EC2 instance, grantAttachVolumeByResourceTag not clear on usage

我有一个堡垒 EC2 实例,我正在尝试将卷挂载到该实例(我希望该卷即使在更换堡垒时也能保持不变)。我已经阅读了 docs 但他们往往首先有不好的非工作示例。我已经创建了 Bastion 和卷,但我无法将卷附加到 EC2 实例。

这是我目前正在使用的代码(注意:我正在处理的更大结构的一部分):

// Bastion
this.bastion = new Instance(this, 'Bastion', {
  instanceName: 'BASTION-' + this._vpcName,
  vpc: this.vpc,
  vpcSubnets: {
    subnets: [_bastionSubnet],
    availabilityZones:[
      Stack.of(this).availabilityZones[0] // Force to same as Volume
    ]
  },
  machineImage: MachineImage.latestAmazonLinux({
    generation: AmazonLinuxGeneration.AMAZON_LINUX_2,
  }),
  instanceType: _instanceType,
  role: bastionRole,
  userData: UserData.custom(bootscript),
  userDataCausesReplacement: true,
  securityGroup: this.securityGroup_Bastion,
  keyName: this._props.bastion.keyName,
  blockDevices: [
    {
      deviceName: '/dev/xvda',
      volume: BlockDeviceVolume.ebs(_rootVolumeSize, {
        volumeType: EbsDeviceVolumeType.GP2,
      }),
    },
  ],
});

const _targetDevice = '/dev/xvdz';

// Create Volume
this.volumeBackups = new Volume(this, 'backupsVolume', {
  availabilityZone: Stack.of(this).availabilityZones[0], // Force to same as Bastion
  size: Size.gibibytes(200),
  encrypted: true,
  volumeName: _targetDevice
});

// Add attach access
this.volumeBackups.grantAttachVolumeByResourceTag(this.bastion.grantPrincipal, [this.bastion]);

到目前为止,我所看到的是创建了 Bastion 和创建了 Volume。它们具有预期的 VolumeGrantAttach-<suffix> 标记并且它们都匹配。在 AWS 控制台中检查时,我没有在实例的存储选项卡下看到卷。当我登录实例并 运行 lsblk 时,我没有看到可用的卷(只有我的根设备)。

$ sudo lsblk
NAME          MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0  30G  0 disk 
├─nvme0n1p1   259:1    0  30G  0 part /
└─nvme0n1p128 259:2    0   1M  0 part 

在这一点上,我以为我缺少映射。我试图将其添加到 bastion blockDevices 属性中,但这似乎不正确,因为这些类型不能一起工作。我什至尝试将挂载添加到 first-运行 脚本,但实例甚至无法识别它,我无法挂载它。

我仍然无法安装卷。我真的不知道还能做什么。

好的,这很简单,但要找出正确的方法并不容易。 docs example 不起作用...(抛出一个我目前不记得的错误)。

您需要使用AWS Cli 来附加实例中的卷。鉴于我想自动执行此任务,这是一个挑战,但我能够解决它。

我在自己的构造中使用 typescript,因此我将尝试只显示我使用的命令,而不是执行此操作的实际代码。

const _volumeId = 'vol-somerandomid';
const _targetDevice = '/dev/xvdz';

// I actually added a sleep for 2 mins here to ensure the volume is detached from a previous bastion instance. Otherwise you can, and will, get `VolumeInUse` error

// Attach VIA AWS CLI
aws --region ${Stack.of(this).region} ec2 attach-volume --volume-id ${_volumeId} --instance-id $(cat /var/lib/cloud/data/instance-id) --device ${_targetDevice}

// Verify it's attached
while ! test -e ${_targetDevice}; do sleep 1; done

附加后,您仍需要在第一次创建时对其进行格式化。这里的问题是,如何让第一个 运行 解决这个问题?这是我能做到的:

首先,添加到fstab:

const _backupVolumeMountLocation = '/home/ec2-user/backups';

// Must create the mount point first
mkdir -p ${_backupVolumeMountLocation}
 
// Add to fstab
echo "'+`${_targetDevice} ${_backupVolumeMountLocation} ext4 defaults,nofail 0 0`+'" >> /etc/fstab

这是棘手的部分,因为这将尝试挂载卷,然后在挂载失败时格式化。

sleep 1 ; mount -a && echo "Backups Volume already formatted and mounted" || (echo "Backups Volume is not formatted" && mkfs -t ext4 ${_targetDevice} && sleep 1 && mount -a && (chown -R ec2-user:ec2-user ${_backupVolumeMountLocation} && echo "Formatted backups volume") || echo "Failed to format and mount the backups volume" )

以上命令分解为以下逻辑:

  • 休眠 1 秒 - 这确保在我们尝试挂载之前先保存 fstab
  • 安装备份卷
    • 如果挂载没有失败:
      • 这将回应已经格式化和安装的备份卷
    • 如果挂载失败:
      • 这将回显备份卷未格式化
      • 它将格式化卷
      • 它将装载卷
        • 如果挂载没有失败:
          • 它将为新格式化的卷设置所有权
          • 这将回显格式化的备份卷
        • 如果挂载失败:
          • 这将回显无法格式化和安装备份卷。

希望这对以后的其他人有所帮助。我不太清楚如何正确执行此操作。