5

我想用 terraform 安装 CRD,我希望这样做会很容易:

data "http" "crd" {
  url = "https://raw.githubusercontent.com/kubernetes-sigs/application/master/deploy/kube-app-manager-aio.yaml"
  request_headers = {
    Accept = "text/plain"
  }
}

resource "kubernetes_manifest" "install-crd" {
  manifest = data.http.crd.body
}

但我得到这个错误:

can't unmarshal tftypes.String into *map[string]tftypes.Value, expected
map[string]tftypes.Value

尝试将其转换为 yamlyamldecode也不起作用,因为yamldecode不支持多文档 yaml 文件。

我可以使用 exec,但在等待kubernetes_manifest资源释放时我已经这样做了。kubernetes_manifest仅支持单个资源还是可以用于从原始文本清单文件创建多个资源?

4

2 回答 2

3

kubernetes_manifest(强调我的)

通过提供清单属性表示一个Kubernetes 资源

在我看来,它不支持多个资源/多文档 yaml 文件。

但是,您可以手动拆分传入文档及其yamldecode部分:

locals {
  yamls = [for data in split("---", data.http.crd.body): yamldecode(data)]
}

resource "kubernetes_manifest" "install-crd" {
  count = length(local.yamls)
  manifest = local.yamls[count.index]
}

不幸的是,在我的机器上,这然后抱怨

清单配置中不允许“状态”属性键

恰好是 11 个清单之一。

而且由于我对 kubernetes 毫无头绪,所以我不知道这意味着什么,也不知道它是否需要修复。

或者,您始终可以将 anull_resource与获取 yaml 文档的脚本一起使用,并使用 bash 工具或 python 或任何已安装的工具来转换、拆分和过滤传入的 yaml。

于 2021-09-14T16:03:02.750 回答
0

我使用kubectl provider 让它工作。最终kubernetes_manifest应该也能正常工作,但它目前(v2.5.0)仍然是测试版并且有一些错误。此示例仅使用 kind+name,但为了完全唯一,它还应包括 API 和命名空间参数。

resource "kubectl_manifest" "cdr" {
  # Create a map { "kind--name" => yaml_doc } from the multi-document yaml text.
  # Each element is a separate kubernetes resource.
  # Must use \n---\n to avoid splitting on strings and comments containing "---".
  # YAML allows "---" to be the first and last line of a file, so make sure
  # raw yaml begins and ends with a newline.
  # The "---" can be followed by spaces, so need to remove those too.
  # Skip blocks that are empty or comments-only in case yaml began with a comment before "---".
  for_each = {
    for pair in [
      for yaml in split(
        "\n---\n",
        "\n${replace(data.http.crd.body, "/(?m)^---[[:blank:]]*(#.*)?$/", "---")}\n"
      ) :
      [yamldecode(yaml), yaml]
      if trimspace(replace(yaml, "/(?m)(^[[:blank:]]*(#.*)?$)+/", "")) != ""
    ] : "${pair.0["kind"]}--${pair.0["metadata"]["name"]}" => pair.1
  }
  yaml_body = each.value
}

一旦 Hashicorp 修复kubernetes_manifest,我建议使用相同的方法。不要使用count+element(),因为如果元素的顺序发生变化,Terraform 将删除/重新创建许多不需要它的资源。

resource "kubernetes_manifest" "crd" {
  for_each = {
    for value in [
      for yaml in split(
        "\n---\n",
        "\n${replace(data.http.crd.body, "/(?m)^---[[:blank:]]*(#.*)?$/", "---")}\n"
      ) :
      yamldecode(yaml)
      if trimspace(replace(yaml, "/(?m)(^[[:blank:]]*(#.*)?$)+/", "")) != ""
    ] : "${value["kind"]}--${value["metadata"]["name"]}" => value
  }
  manifest = each.value
}

PS 请支持多文档的Terraform功能请求yamldecode。将使事情比上面的正则表达式容易得多。

于 2021-10-11T14:17:37.257 回答