puppet-sysctl模块

  1. 先睹为快
  2. 代码讲解
  3. 扩展阅读
  4. 动手练习

sysctl命令被用于在内核运行时动态地修改内核的运行参数,系统可用的内核参数可在目录/proc/sys中查询。它包含了一些TCP/IP堆栈和虚拟内存系统的高级选项, 这可以让系统管理员提高对操作系统的性能进行调优。

本节要谈的puppet-sysctl模块是由个人维护的项目,其目的是在Puppet中提供管理sysctl的接口。

puppet-sysctl项目地址:https://github.com/duritong/puppet-sysctl

1.先睹为快

不想看下面大段的代码解析,已经跃跃欲试了?

OK,我们开始吧!

打开虚拟机终端并输入以下命令:

  1. $ 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文件的所有者和权限进行了管理。

  1. class sysctl::base {
  2. file { '/etc/sysctl.conf':
  3. ensure => 'present',
  4. owner => 'root',
  5. group => '0',
  6. mode => '0644',
  7. }
  8. }

2.2 define sysctl::value

define sysctl::value用于管理/etc/sysctl.conf文件中的配置项。这里,有三处值得展开解析。

  1. define sysctl::value (
  2. $value,
  3. $key = $name,
  4. $target = undef,
  5. ) {
  6. require sysctl::base
  7. $val1 = inline_template("<%= String(@value).split(/[\s\t]/).reject(&:empty?).flatten.join(\"\t\") %>")
  8. sysctl { $key :
  9. val => $val1,
  10. target => $target,
  11. before => Sysctl_runtime[$key],
  12. }
  13. sysctl_runtime { $key:
  14. val => $val1,
  15. }
  16. }

2.2.1 require函数

define sysctl::value出现了require函数 (注意:与require元参数不同),该函数可以声明一个或多个类,并与含有此函数的容器形成依赖关系。

  1. require sysctl::base

在该例中,Puppet在执行sysctl::value实例前,确保class sysctl::base的所有资源已被应用。

2.2.2 inline_template函数

define sysctl::value中出现了以下一段代码:

  1. $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等等,同时用户也可以通过规范进行扩展,上述代码中的sysctlsyscyl_runtimepuppet-sysctl模块中自定义的资源类型,我们会在后文中详细讲解其代码结构和实现等细节。

2.3 class sysctl::values

sysctl::values的代码同样也非常简洁,主要是对sysctl::value进行了封装:

  1. class sysctl::values($args, $defaults = {}) {
  2. create_resources(sysctl::value, $args, $defaults)
  3. }

2.3.1 create_resources函数

create_resources函数接受一个hash类型的参数,将其转换为一个资源集合并添加到catalog中。这么讲比较抽象,我们可以来看一个实际的例子。

假设,接到其他部门的需求,需要在线上开启Linux内核的IP转发功能,要在开启该功能的节点上声明两个sysctl::value实例。

  1. sysctl::value { 'net.ipv4.ip_forward':
  2. value => 1
  3. }
  4. sysctl::value { 'net.ipv6.conf.all.forwarding':
  5. value => 1
  6. }

然而,在事前运维工程师是无法知道服务器需要开启哪些内核参数,按照第一章的理解Hiera一节中提到的节点数据不应该和节点数据放在一起,下面看如何借助create_resources函数来解决这个问题。
在节点定义文件中预先加入:

  1. include ::sysctl::values

接着在common.yamlHiera文件中加入:

  1. ---
  2. sysctl::values:args:
  3. net.ipv4.ip_forward:
  4. value: 1
  5. net.ipv6.conf.all.forwarding:
  6. value: 1

现在只需要对sysctl::values:args参数进行改动就能实现动态地管理服务器上的所有内核参数了!

3.扩展阅读

4.动手练习

  1. 设置net.ipv4.tcp_timestamps参数为0
  2. 设置net.ipv4.tcp_rmem参数为4096 131072 131072(多个值)