0

我正在将 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吗?或者以另一种方式实现这一目标?

4

3 回答 3

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地图中的所有内容,则可以通过将其分解为本地值然后散列地图的字符串表示形式来避免重复,例如 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
}
于 2019-08-06T16:46:21.160 回答
1

kubernetes_config_map资源返回一个resource_version属性作为元数据的一部分。如链接文档中所述:

一个不透明的值,表示此配置映射的内部版本,客户端可以使用它来确定配置映射何时更改。有关更多信息,请参阅Kubernetes 参考

kubernetes_deployment您可以使用它通过直接基于资源中的此值进行插值来触发部署。

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

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

于 2019-08-07T12:34:30.883 回答
0

如果您的部署也在 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
于 2020-01-11T18:41:53.660 回答