[英]Terraform create multiple resources using for_each and jsondecode
[英]Create multiple target groups and listeners using for each
我正在嘗試使用 For Each 在 Terraform 中創建多個應用程序目標組和偵聽器。 我有一些復雜的設置來處理偵聽器規則,以根據 HTTP 標頭將流量路由到目標組。 下面是我寫的資源:
resource "aws_lb_listener" "app_listener_forward" {
for_each = var.listeners
load_balancer_arn = aws_lb.app_alb.arn
port = each.value.listeners
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06"
certificate_arn = var.ssl_cert
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.app_tg[each.key].arn
}
}
resource "aws_lb_listener_rule" "app_https_listener_rule" {
for_each = var.listeners
listener_arn = aws_lb_listener.app_listener_forward[each.key].arn
action {
type = "forward"
target_group_arn = aws_lb_target_group.app_tg[each.key].arn
}
condition {
path_pattern {
values = each.value.paths
}
}
}
resource "aws_lb_target_group" "app_tg" {
for_each = var.listeners
name = each.key
port = each.value.app_port
protocol = "HTTP"
target_type = "ip"
vpc_id = aws_vpc.app_vpc.id
health_check {
interval = 130
timeout = 120
healthy_threshold = 10
unhealthy_threshold = 10
}
stickiness {
type = "lb_cookie"
cookie_duration = 86400
}
}
下面是變量聲明:
variable "listeners" {
type = map(object({
app_port = number
paths = set(string)
listeners = set(number)
}))
default = {
"app_one" = {
app_port = 3000
paths = [
"/appOne",
"/appOne/*"
]
listeners = [
80, 443, 22, 7999, 8999
]
}
"app_two" = {
app_port = 4000
paths = [
"/appTwo",
"/appTwo/*"
]
listeners = [
80, 443, 22, 7999, 8999
]
}
}
}
嘗試執行時,我在處理aws_lb_listener
資源的port
屬性時遇到錯誤。 以下是錯誤:
Error: Incorrect attribute value type
│
│ on alb.tf line 38, in resource "aws_lb_listener" "app_listener_forward":
│ 38: port = each.value.listeners
│ ├────────────────
│ │ each.value.listeners is set of string with 5 elements
│
│ Inappropriate value for attribute "port": number required.
由於數字列表,我嘗試將變量的 listeners 屬性設置為一個集合(數字)和一個集合(字符串),但我仍然收到此錯誤。
關於如何修復此錯誤的任何想法都會有所幫助。
謝謝!
錯誤消息指出resource "aws_lb_listener" "app_listener_forward" {..}
中端口的值似乎不正確。
由於您已經在使用for_each
循環整個資源,因此它不能在用於循環的變量中可用的值內循環。
一種解決方案是將可變listeners
器分成兩部分。
隨意使用任何對您來說更有意義的名稱。
variable "listner_ports" {
type = list(string)
description = "(optional) listeners port numbers"
default = [
80, 443, 22, 7999, 8999
]
}
variable "listeners" {
type = map(object({
app_port = number
paths = set(string)
}))
default = {
"app-one" = {
app_port = 3000
paths = [
"/appOne",
"/appOne/*"
]
}
"app-two" = {
app_port = 4000
paths = [
"/appTwo",
"/appTwo/*"
]
}
}
}
注意:我已將app_{one,two}
更改為app-{one,two}
因為aws_lb_target_group“名稱”中只允許使用字母數字字符和連字符
aws_lb_listener
中的 terraform 動態塊對同一資源中的不同變量使用循環。resource "aws_lb_listener" "app_listener_forward" {
for_each = toset(var.listner_ports)
load_balancer_arn = data.aws_lb.test.arn ## Use aws_lb.app_alb.arn as per your usecase
port = each.value
protocol = "HTTP" # you might need to use a more complex variable to support ports and protocols but it gives an idea.
## Uncommend in your case.
# ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06"
# certificate_arn = var.ssl_cert
dynamic "default_action" {
for_each = var.listeners
content {
type = "forward"
target_group_arn = aws_lb_target_group.app_tg[default_action.key].arn
}
}
}
resource "aws_lb_target_group" "app_tg" {
for_each = var.listeners
name = each.key
port = each.value.app_port
protocol = "HTTP"
target_type = "ip"
vpc_id = local.vpc_id
health_check {
interval = 130
timeout = 120
healthy_threshold = 10
unhealthy_threshold = 10
}
stickiness {
type = "lb_cookie"
cookie_duration = 86400
}
}
aws_lb_listener
和aws_lb_target_group
資源的附加計划。Terraform will perform the following actions:
# aws_lb_listener.app_listener_forward["22"] will be created
+ resource "aws_lb_listener" "app_listener_forward" {
+ arn = (known after apply)
+ id = (known after apply)
+ load_balancer_arn = "arn:aws:elasticloadbalancing:eu-central-1:xxxxxxxxxxxxxx:loadbalancer/app/stackoverflow/be9c11ed9c543788"
+ port = 22
+ protocol = "HTTP"
+ ssl_policy = (known after apply)
+ tags_all = (known after apply)
+ default_action {
+ order = (known after apply)
+ target_group_arn = (known after apply)
+ type = "forward"
}
+ default_action {
+ order = (known after apply)
+ target_group_arn = (known after apply)
+ type = "forward"
}
}
# aws_lb_listener.app_listener_forward["443"] will be created
+ resource "aws_lb_listener" "app_listener_forward" {
+ arn = (known after apply)
+ id = (known after apply)
+ load_balancer_arn = "arn:aws:elasticloadbalancing:eu-central-1:xxxxxxxxxxxxxx:loadbalancer/app/stackoverflow/be9c11ed9c543788"
+ port = 443
+ protocol = "HTTP"
+ ssl_policy = (known after apply)
+ tags_all = (known after apply)
+ default_action {
+ order = (known after apply)
+ target_group_arn = (known after apply)
+ type = "forward"
}
+ default_action {
+ order = (known after apply)
+ target_group_arn = (known after apply)
+ type = "forward"
}
}
# aws_lb_listener.app_listener_forward["7999"] will be created
+ resource "aws_lb_listener" "app_listener_forward" {
+ arn = (known after apply)
+ id = (known after apply)
+ load_balancer_arn = "arn:aws:elasticloadbalancing:eu-central-1:xxxxxxxxxxxxxx:loadbalancer/app/stackoverflow/be9c11ed9c543788"
+ port = 7999
+ protocol = "HTTP"
+ ssl_policy = (known after apply)
+ tags_all = (known after apply)
+ default_action {
+ order = (known after apply)
+ target_group_arn = (known after apply)
+ type = "forward"
}
+ default_action {
+ order = (known after apply)
+ target_group_arn = (known after apply)
+ type = "forward"
}
}
# aws_lb_listener.app_listener_forward["80"] will be created
+ resource "aws_lb_listener" "app_listener_forward" {
+ arn = (known after apply)
+ id = (known after apply)
+ load_balancer_arn = "arn:aws:elasticloadbalancing:eu-central-1:xxxxxxxxxxxxxx:loadbalancer/app/stackoverflow/be9c11ed9c543788"
+ port = 80
+ protocol = "HTTP"
+ ssl_policy = (known after apply)
+ tags_all = (known after apply)
+ default_action {
+ order = (known after apply)
+ target_group_arn = (known after apply)
+ type = "forward"
}
+ default_action {
+ order = (known after apply)
+ target_group_arn = (known after apply)
+ type = "forward"
}
}
# aws_lb_listener.app_listener_forward["8999"] will be created
+ resource "aws_lb_listener" "app_listener_forward" {
+ arn = (known after apply)
+ id = (known after apply)
+ load_balancer_arn = "arn:aws:elasticloadbalancing:eu-central-1:xxxxxxxxxxxxxx:loadbalancer/app/stackoverflow/be9c11ed9c543788"
+ port = 8999
+ protocol = "HTTP"
+ ssl_policy = (known after apply)
+ tags_all = (known after apply)
+ default_action {
+ order = (known after apply)
+ target_group_arn = (known after apply)
+ type = "forward"
}
+ default_action {
+ order = (known after apply)
+ target_group_arn = (known after apply)
+ type = "forward"
}
}
# aws_lb_target_group.app_tg["app-one"] will be created
+ resource "aws_lb_target_group" "app_tg" {
+ arn = (known after apply)
+ arn_suffix = (known after apply)
+ connection_termination = false
+ deregistration_delay = "300"
+ id = (known after apply)
+ ip_address_type = (known after apply)
+ lambda_multi_value_headers_enabled = false
+ load_balancing_algorithm_type = (known after apply)
+ name = "app-one"
+ port = 3000
+ preserve_client_ip = (known after apply)
+ protocol = "HTTP"
+ protocol_version = (known after apply)
+ proxy_protocol_v2 = false
+ slow_start = 0
+ tags_all = (known after apply)
+ target_type = "ip"
+ vpc_id = "vpc-063017c6abb96eab6"
+ health_check {
+ enabled = true
+ healthy_threshold = 10
+ interval = 130
+ matcher = (known after apply)
+ path = (known after apply)
+ port = "traffic-port"
+ protocol = "HTTP"
+ timeout = 120
+ unhealthy_threshold = 10
}
+ stickiness {
+ cookie_duration = 86400
+ enabled = true
+ type = "lb_cookie"
}
+ target_failover {
+ on_deregistration = (known after apply)
+ on_unhealthy = (known after apply)
}
}
# aws_lb_target_group.app_tg["app-two"] will be created
+ resource "aws_lb_target_group" "app_tg" {
+ arn = (known after apply)
+ arn_suffix = (known after apply)
+ connection_termination = false
+ deregistration_delay = "300"
+ id = (known after apply)
+ ip_address_type = (known after apply)
+ lambda_multi_value_headers_enabled = false
+ load_balancing_algorithm_type = (known after apply)
+ name = "app-two"
+ port = 4000
+ preserve_client_ip = (known after apply)
+ protocol = "HTTP"
+ protocol_version = (known after apply)
+ proxy_protocol_v2 = false
+ slow_start = 0
+ tags_all = (known after apply)
+ target_type = "ip"
+ vpc_id = "vpc-063017c6abb96eab6"
+ health_check {
+ enabled = true
+ healthy_threshold = 10
+ interval = 130
+ matcher = (known after apply)
+ path = (known after apply)
+ port = "traffic-port"
+ protocol = "HTTP"
+ timeout = 120
+ unhealthy_threshold = 10
}
+ stickiness {
+ cookie_duration = 86400
+ enabled = true
+ type = "lb_cookie"
}
+ target_failover {
+ on_deregistration = (known after apply)
+ on_unhealthy = (known after apply)
}
}
Plan: 7 to add, 0 to change, 0 to destroy.
希望能幫助到你。 並且,是的,我已經屏蔽了帳戶 ID:)。
這部分是在閱讀@David 的評論后添加的,他在評論中提到了另一個問題 ERROR Message: "InvalidLoadBalancerAction: You cannot specify multiple of the following action type: 'forward'" when trying to create the listener.
將其用作您的aws_lb_listener
的基本代碼,我強烈建議您根據最佳解決方案進行修改。[嵌套動態塊 --> 有關文檔,請參閱此處]
resource "aws_lb_listener" "app_listener_forward" {
for_each = toset(var.listner_ports)
load_balancer_arn = aws_lb.test.arn
port = each.value
protocol = "HTTP" # you might need to use a more complex variable to support ports and protocols but it gives an idea.
## Uncommend in your case.
# ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06"
# certificate_arn = var.ssl_cert
default_action {
type = "forward"
forward {
dynamic "target_group" {
for_each = var.listeners
content {
arn = aws_lb_target_group.app_tg[target_group.key].arn
}
}
stickiness {
enabled = true
duration = 86400
}
}
}
}
結論: Apply 確實按預期使用上述代碼(為具有不同端口的兩個目標組創建了多個偵聽器)但無法確認這是否是您所需要的,但是,可以根據要求調整解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.