![](/img/trans.png)
[英]Terraform/GCP, how to create a firewall rule to deny all traffic without specify IP ranges?
[英]Cannot create many Azure firewall rule sets concurrently in Terraform
我的 Terraform 代码的架构大致如下:
module "firewall_hub" {
# This creates the Azure Firewall resource
source = "/path/to/module/a"
# attribute = value...
}
module "firewall_spoke" {
# This creates, amongst other things, firewall rule sets
source = "/path/to/module/b"
hub = module.firewall_hub
# attribute = value...
}
module "another_firewall_spoke" {
# This creates, amongst other things, firewall rule sets
source = "/path/to/module/c"
hub = module.firewall_hub
# attribute = value...
}
即,Azure 防火墙资源在module.firewall_hub
中创建,用作module.firewall_spoke
和module.another_firewall_spoke
的输入,它们创建必要的资源并将防火墙规则集注入防火墙资源。 重要的是,规则集在辐射模块之间是相互排斥的,并且被设计成它们的优先级不会重叠。
当我尝试部署此代码(构建或销毁)时,Azure 会引发错误:
错误:从防火墙“XXX(资源组“XXX”)删除应用程序规则集合“XXX”:.network.AzureFirewallsClient#CreateOrUpdate:发送请求失败:StatusCode = 0 - 原始错误:autorest / azure:服务返回错误。状态= Code="AnotherOperationInProgress" Message="此资源或依赖资源上的另一个操作正在进行中。 要检索操作的状态,请使用 uri: https://management.azure.com/subscriptions/XXX" Details=[]
我的工作假设是不能同时对同一防火墙发出防火墙规则集的多个创建/更新/删除请求,即使规则集是相互排斥的。 事实上,如果您在部署失败后等待一分钟左右并重新启动它——无需更改任何 Terraform 代码或手动更新 Azure 中的资源——它会愉快地继续运行而不会出现错误并成功完成。
为了测试我的假设,我试图通过强制模块序列化来解决这个问题:
module "another_firewall_spoke" {
# This creates, amongst other things, firewall rule sets
source = "/path/to/module/c"
hub = module.firewall_hub
# attribute = value...
depends_on = [module.firewall_spoke]
}
然而,不幸的是,我的模块的编写方式是不可能的:
不能使用 count、for_each 或 depends_on 在模块中配置提供程序。
如果不重写我的模块(不是一个选项),是否有可能解决这个竞争条件——如果这是问题所在——或者你会认为它是azurerm
提供程序的错误(即,它应该识别 API 错误响应和轮到它了,直到超时)?
(Terraform v1.1.7, azurerm
v2.96.0)
在@silent 对这个答案的提示之后,我能够使用其中描述的方法解决比赛。
是这样的:
module "firewall_hub" {
# This creates the Azure Firewall resource
source = "/path/to/module/a"
# attribute = value...
}
module "firewall_spoke" {
# This creates, amongst other things, firewall rule sets
# Has an output "blockers" containing resources that cannot be deployed concurrently
source = "/path/to/module/b"
hub = module.firewall_hub
# attribute = value...
}
module "another_firewall_spoke" {
# This creates, amongst other things, firewall rule sets
source = "/path/to/module/c"
hub = module.firewall_hub
waits_for = module.firewall_spoke.blockers
# attribute = value...
}
因此,诀窍是让您的模块导出一个 output,其中包含需要首先部署的所有依赖资源的列表。 然后,这可以作为后续模块的输入,通过线程连接到需要depends_on
值的实际资源。
也就是说,在我的模块的深处,资源有:
resource "some_resource" "foo" {
# attribute = value...
depends_on = [var.waits_for]
}
使用此方法时需要牢记两个重要注意事项:
模块中的wait_for
变量必须具有类型any
; list(any)
不起作用,因为 Terraform 将其解释为同类列表(很可能不会)。
奇怪的是,imo, depends_on
子句要求您显式使用列表文字(即[var.waits_for]
而不仅仅是var.waits_for
),即使您正在处理的变量是一个列表。 这并没有在我的脑海中输入检查,但显然 Terraform 不仅适用于它,而且它期待它!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.