12

I'm trying to build an ElasticSearch cluster using Terraform but i'm not able to assign more that 1 subnet! That's really weird cause in the documentation there is this :

https://www.terraform.io/docs/providers/aws/r/elasticsearch_domain.html#subnet_ids

subnet_ids - (Required) List of VPC Subnet IDs for the Elasticsearch domain endpoints to be created in.

But when i try to do that i'm getting this error :

Error: ValidationException: You must specify exactly one subnet

This is my code :

resource "aws_elasticsearch_domain" "es" {
  domain_name           = "${var.es_domain}-${var.environment}"
  elasticsearch_version = "${var.es_version}"

  cluster_config {
    instance_type  = "${var.es_instance_type}"
    instance_count = "${var.es_instance_count}"
  }
  vpc_options {

    subnet_ids = ["${data.aws_subnet.private_1.id}", "${data.aws_subnet.private_2.id}"]

    security_group_ids = ["${aws_security_group.es.id}"]
  }

  snapshot_options { automated_snapshot_start_hour = "${var.es_automated_spanshot_start_hour}" }

  ebs_options {
    ebs_enabled = true
    volume_type = "standard"
    volume_size = "20"
  }


  access_policies = <<CONFIG
    {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": "es:*",
        "Principal": "*",
        "Effect": "Allow",
        "Resource": "arn:aws:es:${var.aws_region}:${data.aws_caller_identity.current.account_id}:domain/${var.es_domain}/*"
      }
    ]
}
CONFIG


}

I'm using terraform v0.12.2

Thanks for your help.

user1297406
  • 1,241
  • 1
  • 18
  • 36
  • Can you share your full `aws_elasticsearch_domain` resource code? I'm assuming you're missing `zone_awareness_enabled` but it's hard to see with your existing example. In general you should try to provide a [mcve] that allows people to actually reproduce your issue. – ydaetskcoR Jun 14 '19 at 09:38
  • ok i edited the post and included all the code – user1297406 Jun 14 '19 at 10:03

2 Answers2

15

You're missing zone_awareness_enabled parameter in the cluster_config which is required when using multi AZ Elasticsearch clusters.

ydaetskcoR
  • 53,225
  • 8
  • 158
  • 177
  • Thanks you i added it and now it works. But i had to add also dedicated_master_count because its required then. – user1297406 Jun 14 '19 at 11:12
  • 2
    So there is a problem with the example in the official website of terraform https://www.terraform.io/docs/providers/aws/r/elasticsearch_domain.html#vpc-based-es – user1297406 Jun 14 '19 at 11:13
  • It uses 2 subnets but they didn't provide the zone_awareness_enable paramater – user1297406 Jun 14 '19 at 11:14
  • 1
    `dedicated_master_count` isn't a required field unless you're also specifying other fields about dedicated masters. It's quite possible to have an ES cluster without dedicated masters (and in fact I run a few). – ydaetskcoR Jun 14 '19 at 11:31
  • I submitted a PR to the official website of terraform to update the example to include the `zone_awareness_enabled` parameter. You can give it a thumbs up to increase its priority: https://github.com/hashicorp/terraform-provider-aws/pull/20627 – Yann Stoneman Aug 19 '21 at 20:25
2

Thanks @ydaetskcoR for pointing out the way.

I'll share the struggles I had with the configuration of availability_zone_count and subnet_ids - hopefully it can save some time for others.

Some context to the problem:

A) I tried to create a Multi zone ES cluster.

B) I had 4 subnets for the data tier (contains other types of DBs as well) and wanted the cluster to be splitted between the available AZs in the current region (3 AZs) - so one of the AZs will have 2 subnets and 2 ES Instances.

Be aware that:

1: The availability_zone_count field under the zone_awareness_config block should have the exact amount like the available AZs.

2: The subnet_ids field under the vpc_options block should contain the same number of AZs you specified under availability_zone_count.

So, in one sentence: availability_zone_count == (available AZs) == length( subnet_ids)

Below is a code snippet with the relevant parts (follow also the comments - it might also save you some time):

resource "aws_elasticsearch_domain" "staging" {
    domain_name  = ...
    vpc_options{
       subnet_ids = "${local.subnet_ids}"  # Instead of: [for s in aws_subnet.data_tier : s.id] which will lead to: Error creating ElasticSearch domain: ValidationException: You must specify exactly three subnets because you’ve set zone count to three.

    }
    cluster_config {
       zone_awareness_enabled = true #If you ignore it you'll get: Error creating ElasticSearch domain: ValidationException: You must specify exactly one subnet
       #Notice that there is no "=" Below - or you'll visit this thread: https://github.com/terraform-providers/terraform-provider-aws/issues/12365
       zone_awareness_config {
         availability_zone_count = "${length(var.region_azs)}"
       }
    }
    .
    . 
}

#Take only X number of subnets where X is the number of available AZs)
locals {
  subnet_ids = "${slice(aws_subnet.data_tier.*.id, 0, length(var.region_azs))}"
}  


# Added this also due to: Error creating ElasticSearch domain: ValidationException: Before you can proceed, you must enable a service-linked role to give Amazon ES permissions to access your VPC.
# Solved with: https://stackoverflow.com/questions/47229247/validationexception-before-you-can-proceed-you-must-enable-a-service-linked-ro (Terraform related Answer)
resource "aws_iam_service_linked_role" "es" {
  aws_service_name = "es.amazonaws.com"
  description      = "Allows Amazon ES to manage AWS resources for a domain on your behalf."
}
Rot-man
  • 18,045
  • 12
  • 118
  • 124