将动态数据传递到导出的资源

Pass dynamic data to an exported resource

对于我的工作,我们正在尝试使用 Puppet 启动一个 docker swarm 集群。我们为此使用 puppetlabs-docker,它有一个模块 docker::swarm。该模块允许您在主节点上实例化一个 docker 群管理器。这到目前为止有效。

在 docker worker 上,你可以加入 docker swarm manager 导出资源:

node 'manager' {
  @@docker::swarm {'cluster_worker':
    join           => true,
    advertise_addr => '192.168.1.2',
    listen_addr    => '192.168.1.2',
    manager_ip     => '192.168.1.1',
    token          => 'your_join_token'
    tag            => 'docker-join'
  }
}

但是,your_join_token 需要使用 docker swarm join-token worker -q 从 docker 集群管理器中检索。这可以通过 Exec.

我的问题是:有没有办法(在不破坏 Puppet 关于幂等和收敛的哲学的情况下)从连接令牌 Exec 获取输出并将其传递给导出的资源,以便我的工作人员可以加入master吗?

My question is: is there a way (without breaking Puppet philosophy on idempotent and convergence) to get the output from the join-token Exec and pass this along to the exported resource, so that my workers can join master?

不,因为资源声明的属性,导出或其他,是在构建目标节点的目录时(在主节点上)确定的,而 Exec 资源的命令是 运行仅稍后,当 fully-built 目录应用于目标节点时。

我不确定令牌生成的详细要求,但您可以使用 Puppet 的 generate() 功能在主目录构建期间根据需要获得一个。

更新

另一种选择是外部(或自定义)事实。这是从节点收集信息以在该节点的目录构建期间使用的常规机制,因此,它可能更适合您的特定需求。这有一些潜在的问题,但我不确定有多少实际适用:

  • 事实必须知道为哪些节点生成加入令牌。根据包括

    在内的因素,这可能更容易/更健壮或更棘手/更脆弱
    • 加入令牌是否 node-specific(如果是则更难)
    • 避免为同一节点生成多个连接令牌是否重要(在多个 Puppet 运行s 上;如果这很重要则更难)
    • 尽管有上述规定,是否需要为已经生成一个节点生成一个新的连接令牌(如果这是一个要求则更难)
  • 如果作为 dynamically-generated 外部事实实施——这似乎是一个合理的选择——那么当一个新节点被添加到列表中时,事实实施将在经理的下一个人偶 运行,但要等到下一个人偶才能获得数据。然而,这不一定是什么大问题,因为它是每个新节点的 one-time 延迟,并且您始终可以在管理器节点上手动执行目录 运行 以更快地移动事物.

  • 它有更多的活动部分,它们之间的关系更复杂,因此存在更大的 cross-section 错误和意外行为。

感谢@John Bollinger,我似乎已经解决了我的问题。最后,它比我想象的要多一些,但就是这个想法:

  1. 我的人偶设置现在使用 PuppetDB 来存储事实和共享导出的资源。
  2. 我在 Docker 的代码库中添加了一个额外的自定义事实(在 ./lib/facter/docker.rb 中)。
  3. site.pp 文件中的最低限度,现在包含:
node 'manager' {
  docker::swarm {'cluster_manager':
    init           => true,
    advertise_addr => "${::ipaddress}",
    listen_addr    => "${::ipaddress}",
    require        => Class['docker'],
  }

  @@docker::swarm {'cluster_worker':
    join           => true,
    manager_ip     => "${::ipaddress}",
    token          => "${worker_join_token}",
    tag            => "cluster_join_command",
    require        => Class['docker'],
  }
}

node 'worker' {
  Docker::Swarm<<| tag == 'cluster_join_command' |>> {
    advertise_addr => "${::ipaddress}",
    listen_addr    => "${::ipaddress}",
  }
}

请记住,要使其正常工作,puppet agent -t 必须在 manager 节点上 运行 两次,并在 [=15= 节点上(在此之后)一次] 节点。管理器上的第一个 运行 将启动 cluster_manager,而第二个将获取 worker_join_token 并将其上传到 PuppetDB。设置此事实后,可以正确编译 worker 的清单并且 运行.

在不同模块的情况下,您必须自己添加自定义事实。当我研究如何做到这一点时,我将自定义事实添加到 ruby 的 LOAD_PATH,但无法在我的 PuppetDB 中找到它。经过一些浏览后,我发现模块中的事实已上传到 PuppetDB,这就是我调整上游 Docker 模块的原因。