在CentOS 6上使用Hiera设置Puppet Server
开源Puppet是基于模型的声明式配置管理解决方案,使我们能够使用Puppet语言定义测试环境基础设施的状态。
换句话说,Puppet是一个配置管理系统。
Hiera是用于配置数据的键/值查找工具,旨在使Puppet更好,并允许我们设置特定于节点的数据而无需重复自己。
安装
添加Puppet存储库:
# rpm -ivh https://yum.puppetlabs.com/puppetlabs-release-el-6.noarch.rpm
安装Puppet服务器(Puppet 3.8版将Hiera安装为依赖项):
# yum install -y puppet-server
配置:Puppet主服务器
打开“ /etc/puppet/puppet.conf”进行编辑和配置,如下所示:
[main] # The Puppet log directory logdir = /var/log/puppet # Where Puppet PID files are kept rundir = /var/run/puppet # Where SSL certificates are kept ssldir = $vardir/ssl server = puppet.igi.local pluginsync = true parser = future # Merge recursively; in the event of a conflict, # allow higher priority values to win merge_behaviour = deeper # Environment variable that is used by Hiera environmet = prod [agent] # The file in which puppetd stores a list of the classes # associated with the retrieved configuration classfile = $vardir/classes.txt # Where puppetd caches the local configuration localconfig = $vardir/localconfig [master] # The comma-separated list of alternative DNS names to use for the local host. # When the node generates a CSR for itself, these are added to the request as # the desired subjectAltName in the certificate dns_alt_names = puppet,puppet.igi.local always_cache_features = true # If set to false, never autosign even if an autosign.conf file is written autosign = true
完成后,启动puppetmaster服务:
# /etc/init.d/puppetmaster start
允许服务在启动时启动:
# chkconfig puppetmaster on
Puppet master现在已启动并正在运行,但没有任何用处。
安装:Puppet模块
我们将使用以下Puppet模块:
# puppet module install puppetlabs-firewall ;\ puppet module install puppetlabs-ntp ;\ puppet module install erwbgy-limits ;\ puppet module install thias-sysctl ;\ puppet module install spiette-selinux ;\ puppet module install Aethylred-postfix ;\ puppet module install puppetlabs-apache ;\ puppet module install puppetlabs-mysql
配置:防火墙模块
创建一个自定义防火墙模块:
# mkdir -p /etc/puppet/modules/lsn_firewall/manifests
放置一些基本的元数据,以便在运行Puppet模块列表时可以看到它:
# cat << EOL > /etc/puppet/modules/lsn_firewall/metadata.json { "name": "lsn_firewall", "version": "1.0.0", "author": "www.theitroad.com", "summary": "Manages iptables firewall", "license": "", "source": "", "project_page": "", "issues_url": "", "operatingsystem_support": [], "requirements": [], "dependencies": [] } EOL
创建lsn_firewall :: pre和lsn_firewall :: post类
由于该部分主要基于PuppetForge文章而进行,因此无需多做解释:https://forge.puppetlabs.com/puppetlabs/firewall
我们的方法将采用白名单设置,因此我们可以定义所需的规则,而忽略所有其他规则,而不是删除所有其他规则。
防火墙规则的运行顺序为:
- lsn_firewall :: pre中的规则,
- 代码中定义的规则('lsn_firewall/manifests/init.pp'),
- 规则lsn_firewall :: post。
前置和后置类中的规则相当通用:允许新的传入SSH连接,允许所有相关/已建立的流量,记录并拒绝其他所有内容。
# cat << EOL > /etc/puppet/modules/lsn_firewall/manifests/pre.pp class lsn_firewall::pre { Firewall { require => undef, } # Default firewall rules firewall { '000 accept all icmp': proto => 'icmp', action => 'accept', }-> firewall { '001 accept all lo interface': proto => 'all', iniface => 'lo', action => 'accept', }-> firewall { '002 Allow ssh traffic': dport => [ 22 ], proto => 'tcp', state => ['NEW'], action => 'accept', } } EOL
# cat << EOL >/etc/puppet/modules/lsn_firewall/manifests/post.pp class lsn_firewall::post { firewall { '997 accept related/established': proto => 'all', state => ['RELATED', 'ESTABLISHED'], action => 'accept', }-> firewall { '998 Log sessions': jump => 'LOG', log_level => '4', log_prefix => 'iptables_input ', }-> firewall { '999 drop all': proto => 'all', action => 'drop', before => undef, } } EOL
从上面可以看到,规则允许基本的联网并确保不关闭现有连接。
创建防火墙规则
我们将为以下服务创建防火墙规则:
- Puppet主控(TCP 8140)
- HTTP/S(TCP 80,443)
- MySQL(TCP 3306)
- DNS(TCP 53,UDP 53)
- DHCP(UDP 67)
- NTP(UDP 123)
- SMTP(TCP 25)
可以根据需要添加更多服务。
大多数规则将仅限于内部10.0.0.0/8网络。
# cat << EOL > /etc/puppet/modules/lsn_firewall/manifests/init.pp class fw_puppet { firewall { '004 Allow puppet traffic': dport => [ 8140 ], source => '10.0.0.0/8', proto => tcp, action => accept, } } class fw_http { firewall { '005 Allow http/s traffic': dport => [ 80, 443 ], source => '10.0.0.0/8', proto => tcp, action => accept, } } class fw_mysql { firewall { '006 Allow MySQL traffic': dport => [ 3306 ], source => '10.0.0.0/8', proto => tcp, action => accept } } class fw_dns { firewall { '007 Allow BIND traffic TCP': dport => [ 53 ], source => '10.0.0.0/8', proto => tcp, action => accept } firewall { '008 Allow BIND traffic UDP': dport => [ 53 ], source => '10.0.0.0/8', proto => udp, action => accept } } class fw_dhcp { firewall { '009 Allow DHCP traffic': dport => [ 67 ], proto => udp, action => accept } } class fw_ntp { firewall { '010 Allow NTP traffic': dport => [ 123 ], source => '10.0.0.0/8', proto => udp, action => accept } } class fw_smtp { firewall { '011 Allow SMTP traffic': dport => [ 25 ], source => '10.0.0.0/8', proto => tcp, action => accept } } EOL
现在,我们要设置一个元类型来清除不受管理的防火墙资源,然后为所有防火墙规则设置默认参数。
这应该确保前置和后置类以正确的顺序运行。
我们还必须声明lsn_firewall :: pre和lsn_firewall :: post类以满足相关性。
最后一行是使用hiera_include函数将类分配给节点的方法(本文稍后将使用)。
# cat << EOL > /etc/puppet/manifests/site.pp # Clear any existing IPv4 rules and make sure that only # rules defined in Puppet exist on the machine resources { "firewall": purge => true } # Ensure that the pre and post classes are run in the correct # order to avoid locking us out of our box during the first # Puppet run Firewall { before => Class['lsn_firewall::post'], require => Class['lsn_firewall::pre'], } # Declare the pre and post classes to satisfy dependencies class { ['lsn_firewall::pre', 'lsn_firewall::post']: } # Assign classes to nodes using the hiera_include function hiera_include('classes') EOL
配置:希拉
层次结构和树结构
本文假设读者(至少)知道什么是希拉以及它应该如何工作。
我们将使用Hiera数据目录为'/etc/puppet/hieradata'的json后端。
层次结构如下:
- fqdn-来自事实,
- server_role-来自配置文件('/etc/puppet/server_role'),请参见下文,
- 环境-来自“ /etc/puppet/puppet.conf”文件。
我们将在'/etc/puppet/hieradata /'下使用以下树结构(按优先级从低到低的顺序排列):
- common.json-适用于所有节点,但可以被其他任何配置覆盖,
- env/envname.json-环境名称,例如“ prod”,
- server_role/role.json-服务器角色,例如“ puppetmaster”,“ mysql”等,
- node/fqdn.json-特定的节点配置(实际上并没有使用,除非节点需要某些特定的配置,而上述所有配置都无法使用)。
其中许多是由变量或者事实(因素)定义的。
每当从Puppet触发Hiera查找时,Hiera都会收到Puppet当前可用的所有变量的副本,包括顶级范围变量和局部变量。
我们可以使用facter加载并检查Puppet特定的事实:
# facter -p
创建一个新的server_role事实:
# cat << EOL > /etc/puppet/modules/stdlib/lib/facter/server_role.rb Facter.add("server_role") do setcode do Facter::Util::Resolution.exec("cat /etc/puppet/server_role") end end EOL
server_role事实将从“/etc/puppet/server_role”(需要创建此文件)中收集。
设定档
创建一个Hiera配置文件:
# cat << EOL > /etc/puppet/hiera.yaml -- :merge_behaviour: deeper :logger: console :backends: - json :json: :datadir: /etc/puppet/hieradata :hierarchy: - "node/%{::fqdn}" - "server_role/%{::server_role}" - "env/%{::environment}" - common EOL
创建一个符号链接:
# ln -sf /etc/puppet/hiera.yaml /etc/hiera.yaml
创建一个hieradata文件夹结构:
# mkdir -p /etc/puppet/hieradata/{node,server_role,env}
定义Puppet主服务器的服务器角色:
# echo "puppetmaster" > /etc/puppet/server_role
为环境创建hiera数据源文件:
# touch /etc/puppet/hieradata/env/{prod.json,dev.json}
为服务器角色创建hiera数据源文件:
# touch /etc/puppet/hieradata/server_role/{default.json,puppetmaster.json,mysql.json}
在此示例中,我们只有三个服务器角色,一个用于Puppet主服务器的puppetmaster角色,一个用于配置MySQL服务器的mysql服务器角色,以及一个用于其他所有服务器的默认服务器角色。
我们将以在产品中启用SELinux但在开发人员中将其设置为允许的方式配置环境。
配置还包括一些用于信息公开的Apache内容。
配置环境:
# cat << EOL > /etc/puppet/hieradata/env/prod.json { "classes": [ "selinux" ], "selinux::mode": "enforcing", "apache::server_signature": "Off", "apache::trace_enable": "Off", "apache::server_tokens": "Prod" } EOL
# cat << EOL > /etc/puppet/hieradata/env/dev.json { "classes": [ "selinux" ], "selinux::mode": "permissive", "apache::server_signature": "On", "apache::trace_enable": "On", "apache::server_tokens": "Full" } EOL
现在,我们可以为puppetmaster服务器角色创建一个Hiera配置。
该配置将执行以下操作:
- 配置防火墙以允许以下服务的传入流量:
- Puppet,HTTP/S,DNS,DHCP,NTP,SMTP,
- 配置NTP服务器。
创建文件:
# cat << EOL > /etc/puppet/hieradata/server_role/puppetmaster.json { "classes": [ "fw_puppet", "fw_http", "fw_dns", "fw_dhcp", "fw_ntp", "fw_smtp", "ntp" ], "ntp::enable": true, "ntp::servers": [ "0.uk.pool.ntp.org iburst", "1.uk.pool.ntp.org iburst", "2.uk.pool.ntp.org iburst", "3.uk.pool.ntp.org iburst" ], "ntp::servers": [ "0.uk.pool.ntp.org", "1.uk.pool.ntp.org", "2.uk.pool.ntp.org", "3.uk.pool.ntp.org" ], "ntp::interfaces": [ "0.0.0.0" ], "ntp::restrict": [ "-4 default kod nomodify notrap nopeer noquery", "-6 default kod nomodify notrap nopeer noquery", "127.0.0.1", "-6 ::1", "10.0.0.0 mask 255.0.0.0 nomodify notrap nopeer" ] } EOL
我们还将为mysql服务器角色创建一个Hiera配置,该配置将执行以下操作:
- 配置防火墙以允许传入的MySQL通信,
- 配置Postfix中继,
- 配置自定义Linux安全限制,
- 使用合理的参数配置MySQL服务器。
创建文件:
# cat << EOL > /etc/puppet/hieradata/server_role/mysql.json { "classes": [ "fw_mysql", "postfix", "mysql::server" ], "postfix::relayhost": "smtp.igi.local", "postfix::inet_interfaces": "localhost", "limits": { "mysql": { "nproc": { "soft": "4096" }, "nofile": { "soft": "4096" } } }, "mysql::server::create_root_user": "true", "mysql::server::root_password": "passwd", "mysql::server::create_root_my_cnf": "true", "mysql::server::remove_default_accounts": "false", "mysql::server::restart": "true", "mysql::server::override_options": { "mysqld": { "bind-address": "0.0.0.0", "datadir": "/var/lib/mysql", "socket": "/var/lib/mysql/mysql.sock", "symbolic-links": "0", "max_allowed_packet": "16M", "max_heap_table_size": "256M", "max_connections": "100", "wait_timeout": "60", "open_files_limit": "4096", "general_log_file": "/var/log/mysql/mysql.log", "general_log": "0", "server_id": "1", "expire_logs_days": "7", "max_binlog_size": "1G", "query_cache_type": "1", "query_cache_limit": "16M", "thread_cache_size": "8", "key_buffer_size": "64M", "innodb_buffer_pool_size": "32M", "innodb_additional_mem_pool_size": "32M", "innodb_log_buffer_size": "10M", "tmp_table_size": "256M", "query_cache_size": "64M", "read_buffer_size": "1M", "read_rnd_buffer_size": "256K", "sort_buffer_size": "2M", "join_buffer_size": "1M", "thread_stack": "256K", "binlog_cache_size": "32K", "innodb_file_per_table": "1", "innodb_flush_method": "fsync", "innodb_flush_log_at_trx_commit": "1", "innodb_log_file_size": "32M", "innodb_lock_wait_timeout": "100", "innodb_data_file_path": "ibdata1:16M:autoextend:max:2048M" }, "client": { "socket": "/var/lib/mysql/mysql.sock" }, "mysqld_safe": { "socket": "/var/lib/mysql/mysql.sock" }, "mysqldump": { "max_allowed_packet": "16M" } } } EOL
默认服务器角色具有仅配置的后缀中继:
# cat << EOL > /etc/puppet/hieradata/server_role/default.json { "classes": [ "postfix" ], "postfix::relayhost": "smtp.igi.local", "postfix::inet_interfaces": "localhost" } EOL
最后一点是创建一个Hiera通用数据源文件。
当Hiera找不到层次结构中其他位置的给定键的匹配项时,此文件将提供我们要使用的任何默认值。
默认配置将包括以下内容:
- 防火墙,
- NTP,
- Postfix中继,
- Linux安全限制
- sysctl内核参数。
创建文件:
# cat << EOL > /etc/puppet/hieradata/common.json { "classes": [ "firewall", "ntp", "limits", "sysctl::base" ], "apache::serveradmin": "Hyman@theitroad", "apache::server_signature": "Off", "apache::trace_enable": "Off", "apache::server_tokens": "Prod", "ntp::package_ensure": "present", "ntp::service_enable": true, "ntp::service_ensure": "running", "ntp::servers": [ "ntp.igi.local" ], "ntp::iburst_enable": true, "ntp::interfaces": [ "127.0.0.1" ], "ntp::restrict": [ "default ignore", "-6 default ignore", "127.0.0.1", "-6 ::1" ], "limits": { "*": { "nofile": { "soft": "2048", "hard": "65536" }, "nproc": { "soft": "2048", "hard": "16384" }, "locks": { "soft": "2048", "hard": "2048" }, "stack": { "soft": "10240", "hard": "32768" }, "fsize": { "soft": " 33554432", "hard": "67108864" }, "memlock": { "soft": "64", "hard": "64" }, "core": { "hard": "0" } }, "root": { "nofile": { "soft": "2048", "hard": "65536" }, "nproc": { "soft": "2048", "hard": "16384" }, "stack": { "soft": "10240", "hard": "32768" }, "fsize": { "soft": "33554432" } } }, "sysctl::base::values": { "fs.suid_dumpable": { "value": "0" }, "vm.swappiness": { "value": "0" }, "kernel.panic": { "value": "10" }, "kernel.sysrq": { "value": "0" }, "kernel.core_uses_pid": { "value": "1" }, "kernel.dmesg_restrict": { "value": "1" }, "kernel.kptr_restrict": { "value": "1" }, "kernel.msgmnb": { "value": "65536" }, "kernel.msgmax": { "value": "65536" }, "kernel.shmmax": { "value": "1073741824" }, "kernel.shmall": { "value": "262144" }, "kernel.exec-shield": { "value": "1" }, "kernel.randomize_va_space": { "value": "2" }, "kernel.pid_max": { "value": "32768" }, "net.core.wmem_max": { "value": "12582912" }, "net.core.rmem_max": { "value": "12582912" }, "net.core.netdev_max_backlog": { "value": "5000" }, "net.ipv4.ip_forward": { "value": "0" }, "net.ipv4.tcp_syncookies": { "value": "1" }, "net.ipv4.tcp_rmem": { "value": "4096 87380 16777216" }, "net.ipv4.tcp_wmem": { "value": "4096 65536 16777216" }, "net.ipv4.tcp_window_scaling": { "value": "1" }, "net.ipv4.tcp_sack": { "value": "1" }, "net.ipv4.tcp_timestamps": { "value": "1" }, "net.ipv4.tcp_no_metrics_save": { "value": "1" }, "net.ipv4.conf.all.accept_source_route": { "value": "0"}, "net.ipv4.conf.default.accept_source_route": { "value": "0" }, "net.ipv4.conf.all.send_redirects": { "value": "0" }, "net.ipv4.conf.all.accept_redirects": { "value": "0" }, "net.ipv4.conf.all.secure_redirects": { "value": "0" }, "net.ipv4.conf.default.send_redirects": { "value": "0" }, "net.ipv4.conf.default.accept_redirects": { "value": "0" }, "net.ipv4.conf.default.secure_redirects": { "value": "0" }, "net.ipv4.conf.all.rp_filter": { "value": "1" }, "net.ipv4.conf.default.rp_filter": { "value": "1" }, "net.ipv4.conf.all.log_martians ": { "value": "1" }, "net.ipv4.conf.default.log_martians": { "value": "1" }, "net.ipv4.icmp_echo_ignore_broadcasts": { "value": "1" }, "net.ipv4.icmp_ignore_bogus_error_messages": { "value": "1" }, "net.ipv4.icmp_ignore_bogus_error_responses": { "value": "1" }, "net.bridge.bridge-nf-call-iptables": { "value": "0" }, "net.bridge.bridge-nf-call-arptables": { "value": "0" }, "net.ipv6.conf.all.rp_filter": { "value": "1" }, "net.ipv6.conf.all.accept_ra": { "value": "0" }, "net.ipv6.conf.default.accept_ra": { "value": "0" }, "net.ipv6.conf.all.accept_redirects": { "value": "0" }, "net.ipv6.conf.default.accept_redirects": { "value": "0" } } } EOL
检查Puppet模块列表:
# puppet module list
现在该手动触发在puppetmaster上运行的Puppet客户端了:
# puppet agent -t
现在,我们应该看到我们的主节点已连接:
# puppet cert list -all