Terraform ConfigMap хэш для повторного развертывания

Я использую Terraform с провайдером Kubernetes. Теперь при создании 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? Или добиться этого другим способом?

2 ответа

В Terraform нет способа реализовать пользовательскую хеш-функцию, но Terraform имеет ряд встроенных функций, которые реализуют различные стандартные хеш-функции.

Например, чтобы использовать хэш SHA256 в кодировке base64, вы можете написать что-то вроде следующего, используя функцию base64sha256:

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

Поскольку file Функция возвращает строку, все ссылки на файлы должны содержать действительный текст UTF-8. В этом случае хэш будет иметь кодировку UTF-8 символов Unicode в файлах.

Страница документации для base64sha256 содержит навигационные ссылки на различные другие "функции хеширования и шифрования", некоторые из которых реализуют другие алгоритмы хеширования.

Если ваша цель просто включить все в data map, вы можете избежать дублирования, разложив это в 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
}

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
          }
        }
      }
    }
  }
}

Стоит отметить, что этот подход в настоящее время имеет неудачное поведение и требует 2 applys, чтобы инициировать развертывание, поскольку Terraform видит изменение карты конфигурации только в первом apply но затем продолжение plan покажет, что контейнер спецификации развертывания env изменилось, и это вызывает развертывание. Я не достаточно углубился в это, чтобы понять, почему провайдер Kubernetes работает таким образом, поскольку Terraform должен видеть, что развертывание зависит от карты конфигурации, и это изменится.

Если вы развертываете также в Terraform, вы можете легко добиться этого, выполнив хэш данных configmap внутри метки развертывания или env, т.е.

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
Другие вопросы по тегам