puppet-sysctl
模块
sysctl
命令被用于在内核运行时动态地修改内核的运行参数,系统可用的内核参数可在目录/proc/sys中查询。它包含了一些TCP/IP堆栈和虚拟内存系统的高级选项, 这可以让系统管理员提高对操作系统的性能进行调优。
本节要谈的puppet-sysctl
模块是由个人维护的项目,其目的是在Puppet中提供管理sysctl的接口。
puppet-sysctl
项目地址:https://github.com/duritong/puppet-sysctl
1.先睹为快
不想看下面大段的代码解析,已经跃跃欲试了?
OK,我们开始吧!
打开虚拟机终端并输入以下命令:
$ puppet apply -e 'sysctl::value { "net.ipv4.tcp_syncookies": value => "1"}'
这将开启内核中的tcp_syscookieds
参数,常用于抵御synflood
攻击。
我们打开puppet-sysctl
模块下manifests/base.pp
文件来一探究竟吧。
2.代码解析
2.1 class sysctl::base
sysctl::base
是该模块仅有的一个类,其中的代码逻辑也非常简单,仅对/etc/sysctl.conf
文件的所有者和权限进行了管理。
class sysctl::base {
file { '/etc/sysctl.conf':
ensure => 'present',
owner => 'root',
group => '0',
mode => '0644',
}
}
2.2 define sysctl::value
define sysctl::value
用于管理/etc/sysctl.conf
文件中的配置项。这里,有三处值得展开解析。
define sysctl::value (
$value,
$key = $name,
$target = undef,
) {
require sysctl::base
$val1 = inline_template("<%= String(@value).split(/[\s\t]/).reject(&:empty?).flatten.join(\"\t\") %>")
sysctl { $key :
val => $val1,
target => $target,
before => Sysctl_runtime[$key],
}
sysctl_runtime { $key:
val => $val1,
}
}
2.2.1 require
函数
在define sysctl::value
出现了require
函数 (注意:与require
元参数不同),该函数可以声明一个或多个类,并与含有此函数的容器形成依赖关系。
require sysctl::base
在该例中,Puppet在执行sysctl::value
实例前,确保class sysctl::base
的所有资源已被应用。
2.2.2 inline_template
函数
在define sysctl::value
中出现了以下一段代码:
$val1 = inline_template("<%= String(@value).split(/[\s\t]/).reject(&:empty?).flatten.join(\"\t\") %>")
inline_template
函数和template
函数类似,可以简单地认为是只有一个字符串的模板。inline_template
对模板求值后,生成字符串,常用于复杂的字符串拼接。
在前文中,已经提到标签<%= %>
是插入值表达式,在该表达式中:首先对$value
做字符串格式转换,然后以正则表达式\s
和\t
匹配进行字符串切割,去除空数组,对数组flatten操作,再做字符串连接。
2.2.3 自定义资源类型
Puppet中有大量内置的资源类型,如user
,package
等等,同时用户也可以通过规范进行扩展,上述代码中的sysctl
和syscyl_runtime
是puppet-sysctl
模块中自定义的资源类型,我们会在后文中详细讲解其代码结构和实现等细节。
2.3 class sysctl::values
sysctl::values
的代码同样也非常简洁,主要是对sysctl::value
进行了封装:
class sysctl::values($args, $defaults = {}) {
create_resources(sysctl::value, $args, $defaults)
}
2.3.1 create_resources
函数
create_resources
函数接受一个hash类型的参数,将其转换为一个资源集合并添加到catalog中。这么讲比较抽象,我们可以来看一个实际的例子。
假设,接到其他部门的需求,需要在线上开启Linux内核的IP转发功能,要在开启该功能的节点上声明两个sysctl::value
实例。
sysctl::value { 'net.ipv4.ip_forward':
value => 1
}
sysctl::value { 'net.ipv6.conf.all.forwarding':
value => 1
}
然而,在事前运维工程师是无法知道服务器需要开启哪些内核参数,按照第一章的理解Hiera
一节中提到的节点数据不应该和节点数据放在一起,下面看如何借助create_resources
函数来解决这个问题。
在节点定义文件中预先加入:
include ::sysctl::values
接着在common.yaml
Hiera文件中加入:
---
sysctl::values:args:
net.ipv4.ip_forward:
value: 1
net.ipv6.conf.all.forwarding:
value: 1
现在只需要对sysctl:args
参数进行改动就能实现动态地管理服务器上的所有内核参数了!
3.扩展阅读
- https://docs.puppet.com/puppet/latest/function.html#createresources
- https://docs.puppet.com/puppet/4.10/lang_template.html#with-a-template-string-inlinetemplate-and-inlineepp
- https://docs.puppet.com/puppet/4.10/lang_classes.html#using-require
4.动手练习
- 设置
net.ipv4.tcp_timestamps
参数为0 - 设置
net.ipv4.tcp_rmem
参数为4096
131072
131072
(多个值)