user1801879
user1801879

Reputation: 822

How to attach and mount volumes to an EC2 instance using CloudFormation

I can't find a way to attach and mount volumes using cloudformation.

I can attach a volume using VolumeAttachment; however, when I do lsblk after my EC2 instance is in running state, I see this attached instances as being unmounted.

Is there a way to mount this instance from Cloudformation file? I can mount this using linux commands but would be much better to handle everything from cloudformation instead.

Here is what I've so far:

"MyEc2Instance" : {
   "Type" : "AWS::EC2::Instance",
   "Properties" : {
      "KeyName" : { "Ref" : "KeyName" }
   }
},
    "MyVolume" : {
      "Type" : "AWS::EC2::Volume",
      "Properties" : {
        "Size" : "50",
        "AvailabilityZone" : "xyz"
      }
    },
    "attachment" : {
      "Type" : "AWS::EC2::VolumeAttachment",
      "Properties" : {
        "InstanceId" : { "Ref" : "MyEc2Instance" },
        "VolumeId"  : { "Ref" : "MyVolume" },
        "Device" : "/dev/sdh"
      }
    }

And when I do lsblk on the instance, this is the result i see:

xvda    202:0    0   8G  0 disk
└─xvda1 202:1    0   8G  0 part /
xvdh    202:112  0  50G  0 disk

Notice even though I specified device name to be 'sdh' it shows attached as 'xvdh'. Why is that? And as you can see this is unmounted. How do I mount this?

Upvotes: 17

Views: 16813

Answers (2)

NHol
NHol

Reputation: 2125

As mentioned by helloV you will need to mount it when the instance launches using UserData. I find the new YAML format for CloudFormation templates is much easier but I've put the example in JSON too.

JSON:

"UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
    "#!/bin/bash -xe\n",
    "# create mount point directory\n",
    "mkdir /mnt/xvdh\n",
    "# create ext4 filesystem on new volume\n",    
    "mkfs -t ext4 /dev/xvdh\n",
    "# add an entry to fstab to mount volume during boot\n",
    "echo \"/dev/xvdh       /mnt/xvdh   ext4    defaults,nofail 0       2\" >> /etc/fstab\n",
    "# mount the volume on current boot\n",
    "mount -a\n"
]]}}

YAML:

UserData:
    'Fn::Base64': !Sub
      - |
        #!/bin/bash -xe
        # create mount point directory
        mkdir /mnt/xvdh
        # create ext4 filesystem on new volume           
        mkfs -t ext4 /dev/xvdh
        # add an entry to fstab to mount volume during boot
        echo "/dev/xvdh       /mnt/xvdh   ext4    defaults,nofail 0       2" >> /etc/fstab
        # mount the volume on current boot
        mount -a

Upvotes: 21

helloV
helloV

Reputation: 52433

Attaching a volume can be done at hypervisor level, hence you can attach a volume using CF.

But mounting a volume is at OS level and CF has no way of knowing/doing it. It is same as asking How can I create a directory in cloudformation after launching an instance?

How do you solve this problem? CF has EC2Instance property called UserData. You supply the command to mount the attached volume. Here is one example

{
   "Type" : "AWS::EC2::Instance",
   "Properties" : {
        ....
        "InstanceType"   : { "Ref" : "InstanceType" },
        "KeyName"        : { "Ref" : "KeyName" },
        "UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
             "#!/bin/bash -xe\n",
             "yum install -y aws-cfn-bootstrap\n",

             "# Install the files and packages from the metadata\n",
             "/opt/aws/bin/cfn-init -v ",
             "         --stack ", { "Ref" : "AWS::StackName" },
             "         --resource WebServerInstance ",
             "         --configsets Install ",
             "         --region ", { "Ref" : "AWS::Region" }, "\n"
        ]]}}
      }
    },

Upvotes: 3

Related Questions