我最近才来跨傀儡继承。围绕它的几个问题:
使用 puppet 继承是一个好习惯吗?一些有经验的puppet同事告诉我puppet的继承不是很好,我不太相信。
来自 OO 世界,我真的很想深入了解 puppet 继承是如何工作的,以及覆盖是如何工作的。
我最近才来跨傀儡继承。围绕它的几个问题:
使用 puppet 继承是一个好习惯吗?一些有经验的puppet同事告诉我puppet的继承不是很好,我不太相信。
来自 OO 世界,我真的很想深入了解 puppet 继承是如何工作的,以及覆盖是如何工作的。
这取决于,因为有两种类型的继承,你没有提到你的意思。
节点继承:从一个node fqdn { }
定义继承到另一个。强烈建议不要这样做,因为它往往不符合最小意外原则。抓住人们的经典例子是这样的:
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
(或另一个“通用”/“基”类)来修复。然后,您也可以使用参数化类。
类继承:类继承的用途是您可以覆盖父类中定义的资源的参数。以这种方式重新实现上面的示例,我们得到:
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...
}
这确实有效,但我会避免深入一层以上的继承,因为维护起来很头疼。
不过,在这两个示例中,可以通过提前指定数据(通过 ENC)或通过 extlookup 或 hiera 查询内联数据来轻松改进它们。
希望以上示例有所帮助。类继承只允许覆盖参数 - 您不能删除以前定义的资源(一个常见问题)。始终使用大写类型名称引用资源(file { ..: }
将成为File[..]
)。
同样有用的是,您还可以将参数定义为undef
,有效地取消设置它们。
首先,我只是说明两者之间的区别,继承是一种“is-a”关系,Composition 是一种“has-a”关系。
1) 在 puppet 继承中是单继承,这意味着我们不能从多个类派生。继承在傀儡中很好,但我们应该知道它适用于何处。例如,Puppet 文档部分["Aside:When to Inherit" 在此链接https://docs.puppetlabs.com/puppet/latest/reference/lang_classes.html#aside-when-to-inherit],它们实际上准确地命名应该发生继承的两种情况:
但请注意这里的一些重要事项:
在 puppet 中,它们是节点和类继承之间的区别。
puppet 最近的新版本不允许节点继承,请检查此https://docs.puppetlabs.com/puppet/latest/reference/lang_node_definitions.html#inheritance-is-not-allowed。
2)另一方面,组合是实现has-a关系的设计技术。我们可以使用include puppet 关键字和class { 'baseclass': }来完成,如果你想使用参数的话。
(请注意:在 puppet 中,我们可以多次使用“include”,但不能使用“class”语法,因为 puppet 会抱怨重复的类定义)
所以在 Puppet 中使用哪个(继承或组合)更好:这取决于我的意思是什么上下文,你现在正在编写什么 puppet 代码,以及理解 puppet 继承的局限性以及何时使用组合。
所以,我会尽量把这一切保持在几点:
1)首先,puppet 使用单继承模型。
2) 在 puppet 中,关于继承的普遍共识是仅在需要从 Base/Parent 继承默认值时使用它
3)但是看看这个问题,你想从父级继承默认值:
class apache {
}
class tomcat inherits apache {
}
class mysql inherits tomcat {
}
class commerceServer inherits mysql {
}
乍一看这看起来合乎逻辑,但请注意 MySQL 模块现在从 tomcat 类继承默认值和资源。这不仅没有任何意义,因为这些服务是不相关的,而且它还为错误最终出现在您的 puppet 清单中提供了机会。
4)因此,更好的方法是简单地对您希望使用的每个类(我的意思是组合)执行包含,因为这消除了所有这种性质的范围问题。
结论:我们可以尝试通过使用继承来简化我们的 puppet manifest,这可能就足够了,但它只能在一定程度上可行。如果您的环境增长到数百甚至数千台服务器,由 20 或 30 多种不同类型组成服务器,一些具有共享属性和细微差异,分布在多个环境中,您可能最终会得到一个无法管理的继承模块的错综复杂的网络。在这一点上,显而易见的选择是组合。
通过这些链接,它有助于以良好的方式理解 puppet 的组成和继承(他们个人帮助了我):
我基本上是一名程序员,个人是控制反转/依赖注入的坚定支持者,这是可以通过组合实现的概念/模式。