基于Terraform管理阿里云Elasticsearch最佳实践

重要

本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。

通过Terraform,您可以使用代码配置实现物理机等资源的分配。也就是说通过Terraform,写一个配置文件,就可以帮助您购买一台云服务器,或者申请到阿里云Elasticsearch、OSS等云资源。本文介绍通过Terraform管理阿里云Elasticsearch的方法,包括创建、更新、查看、删除实例等操作。

背景信息

您可以通过以下两种方式安装并配置Terraform环境:

安装并配置Terraform

  1. 前往Terraform官网,下载适用于您的操作系统的程序包。

    本文以Linux系统为例。如果您还没有Linux环境,可购买阿里云ECS实例,详情请参见步骤一:创建ECS实例

  2. 将程序包解压到/usr/local/bin目录。

    如果您需要将可执行文件解压到其他目录,请按照以下方法为其定义全局路径:

  3. 执行terraform命令验证路径配置。

    执行成功后,返回如下结果。运行terraform

  4. 创建RAM用户,并为其授权。

    为提高权限管理的灵活性和安全性,建议您创建RAM用户,并为其授权。

    1. 登录RAM控制台

    2. 创建名为Terraform的RAM用户,并为该用户创建AccessKey。

      具体操作方法请参见创建RAM用户

      重要

      请不要使用阿里云账号的AccessKey配置Terraform工具。

    3. 为RAM用户授权。

      本示例为用户Terraform授予AliyunElasticsearchFullAccessAliyunVPCFullAccess权限,具体操作方法请参见为RAM用户授权

  5. 创建测试目录。

    因为每个Terraform项目都需要创建一个独立的执行目录,所以需要先创建一个测试目录。以下创建一个名为terraform-test的测试目录。

    mkdir terraform-test
  6. 进入terraform-test目录。

    cd terraform-test
  7. 创建配置文件,并配置身份认证信息。

    Terraform在运行时,会读取该目录下所有的*.tf*.tfvars文件。请按照实际需求,将配置信息写入到不同的文件中。以下列出几个常用的配置文件。

    配置文件

    说明

    provider.tf

    provider配置。

    terraform.tfvars

    配置provider要用到的变量。

    varable.tf

    通用变量。

    resource.tf

    资源定义。

    data.tf

    包文件定义。

    output.tf

    输出文件定义。

    例如创建provider.tf文件时,使用vim provider.tf打开文件,并按照以下格式配置您的身份认证信息。

    provider "alicloud" {
        region      = "cn-hangzhou"
        access_key  = "LTA**********NO2"
        secret_key   = "MOk8x0*********************wwff"
        }

    更多配置信息请参见alicloud_elasticsearch_instance

  8. 使用mkdir -p plugh命令,在当前目录下创建plugh目录,下载provider插件并解压到plugh目录下。

  9. 初始化工作目录,使用-plugin-dir指定provider所在的路径,完成配置。

    terraform init -plugin-dir=./plugh/

    返回Terraform has been successfully initialized表示初始化成功。

    重要

    每个Terraform项目在新建Terraform工作目录并创建配置文件后,都需要初始化工作目录。

通过Terraform创建阿里云Elasticsearch实例

  1. 在测试目录下,创建一个elastic.tf配置文件。

  2. 参考以下脚本配置elastic.tf文件,创建一个跨可用区的通用商业版6.7版本的阿里云Elasticsearch实例。

    resource "alicloud_elasticsearch_instance" "instance" {
      description          = "testInstanceName"
      instance_charge_type = "PostPaid"
      data_node_amount     = "2"
      data_node_spec       = "elasticsearch.sn2ne.large"
      data_node_disk_size  = "20"
      data_node_disk_type  = "cloud_ssd"
      vswitch_id           = "vsw-bp1f7r0ma00pf9h2l****"
      password             = "es_password"
      version              = "6.7_with_X-Pack"
      master_node_spec     = "elasticsearch.sn2ne.large"
      zone_count           = "1"
    }

    provider插件支持的所有参数说明如下。

    参数

    是否必选

    描述

    description

    实例自定义名称的描述。

    instance_charge_type

    计费模式。可选值:

    • PostPaid(默认):按量付费

    • PrePaid:包年包月

    period

    购买时长(单位:月),当instance_charge_typePrePaid时有效。可选值:1~9、12、24、36,默认是1个月。

    data_node_amount

    ES集群的数据节点的个数。可选值:2~50。

    data_node_spec

    数据节点实例规格。

    data_node_disk_size

    指定磁盘空间。不同类型的磁盘,支持的最大存储空间大小不同:

    • cloud_ssd:SSD云盘,支持最大存储2048 GB(2 TB)。

    • cloud_efficiency:高效云盘,支持最大5 TB的存储空间,提供较为低廉的存储能力,适合大规模数据量的日志及分析场景。高效云盘超过2048 GB时,只能取:2560、3072、3584、4096、4608、5120。

    data_node_disk_type

    存储类型。可选值:

    • cloud_ssd:SSD云盘。

    • cloud_efficiency:高效云盘。

    vswitch_id

    虚拟交换机的实例ID。

    password

    实例密码,支持大小写字母、数字、特殊字符,长度为8~32位字符。特殊字符包括!@#$%^&*()_+-=

    kms_encrypted_password

    KMS加密密码。如果配置了password,该字段将被忽略。passwordkms_encrypted_password必须配置一个。

    kms_encryption_context

    KMS加密上下文。只有设置了kms_encrypted_password时才有效。用于对使用kms_encrypted_password加密创建或更新的实例进行解密,详情请参见encryption context

    version

    Elasticsearch版本。可选值:

    • 5.5.3_with_X-Pack:5.5.3版本。

    • 6.3_with_X-Pack:6.3.0版本。

    • 6.7_with_X-Pack:6.7.0版本。

    说明

    Terraform不支持云原生架构实例版本。

    private_whitelist

    设置实例的专有网络VPC(Virtual Private Cloud)网络白名单。

    kibana_whitelist

    设置Kibana访问白名单。

    master_node_spec

    Master节点规格。

    advancedDedicateMaster

    用于表示是否创建专有主节点,取值含义如下:

    • true:创建专有主节点。如果部署多可用区并且启用专有主节点,则需要将该参数设置为true。

    • false(默认值):不创建专有主节点。

    zone_count

    可用区数量。取值为1~3,data_node_amount必须是该值的整数倍。

    更多参数详情请参见alicloud_elasticsearch_instance

    重要
    • kms_encrypted_passwordkms_encryption_context参数要求provider插件版本在1.57.1及以上;zone_count参数要求provider插件版本在1.44.0及以上。

    • 如果需要购买除数据节点外的其他属性节点,请参见createInstance参数开启其他节点属性。例如,购买多可用区专有主节点,脚本中需要加入advancedDedicateMaster="true"

  3. 执行terraform plan命令,查看将会执行的操作。

    执行成功后,返回如下结果。

    Refreshing Terraform state in-memory prior to plan...
    The refreshed state will be used to calculate this plan, but will not be
    persisted to local or remote state storage.
    ------------------------------------------------------------------------
    An execution plan has been generated and is shown below.
    Resource actions are indicated with the following symbols:
      + create
    
    Terraform will perform the following actions:
      # alicloud_elasticsearch_instance.instance will be created
      + resource "alicloud_elasticsearch_instance" "instance" {
          + description          = "testInstanceName"
          + data_node_amount     = 2
          + data_node_disk_size  = 20
          + data_node_disk_type  = "cloud_ssd"
          + data_node_spec       = "elasticsearch.sn2ne.large"
          + domain               = (known after apply)
          + id                   = (known after apply)
          + instance_charge_type = "PostPaid"
          + kibana_domain        = (known after apply)
          + kibana_port          = (known after apply)
          + kibana_whitelist     = (known after apply)
          + master_node_spec     = "elasticsearch.sn2ne.large"
          + password             = (sensitive value)
          + port                 = (known after apply)
          + private_whitelist    = (known after apply)
          + public_whitelist     = (known after apply)
          + status               = (known after apply)
          + version              = "6.7_with_X-Pack"
          + vswitch_id           = "vsw-bp1f7r0ma00pf9h2l****"
          + zone_count           = 1
        }
    
    Plan: 1 to add, 0 to change, 0 to destroy.
    ------------------------------------------------------------------------
    Note: You didn't specify an "-out" parameter to save this plan, so Terraform
    can't guarantee that exactly these actions will be performed if
    "terraform apply" is subsequently run.
  4. 执行terraform apply命令,运行工作目录中的配置文件,输入yes

    执行成功后,返回如下结果。

    Plan: 1 to add, 0 to change, 0 to destroy.
    Do you want to perform these actions?
      Terraform will perform the actions described above.
      Only 'yes' will be accepted to approve.
      Enter a value: yes
     alicloud_elasticsearch_instance.instance: Creating...
     alicloud_elasticsearch_instance.instance: Still creating... [10s elapsed]
    alicloud_elasticsearch_instance.instance: Still creating... [20s elapsed]
     ...............
     Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
  5. 登录阿里云Elasticsearch控制台,查看创建成功的Elasticsearch集群。

    创建成功的ES集群

通过Terraform更新Elasticsearch资源配置

  1. 进入测试目录,修改elastic.tf配置文件。

    例如修改data_node_disk_size50

    resource "alicloud_elasticsearch_instance" "instance" {
      instance_charge_type = "PostPaid"
      data_node_amount     = "2"
      data_node_spec       = "elasticsearch.sn2ne.large"
      data_node_disk_size  = "50"
      data_node_disk_type  = "cloud_ssd"
      vswitch_id           = "vsw-bp1f7r0ma00pf9h2l****"
      password             = "es_password"
      version              = "6.7_with_X-Pack"
      master_node_spec     = "elasticsearch.sn2ne.large"
      zone_count           = "1"
    }
    重要
    • 实例创建成功后,version无法修改。

    • 每次请求,只支持修改一项配置。例如同时修改data_node_specdata_node_disk_size,系统将会出现错误响应。

  2. 执行terraform plan查看资源配置信息。

  3. 执行terraform apply等待资源升配结束。

将Elasticsearch资源导入Terraform

如果阿里云Elasticsearch实例不是通过Terraform创建的,可通过命令,将阿里云Elasticsearch导入到Terraform的state目录下进行管理。

  1. 在测试目录下,创建一个main.tf文件。

    vim main.tf
  2. 进行资源声明,指定所要导入的资源在state中的存放路径。

    resource "alicloud_elasticsearch_instance" "test" {}
  3. 开始资源导入操作。

    terraform import alicloud_elasticsearch_instance.test  es-cn-0pp1f1y5g000h****

    执行成功后,返回如下结果。

    alicloud_elasticsearch_instance.test: Importing from ID "es-cn-0pp1f1y5g000h****"...
    alicloud_elasticsearch_instance.test: Import prepared!
      Prepared alicloud_elasticsearch_instance for import
    alicloud_elasticsearch_instance.test: Refreshing state... [id=es-cn-0pp1f1y5g000h****]
    
    Import successful!
    
    The resources that were imported are shown above. These resources are now in
    your Terraform state and will henceforth be managed by Terraform.
    说明

    有关import如何实现存量资源的管理,请参见一文揭秘存量云资源的管理难题

查看Terraform管理的所有Elasticsearch资源

使用terraform show命令,查看当前state中所有被管理的资源及其所有属性值。

# alicloud_elasticsearch_instance.instance:
resource "alicloud_elasticsearch_instance" "instance" {
    data_node_amount     = 2
    data_node_disk_size  = 20
    data_node_disk_type  = "cloud_ssd"
    data_node_spec       = "elasticsearch.sn2ne.large"
    domain               = "es-cn-dssf9op81lz4q****.elasticsearch.aliyuncs.com"
    id                   = "es-cn-dssf9op81lz4q****"
    instance_charge_type = "PostPaid"
    kibana_domain        = "es-cn-dssf9op81lz4q****.kibana.elasticsearch.aliyuncs.com"
    kibana_port          = 5601
    kibana_whitelist     = []
    master_node_spec     = "elasticsearch.sn2ne.large"
    password             = (sensitive value)
    port                 = 9200
    private_whitelist    = []
    public_whitelist     = []
    status               = "active"
    version              = "6.7.0_with_X-Pack"
    vswitch_id           = "vsw-bp1f7r0ma00pf9h2l****"
    zone_count           = 1
}

# alicloud_elasticsearch_instance.test:
resource "alicloud_elasticsearch_instance" "test" {
    data_node_amount     = 3
    data_node_disk_size  = 51
    data_node_disk_type  = "cloud_ssd"
    data_node_spec       = "elasticsearch.r5.large"
    domain               = "es-cn-0pp1f1y5g000h****.elasticsearch.aliyuncs.com"
    id                   = "es-cn-0pp1f1y5g000h****"
    instance_charge_type = "PostPaid"
    kibana_domain        = "es-cn-0pp1f1y5g000h****.kibana.elasticsearch.aliyuncs.com"
    kibana_port          = 5601
    kibana_whitelist     = []
    port                 = 9200
    private_whitelist    = []
    public_whitelist     = []
    status               = "active"
    version              = "6.7.0_with_X-Pack"
    vswitch_id           = "vsw-bp1f7r0ma00pf9h2l****"
    zone_count           = 1

    timeouts {}
}

通过Terraform删除Elasticsearch实例

警告

实例删除后将不可恢复,实例中的所有数据将被清空。

进入测试目录,执行terraform destroy命令,输入yes,即可删除该实例。

# terraform destroy
alicloud_elasticsearch_instance.instance: Refreshing state... [id=es-cn-v3x49h5397fau****]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # alicloud_elasticsearch_instance.instance will be destroyed
  - resource "alicloud_elasticsearch_instance" "instance" {
      - data_node_amount     = 2 -> null
      - data_node_disk_size  = 20 -> null
      - data_node_disk_type  = "cloud_ssd" -> null
      - data_node_spec       = "elasticsearch.sn2ne.large" -> null
      - domain               = "es-cn-v3x49h5397fau****.elasticsearch.aliyuncs.com" -> null
      - id                   = "es-cn-v3x49h5397fau****" -> null
      - instance_charge_type = "PostPaid" -> null
      - kibana_domain        = "es-cn-v3x49h5397fau****.kibana.elasticsearch.aliyuncs.com" -> null
      - kibana_port          = 5601 -> null
      - kibana_whitelist     = [] -> null
      - master_node_spec     = "elasticsearch.sn2ne.large" -> null
      - password             = (sensitive value)
      - port                 = 9200 -> null
      - private_whitelist    = [] -> null
      - public_whitelist     = [] -> null
      - status               = "active" -> null
      - version              = "6.7.0_with_X-Pack" -> null
      - vswitch_id           = "vsw-bp1f7r0ma00pf9h2l****" -> null
      - zone_count           = 1 -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

alicloud_elasticsearch_instance.instance: Destroying... [id=es-cn-v3x49h5397fau****]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 10s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 20s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 30s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 40s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 50s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 1m0s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 1m10s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 1m20s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 1m30s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 1m40s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 1m50s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 2m0s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 2m10s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 2m20s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 2m30s elapsed]
alicloud_elasticsearch_instance.instance: Still destroying... [id=es-cn-v3x49h5397fau****, 2m40s elapsed]
alicloud_elasticsearch_instance.instance: Destruction complete after 10m2s

Destroy complete! Resources: 1 destroyed.