我正在尝试使用puppetlabs/docker
模块运行docker容器。但是,当Puppet代理试图运行容器时,我收到错误
Error: Failed to apply catalog: No such file or directory - docker
在Puppet尝试创建容器之前,似乎没有安装docker守护进程和docker客户端。
配置的摘录如下:
Puppetfile
# frozen_string_literal: true
forge 'https://forge.puppet.com'
# Modules from the Puppet Forge
# ...
mod 'puppetlabs-docker', '4.4.0'
# ...
agent.pp
class profile::runner::agent (
Enum[present, absent] $ensure = present,
String $version = undef,
String $image = undef,
String $container_name = "${facts['group']}-agent",
Array[String] $container_environment = [],
) {
class { 'docker':
version => $version,
}
# ...
docker::run { $container_name:
ensure => $ensure,
image => $image,
env => $container_environment,
net => 'host',
restart => 'unless-stopped',
}
# ...
}
我的理解是,puppetlabs/docker
模块的这个配置应该确保在任何容器启动之前安装docker。我考虑过对模块本身做一个bug报告,但这个问题肯定是如此普遍,如果它还没有被报告,我会感到惊讶。所以我断定我一定是做错了什么。
我已经尝试了通常的元参数,但似乎没有任何效果,并导致同样的错误。例如,我尝试过
docker::run { $container_name:
ensure => $ensure,
image => $image,
env => $container_environment,
net => 'host',
restart => 'unless-stopped',
require => Class['docker'], # and also Package['docker']
}
值得一提的是,Puppet代理运行在RockyLinux上,因此是RedHat操作系统系列。如果我从配置中删除docker::run
,然后运行Puppet代理,则目录成功应用,但容器当然不会运行。然后将docker::run
添加回配置并再次运行代理将成功运行容器。这表明有一个依赖项问题我无法解决。
由于链接箭头和元参数似乎在这种特定情况下都没有影响,我不得不使用一个保护子句来解决这个问题,该子句检查Docker是否使用puppetlabs/docker
模块提供的事实安装
if $facts['docker_client_version'] != undef {
docker::run { $container_name:
ensure => $ensure,
image => $image,
env => $container_environment,
net => 'host',
restart => 'unless-stopped',
}
}
这是不理想的,因为它需要在运行容器之前应用两次编目,但它确实解决了这个问题。
声明的类之间不会自动排序,也不会相对于同一上下文中声明的资源进行排序。有很好的理由,但它们与问题无关。
但是,您可以使用与用于资源的相同技术来对类施加相对排序:before
、require
、notify
和subscribe
元参数,以及链接箭头。对于您的特殊情况,您可能还可以使用require函数(即使您还使用类docker
的类声明,但在这种情况下,类资源声明必须在require
之前)。
例如,这是一种非常好的方法,可以确保在每个docker::run
实例之前应用docker
类,无论声明在哪里:
class { 'docker':
version => $version,
}
-> Docker::Run<||>
但是,确实有实现您可能已经声明的任何虚拟docker::run
实例的副作用。如果这是一个问题,那么使用其他替代方案之一。