Why is the AWS instance’s private IP outside of the subnet’s range

amazon-web-servicescidrprivate-ipsubnetterraform

I'm trying to launch an instance with the private IP address 172.31.32.101 using Terraform in my default VPC (CIDR 172.31.0.0/16), in the eu-west-1a subnet that has the CIDR 172.31.32.0/20. I can usually do this with no problem, but more and more I find that terraform apply fails with the following error:

* Error launching source instance: InvalidParameterValue: Address 172.31.32.101 does not fall within the subnet's address range
status code: 400, request id: []

I suspect that, as this works at least some of the time, it's a problem with either AWS or Terraform, but I'll admit that my knowledge of CIDR blocks (especially the /x at the end) is a bit lacking. However, I checked this subnet calculator and saw that the IP I'm passing to the instance at least should be valid.

Is AWS failing for some other reason, e.g. I'm trying to raise too many instances in too short a period of time, and Terraform is giving me the wrong error? Or is the IP I'm passing actually invalid?

EDIT – Code below:

instances.tf:

resource "aws_instance" "mgmt-jump" {
  ami = "${lookup(var.amis, var.region)}"
  instance_type = "t2.micro"
  key_name = "${var.key_pair}"
  security_groups = ["${aws_security_group.mgmt-jump-sg.name}"]
  count = "${var.mgmt_jump_count}"
  private_ip = "${lookup(var.mgmt_jump_private_ips,count.index)}"
  tags {
    Name = "mgmt-jump-${count.index+1}"
    category = "dec"
    environment = "management"
    role = "jump"
  }
}

variables.tf:

variable "region" {
  default = "eu-west-1"
}

variable "amis" {
  default = {
    # AMIs for Ubuntu 14.04
    eu-west-1 = "ami-47a23a30"
    eu-west-2 = "ami-accff2b1"
  }
}

variable "mgmt_jump_count" {
  default = "1"
}

variable "mgmt_jump_private_ips" {
  default = {
    "0" = "172.31.32.101"
    "1" = "172.31.32.102"
  }
}

EDIT 2: I ran the following command to bring up the instance with the AWS CLI, which would've successful if not for the dry run flag, so I believe that this may be a problem with Terraform.

➜  ~  aws ec2 run-instances --image-id ami-47a23a30 --private-ip-address 172.31.32.101 --instance-type t2.micro --dry-run

A client error (DryRunOperation) occurred when calling the RunInstances operation: Request would have succeeded, but DryRun flag is set.

Either way I'm not using the default VPC now, even though I'm using the same CIDR blocks as described above, and I've found that I don't encounter the problem anymore. Having said that, I'm now raising my jump host with the IP address 172.31.0.6 instead of 172.31.32.101 so that may be why I'm not encountering the problem.

Best Answer

The aws_instance resource in the example does not have the subnet_id attribute provided, so the instance would launch into your account's default subnet for the target region. It's likely that the default subnet is not the one you were trying to use, and so it has a different IP address range.

To fix this, determine the appropriate subnet id and add a subnet_id attribute to your declaration, and then also switch from the security_groups attribute to the vpc_security_group_ids attribute:

resource "aws_instance" "mgmt-jump" {
  count = "${var.mgmt_jump_count}"

  ami           = "${lookup(var.amis, var.region)}"
  instance_type = "t2.micro"

  key_name      = "${var.key_pair}"
  subnet_id     = "subnet-xxxxxxx"

  vpc_security_group_ids = ["${aws_security_group.mgmt-jump-sg.id}"]

  private_ip = "${lookup(var.mgmt_jump_private_ips,count.index)}"

  tags {
    Name        = "mgmt-jump-${count.index+1}"
    category    = "dec"
    environment = "management"
    role        = "jump"
  }
}