├── .pre-commit-config.yaml ├── README.md ├── example └── main.tf ├── main.tf ├── outputs.tf ├── variables.tf └── versions.tf /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: git://github.com/antonbabenko/pre-commit-terraform 3 | rev: v1.31.0 4 | hooks: 5 | - id: terraform_fmt 6 | - id: terraform_docs 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AWS Elasticsearch Service Terraform Module 2 | ========================================== 3 | 4 | Usage: 5 | 6 | ```hcl 7 | data "aws_region" "current" {} 8 | 9 | data "aws_caller_identity" "current" {} 10 | 11 | module "es-cluster" { 12 | source = "git::https://github.com/egarbi/terraform-aws-es-cluster" 13 | 14 | name = "example" 15 | vpc_id = "vpc-xxxxx" 16 | subnet_ids = [ "subnet-one" ] 17 | zone_id = "ZA863HSKDDD9" 18 | itype = "m4.large.elasticsearch" 19 | ingress_allow_cidr_blocks = [ "10.20.0.0/16", "10.22.0.0/16" ] 20 | access_policies = < 38 | AWS Supports up to 3 AZ's for a multi-az configuration. Understand that if you operate in more than 3 AZ's and you choose to deploy master nodes, only 3 AZ's will be supported and any more than that may result in TF returning AWS API errors.
39 | For more information see [here](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-managedomains-dedicatedmasternodes.html) 40 | 41 | ## Inputs 42 | 43 | | Name | Description | Type | Default | Required | 44 | |------|-------------|:----:|:-----:|:-----:| 45 | | access\_policies | IAM policy document specifying the access policies for the domain. | string | `""` | no | 46 | | create\_iam\_service\_linked\_role | Control the creation of the default service role, set it to false if you have already created it. | bool | true | no | 47 | | dedicated\_master | Indicates whether our cluster have dedicated master nodes enabled. | string | `"false"` | no | 48 | | elasticsearch\_version | Elastic Search Service cluster version number. | string | `"5.5"` | no | 49 | | encryption\_enabled | Enable encription in Elastic Search. | string | `"false"` | no | 50 | | encryption\_kms\_key\_id | Enable encription in Elastic Search. | string | `""` | no | 51 | | icount | Elastic Search Service cluster Ec2 instance number. | string | `"1"` | no | 52 | | indices\_fielddata\_cache\_size | Percentage of Java heap space allocated to field data. | string | `""` | no | 53 | | indices\_query\_bool\_max\_clause\_count | Maximum number of clauses allowed in a Lucene boolean query. | string | `"1024"` | no | 54 | | ingress\_allow\_cidr\_blocks | Specifies the ingress CIDR blocks allowed. | list | `` | no | 55 | | ingress\_allow\_security\_groups | Specifies the ingress security groups allowed. | list | `` | no | 56 | | itype | Elastic Search Service cluster Ec2 instance type. | string | `"m4.large.elasticsearch"` | no | 57 | | mcount | Elastic Search Service cluster dedicated master Ec2 instance number. | string | `"0"` | no | 58 | | mtype | Elastic Search Service cluster dedicated master Ec2 instance type. | string | `""` | no | 59 | | name | Elastic Search Service cluster name. | string | n/a | yes | 60 | | rest\_action\_multi\_allow\_explicit\_index | Specifies whether explicit references to indices are allowed inside the body of HTTP requests. | string | `"true"` | no | 61 | | snapshot\_start | Elastic Search Service maintenance/snapshot start time. | string | `"0"` | no | 62 | | subnet\_ids | List of VPC Subnet IDs for the Elastic Search Service EndPoints will be created. | list | n/a | yes | 63 | | volume\_size | Default size of the EBS volumes. | string | `"35"` | no | 64 | | volume\_type | Default type of the EBS volumes. | string | `"gp2"` | no | 65 | | vpc\_id | Vpc id where the Elastic Search Service cluster will be launched. | string | n/a | yes | 66 | | zone\_awareness | Indicates whether zone awareness is enabled. | string | `"false"` | no | 67 | | zone\_id | Route 53 zone id where the DNS record will be created. | string | `""` | no | 68 | 69 | ## Outputs 70 | | Name | Description | 71 | |------|-------------| 72 | | es\_arn | Amazon Resource Name (ARN) of the domain | 73 | | es\_availability\_zones\_ids | If the domain was created inside a VPC, the names of the availability zones the configured subnet_ids were created inside. | 74 | | es\_domain\_id | Unique identifier for the domain. | 75 | | es\_endpoint | Domain-specific endpoint used to submit index, search, and data upload requests. | 76 | | es\_kibana\_endpoint | Domain-specific endpoint for kibana without https scheme. | 77 | | es\_sg | The SG id created to allow communication with ElasticSearch cluster. | 78 | | es\_vpc\_ids | The VPC ID if the domain was created inside a VPC. | 79 | -------------------------------------------------------------------------------- /example/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "~> 2.0" 6 | } 7 | } 8 | } 9 | # Configure the AWS Provider 10 | provider "aws" { 11 | region = "eu-central-1" 12 | } 13 | 14 | data "aws_vpc" "default" { 15 | default = true 16 | } 17 | 18 | data "aws_subnet_ids" "default" { 19 | vpc_id = data.aws_vpc.default.id 20 | } 21 | 22 | data "aws_subnet" "default" { 23 | count = length(data.aws_subnet_ids.default.ids) 24 | id = tolist(data.aws_subnet_ids.default.ids)[count.index] 25 | } 26 | 27 | data "aws_route53_zone" "selected" { 28 | name = "qndesign.studio" 29 | } 30 | 31 | data "aws_region" "current" {} 32 | 33 | data "aws_caller_identity" "current" {} 34 | 35 | module "es-cluster" { 36 | source = "../" 37 | 38 | name = "example" 39 | vpc_id = data.aws_vpc.default.id 40 | subnet_ids = [data.aws_subnet.default.0.id, data.aws_subnet.default.1.id] 41 | zone_id = data.aws_route53_zone.selected.zone_id 42 | itype = "m4.large.elasticsearch" 43 | icount = 2 44 | zone_awareness = true 45 | ingress_allow_cidr_blocks = [data.aws_vpc.default.cidr_block] 46 | access_policies = < 0 ? 1 : 0 10 | 11 | type = "ingress" 12 | from_port = 443 13 | to_port = 443 14 | protocol = "TCP" 15 | cidr_blocks = var.ingress_allow_cidr_blocks 16 | 17 | security_group_id = aws_security_group.elasticsearch.id 18 | } 19 | 20 | resource "aws_security_group_rule" "secure_sgs" { 21 | count = length(var.ingress_allow_security_groups) 22 | 23 | type = "ingress" 24 | from_port = 443 25 | to_port = 443 26 | protocol = "tcp" 27 | source_security_group_id = element(var.ingress_allow_security_groups, count.index) 28 | 29 | security_group_id = aws_security_group.elasticsearch.id 30 | } 31 | 32 | resource "aws_security_group_rule" "egress_all" { 33 | type = "egress" 34 | from_port = 0 35 | to_port = 0 36 | protocol = "-1" 37 | cidr_blocks = ["0.0.0.0/0"] 38 | 39 | security_group_id = aws_security_group.elasticsearch.id 40 | } 41 | 42 | # https://github.com/terraform-providers/terraform-provider-aws/issues/5218 43 | resource "aws_iam_service_linked_role" "default" { 44 | count = var.create_iam_service_linked_role ? 1 : 0 45 | aws_service_name = "es.amazonaws.com" 46 | description = "AWSServiceRoleForAmazonElasticsearchService Service-Linked Role" 47 | } 48 | 49 | resource "aws_elasticsearch_domain" "es" { 50 | domain_name = var.name 51 | elasticsearch_version = var.elasticsearch_version 52 | 53 | encrypt_at_rest { 54 | enabled = var.encryption_enabled 55 | kms_key_id = var.encryption_kms_key_id 56 | } 57 | 58 | cluster_config { 59 | instance_type = var.itype 60 | instance_count = var.icount 61 | dedicated_master_enabled = var.dedicated_master 62 | dedicated_master_type = var.mtype 63 | dedicated_master_count = var.mcount 64 | zone_awareness_enabled = var.zone_awareness 65 | zone_awareness_config { 66 | availability_zone_count = length(var.subnet_ids) > 2 ? 3 : 2 67 | } 68 | } 69 | 70 | access_policies = var.access_policies 71 | 72 | vpc_options { 73 | security_group_ids = [aws_security_group.elasticsearch.id] 74 | subnet_ids = var.subnet_ids 75 | } 76 | 77 | advanced_options = { 78 | "rest.action.multi.allow_explicit_index" = var.rest_action_multi_allow_explicit_index 79 | "indices.fielddata.cache.size" = var.indices_fielddata_cache_size 80 | "indices.query.bool.max_clause_count" = var.indices_query_bool_max_clause_count 81 | } 82 | 83 | ebs_options { 84 | ebs_enabled = true 85 | volume_type = var.volume_type 86 | volume_size = var.volume_size 87 | } 88 | 89 | snapshot_options { 90 | automated_snapshot_start_hour = var.snapshot_start 91 | } 92 | 93 | tags = { 94 | Domain = var.name 95 | } 96 | 97 | depends_on = [ 98 | aws_iam_service_linked_role.default, 99 | ] 100 | } 101 | 102 | # Add ALB record on DNS 103 | resource "aws_route53_record" "main" { 104 | count = length(var.zone_id) > 0 ? 1 : 0 105 | zone_id = var.zone_id 106 | name = var.name 107 | type = "CNAME" 108 | ttl = "300" 109 | 110 | records = [aws_elasticsearch_domain.es.endpoint] 111 | } 112 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | output "es_arn" { 2 | description = "Amazon Resource Name (ARN) of the domain" 3 | value = aws_elasticsearch_domain.es.arn 4 | } 5 | 6 | output "es_availability_zones_ids" { 7 | description = "If the domain was created inside a VPC, the names of the availability zones the configured subnet_ids were created inside." 8 | value = aws_elasticsearch_domain.es.vpc_options.0.availability_zones 9 | } 10 | 11 | output "es_domain_id" { 12 | description = "Unique identifier for the domain." 13 | value = aws_elasticsearch_domain.es.domain_id 14 | } 15 | 16 | output "es_endpoint" { 17 | description = "Domain-specific endpoint used to submit index, search, and data upload requests." 18 | value = aws_elasticsearch_domain.es.endpoint 19 | } 20 | 21 | output "es_kibana_endpoint" { 22 | description = "Domain-specific endpoint for kibana without https scheme." 23 | value = aws_elasticsearch_domain.es.kibana_endpoint 24 | } 25 | 26 | output "es_sg" { 27 | description = "The SG id created to allow communication with ElasticSearch cluster." 28 | value = aws_security_group.elasticsearch.id 29 | } 30 | 31 | output "es_vpc_ids" { 32 | description = "The VPC ID if the domain was created inside a VPC." 33 | value = aws_elasticsearch_domain.es.vpc_options.0.vpc_id 34 | } 35 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | // Required 2 | variable "name" { 3 | description = "Elastic Search Service cluster name." 4 | type = string 5 | } 6 | 7 | variable "subnet_ids" { 8 | description = "List of VPC Subnet IDs for the Elastic Search Service EndPoints will be created." 9 | type = list(string) 10 | } 11 | 12 | variable "vpc_id" { 13 | description = "Vpc id where the Elastic Search Service cluster will be launched." 14 | type = string 15 | } 16 | 17 | // Optional 18 | variable "create_iam_service_linked_role" { 19 | description = "Control the creation of the default service role, set it to false if you have already created it" 20 | default = true 21 | } 22 | 23 | variable "zone_id" { 24 | default = "" 25 | description = "Route 53 zone id where the DNS record will be created." 26 | type = string 27 | } 28 | 29 | variable "access_policies" { 30 | default = "" 31 | description = "IAM policy document specifying the access policies for the domain." 32 | type = string 33 | } 34 | 35 | variable "dedicated_master" { 36 | default = false 37 | description = "Indicates whether our cluster have dedicated master nodes enabled." 38 | type = string 39 | } 40 | 41 | variable "encryption_enabled" { 42 | default = "false" 43 | description = "Enable encription in Elastic Search." 44 | type = string 45 | } 46 | 47 | variable "encryption_kms_key_id" { 48 | default = "" 49 | description = "Enable encription in Elastic Search." 50 | type = string 51 | } 52 | 53 | variable "elasticsearch_version" { 54 | default = "5.5" 55 | description = "Elastic Search Service cluster version number." 56 | type = string 57 | } 58 | 59 | variable "icount" { 60 | default = 1 61 | description = "Elastic Search Service cluster Ec2 instance number." 62 | type = string 63 | } 64 | 65 | variable "indices_fielddata_cache_size" { 66 | default = "" 67 | description = "Percentage of Java heap space allocated to field data." 68 | type = string 69 | } 70 | 71 | variable "indices_query_bool_max_clause_count" { 72 | default = 1024 73 | description = "Maximum number of clauses allowed in a Lucene boolean query." 74 | type = string 75 | } 76 | 77 | variable "ingress_allow_cidr_blocks" { 78 | default = [] 79 | description = "Specifies the ingress CIDR blocks allowed." 80 | type = list(string) 81 | } 82 | 83 | variable "ingress_allow_security_groups" { 84 | default = [] 85 | description = "Specifies the ingress security groups allowed." 86 | type = list(string) 87 | } 88 | 89 | variable "itype" { 90 | default = "m4.large.elasticsearch" 91 | description = "Elastic Search Service cluster Ec2 instance type." 92 | type = string 93 | } 94 | 95 | variable "mcount" { 96 | default = 0 97 | description = "Elastic Search Service cluster dedicated master Ec2 instance number." 98 | type = string 99 | } 100 | 101 | variable "mtype" { 102 | default = "" 103 | description = "Elastic Search Service cluster dedicated master Ec2 instance type." 104 | type = string 105 | } 106 | 107 | variable "zone_awareness" { 108 | default = false 109 | description = "Indicates whether zone awareness is enabled." 110 | type = string 111 | } 112 | 113 | variable "rest_action_multi_allow_explicit_index" { 114 | default = "true" 115 | description = "Specifies whether explicit references to indices are allowed inside the body of HTTP requests." 116 | type = string 117 | } 118 | 119 | variable "snapshot_start" { 120 | default = 0 121 | description = "Elastic Search Service maintenance/snapshot start time." 122 | type = string 123 | } 124 | 125 | variable "volume_size" { 126 | default = "35" 127 | description = "Default size of the EBS volumes." 128 | type = string 129 | } 130 | 131 | variable "volume_type" { 132 | default = "gp2" 133 | description = "Default type of the EBS volumes." 134 | type = string 135 | } 136 | -------------------------------------------------------------------------------- /versions.tf: -------------------------------------------------------------------------------- 1 | 2 | terraform { 3 | required_version = ">= 0.12" 4 | } --------------------------------------------------------------------------------