【问题标题】:How to debug Terraform external providers with concurrency issues?如何调试存在并发问题的 Terraform 外部提供程序?
【发布时间】:2021-03-05 09:42:34
【问题描述】:

我使用 Terraform 0.14.7 来部署我的基础架构。由于我使用 AWS Lambda 作为我的 Whook API 的部署目标,因此我有很多脚本(7 个不同的,但一个为所有 lambdas ~200 运行的脚本)来检索有关 API 和每个 lambdas 的各种信息(请参阅此示例: https://github.com/nfroidure/whook/pull/108/files#diff-47625134d02e23a98ccff7918d11baa19c2ac409f4c90d76520b031b613b555cR74-R78)。

为此,我使用了 external 提供程序,它期望一些 JSON 作为回报。我的各种命令确实返回 JSON,但事实是我的 terraform plan -out=terraform.plan 失败并显示一条消息:“错误:命令“env”生成无效 JSON:JSON 输入意外结束”。

到目前为止我尝试了什么:

  • 运行TF_LOG=TRACE terraform plan -out=terraform.plan 2>&1:计划执行正确。我对这种意外成功的猜测是,在某种程度上,某些资源(文件描述符、内存?)存在并发问题,因为写入大量跟踪日志的事实的背压可能会降低并发性。也就是说,我不确定,也许跟踪/调试模式本身会降低并发性?
  • 运行TF_LOG=TRACE terraform plan -out=terraform.plan 2>&1 | grep terraform-provider-external > out.txt:它重现了错误,但是,日志中没有任何异常……甚至上述错误似乎合法。也许您有一个 grep 的想法,可以在减少日志容量的同时捕获更多信息,以避免上述背压
  • env 创建别名至少可以知道哪个命令失败,但 terraform 似乎不喜欢别名
  • 通过注入器中的调试日志服务记录命令的 JSON 输出,但一切正常。

我目前正在使用tee 命令创建外部脚本以在 bash 级别上输出,但我怀疑它需要更多的文件描述符,所以不确定这是一个好方法。

除此之外,我真的不知道如何摆脱这个问题,所以我在创建问题之前尝试在这里为 Terraform 中的外部提供程序获取更详细的输出。

感谢您的帮助:)

更新: 通过这样做,我设法找出了错误的 JSON:

data "external" "lambdas" {
  program     = [
    "bash", "-ec",
    <<-EOF
    echo \"env NODE_ENV=${terraform.workspace} npx whook terraformValues --type='lambdas'\" >> lambdas-stderr.log
    env NODE_ENV=${terraform.workspace} npx whook terraformValues --type='lambdas' 2>> lambdas-stderr.log | tee lambdas-stdout.log
    EOF
  ]
  working_dir = ".."
}

它基本上将 stderr 写入一个文件,将 stdout 写入另一个文件,同时仍将 stdout 代理到命令输出。

有了它,我可以遍历所有保存的文件并发现错误的 JSON 是一个截断为 65536 字节 (2^16) 的 JSON,所以我认为某处存在一些限制。如果我设法找出限制 JSON 大小的原因,会及时通知您。

为了每次都重现该问题,我不得不将 parallelism 选项设置为 100。它认为它可能与管道缓冲区大小有关(参见 https://unix.stackexchange.com/questions/11946/how-big-is-the-pipe-buffer),并且在某些情况下,输出读取块和没有背压机制考虑到这一点。

【问题讨论】:

  • 得到帮助,terraform plan -out=terraform.plan -parallelism=5 可以工作!也就是说,问题仍然存在,因为它修复了我的部署,但我不知道背后的并发问题。
  • 这听起来很像依赖问题,但我们需要查看 MCVE 来进一步提供帮助。
  • 我将等待最终提示,以便从外部插件中获得更多见解,如果没有,我将尝试在上面的链接中添加几个端点,并希望它足以允许任何人重现行为。

标签: terraform


【解决方案1】:

我终于找到了问题所在。 JSON 被截断,因为子进程退出时主要没有刷新输出。在此处查看 NodeJS 子流程的详细信息:https://nodejs.org/api/process.html#process_process_exit_code

背压已生效,因此仅传输了标准输出缓冲区大小 (64kb),其余 JSON 被截断。最后,与 Terraform 无关。

【讨论】:

    猜你喜欢
    • 2018-12-14
    • 2021-07-13
    • 2021-05-05
    • 2019-11-23
    • 1970-01-01
    • 2020-05-16
    • 2021-11-15
    • 1970-01-01
    • 2021-10-17
    相关资源
    最近更新 更多