简介
随着各种业务对IT服务的依赖器重,企业IT基础架构,规模不断扩张。作为一名系统工程师我们将如何应对这种日益增长的IT架构呢?以前系统工程师就像流水线上的工人,不断重复做着同样工作,现在这一切即将改变,我们将引入运维自动化工具puppet。本章首先介绍puppet的工作原理,然后介绍puppet的部署与应用。
1.案例概述
作为一名系统管理员,维护服务器正常运行是最基本的职责,在管理几台到几十台服务器时,大部分系统管理员喜欢写自己的小工具来维护,但是随着服务器数量的增多,任务量也逐渐增加,这时就需要简洁的,强大的框架来完成系统管理任务。
2.案例前置知识点
puppet工作原理如下。
puppet的目的是让管理员只集中于要管理的目标,而忽略实现的细节。puppet既可以在单个机器上使用,也可以C/S结构使用。在大规模使用puppet的情况下,通常使用C/S结构,在这种结构中puppet客户端之运行puppetclient,puppet服务器端只运行puppetmaster。
具体的工作流程如图12.1所示
(1)客户端puppet调用facter(facter是通过ssl加密收集及检测分析客户端配置信息的一个工具),facter探测出主机的一些变量,如主机名、内存大小、ip地址等。puppet把这些信息通过ssl连接发送到服务器端。
(2)服务器端的puppetmaster通过facter工具分析检测客户端的主机名,然后找到项目主配置文件manifest里对应的node配置,并对部分内容进行解析。facter发送过来的信息可以作为变量处理,node牵涉到的代码才解析,其他没牵涉到的代码不解析。解析分为几个阶段,首先进行语法检查,如语法没错,就继续解析,解析的结果生成一个中间的“伪代码”,然后把伪代码发送到客户端。
(3)客户端收到“伪代码”并且执行,客户端把执行结果发送给服务器。
(4)服务器端把客户端的执行结果写入日志。
puppet工作过程中有以下两个点值得注意。
(1)为了保证安全,client和master之间是基于ssl和证书的,只有经master证书认证的client可以与master通信。
(2)puppet会让系统保持在人们所期望的某种状态并一直维持下去,如检测到某个文件并保证其一直存在,保证ssh服务始终开启,如果文件被删除了或者ssh服务被关闭了,puppet下次执行时(默认30分钟),会重新创建该文件或者启动ssh服务。
1.搭建时间同步服务器
由于facter使用SSL证书,依赖时间同步,所有需要搭建NTP服务器
1)搭建NTP Server
[root@RHEL6-Server4 ~]# yum -y install ntp
[root@RHEL6-Server4 ~]# vim /etc/ntp.conf
server 127.127.1.0
fudge 127.127.1.0 stratum 8
当/etc/ntp.conf文件中的server都不可用时,使用local时间作为NTP server 提供给 client
[root@RHEL6-Server4 ~]# service ntpd start
[root@RHEL6-Server4 ~]# chkconfig ntpd on
2.搭建 puppetmaster
1)规划服务器主机名
在小规模puppet环境下,修改/etc/hosts文件,在上千台服务器环境下,需要自己搭建DNS服务器来保证服务器直接通过主机名通信。
[root@RHEL6-Server1 ~]# vim /etc/sysconfig/network
HOSTNAME=master.test.cn
[root@RHEL6-Server1 ~]# hostname master.test.cn
[root@RHEL6-Server1 ~]# bash
[root@master ~]# vim /etc/hosts
192.168.200.211 master.test.cn
192.168.200.212 client1.test.cn
192.168.200.213 client2.test.cn
2)puppetmaster 作为NTP客户端的配置
[root@master ~]# yum -y install ntpdate
[root@master ~]# ntpdate 192.168.200.214
3)安装ruby
先安装compat-readline5
[root@master ~]# mount /dev/cdrom /media/cdrom/
[root@master ~]# rpm -ivh /media/cdrom/Packages/compat-readline5-5.2-17.1.el6.x86_64.rpm
[root@master ~]# rpm -ivh ruby-*
检查ruby的版本
[root@master ~]# ruby -v
ruby 1.8.7 (2011-06-30 patchlevel 352) [x86_64-linux]
4)安装puppet facter
[root@master ~]# useradd -s /sbin/nologin puppet
通过facter工具分析检测客户端传输过来的信息
a) 安装facter:
[root@master ~]# tar xf facter-1.7.1.tar.gz
[root@master ~]# cd facter-1.7.1
[root@master facter-1.7.1]# ruby install.rb
b) 安装puppet:
[root@master ~]# tar xf puppet-2.7.21.tar.gz
[root@master ~]# cd puppet-2.7.21
[root@master puppet-2.7.21]# ruby install.rb
c) 复制配置文件
[root@master puppet-2.7.21]# cp conf/redhat/fileserver.conf /etc/puppet/
[root@master puppet-2.7.21]# cp conf/redhat/puppet.conf /etc/puppet/
[root@master puppet-2.7.21]# cp conf/redhat/server.init /etc/init.d/puppetmaster
d) 修改文件属性
[root@master puppet-2.7.21]# chmod +x /etc/init.d/puppetmaster
e) 创建puppet主目录
[root@master ~]# mkdir /etc/puppet/manifests
[root@master ~]# mkdir /etc/puppet/modules
f) puppet服务证书请求与签名
生产环境中iptables默认都是全部关闭的
master端配置:
[root@master ~]# service iptables stop
g) 修改配置文件:配置服务器模块路径 在main标题下
[root@master ~]# vim /etc/puppet/puppet.conf
13 modulepath = /etc/puppet/modules:/usr/share/puppet/modules
h) 启动puppet主程序
[root@master ~]# /etc/init.d/puppetmaster start
启动 puppetmaster: [确定]
3.搭建puppetclient
配置puppetclient1
1)规划服务器主机名
[root@RHEL6-Server2 ~]# vim /etc/sysconfig/network
HOSTNAME=client1.test.cn
[root@RHEL6-Server2 ~]# hostname client1.test.cn
[root@RHEL6-Server2 ~]# bash
[root@client1 ~]# vim /etc/hosts
192.168.200.211 master.test.cn
192.168.200.212 client1.test.cn
192.168.200.213 client2.test.cn
确保通过主机与master通信
[root@client1 ~]# ping master.test.cn
PING master.test.cn (192.168.200.211) 56(84) bytes of data.
64 bytes from master.test.cn (192.168.200.211): icmp_seq=1 ttl=64 time=0.509 ms
2)服务器时间同步
[root@client1 ~]# yum -y install ntpdate
[root@client1 ~]# ntpdate 192.168.200.214
3)安装ruby
先安装compat-readline5
[root@client1 ~]# mount /dev/cdrom /media/cdrom/
[root@client1 ~]# rpm -ivh /media/cdrom/Packages/compat-readline5-5.2-17.1.el6.x86_64.rpm
[root@client1 ~]# rpm -ivh ruby-*
检查ruby的版本
[root@client1 ~]# ruby -v
ruby 1.8.7 (2011-06-30 patchlevel 352) [x86_64-linux]
4)安装puppet facter
[root@client1 ~]# useradd -s /sbin/nologin puppet
通过facter工具分析检测客户端传输过来的信息
a) 安装facter:
[root@client1 ~]# tar xf facter-1.7.1.tar.gz
[root@client1 ~]# cd facter-1.7.1
[root@client1 facter-1.7.1]# ruby install.rb
b) 安装puppet:
[root@client1 ~]# tar xf puppet-2.7.21.tar.gz
[root@client1 ~]# cd puppet-2.7.21
[root@client1 puppet-2.7.21]# ruby install.rb
c) 复制配置文件
[root@client1 puppet-2.7.21]# cp conf/redhat/puppet.conf /etc/puppet/
[root@client1 puppet-2.7.21]# cp conf/redhat/client.init /etc/init.d/puppetclient
d) 修改文件属性
[root@client1 puppet-2.7.21]# chmod +x /etc/init.d/puppetclient
e) puppet服务证书请求与签名
生产环境中iptables默认都是全部关闭的
master端配置:
[root@client1 puppet-2.7.21]# service iptables stop
f) 修改配置文件:配置服务器的域名 在main标题下
[root@client1 ~]# vim /etc/puppet/puppet.conf
13 server = master.test.cn
puppetclient1 与 puppetclient2 配置基本一致,注意主机名
g)申请与注册
puppetclient1 与 puppetclient2 上进行注册
[root@client1 ~]# puppet agent --server=master.test.cn --no-daemonize --verbose
info: Creating a new SSL key for client2.test.cn
info: Caching certificate for ca
info: Creating a new SSL certificate request for client2.test.cn
info: Certificate Request fingerprint (md5): D8:FF:EC:D9:F8:58:52:69:21:07:3C:7A:05:D3:BB:AF
此时可以按Ctrl+C,因为puppet一直等待任务
master端:查看申请注册的客户端:
[root@master ~]# puppet cert --list
"client1.test.cn" (B8:30:C5:19:4F:15:0F:D6:49:27:88:D6:0C:36:8F:EB)
"client2.test.cn" (D8:FF:EC:D9:F8:58:52:69:21:07:3C:7A:05:D3:BB:AF)
将未注册的客户端进行注册:
[root@master ~]# puppet cert sign --all
notice: Signed certificate request for client2.test.cn
notice: Removing file Puppet::SSL::CertificateRequest client2.test.cn at '/var/lib/puppet/ssl/ca/requests/client2.test.cn.pem'
notice: Signed certificate request for client1.test.cn
notice: Removing file Puppet::SSL::CertificateRequest client1.test.cn at '/var/lib/puppet/ssl/ca/requests/client1.test.cn.pem'
通过目录去查看已经注册的客户端:
[root@master ~]# ll /var/lib/puppet/ssl/ca/signed/
总用量 12
-rw-r----- 1 puppet puppet 1911 10月 21 17:57 client1.test.cn.pem
-rw-r----- 1 puppet puppet 1911 10月 21 17:57 client2.test.cn.pem
-rw-r----- 1 puppet puppet 1976 10月 21 17:25 master.test.cn.pem
客户端已经完成证书的申请与签名;
4.配置实例
4.1 配置一个测试节点
节点信息:/etc/puppet/manifests/nodes
模块信息:/etc/puppet/modules
为了保护Linux的ssh端口爆破,批量修改客户端sshd端口,将端口22修改为9922并实现重启工作。
创建ssh模块,模块目录为ssh,模块下面有三个文件:manifests,templates和files。
manifests里面必须要包含一个init.pp的文件,这是该模块的初始(入口)文件,导入一个模块的时候,会从init.pp开始开始执行。可以把所有的代码都写到init.pp里面,也可以分成多个pp文件,init再去包含其他文件,定义class类名的时候必须是ssh,这样能实现调用。
files 目录是该模块的文件发布目录,puppet提供一个文件分发机制,类似于rsync的模块
templates目录包含erb模型文件,这个和files资源的template属性有关(很少用)
master端:
1)创建需要的必要目录。
[root@master ~]# mkdir -p /etc/puppet/modules/ssh/{manifests,templates,files}
[root@master ~]# mkdir /etc/puppet/manifests/nodes
[root@master ~]# mkdir /etc/puppet/modules/ssh/files/ssh
[root@master ~]# chown -R puppet /etc/puppet/modules/
[root@master ~]# ls -l /etc/puppet/modules/ssh/
总用量 12
drwxr-xr-x 3 puppet root 4096 10月 21 18:05 files
drwxr-xr-x 2 puppet root 4096 10月 21 18:05 manifests
drwxr-xr-x 2 puppet root 4096 10月 21 18:04 templates
2)创建模块配置文件install.pp(首先确定客户端安装ssh服务)
[root@master ~]# vim /etc/puppet/modules/ssh/manifests/install.pp
class ssh::install{
package{ "openssh":
ensure => present,
}
}
3)创建模块配置文件config.pp (配置需要同步的文件)
[root@master ~]# vim /etc/puppet/modules/ssh/manifests/config.pp
class ssh::config {
file { "/etc/ssh/sshd_config": //配置客户端需要同步的文件
ensure => present, //确定客户端此文件存在
owner => "root",
group => "root",
mode => "0600",
source => "puppet://$puppetserver/modules/ssh/ssh/sshd_config", //从服务器端同步文件 $puppetserver 指定 /etc/puppet 文件
require => Class["ssh::install"], //调用install.pp确定ssh已经安装
notify => Class["ssh::service"], //如果config.pp发生变化通知service.pp
}
}
4)创建模块配置文件service.pp
[root@master ~]# vim /etc/puppet/modules/ssh/manifests/service.pp
class ssh::service {
service { "sshd": //确定ssh运行
ensure => running,
hasstatus => true, //puppet该服务支持status命令,类似service sshd status
hasrestart => true, //puppet该服务支持restart命令,类似service sshd restart
enable => true, //服务器是否开机启动
require => Class["ssh::config"] //确认config.pp调用
}
}
class ssh::service {
service { "sshd":
ensure => running,
hasstatus => true,
hasrestart => true,
enable => true,
require => Class["ssh::config"]
}
}
5)创建模块配置文件init.pp
[root@master ~]# vim /etc/puppet/modules/ssh/manifests/init.pp
class ssh {
include ssh::install,ssh::config,ssh::service
}
[root@master ~]# ll /etc/puppet/modules/ssh/manifests/
总用量 16
-rw-r--r-- 1 root root 254 10月 21 18:16 config.pp
-rw-r--r-- 1 root root 60 10月 21 18:23 init.pp
-rw-r--r-- 1 root root 65 10月 21 18:09 install.pp
-rw-r--r-- 1 root root 148 10月 21 18:19 service.pp
6)建立服务器端 ssh 统一维护文件
由于服务器端和客户端sshd_config 文件默认一样,将服务端配置文件复制到模块默认路径
[root@master ~]# cp /etc/ssh/sshd_config /etc/puppet/modules/ssh/files/ssh/
[root@master ~]# chown puppet /etc/puppet/modules/ssh/files/ssh/sshd_config
7)创建测试节点配置文件,并将ssh加载进去
[root@master ~]# vim /etc/puppet/manifests/nodes/ssh.pp
node 'client1.test.cn' {
include ssh
}
node 'client2.test.cn' {
include ssh
}
8) 将测试节点载入puppet,即修改site.pp
[root@master ~]# vim /etc/puppet/manifests/site.pp
import "nodes/ssh.pp"
9) 修改服务器端维护的sshd_config配置文件
[root@master ~]# vim /etc/puppet/modules/ssh/files/ssh/sshd_config
Port 9922
10)重启puppet
[root@master ~]# /etc/init.d/puppetmaster restart
停止 puppetmaster: [确定]
启动 puppetmaster: [确定]
4.2 客户端主动拉取
一般在小规模自动化集群中,如代码上线需重启服务时,为了防止网站暂时性无法访问的问题,每台客户端运行一次puppet agent -t命令,选择模式根据客户端集群规模大小,根据经验,一般运维工程师puppet服务器到客户端会建立ssh信任,然后自定义shell脚本,ssh批量让客户端执行puppet同步命令。
Client端:192.168.200.212 端执行命令如下:
[root@client2 ~]# puppet agent -t
info: Caching catalog for client2.test.cn
info: Applying configuration version '1445426326'
notice: /Stage[main]/Ssh::Config/File[/etc/ssh/sshd_config]/content:
--- /etc/ssh/sshd_config 2015-08-08 16:39:36.986999633 +0800
+++ /tmp/puppet-file20151022-57210-s37jl6-0 2015-10-22 19:24:28.555648885 +0800
@@ -10,7 +10,7 @@
# possible, but leave them commented. Uncommented options change a
# default value.
-Port 22
+Port 9922
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
info: FileBucket adding {md5}00d0f172a955e42dcb9dc5074afee3e8
info: /Stage[main]/Ssh::Config/File[/etc/ssh/sshd_config]: Filebucketed /etc/ssh/sshd_config to puppet with sum 00d0f172a955e42dcb9dc5074afee3e8
notice: /Stage[main]/Ssh::Config/File[/etc/ssh/sshd_config]/content: content changed '{md5}00d0f172a955e42dcb9dc5074afee3e8' to '{md5}470d359ae263214d5319f2c8ef4014ae'
info: /Stage[main]/Ssh::Config/File[/etc/ssh/sshd_config]: Scheduling refresh of Class[Ssh::Service]
info: Class[Ssh::Service]: Scheduling refresh of Service[sshd]
notice: /Stage[main]/Ssh::Service/Service[sshd]: Triggered 'refresh' from 1 events
info: Creating state file /var/lib/puppet/state/state.yaml
notice: Finished catalog run in 3.75 seconds
此时,在客户端已经成功执行。验证如下
[root@client1 ~]# grep "9922" /etc/ssh/sshd_config
Port 9922
查看服务器ssh服务重启,端口是否生效
[root@client1 ~]# netstat -anpt | grep sshd
tcp 0 0 0.0.0.0:9922 0.0.0.0:* LISTEN 61132/sshd
tcp 0 52 192.168.200.212:22 192.168.200.1:64178 ESTABLISHED 57619/sshd
tcp 0 0 :::9922 :::* LISTEN 61132/sshd
4.3 服务器推送同步
当大规模部署时采用服务器推送模式。
Client端:192.168.200.212端修改
1) 修改配置文件:
[root@client1 ~]# vi /etc/puppet/puppet.conf 最后添加一行如下:
listen = true //使puppet监听8139端口
[root@client1 ~]# vi /etc/puppet/auth.conf //验证配置文件auth.conf定义一些验证信息及访问权限,最后一行添加如下:
allow * //允许任何服务器端推送
启动puppet客户端
[root@client1 ~]# sed -n '11,15p' /etc/ssh/sshd_config
# default value.
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
[root@client1 ~]# /etc/init.d/puppetclient start
启动 puppet: [确定]
稍等一会儿再去查看
[root@client1 ~]# sed -n '11,15p' /etc/ssh/sshd_config
# default value.
Port 9922
#AddressFamily any
#ListenAddress 0.0.0.0
Master端也可以强制推送
[root@master ~]# puppet kick client1.test.cn
Triggering client1.test.cn
Getting status
status is success
client1.test.cn finished with exit code 0
Finished