Jed*_*der 36 amazon-s3 terraform
我刚刚开始使用terraform,我希望能够使用AWS S3作为我的后端来存储我的项目状态.
terraform {
backend "s3" {
bucket = "tfstate"
key = "app-state"
region = "us-east-1"
}
}
Run Code Online (Sandbox Code Playgroud)
我觉得使用terraform为后端存储基础架构设置我的S3存储桶,IAM组和策略是明智的.
如果我在应用初始terraform基础设施之前设置后端状态,则会合理地抱怨后端存储桶尚未创建.所以,我的问题是,如何设置我的terraform后端与terraform,同时保持我的状态为terraform追踪的后端.看起来像一个嵌套的玩偶问题.
我对如何编写脚本有一些想法,例如,检查存储桶是否存在或是否已设置某个状态,然后引导terraform,最后在第一次运行后将terraform tfstate从本地文件系统复制到s3.但在走下这条艰难的道路之前,我想我会确保自己没有遗漏一些明显的东西.
Aus*_*vis 40
要使用terraform远程状态进行设置,我通常remote-state在dev和prod terraform文件夹中有一个单独的文件夹.
以下main.tf文件将为您发布的内容设置远程状态:
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "terraform_state" {
bucket = "tfstate"
versioning {
enabled = true
}
lifecycle {
prevent_destroy = true
}
}
resource "aws_dynamodb_table" "terraform_state_lock" {
name = "app-state"
read_capacity = 1
write_capacity = 1
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
Run Code Online (Sandbox Code Playgroud)
然后使用cd remote-state,运行进入此文件夹terraform init && terraform apply- 这应该只需要运行一次.您可以添加一些内容到bucket和dynamodb表名来分隔您的不同环境.
Mat*_*vin 13
在奥斯汀戴维斯的巨大贡献的基础上,我使用的变体包括数据加密的要求:
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "terraform_state" {
bucket = "tfstate"
versioning {
enabled = true
}
lifecycle {
prevent_destroy = true
}
}
resource "aws_dynamodb_table" "terraform_state_lock" {
name = "app-state"
read_capacity = 1
write_capacity = 1
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
resource "aws_s3_bucket_policy" "terraform_state" {
bucket = "${aws_s3_bucket.terraform_state.id}"
policy =<<EOF
{
"Version": "2012-10-17",
"Id": "RequireEncryption",
"Statement": [
{
"Sid": "RequireEncryptedTransport",
"Effect": "Deny",
"Action": ["s3:*"],
"Resource": ["arn:aws:s3:::${aws_s3_bucket.terraform_state.bucket}/*"],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
},
"Principal": "*"
},
{
"Sid": "RequireEncryptedStorage",
"Effect": "Deny",
"Action": ["s3:PutObject"],
"Resource": ["arn:aws:s3:::${aws_s3_bucket.terraform_state.bucket}/*"],
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "AES256"
}
},
"Principal": "*"
}
]
}
EOF
}
Run Code Online (Sandbox Code Playgroud)
sam*_*tav 11
我创建了一个带有一些引导命令/说明的 terraform 模块来解决这个问题:
https://github.com/samstav/terraform-aws-backend
README 中有详细说明,但要点是:
# conf.tf
module "backend" {
source = "github.com/samstav/terraform-aws-backend"
backend_bucket = "terraform-state-bucket"
}
Run Code Online (Sandbox Code Playgroud)
然后,在你的 shell 中(确保你还没有写你的terraform {}块):
terraform get -update
terraform init -backend=false
terraform plan -out=backend.plan -target=module.backend
terraform apply backend.plan
Run Code Online (Sandbox Code Playgroud)
现在写你的terraform {}块:
# conf.tf
terraform {
backend "s3" {
bucket = "terraform-state-bucket"
key = "states/terraform.tfstate"
dynamodb_table = "terraform-lock"
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以重新初始化:
terraform init -reconfigure
Run Code Online (Sandbox Code Playgroud)
正如您所发现的那样,您不能首先使用terraform来构建组件所需的组件.
虽然我理解让terraform"追踪一切"的倾向,但这是非常困难的,而且比它的价值更令人头痛.
我通常通过创建一个简单的bootstrap shell脚本来处理这种情况.它创造了以下内容:
虽然你应该只需要运行一次(技术上),但我发现当我开发一个新系统时,我会反复旋转并撕下来.因此,在一个脚本中使用这些步骤可以使这更简单.
我通常将脚本构建为幂等的.这样,您可以多次运行它,而无需担心您正在创建重复的存储桶,用户等
利用 AWS s3 存储桶设置 Terraform 后端相对容易。
\n\n首先,在您选择的区域(例如 eu-west-1)创建一个存储桶,命名为terraform-backend-store(记住选择一个唯一的名称。)
\n\n为此,请打开终端并运行以下命令,假设您已正确设置 AWS CLI(否则,请按照官方文档中的说明进行操作):
\n\naws s3api create-bucket --bucket terraform-backend-store \\\n --region eu-west-1 \\\n --create-bucket-configuration \\\n LocationConstraint=eu-west-1\n# Output:\n{\n "Location": "http://terraform-backend-store.s3.amazonaws.com/"\n}\nRun Code Online (Sandbox Code Playgroud)\n\n该命令应该是不言自明的;要了解更多信息,请查看此处的文档。
\n\n存储桶就位后,需要进行适当的配置以确保安全性和可靠性。\n对于保存 Terraform 状态的存储桶,\xe2\x80\x99 是启用服务器端加密的常识。为了简单起见,首先尝试AES256方法(尽管我建议使用KMS并实现适当的密钥轮换):
\n\naws s3api put-bucket-encryption \\\n --bucket terraform-backend-store \\\n --server-side-encryption-configuration={\\"Rules\\":[{\\"ApplyServerSideEncryptionByDefault\\":{\\"SSEAlgorithm\\":\\"AES256\\"}}]}\n# Output: expect none when the command is executed successfully\nRun Code Online (Sandbox Code Playgroud)\n\n接下来,\xe2\x80\x99 是限制对存储桶的访问的关键;创建一个非特权 IAM 用户,如下所示:
\n\naws iam create-user --user-name terraform-deployer\n# Output:\n{\n "User": {\n "UserName": "terraform-deployer",\n "Path": "/",\n "CreateDate": "2019-01-27T03:20:41.270Z",\n "UserId": "AIDAIOSFODNN7EXAMPLE",\n "Arn": "arn:aws:iam::123456789012:user/terraform-deployer"\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n记下命令\xe2\x80\x99s 输出中的 Arn(如下所示:\xe2\x80\x9cArn\xe2\x80\x9d:\xe2\x80\x9carn:aws:iam::123456789012:user/terraform -部署\xe2\x80\x9d)。
\n\n为了在稍后阶段与 s3 服务和 DynamoDB 正确交互以实现锁定,我们的 IAM 用户必须拥有足够的权限集。\n建议对生产环境实施严格的限制,但为了简单起见,请开始分配AmazonS3FullAccess和AmazonDynamoDBFullAccess:
\n\naws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess --user-name terraform-deployer\n# Output: expect none when the command execution is successful\n\naws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess --user-name terraform-deployer\n# Output: expect none when the command execution is successful\nRun Code Online (Sandbox Code Playgroud)\n\n必须启用新创建的 IAM 用户才能对您的 s3 存储桶执行所需的操作。您可以通过创建并应用正确的策略来做到这一点,如下所示:
\n\ncat <<-EOF >> policy.json\n{\n "Statement": [\n {\n "Effect": "Allow",\n "Principal": {\n "AWS": "arn:aws:iam::123456789012:user/terraform-deployer"\n },\n "Action": "s3:*",\n "Resource": "arn:aws:s3:::terraform-remote-store"\n }\n ]\n}\nEOF\nRun Code Online (Sandbox Code Playgroud)\n\n此基本策略文件向委托人授予 arn \xe2\x80\x9carn:aws:iam::123456789012:user/terraform-deployer\xe2\x80\x9d 的权限,以执行所有可用操作 (\xe2\x80\x9cAction\xe2 \x80\x9d: \xe2\x80\x9cs3:*") 针对带有 arn \xe2\x80\x9carn:aws:s3:::terraform-remote-store\xe2\x80\x9d 的存储桶。\n再次,在生产中希望强制执行更严格的策略。作为参考,请查看AWS 策略生成器。
\n\n返回终端并运行如下所示的命令,以在您的存储桶中强制执行该策略:
\n\naws s3api put-bucket-policy --bucket terraform-remote-store --policy file://policy.json\n# Output: none\nRun Code Online (Sandbox Code Playgroud)\n\n最后一步,启用存储桶\xe2\x80\x99s 版本控制:
\n\naws s3api put-bucket-versioning --bucket terraform-remote-store --versioning-configuration Status=Enabled\nRun Code Online (Sandbox Code Playgroud)\n\n它允许保存不同版本的基础设施\xe2\x80\x99s 状态并轻松回滚到前一阶段,而无需费力。
\n\nAWS s3 存储桶已准备就绪,是时候将其与 Terraform 集成了。下面列出了设置此远程后端所需的最低配置:
\n\n# terraform.tf\n\nprovider "aws" {\n region = "${var.aws_region}"\n shared_credentials_file = "~/.aws/credentials"\n profile = "default"\n}\n\nterraform { \n backend "s3" {\n bucket = "terraform-remote-store"\n encrypt = true\n key = "terraform.tfstate" \n region = "eu-west-1" \n }\n}\n\n# the rest of your configuration and resources to deploy\nRun Code Online (Sandbox Code Playgroud)\n\n就位后,必须(再次)初始化 terraform。\n terraform init\n远程后端已准备好运行,请对其进行测试。
锁定怎么样?\n远程存储状态会带来陷阱,尤其是在多个任务、作业和团队成员可以访问它的情况下工作时。在这些情况下,多次并发尝试更改状态的风险很高。这里来帮助锁定,这是一种防止打开已在使用的状态文件的功能。
\n\n您可以通过创建AWS DynamoDB 表来实现锁定,terraform 使用该表来设置和取消设置锁定。\n使用 terraform 本身配置资源:
\n\n# create-dynamodb-lock-table.tf\nresource "aws_dynamodb_table" "dynamodb-terraform-state-lock" {\n name = "terraform-state-lock-dynamo"\n hash_key = "LockID"\n read_capacity = 20\n write_capacity = 20\nattribute {\n name = "LockID"\n type = "S"\n }\ntags {\n Name = "DynamoDB Terraform State Lock Table"\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n并按如下所示部署它:\nterraform plan -out "planfile" && terraform apply -input=false -auto-approve "planfile"
命令执行完成后,必须将锁定机制添加到后端配置中,如下所示:
\n\n# terraform.tf\n\nprovider "aws" {\n region = "${var.aws_region}"\n shared_credentials_file = "~/.aws/credentials"\n profile = "default"\n}\n\nterraform { \n backend "s3" {\n bucket = "terraform-remote-store"\n encrypt = true\n key = "terraform.tfstate" \n region = "eu-west-1"\n dynamodb_table = "terraform-state-lock-dynamo"\n }\n}\n\n# the rest of your configuration and resources to deploy\nRun Code Online (Sandbox Code Playgroud)\n\n全做完了。请记住再次运行terraform init并享受您的远程后端。
小智 8
我通常做的是在没有远程后端的情况下开始创建初始基础设施(如您所说)、S3、IAM 角色和其他重要内容。一旦完成,我只需添加后端配置并运行 terraform init 即可迁移到 S3。
这不是最好的情况,但在大多数情况下,我不会每天重建整个环境,因此这种半自动化方法已经足够好了。我还将基础设施的下一个“层”(VPC、子网、IGW、NAT 等)分为不同的状态。
我一直在解决这个问题,您可以注释掉初始运行的“后端”块,并仅将选定的 terraform 应用到状态存储桶和任何相关资源(例如存储桶策略)。
# backend "s3" {
# bucket = "foo-bar-state-bucket"
# key = "core-terraform.tfstate"
# region = "eu-west-1"
# }
#}
provider "aws" {
region = "eu-west-1"
profile = "terraform-iam-user"
shared_credentials_file = "~/.aws/credentials"
}
Run Code Online (Sandbox Code Playgroud)
terraform apply --target aws_s3_bucket.foobar-terraform --target aws_s3_bucket_policy.foobar-terraform
Run Code Online (Sandbox Code Playgroud)
这将配置您的 s3 状态存储桶,并将 .tfstate 文件本地存储在您的工作目录中。
稍后,取消注释“后端”块并重新配置后端 ,这将提示您将本地存在的 .tfstate 文件(跟踪后端 s3 存储桶的状态terraform init --reconfigure)
复制到远程后端,该后端现在可供 terraform 用于任何后续运行。
| 归档时间: |
|
| 查看次数: |
9360 次 |
| 最近记录: |