【问题标题】:Terraform ConfigMap hash for redeploy用于重新部署的 Terraform ConfigMap 哈希
【发布时间】:2019-12-13 22:09:04
【问题描述】:

我正在将 Terraform 与 Kubernetes Provider 一起使用。 现在,在创建 ConfigMap 时,我希望它们的名称具有内容后缀。 通常是内容的哈希。

这样,它应该在使用时强制执行部署。

所以我希望它的工作方式类似于:

resource "kubernetes_config_map" "prometheus_config" {
  metadata {
    name      = "prometheus-" + computeHash(file("${path.module}/alerts.yml"), file("${path.module}/recordings.yml"), "abcd")
  }

  data = {
    "foo" = file("${path.module}/alerts.yml")
    "bar" = file("${path.module}/recordings.yml")
    "txt" = "abcd"
  }
}

有没有办法实现像computeHash 这样的自定义函数? 或者以其他方式实现这一目标?

【问题讨论】:

    标签: kubernetes terraform terraform-provider-kubernetes


    【解决方案1】:

    无法在 Terraform 中实现自定义哈希函数,但 Terraform 有许多内置函数可以实现不同的标准哈希函数。

    例如,要使用 base64 编码的 SHA256 哈希,您可以使用函数 base64sha256 编写如下内容:

      name = "prometheus-" + base64sha256(join("\n", [
        file("${path.module}/alerts.yml"),
        file("${path.module}/recordings.yml"),
        "abcd",
      ])
    

    因为file 函数返回一个字符串,所以所有引用的文件都必须包含有效的UTF-8 文本。然后哈希将是文件中 unicode 字符的 UTF-8 编码。

    base64sha256 的文档页面包含指向各种其他“哈希和加密函数”的导航链接,其中一些实现了其他哈希算法。

    如果您的目标是仅将所有内容包含在 data 映射中,您可以通过将其分解为 Local Value 来避免重复,然后散列映射的字符串表示形式,例如 JSON 序列化:

    locals {
      prometheus_config = {
        "foo" = file("${path.module}/alerts.yml")
        "bar" = file("${path.module}/recordings.yml")
        "txt" = "abcd"
      }
    }
    
    resource "kubernetes_config_map" "prometheus_config" {
      metadata {
        name = "prometheus-" + base64sha256(jsonencode(local.prometheus_config))
      }
    
      data = local.prometheus_config
    }
    

    【讨论】:

    • 问题是base64生成的字符对kubernetes无效!
    • 您可以使用sha256sha1 代替,如果名称只包含十六进制数字是可以接受的。
    【解决方案2】:

    kubernetes_config_map resource 返回一个resource_version attribute as part of the metadata。如链接文档中所述:

    表示此配置映射的内部版本的不透明值,客户端可以使用该值来确定配置映射何时更改。欲了解更多信息,请参阅Kubernetes reference

    您可以使用它来触发部署,方法是根据您的 kubernetes_deployment resource 中的此值直接进行插值。

    我个人将值放入容器规范中的环境变量中,然后在配置映射更改时触发部署以重新部署。调整kubernetes_deployment 文档中给出的示例:

    resource "kubernetes_deployment" "example" {
      metadata {
        name = "terraform-example"
        labels = {
          test = "MyExampleApp"
        }
      }
    
      spec {
        replicas = 3
    
        selector {
          match_labels = {
            test = "MyExampleApp"
          }
        }
    
        template {
          metadata {
            labels = {
              test = "MyExampleApp"
            }
          }
    
          spec {
            container {
              image = "nginx:1.7.8"
              name  = "example"
    
              env = [
                {
                  name  = "configmap"
                  value = "${kubernetes_config_map.example.metadata.0.resource_version}"
                },
              ]
    
              resources {
                limits {
                  cpu    = "0.5"
                  memory = "512Mi"
                }
                requests {
                  cpu    = "250m"
                  memory = "50Mi"
                }
              }
    
              liveness_probe {
                http_get {
                  path = "/nginx_status"
                  port = 80
    
                  http_header {
                    name  = "X-Custom-Header"
                    value = "Awesome"
                  }
                }
    
                initial_delay_seconds = 3
                period_seconds        = 3
              }
            }
          }
        }
      }
    }
    

    值得注意的是,这种方法目前有一个不幸的行为,即需要 2 个applys 来触发部署,因为 Terraform 仅在第一个 apply 中看到对配置映射的更改,但随后是 plan将显示部署规范的容器env 已更改,这将触发部署。我还没有深入了解为什么 Kubernetes 提供程序会以这种方式工作,因为 Terraform 应该能够看到部署依赖于配置映射并且这种情况将会改变。

    【讨论】:

      【解决方案3】:

      如果您的部署也在 Terraform 中,您可以通过在部署的标签或环境中对 configmap 数据进行哈希来轻松实现它,即:

      env {
        name  = "prometheus_cfgmap_version"
        value = base64sha256(jsonencode(kubernetes_config_map.prometheus_config.data))
      }
      

      如果部署在 terraform 之外,您也可以直接在部署对象内部进行,即:

      env:
        - name: CONFIG_HASH
          valueFrom:
            fieldRef:
              fieldPath: spec.template.metadata.annotations.configHash
      

      【讨论】:

        猜你喜欢
        • 2021-12-08
        • 2017-04-23
        • 2016-09-14
        • 2020-03-25
        • 1970-01-01
        • 1970-01-01
        • 2012-12-25
        • 1970-01-01
        • 2020-05-18
        相关资源
        最近更新 更多