我正在使用带有Kubernetes Provider的Terraform。 现在,在创建 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
这样的自定义函数? 还是以另一种方式实现这一目标?
中无法实现自定义哈希函数,但 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
}
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 个apply
来触发部署,因为 Terraform 只在第一个apply
中看到对配置映射的更改,但随后的后续plan
将显示部署规范的容器env
已更改,这会触发部署。我还没有深入研究这一点,以了解为什么 Kubernetes 提供商以这种方式工作,因为 Terraform 应该能够看到部署依赖于配置映射并且这种情况会改变。
如果你的部署也在Terraform中,你可以通过在内部部署的标签或环境中对配置映射数据进行哈希处理来轻松实现它,即:
env {
name = "prometheus_cfgmap_version"
value = base64sha256(jsonencode(kubernetes_config_map.prometheus_config.data))
}
如果部署是在地形之外,您也可以直接在部署对象中进行,即:
env:
- name: CONFIG_HASH
valueFrom:
fieldRef:
fieldPath: spec.template.metadata.annotations.configHash