2017-06-28 44 views
0

我已经开始使用Terraform,并且已经完全购买了它 - 令人惊叹!根据AWS VPC,子网,NACL,SG,路由表等等创建了我的整个开发环境,我决定最好把它变成可重用的模块。Terraform s3后端未被模块使用

所以现在我已经把它变成模块,变量等。现在我的开发模板只需要变量,并将它们用作模块的输入。我结束了这一点:

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 = "[email protected]: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

回答

0

我们就遇到了这个问题,并决定每个环境需要一个代码表示,我们可以在同一时间,如果需要其他人,即开发CONFIGS比较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你的要求是什么,但是这已经满足了我合作过的大多数项目,事实上,我们正在扩大我的组织使用这个模型。

+0

嘿,谢谢你的回复。所以我试图遵循一个非常类似的模型,其中/ dev,/ test和/ prod文件夹基本上只是调用一堆模块。我坚持的一点是,我在这些文件夹中持有s3后端配置,似乎使用模块意味着他们将现有状态视为不再需要,即标记为销毁,然后重新配置所有内容。你有没有可能分享dev.tf的编辑版本以显示你如何管理后端? –

+0

@TomNorth使用我的'dev/main.tf'进行了更新,主要区别在于显示'qa/main.tf'的变化。这可以让你的状态文件完全隔离,避免在创建qa时撕毁开发 – JBirdVegas

1

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

我发现这个伟大的博客条目帮助我让我的头周围: https://ryaneschinger.com/blog/terraform-state-move/

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

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