背景
基础设施代码(IAC)允许你通过配置文件而不是通过图形界面来管理基础设施。Terraform使用可读性的声明性配置文件中定义资源和基础设施。Terraform将资源元数据存储在一个状态state文件中,可以使用该状态文件更新和删除这些资源,并保证资源部署一致性(幂等性)。Terraform是一个与云无关的工具,它可以跨多个云提供商共同使用。
需求
公司的数据分析SaaS服务部署在多个region,服务不同地域客户, 因此需要有多region环境基础设施的支持。此外,DevOps团队也确保基于开发/QA/生产等环境实现应用程序分离。
因此,本文我们将讨论如何使用terrform管理多个环境。
方案
当Terraform部署资源时,它将元数据存储在状态文件中以跟踪资源。因此,如果我们希望为多个环境(如DEV/QA/PROD)部署资源,我们还需要区分部署操作和状态文件。然而,通过terrform工作区Workspace和Reusable Modules (可重用模块)体系结构,我们可以实现单独的环境供应。
- Terraform Workspace——Terraform Workspace允许我们从单个配置文件源为所提供的后端中每个工作区管理单独的状态文件
- Reusable Modules ——在这种体系结构中,配置文件存储在单个目录中。通过共有模块,我们可以查找到对应目录并传递变量。
案例
公司使用Terraform在多个环境(INT,Staging, Prod)上部署Elastic Cloud,用作系统及客户日志存储分析等 。结合 Terraform Workspace 我们可以实现在不同环境中使用同个Terraform Module 来动态部署资源。例如,在INT环境中部署的 ES 节点使用更小的内存,分布在较少的Zone(以节省开支), 而在Prod环境中需要启用更多的节点,来提高ES性能以及大量数据存储。
具体实现
整体目录结构
-- terraform
| |-- envs
| | |-- us-production
| |-- staging
| |-- qa
| |-- dev
| |-- modules
| | |-- ec_deployment
| |-- ec_backup
| |-- ec_index_magement
首先,来看下 Reusable Modules (可重用模块), 放置在terraform/modules目录下
ec_deployment module 实现了整个ElastcCloud 部署代码
`-- modules
|-- ec_deployment
| |-- README.md
| |-- data.tf
| |-- locals.tf
| |-- main.tf
| |-- outputs.tf
| |-- provider.tf
| |-- variables.tf
其中main.tf 为主代码实现elasticsearch主体结构,语法具体参考官网
resource "ec_deployment" "main" {
name = var.deployment_name
region = var.deployment_region
version = var.deployment_stack_version
deployment_template_id = var.deployment_template_id
alias = var.deployment_alias != "" ? var.deployment_alias : ""
tags = var.tags
elasticsearch {
autoscale = "false"
config {
plugins = var.elasticsearch_plugins
}
topology {
id = "hot_content"
zone_count = var.elasticsearch_hot_zones
size = var.elasticsearch_hot_size
size_resource = "memory"
}
}
kibana {
topology {
zone_count = var.kibana_zones
size = var.kibana_size
size_resource = "memory"
}
}
variables.tf 放置main.tf所引用的变量
variable "deployment_name" {
type = string
description = "Identify deployment within ElasticCloud managed service"
}
variable "deployment_region" {
type = string
description = "Select one of the available regions, https://www.elastic.co/guide/en/cloud/current/ec-reference-regions.html"
}
接着,在envs 目录中 定制各个ElasticCloud Terraform Code具体变量值
| |-- envs
| | |-- us-production
| | | |-- ec_deployment
| | | | |-- locals.tf
| | | | |-- main.tf
| | | | |-- outputs.tf
| | | | `-- provider.tf
| | |-- staging
| | | |-- ec_deployment
| | | | |-- locals.tf
| | | | |-- main.tf
| | | | |-- outputs.tf
| | | | `-- provider.tf
| | |-- int
| | | |-- ec_deployment
| | | | |-- locals.tf
| | | | |-- main.tf
| | | | |-- outputs.tf
| | | | `-- provider.tf
如INT下 main.tf
module "ec_deployment" {
source = "../../../../modules/ec_deployment/"
deployment_name = "aws-integration-infra"
deployment_region = "us-east-1"
deployment_stack_version = "8.4.1"
deployment_template_id = "aws-storage-optimized-v3"
elasticsearch_hot_size = "15g"
elasticsearch_hot_zones = 2
elasticsearch_warm_size = "4g"
elasticsearch_warm_zones = 0
PROD下 main.tf
module "ec_deployment" {
source = "../../../../modules/ec_deployment/"
deployment_name = "aws-production-us-infra"
deployment_region = "us-east-1"
deployment_stack_version = "8.4.1"
deployment_template_id = "aws-storage-optimized-v3"
elasticsearch_hot_size = "15g"
elasticsearch_hot_zones = 4
elasticsearch_warm_size = "4g"
elasticsearch_warm_zones = 2
可以看到 INT和PROD的main.tf 中 使用source
引用同个ec_deployment
模块,并配置相应的环境变量参数
最后,重要的事,我们将不同Terraform Workspace的定义放在各自env下 provider.tf 中
如INT下provider.tf
terraform {
required_version = "~> 1.3.2"
required_providers {
ec = {
source = "elastic/ec"
version = "~> 0.4.0"
}
aws = {
source = "hashicorp/aws"
version = "~> 4.5"
}
}
cloud {
organization = "terraform-cloud"
workspaces {
name = "infra-elasticsearch--ec_deployment--aws--integration--infra"
}
}
}
这样,该目录下只为该工作区完成ElasticCloud的部署
例如,我们在envs/integration/ec_deployment/目录下 执行terraform plan
Terraform Plan 之后, 该目录下会生产terraform.tfstate 文件,用以保存当前工作区下已部署的资源状态
最终效果
Terraform Apply 之后可以看到不同环境下 Elastic Cloud集群的差异
INT环境下的 ES hot 节点状态:
Prod 环境下的 ES hot 节点状态:
结论
我们看到了Workspace和reusable modules(可重用模块)如何帮助我们使用独立的状态文件管理独立的基础设施。Reusable modules可重用模块在env下各自的目录架构中运行,包含各个模块bolck、变量、提供程序和后端配置等。其中工作区工作在单个配置文件源上,并在后端创建工作区特定的状态文件。
参考链接:
https://techifysolutions.com/managing-multiple-environments-with-terraform/
https://registry.terraform.io/providers/elastic/ec/latest/docs/resources/ec_deployment