Terraform 0.12 使用模板创建入口规则

Posted

技术标签:

【中文标题】Terraform 0.12 使用模板创建入口规则【英文标题】:Terraform 0.12 Creating ingress rules with template 【发布时间】:2020-06-03 12:39:06 【问题描述】:

我想知道是否可以使用这样的东西。我有功能代码工作,但由于 kubernetes 中的 pod 会快速增长,我想转换为模板。这是为每个 wordpress 站点 pod 创建每个 nginx 入口规则的示例。

现在,每个 pod 都有其 wordpress 入口条目:

resource "kubernetes_ingress" "ingress_nginx_siteA" 
  metadata 
    name        = "ingress-nginx-siteA"
    namespace   = "default"
    annotations =  "kubernetes.io/ingress.class" = "nginx", "nginx.ingress.kubernetes.io/configuration-snippet" = "modsecurity_rules '\n SecRuleEngine On\n SecRequestBodyAccess On\n SecAuditEngine RelevantOnly\n SecAuditLogParts ABCIJDEFHZ\n SecAuditLog /var/log/modsec_audit.log\n SecRuleRemoveById 932140\n';\n", "nginx.ingress.kubernetes.io/ssl-passthrough" = "true" 
  
  spec 
    tls 
      hosts       = ["siteA.test.com"]
      secret_name = "wildcard-test-com"
    
    rule 
      host = "siteA.test.com"
      http 
        path 
          path = "/"
          backend 
            service_name = "siteA"
            service_port = "80"
          
        
      
    
  

现在我想拆分成包含整个站点变量的 variables.tf、模板文件 rules.tplma​​in.tf > 编排这些东西。

变量.tf:

variable "wordpress_site" 
  type = map(object(
    name        = string
    url         = string
    certificate = string
  ))
    default = 
    siteA = 
      name        = siteA
      url         = siteA.test.com
      certificate = wildcard-test-com
    
    siteB = 
      name        = siteB
      url         = siteB.test.com
      certificate = wildcard-test-com
    
  
 

rules.tpl:

% for name in wordpress_site.name ~
resource "kubernetes_ingress" "ingress_nginx_$name" 
  metadata 
    name        = "ingress-nginx-$name"
    namespace   = "default"
    annotations =  "kubernetes.io/ingress.class" = "nginx", "nginx.ingress.kubernetes.io/configuration-snippet" = "modsecurity_rules '\n SecRuleEngine On\n SecRequestBodyAccess On\n SecAuditEngine RelevantOnly\n SecAuditLogParts ABCIJDEFHZ\n SecAuditLog /var/log/modsec_audit.log\n SecRuleRemoveById 932140\n';\n", "nginx.ingress.kubernetes.io/ssl-passthrough" = "true" 
  
  spec 
    tls 
      hosts       = ["$wordpress_site.url"]
      secret_name = "$wordpress_site.certificate"
    
    rule 
      host = "$wordpress_site.url"
      http 
        path 
          path = "/"
          backend 
            service_name = "$name"
            service_port = "80"
          
        
      
    
  

% endfor ~

现在,在 main.tf 中,混合所有内容的最佳方法是什么?我看到在 TF 0.12 中添加了新功能,例如 templatefile 功能,但根本不知道我是否可以像这样使用它:

main.tf:

templatefile($path.module/rules.tpl, $module.var.wordpress_site)

感谢大家的支持!

【问题讨论】:

【参考方案1】:

templatefile 函数用于从模板生成字符串,而不是用于生成 Terraform 配置。尽管可以渲染给定模板以生成包含 Terraform 配置的字符串,但 Terraform 只会将结果视为普通字符串,而不是要评估的更多配置。

相反,我们需要得到所需结果的是resource for_each,它允许基于映射值从单个资源创建多个实例。

resource "kubernetes_ingress" "nginx" 
  for_each = var.wordpress_site

  metadata 
    name        = "ingress-nginx-$each.value.name"
    namespace   = "default"
    annotations = 
      "kubernetes.io/ingress.class" = "nginx"
      "nginx.ingress.kubernetes.io/configuration-snippet" = <<-EOT
        modsecurity_rules '
         SecRuleEngine On
         SecRequestBodyAccess On
         SecAuditEngine RelevantOnly
         SecAuditLogParts ABCIJDEFHZ
         SecAuditLog /var/log/modsec_audit.log
         SecRuleRemoveById 932140
        ';
      EOT
      "nginx.ingress.kubernetes.io/ssl-passthrough" = "true"
    
  
  spec 
    tls 
      hosts       = [each.value.url]
      secret_name = each.value.certificate
    
    rule 
      host = each.value.url
      http 
        path 
          path = "/"
          backend 
            service_name = each.value.name
            service_port = "80"
          
        
      
    
  

当资源设置了for_each 时,Terraform 将评估给定参数以获取地图,然后将为该地图中的每个元素创建一个资源实例,每个元素由其对应的地图键标识。在这种情况下,假设默认值为var.wordpress_site,您将获得两个具有以下地址的实例:

kubernetes_ingress.nginx["siteA"] kubernetes_ingress.nginx["siteB"]

resource 块内,以each.value 开头的引用指的是地图中的值,在本例中是描述每个站点的对象。

【讨论】:

非常感谢@martin-atkins!我将调整代码并对其进行测试。我会带着结果回来的。

以上是关于Terraform 0.12 使用模板创建入口规则的主要内容,如果未能解决你的问题,请参考以下文章

Terraform 模块依赖项不起作用(版本 0.12)

如何使用 Terraform 附加或删除安全组的入口/出口规则?

Terraform 0.12:桶的输出列表,用作另一个模块的输入并迭代

Cloud Formation 模板将入口规则添加到现有安全组

通过 Terraform 添加 AWS 安全组时出现问题

带有 ALB 入口控制器的 Terraform AWS Kubernetes EKS 资源不会创建负载均衡器