傀儡继承VS木偶组成

时间:2012-06-22 10:02:04

标签: puppet

我最近刚刚来到了傀儡遗产。围绕它的一些问题:

  1. 使用木偶继承是一种好习惯吗?一些有经验的傀儡同事告诉我,傀儡中的遗产不是很好,我不太相信。

  2. 来自OO世界,我真的想在封面下理解,傀儡继承是如何运作的,以及如何压倒一切。

2 个答案:

答案 0 :(得分:40)

  1. 这取决于,因为有两种类型的继承,你没有提到你的意思。

    1. 节点继承:从一个node fqdn { }定义继承到另一个。特别强烈建议这样做,因为它往往会失败the principle of least surprise。吸引人们的典型例子是:

      node base {
        $mta_config = "main.cf.normal"
        include mta::postfix  # uses $mta_config internally
      }
      node mailserver inherits base {
        $mta_config = "main.cf.mailserver"
      }
      

      $mta_config变量在基本范围内进行评估,因此在邮件服务器中尝试的“覆盖”不起作用。

      没有办法直接影响父节点中的内容,因此对构图的好处不大。这个例子将通过删除继承并从两者中包括mta::postfix(或另一个“common”/“base”类)来解决。然后,您也可以使用parameterised classes

    2. 类继承:类继承的用途是可以覆盖父类中定义的资源的参数。以这种方式重新实现上面的例子,我们得到:

      class mta::postfix {
        file { "/etc/postfix/main.cf":
          source => "puppet:///modules/mta/main.cf.normal",
        }
        service { ... }
      }
      
      class mta::postfix::server inherits mta::postfix {
        File["/etc/postfix/main.cf"]:
          source => "puppet:///modules/mta/main.cf.server",
        }
        # other config...
      }
      

      这确实有效,但我会避免进行多层次的继承,因为它很难维护。

    3. 在这两个例子中,通过提前指定数据(通过ENC)或通过extlookup或hiera内联查询数据,可以轻松改进它们。

  2. 希望以上示例有所帮助。类继承允许仅覆盖参数 - 您无法删除以前定义的资源(常见问题)。始终使用大写类型名称引用资源(file { ..: }将成为File[..])。

    同样有用的是,您还可以将参数定义为undef,有效地取消设置。

答案 1 :(得分:3)

首先,我只是指定两者之间的差异,继承是“is-a”关系,而Composition是“has-a”关系。

1)在puppet继承中单继承,这意味着,我们不能从多个类派生。傀儡的继承是好的,但我们应该知道它适用的地方。例如, Puppet docs部分 [“Aside:When to Inherit”在此链接https://docs.puppetlabs.com/puppet/latest/reference/lang_classes.html#aside-when-to-inherit],它们实际上只列出了两种情况,即继承应该发生:

  • 当您要覆盖在中定义的资源的参数时 父类
  • 如果要从标准参数值的参数类继承

但请注意一些重要的事情:

2)另一方面,组合是实现有关系的设计技术。我们可以使用包含puppet关键字以及 class {'baseclass':} 来执行,后者是,如果您想使用参数。

请注意:在傀儡中,我们可以多次使用“include”而不是“class”语法,因为puppet会抱怨重复的类定义)< / p>

那么(继承或组合)最好在Puppet中使用:这取决于我的意思是什么,你现在正在写什么木偶代码并理解木偶的局限性继承和何时使用组合。

所以,我会尝试将所有这些保持在几点:

1)首先,puppet使用单继承模型。

2)在puppet中,关于继承的一般共识是仅在需要从Base / Parent继承默认值时使用它

3)但是看看这个问题,你要从父级继承默认值:

class apache {
}

class tomcat inherits apache {
}

class mysql inherits tomcat {
}

class commerceServer inherits mysql {
}

乍一看,这看似合乎逻辑,但请注意,MySQL模块现在继承了tomcat类的默认值和资源。这不仅没有意义,因为这些服务是无关的,它也提供了错误最终进入你的木偶清单的机会。

4)所以更好的方法是简单地在你希望使用的每个类(我的意思是组合)上执行包含,因为这消除了这种性质的所有范围问题。

结论:我们可以通过使用继承来尝试简化我们的木偶清单,这可能就足够了,但它只能在某一点上起作用。如果你的环境增长到数百甚至数千服务器由20或30种不同类型的服务器组成,其中一些具有共享属性和细微差别,分布在多个环境中,您可能最终会得到一个无法管理的遗留模块的纠结网络。在这一点上,明显的选择是构图。

通过这些链接,有助于以良好的方式理解傀儡的构成和继承(他们个人帮助我):

  1. 设计Puppet - 非常好,http://www.craigdunn.org/2012/05/239/
  2. Wiki链接:http://en.wikipedia.org/wiki/Composition_over_inheritance
  3. 使用参数化类建模类组合:https://puppetlabs.com/blog/modeling-class-composition-with-parameterized-classes
  4. 我基本上是一名程序员,个人是控制/依赖注入反转的强力支持者,这是通过组合可能实现的概念/模式。