You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform kubernetes_network_policy动态块null值报错解决方案

问题描述

使用kubernetes_network_policy资源配置10条差异化网络策略:1条仅配置ingress规则、1条仅配置egress规则,其余同时配置两类规则。当前动态块关联变量为null时触发报错,需要实现仅当ingress_number等变量存在有效值时才执行对应动态块。

报错信息如下:

Error: Invalid function argument
│
│   on main.tf line 16, in resource "kubernetes_network_policy" "example-policy":
│   16:       for_each = range(length(each.value.ingress_number))
│     ├────────────────
│     │ each.value.ingress_number is null
│
│ Invalid value for "value" parameter: argument must not be null.
原有配置

资源配置代码

resource "kubernetes_network_policy" "example-policy" {
  for_each = var.inputs
  metadata {
    name      = each.value.name
    namespace = each.value.namespace
  }
  spec {
    pod_selector {
      match_labels = {
        app = each.value.selector
      }
    }
    policy_types = each.value.policy
    dynamic "ingress" {
        
        for_each = range(length(each.value.ingress_number))
        
        content {
            ports {
                port     = each.value.ingress_number[ingress.value]
                protocol = each.value.ingress_protocol[ingress.value]
            }
            
            to {
                namespace_selector {
                    match_labels = {
                        app = each.value.ingress_label
                    }
                }
           } 
      }       
    }      
    dynamic "egress" {
        
        for_each = range(length(each.value.egress_number))
        
        content {
            ports {
                port     = each.value.egress_number[egress.value]
                protocol = each.value.egress_protocol[egress.value]
            }
            
            to {
                namespace_selector {
                    match_labels = {
                        app = each.value.egress_label
                    }
                }
           } 
      }       
    }    
  }
}

variable.tf配置代码

variable "inputs" {
  type = map(object({
    name            = string
    namespace       = string
    selector        = string
    policy          = list(string)
    ingress_number   = optional(list(string))
    ingress_protocol = optional(list(string))
    ingress_label    = optional(string)
    egress_number   = optional(list(string))
    egress_protocol = optional(list(string))
    egress_label    = optional(string)
  }))
  default = {}
}

tfvars配置代码

inputs = {
  app1 = {
    name           = "apache"
    namespace       = "default"
    selector        = "apache-app"
    policy          = ["ingrees", "Egress"]
    egress_label    = "example"
    egress_number   = ["443", "8080"]
    egress_protocol = ["TCP", "TCP"]
  }
  app2 = {
    name           = "nignx"
    namespace       = "default"
    selector        = "nignix-app"
    policy          = ["ingrees", "Egress"]
    ingress_label    = "play"
    ingress_number   = ["9080", "9320"]
    ingress_protocol = ["TCP", "TCP"]
    egress_label    = "example"
    egress_number   = ["443", "8080"]
    egress_protocol = ["TCP", "TCP"]
  }
}
解决方案

报错根因:optional类型属性未显式赋值时默认值为null,直接传入length()函数会触发参数非空校验失败。Terraform动态块的for_each接收空列表/空集合时会自动跳过块生成,不需要额外做逻辑判断,只需要处理null值兜底即可。

步骤1:为可选属性设置默认值(推荐)

直接在变量定义阶段给所有可选属性设置默认值,后续所有引用位置不需要重复判空,是最规范的写法:列表类型默认空列表[],字符串类型默认空字符串""。

修改后的variable.tf:

variable "inputs" {
  type = map(object({
    name            = string
    namespace       = string
    selector        = string
    policy          = list(string)
    ingress_number   = optional(list(string), [])
    ingress_protocol = optional(list(string), [])
    ingress_label    = optional(string, "")
    egress_number   = optional(list(string), [])
    egress_protocol = optional(list(string), [])
    egress_label    = optional(string, "")
  }))
  default = {}
}

步骤2:优化动态块遍历逻辑

原写法用range(length())做索引遍历属于冗余写法,直接遍历规则列表即可,空列表时动态块自动不生成,同时减少索引越界风险。

修改后的资源配置:

resource "kubernetes_network_policy" "example-policy" {
  for_each = var.inputs
  metadata {
    name      = each.value.name
    namespace = each.value.namespace
  }
  spec {
    pod_selector {
      match_labels = {
        app = each.value.selector
      }
    }
    policy_types = each.value.policy
    dynamic "ingress" {
      for_each = each.value.ingress_number
      content {
        ports {
          port     = ingress.value
          protocol = each.value.ingress_protocol[ingress.key]
        }
        to {
          namespace_selector {
            match_labels = {
              app = each.value.ingress_label
            }
          }
        }
      }
    }
    dynamic "egress" {
      for_each = each.value.egress_number
      content {
        ports {
          port     = egress.value
          protocol = each.value.egress_protocol[egress.key]
        }
        to {
          namespace_selector {
            match_labels = {
              app = each.value.egress_label
            }
          }
        }
      }
    }
  }
}

补充说明

  • 如果不想修改变量默认值,也可以在for_each参数中用try(each.value.ingress_number, [])做null值兜底,效果一致,但可维护性不如统一设置变量默认值。
  • 现有tfvars中policy字段存在拼写错误:ingrees应修正为Ingress,否则Kubernetes无法正确识别策略类型。
  • 当前靠同索引匹配端口和协议的写法存在隐患,如果端口列表和协议列表长度不一致会触发报错,后续可将规则配置调整为对象结构,比如ingress_rules = list(object({port = string, protocol = string})),遍历时不需要依赖索引匹配,稳定性更高。

内容的提问来源于stack exchange,提问作者Eva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 20:48:18