我正在浏览terraform
指南,其中作者正在使用docker_image
和docker_container
资源旋转docker设置。
main.tf
文件包括和required_providers
和provider
块,如下所示:
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
}
}
}
provider "docker" {}
为什么两者都需要?
难道terraform
不能理解docker
提供程序的需求吗?
provider "docker" {}
在考虑Terraform提供程序时,需要考虑两个相关的概念:提供程序本身,以及提供程序的配置。
作为一个类比,这里的提供程序kreuzwerker/docker
有点像您从另一个库导入的类,给它一个本地名称docker
。为了更具体一点,我将使用伪javascript语法:
var docker = require("kreuzwerker/docker");
然而,到目前为止,我们所拥有的只是类本身。为了使用它,我们需要创建它的实例,在Terraform的术语中称为"配置"。同样,使用伪javascript语法:
var dockerInstance = new docker({});
Terraform的语法显然没有这个伪javascript表单那么显式,但是我们可以通过在配置中添加第二个提供商实例来使区别更明显,在Terraform中,我们通过为它分配一个配置"别名":
provider "docker" {
alias = "example"
host = "ssh://user@remote-host:22"
}
这就像是创建了提供者"类"的第二个实例。在我们的伪javascript示例中:
var dockerInstance2 = new docker({
host: 'ssh://user@remote-host:22'
});
另一个显示这种区别的变体是当一个模块从它的调用模块继承提供者配置时。在这种情况下,就好像调用模块隐式地将提供程序配置(实例)传递到模块中,但子模块仍然需要导入提供程序"类";因此,Terraform可以看到我们正在谈论的是kreuzwerker/docker
,而不是任何其他可能具有"docker"名称的提供商。
地形有一些自动的"魔法"这些行为试图使更简单的情况隐式化,但不幸的是,这样做的代价是,当事情变得更复杂时,很难理解发生了什么。提供程序和提供程序配置是一个特别困难的例子,因为提供程序已经在Terraform语言中使用了很长时间,而该语言的当前版本正在努力保持与简单用法的广泛向后兼容,同时仍然允许从多个命名空间安装第三方提供程序等新特性。
这里特别令人困惑的假设是,如果您不声明特定的提供商,Terraform将创建一个隐式的required_providers
声明,假设您的意思是hashicorp/
名称空间中的提供商,这使得required_providers
似乎仅适用于第三方提供商。事实上,这很大程度上是一种向后兼容机制,所以我建议总是写出required_providers
条目,即使是hashicorp/
名称空间中的提供者,这样经验不足的读者不需要知道这种特殊的向后兼容行为。但是,在您的情况下,您使用的提供程序无论如何都在第三方名称空间中,因此required_providers
条目是强制性的。
需要提供source
,因为这不是"官方的";HashiCorp提供者。可能有多个名为"docker"的提供程序。因此需要提供source
,以便告诉Terraform准确地下载哪个提供程序。