0

我已经实现了一个 kubernetes terraform 提供程序,它将清单文件应用于 k8s 集群。我也创建了 .tf 文件,但是当我运行terraform init它时,它会从 terraform 注册表下载插件。

如何让我的插件运行 terraform 应用。

4

1 回答 1

0

调试 TerraForm 提供程序

了解设计

为了做到这一点,您首先必须了解 Go 是如何构建应用程序的,然后是 terraform 如何与它一起工作。

每个 terraform 提供程序都是一种module. 为了支持几乎任何语言的开放模块化系统,您需要能够动态加载模块并与它们交互。Terraform 也不例外。

然而,go lang 团队很久以前就决定编译成静态链接的应用程序;您拥有的任何依赖项都将被编译为 1 个单个二进制文件。与其他本地语言(如 C 或 C++)不同, 不使用a .dllor ;.so在运行时没有动态库可以加载,因此,模块化变成了另一个技巧。这样做是为了避免臭名昭著的dll 地狱,这种地狱在大多数现代系统都包含某种依赖管理之前非常普遍。是的,这仍然是一个问题。

每个 terraform 提供者都是它自己的迷你 RPC 服务器。当 terraform 运行您的提供程序时,它实际上会启动一个作为您的提供程序的新进程,并通过此 RPC 通道连接到它。使问题更加复杂的是,您的提供者进程的生命周期非常短暂。可能持续不超过几秒钟。这是您需要与调试器连接的过程

正常调试

通常,您会直接启动您的应用程序,并将模块加载到应用程序内存中。这就是您可以实际调试它的原因,因为您的调试器知道如何为您的提供者找到确切的内存地址。但是,您没有这种安排,您需要进行远程调试会话。

难题

因此,您不会直接加载 terraform,即使您这样做了,您的module(也就是您的提供者)位于完全不同进程的内存空间中;这可能持续不超过几秒钟。

解决方案

  1. 您需要调试工具delve
  2. 您将不得不在代码中要开始调试的位置附近放置一些 shim 代码。我们需要在连接之前阻止此提供程序进程退出。所以,把这段代码放在适当的位置:
    connected := false
    for !connected {
        time.Sleep(time.Second) // set breakpoint here
    }

这段代码有效地创建了一个无限睡眠循环;但这实际上对于解决问题至关重要。

  1. 在此循环内放置一个断点。它还不会做任何事情。
  2. 现在运行您需要的 terraform 命令,以使用您想要调试的代码。这样做后,terraform 将基本上停止,因为它等待您的提供者的响应;因为你放了一个无限睡眠循环
  3. 您现在必须告诉delve使用它的 PID 连接到这个远程进程。这并不像看起来那么难。运行此命令: dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient attach $(pgrep terraform-provider-artifactory) 最后一个参数PID为您的提供者获取并提供它以delve进行连接。运行此命令后,您将立即到达断点。请确保替换terraform-provider-artifactory您的提供商名称
  4. 要退出此无限循环,请使用调试器设置connectedtrue. 通过这样做,您可以更改循环谓词,它将在下一次迭代中退出此循环。
  5. 调试!- 此时,您可以跨步、观察、删除调用堆栈等。您的整个武器库都可用
于 2021-08-13T23:59:26.360 回答