模块

时间:2017-06-28 17:18:48

标签: terraform

我已经开始使用Terraform并完全收购了它 - 太棒了!我已经根据AWS VPC,子网,NACL,SG,路由表等创建了我的整个Dev环境,我已经决定最好把它变成可重用的模块。

所以现在我把它变成了模块,变量等等。现在我的开发模板只需要变量并将它们用作模块的输入。我最终得到了这个:

terraform {
  backend "s3" {
    bucket = "redacted"
    key    = "dev/vpc/terraform.tfstate"
    region = "eu-west-1"
    encrypt = true
    dynamodb_table = "terraform_statelock_redacted"
  }
}

provider "aws"{
  access_key = ""
  secret_key = ""
  region     = "eu-west-1"
}

module "base_vpc" {
  source = "git@github.com:closed/terraform-modules.git//vpc"


  vpc_cidr = "${var.vpc_cidr}"
  vpc_region = "${var.vpc_region}"
  Environment = "${var.Environment}"
  Public-subnet-1a = "${var.Public-subnet-1a}"
  Public-subnet-1b = "${var.Public-subnet-1b}"
  Private-subnet-1a = "${var.Private-subnet-1a}"
  Private-subnet-1b = "${var.Private-subnet-1b}"
  Private-db-subnet-1a = "${var.Private-db-subnet-1a}"
  Private-db-subnet-1b = "${var.Private-db-subnet-1b}"
  Onsite-computers = "${var.Onsite-computers}"
  browse_access = "${var.browse_access}"
}

现在我已经在s3后端管理了所有状态,正如您在上面的配置中看到的那样。我还有正在运行的服务/实例的其他状态文件。我的问题是,现在我把它变成了一个模块,如上所述引用它,它想要吹走我的状态!我的印象是它会导入模块并运行它,同时尊重其他配置。实际的模块代码是从原始模板复制的,所以没有任何改变。

是否有理由将所有东西吹走并重新开始?在使用模块的情况下,如何管理每个环境的单独状态?我没有其他错误。我现在有些开发人员正在研究一些服务器,所以我现在瘫痪了哈哈!

我想我误解了一些东西,任何帮助都非常感激:) 谢谢。 编辑 - 使用Terraform 0.9.8

2 个答案:

答案 0 :(得分:1)

好的,所以我认为我误解的是使用模块改变状态文件中路径的方式。我意识到我在阅读关于州迁移的Terraform文档时处于正确的位置。

我找到了这篇很棒的博客文章来帮助我解决这个问题: https://ryaneschinger.com/blog/terraform-state-move/

没有评论部分让我感谢那家伙!无论如何,在看到它有多简单之后,我只需将terraform state list命令输出到主文件的文本文件中。使用PowerShell快速迭代这些并编写我正在移动它们的模块的命令。当我尝试用这个脚本执行这些行时,我得到了“Terraform已经崩溃!!!!”错误,所以只需将它们一个一个地剪切并粘贴到我的shell中。适当的nooby,但只有50左右的资源,所以不是那么耗费时间。我很高兴我在开发阶段这样做,而不是决定在生产中回顾性地做这件事。

所以我排序了。感谢您通过JBirdVegas提供的输入。

答案 1 :(得分:0)

我们遇到了这个问题,并决定每个环境都需要一个代码表示,我们可以在需要时同时查看其他代码,即将开发配置与qa进行比较。

所以现在我们有一个dev文件夹和一个qa文件夹,我们从那里启动terraform。每个基本上都是为每个组件调用模块的变量列表。

这是我的可视化表示树

$ tree terraform/
terraform/
├── api_gateway
│   ├── main.tf
│   ├── output.tf
│   └── variables.tf
├── database
│   ├── main.tf
│   ├── output.tf
│   └── variables.tf
├── dev
│   └── main.tf
├── ec2
│   ├── main.tf
│   ├── output.tf
│   └── variables.tf
├── kms
│   ├── main.tf
│   ├── output.tf
│   └── variables.tf
├── network
│   ├── main.tf
│   ├── output.tf
│   └── variables.tf
├── qa
│   └── main.tf
└── sns
    ├── output.tf
    ├── main.tf
    └── variables.tf

dev/main.tfqa/main.tf导入其他文件夹提供的模块,为每个模块提供特定于环境的配置。

编辑:这是我的dev/main.tf

的清理版本
provider "aws" {
  region = "us-east-1"
  profile = "blah-dev"
  shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
}

terraform {
  backend "s3" {
    bucket = "sweet-dev-bucket"
    key = "sweet/dev.terraform.tfstate"
    region = "us-east-1"
    profile = "blah-dev"
  }
}

variable "aws_account" {
  default = "000000000000"
}
variable "env" {
  default = "dev"
}
variable "aws_region" {
  default = "us-east-1"
}
variable "tag_product" {
  default = "sweet"
}
variable "tag_business_region" {
  default = "east"
}
variable "tag_business_unit" {
  default = "my-department"
}
variable "tag_client" {
  default = "some-client"
}

module build_env {
  source = "../datasources"
}

module "kms" {
  source = "../kms"
  tag_client = "${var.tag_client}"
  tag_business_region = "${var.tag_business_region}"
  tag_business_unit = "${var.tag_business_unit}"
  tag_product = "${var.tag_product}"
}

module "network" {
  source = "../network"
  vpc_id = "vpc-000a0000"
  subnet_external_1B = "subnet-000a0000"
  subnet_external_1D = "subnet-000a0001"
  subnet_db_1A = "subnet-000a0002"
  subnet_db_1B = "subnet-000a0003"
}

module "database" {
  source = "../database"
  env = "dev"
  vpc_id = "${module.network.vpc_id}"
  subnet_external_1B = "${module.network.subnet_external_1B}"
  subnet_external_1D = "${module.network.subnet_external_1D}"
  subnet_db_1A = "${module.network.subnet_db_1A}"
  subnet_db_1B = "${module.network.subnet_db_1B}"
  database_instance_size = "db.t2.small"
  database_name = "my-${var.tag_product}-db"
  database_user_name = "${var.tag_product}"
  database_passwd = "${module.kms.passwd_plaintext}"
  database_identifier = "${var.tag_product}-rds-database"
  database_max_connections = "150"
}

module sns {
  source = "../sns"
  aws_account = "${var.aws_account}"
}

module "api_gateway" {
  source = "../api_gateway"
  env = "${var.env}"
  vpc_id = "${module.network.vpc_id}"
  domain_name = "${var.tag_product}-dev.example.com"
  dev_certificate_arn = "arn:aws:acm:${var.aws_region}:${var.aws_account}:certificate/abcd0000-a000-a000-a000-1234567890ab"
  aws_account = "${var.aws_account}"
  aws_region = "${var.aws_region}"
  tag_client = "${var.tag_client}"
  tag_business_unit = "${var.tag_business_unit}"
  tag_product = "${var.tag_product}"
  tag_business_region = "${var.tag_business_region}"
  autoscaling_events_sns_topic_arn = "${module.sns.sns_topic_arn}"
  db_subnet_id_1 = "${module.network.subnet_db_1A}"
  db_subnet_id_2 = "${module.network.subnet_db_1B}"
  ec2_role = "${var.tag_product}-assume-iam-role"
  kms_key_arn = "${module.kms.kms_arn}"
  passwd_cypher_text = "${module.kms.passwd_cyphertext}"
}

module "ec2" {
  source = "../ec2"
  s3_bucket = "${var.tag_product}_dev_bucket"
  aws_region = "${var.aws_region}"
  env = "${var.env}"
  ec2_key_name = "my-${var.tag_product}-key"
  ec2_instance_type = "t2.micro"
  aws_account = "${var.aws_account}"
  vpc_id = "${module.network.vpc_id}"
  binary_path = "${module.build_env.binary_path}"
  binary_hash = "${module.build_env.binary_hash}"
  git_hash_short = "${module.build_env.git_hash_short}"
  private_key = "${format("%s/keys/%s-%s.pem", path.root, var.tag_product, var.env)}"
  cloudfront_domain = "${module.api_gateway.cloudfront_domain}"
  api_gateway_domain = "${module.api_gateway.api_gateway_cname}"
  tag_client = "${var.tag_client}"
  tag_business_region = "${var.tag_business_region}"
  tag_product = "${var.tag_product}"
  tag_business_unit = "${var.tag_business_unit}"
  auto_scale_desired_capacity = "1"
  auto_scale_max = "2"
  auto_scale_min = "1"
  autoscaling_events_sns_topic = "${module.sns.sns_topic_arn}"
  subnet_external_b = "${module.network.subnet_external_b}"
  subnet_external_a = "${module.network.subnet_external_a}"
  kms_key_arn = "${module.kms.kms_arn}"
  passwd_cypher_text = "${module.kms.passwd_cyphertext}"
}

然后我的QA基本相同(修改顶部的几个变量)然而最重要的区别是qa/main.tf最顶层的这些变量:

provider "aws" {
  region = "us-east-1"
  profile = "blah-qa"
  shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
}

terraform {
  backend "s3" {
    bucket = "sweet-qa-bucket"
    key = "sweet/qa.terraform.tfstate"
    region = "us-east-1"
    profile = "blah-qa"
  }
}

variable "aws_account" {
  default = "000000000001"
}
variable "env" {
  default = "qa"
}

使用此devqa的后端在不同的aws帐户中的不同存储桶中具有不同的状态文件。 Idk您的要求是什么,但这已经满足了我与之合作过的大多数项目,实际上我们正在扩展我的组织在该组织中的使用。