【问题标题】:How to use Puppet parameterized classes to force order of resources applied?如何使用 Puppet 参数化类来强制应用资源的顺序?
【发布时间】:2012-07-24 17:01:00
【问题描述】:

Puppetlabs 文档指出,为了让一个类需要另一个类,您应该使用关系链语法并在外部节点中声明这两个类。

我有一个 repo 类,它创建每个模块中的许多包所依赖的 yum repo 定义。在每个模块中,我都有一个 Class['repo'] -> Class['modulename'] 语句,并且两个类都在节点中声明。但是,当 puppet 运行时,它并不总是像预期的那样在模块类之前执行 repo 类。为什么不?下面的例子(puppet 2.6.16):

编辑:似乎有 3 个基本解决方案可以解决这个问题。

  1. 使用资源依赖替换类依赖 before/require 元参数(如图灵机的答案所示)。
  2. 移除外部类依赖并显式声明依赖 内部类之间。
  3. 使用 Puppetlabs 在 stdlib 模块中提供的锚类型 包含一个允许依赖类创建引用的类 使用链接语法到外部类。

那么,考虑到 Puppet v3 以及未来将重构保持在最低限度的愿望,这些方法中哪一种最好?

清单puppettest.pp:

class { 'repo': }
class { 'maradns': }

class repo {
  class { 'repo::custom': }
}

class repo::custom {
  yumrepo {'custom':
    enabled  => 1,
    gpgcheck => 0,
    descr    => "Local respository - ${::architecture}",
    baseurl  => 'http://repo.nike.local/CentOS/\$releasever/\$basearch';
  }
}

class maradns {
  Class['repo'] -> Class['maradns::install']
  Class['maradns::install'] -> Class['maradns::config']
  Class['maradns::config'] ~> Class['maradns::service']
  class { 'maradns::install': }
  class { 'maradns::config':  }
  class { 'maradns::service': }
}

class maradns::install {
  package { 'maradns':
    ensure  => present,
  }
}

class maradns::config {
  file { 'mararc':
    ensure  => present,
    path    => '/etc/mararc',
    mode    => '0644',
    owner   => root,
    group   => root,
  }
}

class maradns::service {
  service { 'maradns':
    ensure     => running,
    enable     => true,
    hasrestart => true,
  }
}

输出:

puppet apply puppettest.pp    
err: /Stage[main]/Maradns::Install/Package[maradns]/ensure: change from absent to present failed: Execution of '/usr/bin/yum -d 0 -e 0 -y install maradns' returned 1: Error: Nothing to do

notice: /Stage[main]/Maradns::Config/File[mararc]: Dependency Package[maradns] has failures: true
warning: /Stage[main]/Maradns::Config/File[mararc]: Skipping because of failed dependencies
notice: /Stage[main]/Maradns::Service/Service[maradns]: Dependency Package[maradns] has failures: true
warning: /Stage[main]/Maradns::Service/Service[maradns]: Skipping because of failed dependencies
notice: /Stage[main]/Repo::Custom/Yumrepo[custom]/descr: descr changed '' to 'Local respository - x86_64'
notice: /Stage[main]/Repo::Custom/Yumrepo[custom]/baseurl: baseurl changed '' to 'http://repo.test.com/CentOS/\$releasever/\$basearch'
notice: /Stage[main]/Repo::Custom/Yumrepo[custom]/enabled: enabled changed '' to '1'
notice: /Stage[main]/Repo::Custom/Yumrepo[custom]/gpgcheck: gpgcheck changed '' to '0'
notice: Finished catalog run in 2.15 seconds

【问题讨论】:

  • 根据你的旗帜,@Michelle,我已经删除了赏金评论。不幸的是,它无法更改。然而,即使没有通知,悬赏问题也会引起注意。
  • 我喜欢你的想法。我认为它在 3.2.* 中解决了吗?

标签: puppet


【解决方案1】:

调试依赖问题的一个很好的起点是指示 puppet 生成依赖图。

puppet apply --graph --noop manifest.pp
dot -Tpng /var/lib/puppet/state/graphs/relationships.dot -o relationships.png

通过这样做,您会看到 repo:custom 类根本没有依赖信息。

maradns::install 肯定依赖于repo 类,但不依赖于repo::custom 类,因为repo::custom 不依赖于repo

新的类声明语法class {'classname':} 没有设置任何依赖关系,它的行为就像include classname 语法一样。

因此,要么设置从 repo::customrepo 的依赖关系,要么指示 maradns::install 类直接依赖于 repo:custom 类。

但是你会遇到更多的麻烦。对类的依赖只会确保应用这个类。但是,不会对包含资源设置依赖项。

我会像这样为您的案例建模:

class { 'repo:custom': }
class { 'maradns': }

class repo {
}

class repo::custom {
  yumrepo {'custom':
    enabled  => 1,
    gpgcheck => 0,
    descr    => "Local respository - ${::architecture}",
    baseurl  => 'http://repo.nike.local/CentOS/\$releasever/\$basearch';
  }
}

class maradns {
  class{[
    'maradns::package',
    'maradns::config',
    'maradns::service',
  ]:}
}

class maradns::package {
  package { 'maradns':
    ensure  => present,
    require => Yumrepo['custom'],
  }
}

class maradns::config {
  file { 'marac:config':
    ensure  => present,
    mode    => '0644',
    owner   => root,
    group   => root,
  }
}

class maradns::service {
  service { 'maradns':
    ensure     => running,
    enable     => true,
    hasrestart => true,
    require => [
      Package['maradns'],
      File['mararc:config'],
    ],
  }
}

【讨论】:

    【解决方案2】:

    来自puppetlabs stdlib documentation

    在 Puppet 2.6 中,当一个类声明另一个类时, 内部类不包含在外部类中。这个 与从 较小的类,因为最终用户无法指定 外部类与其他模块的顺序关系。

    锚类型可让您解决此问题。通过夹入任何内部 包含的两个无操作资源之间的类 外部类,可以保证模块中的所有资源都是 包含。

    根据发布的清单,示例如下:

    清单puppettest.pp:

    class { 'repo': }
    class { 'maradns': }
    
    class repo {
      anchor { 'repo::begin': } ->
      class { 'repo::custom': } ->
      anchor { 'repo::end': }
    }
    
    class repo::custom {
      yumrepo {'custom':
        enabled  => 1,
        gpgcheck => 0,
        descr    => "Local respository - ${::architecture}",
        baseurl  => 'http://repo.nike.local/CentOS/\$releasever/\$basearch';
      }
    }
    
    class maradns {
      Class['repo'] -> Class['maradns::install']
      Class['maradns::install'] -> Class['maradns::config']
      Class['maradns::config'] ~> Class['maradns::service']
      class { 'maradns::install': }
      class { 'maradns::config':  }
      class { 'maradns::service': }
    }
    
    class maradns::install {
      package { 'maradns':
        ensure  => present,
      }
    }
    
    class maradns::config {
      file { 'mararc':
        ensure  => present,
        path    => '/etc/mararc',
        mode    => '0644',
        owner   => root,
        group   => root,
      }
    }
    
    class maradns::service {
      service { 'maradns':
        ensure     => running,
        enable     => true,
        hasrestart => true,
      }
    }
    

    【讨论】:

    • 这个答案已经过时了?我在文档中看不到这样的东西,而且它适用于 >3.2。 @michelle 你能验证一下吗?
    【解决方案3】:

    您是否考虑过将run stages 作为替代机制?通过运行阶段,您可以将类与“阶段”相关联。默认情况下,一切都发生在 ma​​in 阶段。但是您可以设置一个发生在 main 之前的阶段,然后将该类与该“main 之前”阶段相关联。

    回购是一个非常好的前阶段候选者。在按照您想要的方式设置存储库之前,您真的不希望检索任何包;如果您正在镜像自己的软件包回购并落后于官方回购,这可能会令人头疼。

    更棘手的情况是,当一个新的 puppetized 服务器在你声明你的 repo 之前意外地获取了一个包,它从最新的公共镜像中获取它;然后 您的 存储库已安装(假设您现在已删除公共镜像)。因为这台机器“潜入”了一个新的工件,所以很容易出现依赖地狱的情况,一个太新的包正在阻止你关心的包被安装,因为有问题的包不会安装,因为你已经安装了一个太- 新版本和许多包管理器不会为你降级;你必须手动干预。这种情况本质上需要手动调试才能修复;仅仅修复你的傀儡规则是不够的,因为损害已经造成。

    因此,只需将所有 repo 定义与之前的阶段相关联,然后就可以完成它。停止跟踪对你的包的依赖,以便更轻松地进行回购和呼吸。

    【讨论】:

      【解决方案4】:

      通过将 repo::custom 包含在 repo 中而不是直接依赖 repo::custom 可以获得什么?

      在这样的类中声明类的模式也可能会导致您出现重复定义。如果可能,我会专注于直接使用 repo::custom。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多