Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AWS ephemeral storage #858

Closed
ameir opened this issue Jan 23, 2015 · 12 comments · Fixed by #1045
Closed

AWS ephemeral storage #858

ameir opened this issue Jan 23, 2015 · 12 comments · Fixed by #1045

Comments

@ameir
Copy link
Contributor

ameir commented Jan 23, 2015

It looks like #440 just supports EBS volumes, and not ephemeral storage. If that's the case, does Terraform support ephemeral storage at all? We treat our instances as being disposable, and make extensive use of ephemeral storage; such support would be great.

Thanks!
-Ameir

@knuckolls
Copy link
Contributor

There may be more nuances in the general case but all of the ephemeral drives for a given instance flavor should already be available as block devices within /dev/. I use the ephemeral drives on instances fired up with terraform currently. Raiding, formatting, and mounting them all occurs in postlaunch scripting.

@ameir
Copy link
Contributor Author

ameir commented Jan 24, 2015

After some research, I was able to add both EBS and ephemeral storage using the following config (on an m3.xlarge):

block_device {
  device_name = "/dev/sda"
  volume_type = "standard"
  volume_size = 20
  delete_on_termination = 1
}

block_device {
  device_name = "/dev/sdb"
  volume_type = "standard"
  volume_size = 50
  delete_on_termination = 0
}

block_device {
  device_name = "/dev/sdc"
  virtual_name = "ephemeral0"
}

block_device {
  device_name = "/dev/sdd"
  virtual_name = "ephemeral1"
}

If I leave out the latter two block_devices, I do get the two EBS volumes, but none of the ephemeral storage. In short, this may not be a bug, but certainly something that should be documented better.

@knuckolls
Copy link
Contributor

I've been thinking about this. I think if you don't provide a block_device configuration that it'll default to providing all of the ephemerals to the instance. That's the case I'm seeing. The case you're seeing is that if you provide a block_device configuration then you need to make sure the ephemerals are attached as well as the ebs drives.

I'd say that all the ephemerals available to a given instance type should always be available regardless of whether or not you intend to attach ebs drives on launch. I think the trick is making sure that you don't attach an ebs drive on one of the /dev/{sd,xvd}* devices that the ephemerals default to. That's a bit tricky because they are different devices on different instance types. I generally ping the ec2 metadata service to see what ephemeral drives are available to me and what their device names are before I subsequently auto raid0 them (in most cases).

If I get a chance I'll take a peek at the current implementation and see what might need to be done to get all the ephemerals attached by default. IMO, there is no reason to ever omit any storage that is freely available to an instance flavor. It should be there by default if you want to use it.

@ameir
Copy link
Contributor Author

ameir commented Jan 24, 2015

Thanks for looking into this, @knuckolls . It looks like this is very much related to #859 as well. Upon a terraform plan I'm forced to create a new instance due to "upsizing" my block size count (i.e. the ephemeral storage isn't factored in when polling the running instance). I think a good approach is to only factor in EBS with block_device, and always add the available ephemeral storage to instances. There can be a boolean to not add ephemeral storage in case anyone prefers that.

-/+ aws_instance.chef-server
    ami:                                           "ami-c2a818aa" => "ami-c2a818aa"
    availability_zone:                             "us-east-1a" => "<computed>"
    block_device.#:                                "2" => "4"
    block_device.2875656368.delete_on_termination: "" => "1" (forces new resource)
    block_device.2875656368.device_name:           "" => "/dev/sdc" (forces new resource)
    block_device.2875656368.encrypted:             "" => "<computed>" (forces new resource)
    block_device.2875656368.snapshot_id:           "" => "<computed>" (forces new resource)
    block_device.2875656368.virtual_name:          "" => "ephemeral0" (forces new resource)
    block_device.2875656368.volume_size:           "" => "<computed>" (forces new resource)
    block_device.2875656368.volume_type:           "" => "<computed>" (forces new resource)
    block_device.2936417914.delete_on_termination: "true" => "1" (forces new resource)
    block_device.2936417914.device_name:           "/dev/sda1" => "/dev/sda1" (forces new resource)
    block_device.2936417914.encrypted:             "false" => "<computed>"
    block_device.2936417914.snapshot_id:           "snap-b3032417" => "<computed>"
    block_device.2936417914.virtual_name:          "" => ""
    block_device.2936417914.volume_size:           "20" => "20" (forces new resource)
    block_device.2936417914.volume_type:           "standard" => "standard" (forces new resource)
    block_device.3293284504.delete_on_termination: "false" => "0" (forces new resource)
    block_device.3293284504.device_name:           "/dev/sdb" => "/dev/sdb" (forces new resource)
    block_device.3293284504.encrypted:             "false" => "<computed>"
    block_device.3293284504.snapshot_id:           "" => "<computed>"
    block_device.3293284504.virtual_name:          "" => ""
    block_device.3293284504.volume_size:           "50" => "50" (forces new resource)
    block_device.3293284504.volume_type:           "standard" => "standard" (forces new resource)
    block_device.770933605.delete_on_termination:  "" => "1" (forces new resource)
    block_device.770933605.device_name:            "" => "/dev/sdd" (forces new resource)
    block_device.770933605.encrypted:              "" => "<computed>" (forces new resource)
    block_device.770933605.snapshot_id:            "" => "<computed>" (forces new resource)
    block_device.770933605.virtual_name:           "" => "ephemeral1" (forces new resource)
    block_device.770933605.volume_size:            "" => "<computed>" (forces new resource)
    block_device.770933605.volume_type:            "" => "<computed>" (forces new resource)
    instance_type:                                 "r3.large" => "r3.large"
    key_name:                                      "pcs" => "pcs"
    private_dns:                                   "ip-10-48-44-53.ec2.internal" => "<computed>"
    private_ip:                                    "10.48.44.53" => "<computed>"
    public_dns:                                    "ec2-54-173-194-241.compute-1.amazonaws.com" => "<computed>"
    public_ip:                                     "54.173.194.241" => "<computed>"
    security_groups.#:                             "1" => "1"
    security_groups.2296956296:                    "sg-ea8e518e" => "sg-ea8e518e"
    subnet_id:                                     "subnet-7e57c209" => "subnet-7e57c209"
    tags.#:                                        "2" => "2"
    tags.Name:                                     "chef-server" => "chef-server"
    tags.orbElementId:                             "34386889" => ""
    tags.orbProjectId:                             "28513720" => ""
    tenancy:                                       "default" => "<computed>"

@phinze phinze self-assigned this Jan 28, 2015
phinze added a commit that referenced this issue Feb 18, 2015
AWS provides a single `BlockDeviceMapping` to manage three different
kinds of block devices:

 (a) The root volume
 (b) Ephemeral storage
 (c) Additional EBS volumes

Each of these types has slightly different semantics [1].

(a) The root volume is defined by the AMI; it can only be customized
with `volume_size`, `volume_type`, and `delete_on_termination`.

(b) Ephemeral storage is made available based on instance type [2]. It's
attached automatically if _no_ block device mappings are specified, and
must otherwise be defined with block device mapping entries that contain
only DeviceName set to a device like "/dev/sdX" and VirtualName set to
"ephemeralN".

(c) Additional EBS volumes are controlled by mappings that omit
`virtual_name` and can specify `volume_size`, `volume_type`,
`delete_on_termination`, `snapshot_id`, and `encryption`.

After deciding to ignore root block devices to fix #859, we had users
with configurations that were attempting to manage the root block device chime
in on #913.

Terraform does not have the primitives to be able to properly handle a
single collection of resources that is partially managed and partially
computed, so our strategy here is to break out logical sub-resources for
Terraform and hide the BlockDeviceMapping inside the provider
implementation.

Now (a) is supported by the `root_block_device` sub-resource, and (b)
and (c) are still both merged together under `block_device`, though I
have yet to see ephemeral block devices working properly.

Looking into possibly separating out `ephemeral_block_device` and
`ebs_block_device` sub-resources as well, which seem like the logical
next step. We'll wait until the next big release for this, though, since
it will break backcompat.

[1] http://bit.ly/ec2bdmap
[2] http://bit.ly/instancestorebytype

Fixes #913
Refs #858
phinze added a commit that referenced this issue Feb 25, 2015
Instance block devices are now managed by three distinct sub-resources:

 * `root_block_device` - introduced previously
 * `ebs_block_device` - all additional ebs-backed volumes
 * `ephemeral_block_device` - instance store / ephemeral devices

The AWS API support around BlockDeviceMapping is pretty confusing. It's
a single collection type that supports these three members each of which
has different fields and different behavior.

My biggest hiccup came from the fact that Instance Store volumes do not
show up in any response BlockDeviceMapping for any EC2 Describe* AWS API
calls. They're only available from the instance meta-data service as
queried from inside the node.

Also note this removes `block_device` altogether for a clean break from
old configs.  New configs will need to sort their `block_device`
declarations into the three new types.

Fixes #858
phinze added a commit that referenced this issue Feb 25, 2015
Instance block devices are now managed by three distinct sub-resources:

 * `root_block_device` - introduced previously
 * `ebs_block_device` - all additional ebs-backed volumes
 * `ephemeral_block_device` - instance store / ephemeral devices

The AWS API support around BlockDeviceMapping is pretty confusing. It's
a single collection type that supports these three members each of which
has different fields and different behavior.

My biggest hiccup came from the fact that Instance Store volumes do not
show up in any response BlockDeviceMapping for any EC2 Describe* AWS API
calls. They're only available from the instance meta-data service as
queried from inside the node.

Also note this removes `block_device` altogether for a clean break from
old configs.  New configs will need to sort their `block_device`
declarations into the three new types.

Fixes #858
yahyapo pushed a commit to yahyapo/terraform that referenced this issue Mar 13, 2015
AWS provides a single `BlockDeviceMapping` to manage three different
kinds of block devices:

 (a) The root volume
 (b) Ephemeral storage
 (c) Additional EBS volumes

Each of these types has slightly different semantics [1].

(a) The root volume is defined by the AMI; it can only be customized
with `volume_size`, `volume_type`, and `delete_on_termination`.

(b) Ephemeral storage is made available based on instance type [2]. It's
attached automatically if _no_ block device mappings are specified, and
must otherwise be defined with block device mapping entries that contain
only DeviceName set to a device like "/dev/sdX" and VirtualName set to
"ephemeralN".

(c) Additional EBS volumes are controlled by mappings that omit
`virtual_name` and can specify `volume_size`, `volume_type`,
`delete_on_termination`, `snapshot_id`, and `encryption`.

After deciding to ignore root block devices to fix hashicorp#859, we had users
with configurations that were attempting to manage the root block device chime
in on hashicorp#913.

Terraform does not have the primitives to be able to properly handle a
single collection of resources that is partially managed and partially
computed, so our strategy here is to break out logical sub-resources for
Terraform and hide the BlockDeviceMapping inside the provider
implementation.

Now (a) is supported by the `root_block_device` sub-resource, and (b)
and (c) are still both merged together under `block_device`, though I
have yet to see ephemeral block devices working properly.

Looking into possibly separating out `ephemeral_block_device` and
`ebs_block_device` sub-resources as well, which seem like the logical
next step. We'll wait until the next big release for this, though, since
it will break backcompat.

[1] http://bit.ly/ec2bdmap
[2] http://bit.ly/instancestorebytype

Fixes hashicorp#913
Refs hashicorp#858
phinze added a commit that referenced this issue Mar 13, 2015
Instance block devices are now managed by three distinct sub-resources:

 * `root_block_device` - introduced previously
 * `ebs_block_device` - all additional ebs-backed volumes
 * `ephemeral_block_device` - instance store / ephemeral devices

The AWS API support around BlockDeviceMapping is pretty confusing. It's
a single collection type that supports these three members each of which
has different fields and different behavior.

My biggest hiccup came from the fact that Instance Store volumes do not
show up in any response BlockDeviceMapping for any EC2 Describe* AWS API
calls. They're only available from the instance meta-data service as
queried from inside the node.

Also note this removes `block_device` altogether for a clean break from
old configs.  New configs will need to sort their `block_device`
declarations into the three new types.

Fixes #858
phinze added a commit that referenced this issue Mar 19, 2015
Instance block devices are now managed by three distinct sub-resources:

 * `root_block_device` - introduced previously
 * `ebs_block_device` - all additional ebs-backed volumes
 * `ephemeral_block_device` - instance store / ephemeral devices

The AWS API support around BlockDeviceMapping is pretty confusing. It's
a single collection type that supports these three members each of which
has different fields and different behavior.

My biggest hiccup came from the fact that Instance Store volumes do not
show up in any response BlockDeviceMapping for any EC2 `Describe*` API
calls. They're only available from the instance meta-data service as
queried from inside the node.

This removes `block_device` altogether for a clean break from old
configs. New configs will need to sort their `block_device`
declarations into the three new types. The field has been marked
`Removed` to indicate this to users.

With the new block device format being introduced, we need to ensure
Terraform is able to properly read statefiles written in the old format.
So we use the new `helper/schema` facility of "state migrations" to
transform statefiles in the old format to something that the current
version of the schema can use.

Fixes #858
phinze added a commit that referenced this issue Mar 19, 2015
Instance block devices are now managed by three distinct sub-resources:

 * `root_block_device` - introduced previously
 * `ebs_block_device` - all additional ebs-backed volumes
 * `ephemeral_block_device` - instance store / ephemeral devices

The AWS API support around BlockDeviceMapping is pretty confusing. It's
a single collection type that supports these three members each of which
has different fields and different behavior.

My biggest hiccup came from the fact that Instance Store volumes do not
show up in any response BlockDeviceMapping for any EC2 `Describe*` API
calls. They're only available from the instance meta-data service as
queried from inside the node.

This removes `block_device` altogether for a clean break from old
configs. New configs will need to sort their `block_device`
declarations into the three new types. The field has been marked
`Removed` to indicate this to users.

With the new block device format being introduced, we need to ensure
Terraform is able to properly read statefiles written in the old format.
So we use the new `helper/schema` facility of "state migrations" to
transform statefiles in the old format to something that the current
version of the schema can use.

Fixes #858
@mihasya
Copy link

mihasya commented Jan 6, 2016

Came across this while trying to figure out what I should do in order to have an aws_launch_configuration automatically attach all available ephemeral storage (hi @knuckolls !). I am not specifying any block device mappings in my launch config, but only the root device is available on the instance. Do I need to explicitly specify all of them?

@phinze
Copy link
Contributor

phinze commented Jan 6, 2016

Hi @mihasya - if you don't specify any block device mappings in your Launch Configuration, the Block Device Mappings of your AMI will apply.

This is more of an AWS behavior question, but I believe that since the available ephemeral devices change per instance type, you'd need to specify a "superset" block device mapping mentioning any possible ephemeral devices in order to ensure that they'd all be available.

Probably a good question for your AWS support rep though!

@mihasya
Copy link

mihasya commented Jan 6, 2016

@phinze I'm literally about to type out mappings for ephemeral[0-3] and see if it works on an instance type with only 2 drives :) Would love to not have to do this by hand for every cluster..

@phinze
Copy link
Contributor

phinze commented Jan 6, 2016

@mihasya definitely keep us posted! If it turns out to be boilerplate applicable anywhere it might be worth wrapping up into a community module or something

@mihasya
Copy link

mihasya commented Jan 6, 2016

@phinze yeah if I end up having to do an instance size-to-volume count mapping, I'll publish it for sure.

@mihasya
Copy link

mihasya commented Jan 6, 2016

@phinze prefilling ephemeral[0-7] on the launch config appears to not break even if the instance only has 2 drives. To give a bit more context, and hopefully help posterity: I'm creating a small abstraction layer around making launch configs and autoscaling groups. We're also trying to use a standard bootstrap script, and the goal was for the bootstrap script to automatically format and mount any ephemeral storage available at easy-to-find mountpoints (basically data[1-8]).

Inside the module, I was able to do the following:

resource "aws_launch_configuration" "launch-config" {
  name = "${var.envname}-${var.rolename}-launch"
  image_id = "${var.ami_id}"
  instance_type = "${var.instance_type}"
  ...
  ephemeral_block_device {
    device_name = "xvdd"
    virtual_name = "ephemeral0"
  }
  ephemeral_block_device {
    device_name = "xvde"
    virtual_name = "ephemeral1"
  }
  ephemeral_block_device {
    device_name = "xvdf"
    virtual_name = "ephemeral2"
  }
 ephemeral_block_device {
    device_name = "xvdg"
    virtual_name = "ephemeral3"
  }
  ephemeral_block_device {
    device_name = "xvdh"
    virtual_name = "ephemeral4"
  }
  ephemeral_block_device {
    device_name = "xvdi"
    virtual_name = "ephemeral5"
  }
  ephemeral_block_device {
    device_name = "xvdj"
    virtual_name = "ephemeral6"
  }
  ephemeral_block_device {
    device_name = "xvdk"
    virtual_name = "ephemeral7"
  }
}

which means that on any instance, all ephemeral devices will be available on xvd[d-...], depending on how many are actually available. That means our bootstrap script can just do the following to find all the ephemeral drives available, no matter what instance size was specified when invoking the module:

$ find /dev -name "xvd*" -not -name "xvda*" | sort
/dev/xvdd
/dev/xvde

@MikeWillCook
Copy link

MikeWillCook commented Jun 19, 2016

@mihasya, I had to do the same (define possible ephemeral devices) to get them attached, but it still wants to recreate the instance every time (which sounds exactly like root devices in #859, unless this is possibly an IAM permissions problem). Does a plan keep your instance, or want to destroy/add? Here's the line of interest in the output:
ephemeral_block_device.#: "0" => "6" (forces new resource)

According to the AWS docs it would appear you can only get the ephemeral device mappings via metadata query, so we may need to ignore them to have plan work as needed (unless I'm missing something).

@ghost
Copy link

ghost commented Apr 25, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Apr 25, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants