我的团队将 AWS 用于我们的基础设施,跨越 3 个不同的 AWS 账户。我们将简单地给他们打电话sandbox,staging和production。
我最近针对我们的 AWS 基础设施设置了 Terraform,它的层次结构映射到我们的帐户,然后是应用程序或 AWS 服务本身。回购结构看起来像这样:
staging
iam
groups
main.tf
users
main.tf
s3
main.tf
sandbox
iam
...
production
applications
gitlab
main.tf
route53
main.tf
...
Run Code Online (Sandbox Code Playgroud)
我们为每个 AWS 服务(例如,IAM 或 S3)或应用程序(例如,GitLab)使用单独的配置,因此我们最终不会在.tf每个帐户中生成庞大的文件,这需要很长时间才能为任何一项更改应用更新。理想情况下,我们希望摆脱基于服务的配置方法,转向更多基于应用程序的配置,但无论哪种方式,手头的问题都是一样的。
当从命令行手动应用更新时,这种方法一直运行良好,但我很想将它移动到 GitLab CI/CD 以更好地自动化我们的工作流程,而这正是问题所在。
在我现有的设置中,如果我对,比如说,做一个单一的改变staging/s3/main.tf,GitLab 似乎没有一个开箱即用的好方法来只运行terraform plan或terraform apply用于特定的配置。
如果我改为将所有内容移动到main.tf整个 AWS 帐户的单个文件中(或多个文件但与单个状态文件相关联),我可以简单地让 GitLab 触发一个作业plan或apply仅触发该配置。根据我们在每个账户中拥有的 AWS 资源数量,运行可能需要 15 分钟,但我认为这是一个潜在的选择。
似乎我的问题最终可能与 GitLab 如何处理“monorepos”有关,而不是与 Terraform 如何处理其工作流程有关(毕竟,如果我只是告诉它 …
我将在 AWS 上启动一个新的 Terraform 项目。VPC 已经创建,我想知道将它集成到我的代码中的最佳方式是什么。我是否必须再次创建它并且 Terraform 会检测到它并且不会覆盖它?或者我必须为此使用数据源吗?或者还有其他最好的方法,比如 Terraform Import ?
我还希望将来能够在其他区域或其他账户中部署整个基础设施。
谢谢。
我正在尝试从远程状态调用数据以引用网络 acl 的 vpc_id。当我运行计划/应用时,我收到错误“此对象没有参数、嵌套块或名为“vpc_id”的导出属性。
我试过使用“data.terraform_remote_state.*.vpc_id”以及“${}”语法。我尝试在子模块和父模块的 variables.tf 中定义 data.remote 信息。
我最终需要能够为不同的 VPC/子网动态调用这个模块。
相关的 VPC 已经存在,并且所有模块都已初始化。
s3 存储桶阶段/网络/vpc/terraform.tfstate:
"outputs": {
"vpc_id": {
"value": "vpc-1234567890",
"type": "string"
}
},
enter code here
Run Code Online (Sandbox Code Playgroud)
模块/网络/acl/main.tf:
data "terraform_remote_state" "stage-network" {
backend = "s3"
config = {
bucket = "bucket"
key = "stage/network/vpc/terraform.tfstate"
}
}
resource "aws_network_acl" "main" {
vpc_id = data.terraform_remote_state.stage-network.vpc_id
# acl variables here
Run Code Online (Sandbox Code Playgroud)
阶段/网络/acl/main.tf:
data "terraform_remote_state" "stage-network" {
backend = "s3"
config = {
bucket = "bucket"
key = "stage/network/vpc/terraform.tfstate"
}
}
module "create_acl" …Run Code Online (Sandbox Code Playgroud) 我正在将我的 terraform 0.11 配置迁移到 terraform 0.12.5。
迁移(使用0.12upgrade)进行的比较顺利,但是后来我在下一个计划的时候遇到了这个错误
Error: Invalid value for module argument
on main.tf line 72, in module "foo":
72: subnet_ids = module.vpc.subnet_ids
The given value is not suitable for child module variable "subnet_ids"
defined at ../../modules/foo/main.tf:10,1-30: element 0: string
required.
Run Code Online (Sandbox Code Playgroud)
该模块foo有一个(迁移的)变量声明子网_ids,如下所示:
variable "subnet_ids" {
type = list(string)
}
Run Code Online (Sandbox Code Playgroud)
而vpc模块有一个输出声明,声明如下:
output "subnet_ids" {
value = [aws_subnet.private.*.id]
}
Run Code Online (Sandbox Code Playgroud)
似乎如果我放松对foo模块的类型约束,错误就会消失。
然而,这是正确的做法。毕竟,vpc 模块的输出实际上不是一个字符串列表吗?如何检查 vpc 输出变量的类型?
更新:放宽类型约束允许验证的第一部分成功,但仅在根据此输出应用变量时对消费模块造成问题
Error: Incorrect attribute value type
on ../../modules/foo/main.tf line 350, …Run Code Online (Sandbox Code Playgroud) 我有一个users.tf为 aws 创建管理员用户的文件。它通过定义一个列表(例如users = ["bob", "john", "tom"])
然后aws_iam_user使用countterraform 中的功能使用资源迭代它们,如下所示:
resource "aws_iam_user" "user" {
count = length(local.users)
name = local.users[count.index]
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是,如果我删除数组的第一个元素(上面示例中的“bob”),那么 terraform 会建议在发出后执行的操作terraform plan,而不是删除 bob,是将 bob 更改为 john,将 john 更改为 tom ,并删除汤姆。
像这样:
# aws_iam_user.user[0] will be updated in-place
~ resource "aws_iam_user" "user" {
arn = "arn:aws:iam::5555555:user/bob"
force_destroy = false
id = "bob"
~ name = "bob" -> "john"
path = "/"
tags = {}
unique_id = "BLABLABLA11111"
}
# …Run Code Online (Sandbox Code Playgroud) 我发现我的 aws 帐户中有一个不是由 terraform 创建的存储桶。
我想确保它在我的 terraform 存储库中说明,但在我添加它之前,我运行terraform plan并得到以下响应:
No changes. Infrastructure is up-to-date.
This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.
Run Code Online (Sandbox Code Playgroud)
这很奇怪,因为当我跑步时,aws s3 ls我看到了桶:
#not real names from obvious reasons
2019-07-15 13:33:16 bucket-from-terrform
2019-07-15 13:19:26 terraform-state-bucket
2019-07-23 17:47:26 bucket-created-manually
Run Code Online (Sandbox Code Playgroud)
更重要的是,当我添加一个名称与之前忽略的存储桶匹配的资源时,terraform 会尝试添加它(即使它已经存在)
怎么了?terraform 忽略那个桶的原因可能是什么?
我希望从自动缩放启动配置中创建一个新启动的 ec2 实例,其中 source_dest_check = disabled(默认情况下已启用)。
我知道我们可以使用 source_dest_check = false 来创建 ec2 资源,但是如何在从 ASG 管理实例时实现相同的目标。
Terraform 不接受下面的 (source_dest_check = false) ,还有其他替代方法可以实现吗?
我可以从用户数据中实现这一点吗?
resource "aws_launch_configuration" "launchconfig" {
name_prefix = "bastion-"
image_id = "${data.aws_ami.amazon-linux-2.id}"
instance_type = "${var.instance_type}"
placement_tenancy = "default"
enable_monitoring = true
#source_dest_check = false
security_groups = ["${aws_security_group. security_group.id}"]
iam_instance_profile = "${aws_iam_instance_profile.instance_profile.name}"
key_name = "${var. pem_key}"
#Include user-data
user_data = "${element(data.template_file.user_data.*.rendered, count.index)}"
lifecycle {
create_before_destroy = true
}
}
Run Code Online (Sandbox Code Playgroud) amazon-ec2 amazon-web-services boto3 terraform terraform-provider-aws
上下文:我正在实现(我的第一个)Terraform 插件/提供程序作为现有公共 API 的包装器。
API 中的创建操作之一指定了一个整数字段,该字段采用正值或-1作为默认值。如果您-1在 create API 调用中指定,该值将被服务器端的某个默认值替换(例如field = 1000),并1000从现在开始存储。
如果我将其呈现给我的 Terraform 插件 ( terraform apply):
resource "something" "mysomething" {
name = "someName"
field = -1
}
Run Code Online (Sandbox Code Playgroud)
调用不是幂等的。Terraform 继续看到漂移,随后提供:
# something.mysomething will be updated in-place
~ resource "something" "mysomething" {
id = "165-1567498530352"
name = "someName"
~ field = 1000 -> -1
}
Plan: 0 to add, 1 to change, 0 to destroy.
Run Code Online (Sandbox Code Playgroud)
如何处理这样的API?
我正在尝试将 Kube 状态指标部署到kube-system运行 Kubernetes v1.14 的 EKS 集群 (eks.4) 中的命名空间中。
Kubernetes 连接
provider "kubernetes" {
host = var.cluster.endpoint
token = data.aws_eks_cluster_auth.cluster_auth.token
cluster_ca_certificate = base64decode(var.cluster.certificate)
load_config_file = true
}
Run Code Online (Sandbox Code Playgroud)
部署清单(作为 .tf)
resource "kubernetes_deployment" "kube_state_metrics" {
metadata {
name = "kube-state-metrics"
namespace = "kube-system"
labels = {
k8s-app = "kube-state-metrics"
}
}
spec {
replicas = 1
selector {
match_labels = {
k8s-app = "kube-state-metrics"
}
}
template {
metadata {
labels = {
k8s-app = "kube-state-metrics"
}
}
spec …Run Code Online (Sandbox Code Playgroud) 我正在努力理解数据在 Terraform (v0.12.12) 中传入和传出模块的方式。我有一个我认为非常简单的例子,但无法理解数据应该如何在模块之间传递。我能找到的大多数例子要么不完整,要么过时。
我创建了一个包含两个模块的简单示例。创建 vpc 和子网的网络模块,以及创建 EC2 实例的计算模块。我只是想为计算模块提供 EC2 实例应该去的子网的 ID。但我不明白:
基本结构如下
.
??? main.tf
??? modules
??? compute
? ??? main.tf
??? network
??? main.tf
??? output.tf
# main.tf
provider "aws" {
region = "eu-west-1"
}
module "m_network" {
source = "./modules/network"
}
# The problem is how to make that subnet id available to the compute module
# so the ec2 instance can be added to it?
module "m_compute" {
source …Run Code Online (Sandbox Code Playgroud) terraform ×10
module ×2
amazon-ec2 ×1
amazon-eks ×1
amazon-s3 ×1
boto3 ×1
gitlab ×1
go ×1
kubernetes ×1
output ×1
vpc ×1