在Terraform提供程序中映射全局资源的最佳方法是什么?

huangapple go评论84阅读模式
英文:

Best approach to map global resources in terraform provider

问题

我正在为一个软件编写一个 Terraform 提供程序,该软件具有大量的实例特定全局配置(大约有 300 个)。当您使用该提供程序时,您需要定义终端点和凭据,然后在该实例中进行操作。我正在努力决定如何管理这个配置。它不是一个创建或销毁的资源,所以我不确定是否创建一个 global_config 资源是最好的方法。由于所有的值在系统设置期间已经初始化,并且只能被覆盖;配置不能被销毁;您不能拥有超过两个配置资源。由于您应该能够覆盖所有条目,它也不能是一个数据源。

到目前为止,我还没有找到任何相关的文档(甚至是类似的示例),所以如果有人能指点我任何相关的内容,或者建议如何最好地实现这一点,我将非常感激。谢谢。

英文:

I'm writing a terraform provider for a software, which has a large set of instance specific global configurations (approximately 300 of them). When you use the provider, you define your endpoint and credentials and then operate within this instance. What I'm struggling to decide is how exactly to manage this config. It's not a resource that is created or destroyed, so I'm not sure if creating a global_config resource would be the best approach. Since all the values will already have been initialised during the setup of the system and can only be overridden; the config cannot be destroyed; you can't have more than two config resources. Since you should be able to override all entries, it can't be a data source either.

I haven't managed to find any relevant documentation (or even similar examples) so far, so I would be very grateful, if someone could point me to anything relevant, or suggest how to best achieve this. Thanks.

答案1

得分: 1

Terraform的提供程序模型主要设计用于Terraform本身可以创建或销毁的对象。它没有内置支持自动“采用”现有对象以处于Terraform的管理之下,因为Terraform通常假设每个对象都由一个声明的资源实例管理,并且Terraform旨在通过创建对象来保持这种假设。

然而,在其他系统中存在一些此类“单例”对象的示例,这些对象隐式创建,但可以更改其设置。值得研究的关键示例是AWS中默认VPC及其默认公共子网的资源类型。

目前有两种广泛的方法可以在Terraform中表示这种情况,但两种方法都不完美,因此各自都有一些优点和缺点需要考虑:

  • 强制性的terraform import:您可以构建资源类型,使其“创建”操作始终立即失败,并告诉用户导入现有对象,然后使用terraform import命令实现“导入”操作,以允许用户显式地将其现有对象绑定到Terraform资源实例。

    这是两种选项中更明确的一种,因为它要求用户_有意地_声明现有对象应由此Terraform配置管理,就像用户在Terraform中通常采取的那样。这意味着用户仍然控制,并且可以(如导入时必须始终执行的操作)确保将该对象导入到一个Terraform配置中的一个资源实例中,从而保持Terraform的唯一性假设。

    然而,这也为使用此资源类型的任何Terraform配置添加了一个强制性的额外设置步骤。这个额外的步骤不适合Typical automation around Terraform,因此通常需要以异常方式在团队的正常工作流之外进行。

  • 将“创建”视为“采用”:由于提供程序为资源类型预期实现的操作只是一种约定,没有技术上的原因使您的“创建”操作不能仅验证配置的对象是否存在,并在不创建任何内容的情况下返回成功。我在这里称之为“采用”,表示Terraform将假设此现有对象现在由声称创建它的任何资源实例独占管理,但“采用”实际上不是Terraform工作流程的正式部分。

    这样做的好处是它很好地适应了现有的Terraform工作流程,操作员不需要额外的不寻常步骤。

    然而,这也意味着更容易意外地将同一个对象采用到两个不同的资源实例中,无论是在同一个配置中还是在不同的配置中。这样做的后果将取决于对象代表的内容,但至少很可能导致不同的资源实例相互“争夺”,在每次新的Terraform运行中不断撤消彼此的工作,从而无法达到稳定的期望状态。

这两种方法中的第二种更方便,因此是现有提供程序通常选择的方法,只要错误的多次采用的后果仅仅是系统无法收敛:这种情况令人困惑和有点烦人,但通常并不会造成太大的伤害。

第一种方法更安全,因为它防止了意外多次采用的问题。如果两个配置争夺控制单个对象可能会产生更重大的后果,例如一个配置通过更改其设置以对其他用例无效的方式来“破坏”另一个配置,那么这种方法可能是合适的。

英文:

Terraform's provider model is designed primarily for objects that Terraform itself can create or destroy. There is no built-in support for automatically "adopting" an existing object to be under Terraform's management, because Terraform generally assumes that each object is managed by exactly one declared resource instance and Terraform aims to preserve that assumption by being the one to have created the object.

However, there are some existing examples in other systems of this sort of "singleton" object that is implicitly created but can have its settings changed. Key examples for study are the resource types for default VPCs and their default public subnets in AWS.

There are currently two broad ways to represent this situation in Terraform, neither of which is perfect and so each of which has some advantages and disadvantages to consider:

  • Mandatory terraform import: you can potentially build your resource type so that its "create" action always immediately fails telling the user to import the existing object, and then to implement the "import" action to allow users to explicitly bind their existing object to their Terraform resource instance using the terraform import command.

    This is the more explicit of the two options in that it requires the user to intentionally declare that the existing object should be managed by this Terraform configuration, in the same way that users normally take that action in Terraform. This means that the user remains in control and can (as they must always do when importing) take care to import that object into only one resource instance in one Terraform configuration, thereby preserving Terraform's uniqueness assumption.

    However, it also adds a mandatory extra setup step to any Terraform configuration which uses this resource type. That extra step does not fit well into typical automation around Terraform, and so that step will often need to be taken in an exceptional way outside of a team's normal workflow.

  • Treat "create" as if it were "adopt": since the actions a provider is expected to implement for a resource type are just a matter convention, there's no technical reason that your "create" action cannot just verify that the configured object exists and return success without creating anything. I call that "adopting" here to represent the idea that Terraform will then assume that this existing object is now under the exclusive management of whatever resource instance claimed to have created it, but "adopting" is not actually a formal part of Terraform's workflow.

    This has the advantage of fitting well into an existing Terraform workflow, requiring no unusual additional steps on the part of the operator.

    However, it also means that it's easier to accidentally adopt the same object into two different resource instances, either in the same configuration or in separate configurations. The consequences of doing that will vary depending on what the object represents, but at minimum it will likely result in the different resource instances "fighting" one another, constantly undoing each other's work on each new Terraform run and thus never converging on a stable desired state.

The second of these is the more convenient of the two and so is the one that existing providers have typically chosen as long as the consequences of incorrect multiple-adoption are just the risk of a non-converging system: that situation is confusing and kinda annoying, but also often not super harmful.

The first is the safer of the two because it guards against the accidental multiple-adoption problem. It could be appropriate if two configurations fighting to control a single object may have more significant consequences, such as one configuration breaking the other one by changing its settings in a way that is invalid for the other use-case.

huangapple
  • 本文由 发表于 2022年8月25日 18:16:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/73485790.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定