Winse Blog

走走停停, 熙熙攘攘, 忙忙碌碌, 不知何畏.

Puppet批量自动化部署实战

断断续续使用Puppet近一年,多次体验到Puppet的强大:SSH更新、需ROOT权限批量处理等等。这次集群新上架了又爽了一把。把整个过程记录下来,方便今后参考。

运维的同事也想了解puppet,在docker容器上安装了一遍,把具体的内容附上:expect+puppet.txt

这次操作是对以前零零碎碎积累的一次检验和温习。需要用到的工具比较多:

  • RPM打包、本地YUM仓库 - RPMBUILD、CREATEREPO
  • SSH无密钥登录 - EXPECT&FOR
  • 时间同步、host配置 - SCP、SSH&FOR
  • 创建用户、新用户无密钥等 - PUPPET
  • ssh_known_hosts - PUPPETDB
  • rhel.repo、gmond、时区设置 - PUPPET

远程配置机器首先当然是进行无密钥登录的设置,这样才能进行批量操作,不然几百台机器每次都需要干预太烦人、工作量太大。无密钥登录使用原来写好的EXPECT脚本,使用FOR循环执行,等待结果即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@hadoop-master1 ~]# cat ssh-copy-id.expect 
#!/usr/bin/expect  

## Usage $0 [user@]host password

set host [lrange $argv 0 0];
set password [lrange $argv 1 1] ;

set timeout 30;

spawn ssh-copy-id $host ;

expect {
  "(yes/no)?" { send yes\n; exp_continue; }
  "password:" { send $password\n; exp_continue; }
}

exec sleep 1;

# 用for,不要用while
for h in `cat /etc/hosts | grep -v '^#' | grep slaver | grep -E '\.36\.|\.37\.' | awk '{print $2}' ` ; do 
  ./ssh-copy-id.expect $h 'PASSWD';
done

做好无密钥登录,拷贝 /etc/hosts, /etc/cron.daily/ntp.cron, /etc/yum.repos.d/puppet.repo 到全部的新机器。这里puppet.repo是自己编译搭建的私有仓库(具体编译配置步骤查看puppet分类下的文章),通过 yum install mcollective-plugins-simple 就可以把mcolletive和puppet-agent安装好。把所有步骤封装到一个prepare.sh脚本,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/sh

# must be hostname!!
HOSTS="$@"
PASSWD=${PASSWD:-'root'}
PUPPETSERVER="hadoop-master1"

for h in $HOSTS ; do ./ssh-copy-id.expect $h "$PASSWD" ; done

for h in $HOSTS ; do
scp /etc/hosts $h:/etc ;
scp /etc/yum.repos.d/puppet.repo $h:/etc/yum.repos.d/ ;
scp /etc/cron.daily/ntp.cron $h:/etc/cron.daily/ ;

ssh $h '
#ntpdate cu-omc1 #着重注意
rm -rf /etc/yum.repos.d/CentOS-*
yum install mcollective-plugins-simple -y
' ;

scp /etc/puppetlabs/mcollective/server.cfg $h:/etc/puppetlabs/mcollective/
ssh $h "
sed -i '/HOSTNAME/ {
i \
HOSTNAME=$h
d
} ' /etc/sysconfig/network
hostname $h

echo -e '\n\n[agent]\nserver = $PUPPETSERVER\ncertname=$h' > /etc/puppetlabs/puppet/puppet.conf
chkconfig mcollective on
service mcollective start
"

done

然后执行 ./prepare.sh hadoop-slaver{200..500} 就可以了。

接下来重点讲讲PUPPET配置的编写。

首先根据当前需要创建的用户、组把创建用户的配置写好:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@hadoop-master1 ~]# puppet resource -e group hadoop
group { 'hadoop':
  ensure => 'present',
  gid    => '501',
}
[root@hadoop-master1 ~]# puppet resource -e user hadoop
user { 'hadoop':
  ensure           => 'present',
  gid              => '501',
  groups           => ['wheel'],
  home             => '/home/hadoop',
  password         => '$6$AfnA...uIhHC9I.',
  password_max_age => '99999',
  password_min_age => '0',
  shell            => '/bin/bash',
  uid              => '501',
}

添加require、groups,然后删除uid、gid。最后需要添加 managehome => true, 否则用户目录就不会自动创建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 默认不创建用户目录
[root@hadoop-slaver200 ~]# su - hadoop
su: warning: cannot change directory to /home/hadoop: No such file or directory
-bash-4.1$ 

# 创建用户配置成品
group { 'hadoop':
  ensure => 'present',
}

user { 'hadoop':
  ensure           => 'present',
  groups           => ['hadoop', 'wheel'],
  home             => '/home/hadoop',
  password         => '$6$Af...IhHC9I.',
  password_max_age => '99999',
  password_min_age => '0',
  shell            => '/bin/bash',
  managehome       => true,
  require          => Group['hadoop'],
}

添加好用户后,就是把无密钥登录也让PUPPET来弄。其实就是把 id_rsa.pub 的内容写入都行机器的 authorized_keys ,PUPPET已经自带了这个类:ssh_authorized_key。把id_ras.pub的内容(中间的内容)赋值给 key 属性即可。

1
2
3
4
5
6
7
8
9
10
11
12
ssh_authorized_key {'root@hadoop-master1':
  user => 'root',
  type => 'ssh-rsa',
  key => 'AAAAB3NzaC1y...O1Q==',
}

ssh_authorized_key {'hadoop@hadoop-master1':
  user => 'hadoop',
  type => 'ssh-rsa',
  key => 'AAAAB3Nza...IZYPw==',
  require  => User['hadoop'],
}

无密钥登录比较容易,没有涉及到收集节点信息。仅仅把公钥写入新机器还不够,还得把 known_hosts 也处理好,不然第一次连接新机器都需要输入一下yes。内容如下:

1
2
3
4
[hadoop@hadoop-slaver200 ~]$ ssh hadoop-slaver202
The authenticity of host 'hadoop-slaver202 (192.168.36.59)' can't be established.
RSA key fingerprint is fe:7e:26:c4:56:ea:f4:21:61:82:6d:9b:4a:72:93:a4.
Are you sure you want to continue connecting (yes/no)? 

正如上面官网介绍的,需要用到虚拟资源,自动把新机器指纹(fingerprint)写入到机器需要PUPPETDB的支持,安装配置又需要PGSQL的配合。需要耗费一番功夫,但是还是划得来的(具体安装步骤查看puppet分类下的文章)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if $hostname =~ /^hadoop-/ {

  $host_aliases = [ $ipaddress, $hostname ]
  
  # Export hostkeys from all hosts.
  @@sshkey { $::fqdn:
    ensure => present,
    host_aliases => $host_aliases,
    type => 'ssh-rsa',
    key => $sshrsakey,
  }
  
  if $hostname =~ /^hadoop-master/ {
    # realize all exported
    Sshkey <<| |>>
  }
  
}

先在所有slaver机器运行一遍 puppet agent -t ,然后再在master节点把收集的指纹写入到 /etc/ssh/ssh_known_hosts 。

这里说个插曲:机器的hosts和hostname是通过 FOR&SSH 命令来统一修改的,有些可能没有配置好导致机器的主机名有重复。通过执行配置known_hosts竟然帮我找出了hostname重复的机器,意外的收获。该问题的处理我是直接登录到PGSQL改了对应表的数据处理的。

到这里机器基本能用了。主机名、hosts、时间同步、hadoop用户以及master到该用户的无密钥登录都已经配置好了。

接下来把实战过程中安装gmond的步骤帖出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
$$ cd /etc/puppetlabs/code/environments/production/manifests/

$$ vi change_site.sh
#!/bin/sh

## Usage:
##  ./change_site.sh nrpe.site
##

[[ $# != 1 ]] && exit 1

cd $(cd $(dirname $0); pwd)

rm -rf site.pp
ln -s $1 site.pp

$$ vi pexec.sh
#!/bin/sh

## Usage:
##   ./pexec.sh /cu-ud/ sudo_revert.site 
##

case $# in
1)
  FUNC="$1"
  HOST_PARAM=
  ;;
2)
  FUNC="$2"
  HOST_PARAM="-I $1"
  ;;
*)
  while [ $# -gt 1 ] ; do 
    HOST_PARAM="$HOST_PARAM -I $1"
    shift
  done
  FUNC=$1
  ;;
esac

cd $(cd $(dirname $0); pwd)

./change_site.sh "$FUNC"

if [[ "$HOST_PARAM" != "" && ! "$HOST_PARAM" =~ */* ]] ; then
  mco shell $HOST_PARAM run -- `which puppet` agent -t
else
  mco puppet $HOST_PARAM runall 20
fi

由于机器增加比较多,且网络环境变的复杂化。把原来的2个分组修改成4个。不同的网络段和功能分别设置不同的广播端口。

1
2
3
4
5
6
7
$ ./pexec.sh /hadoop-slaver.$/ gmond.site 

# 采集数据的节点重启后,其他发送数据的节点貌似都需要重启。
$ screen
$ for ((i=1;i<=53;i++)); do  mco shell -I /hadoop-slaver${i}.$/ run -- ' service gmond restart ' ; done 
# 这个确认搞的很麻烦,
# 想通过ganglia-web获取数据然后判断是否有数据进行重启。

Ganglia删除某节点后,如果要从rrds上去掉改节点的信息,需要:重启对应收集的gmond,对应集群的rrds目录,然后重启gmetad。或者等够一段时间,gmetad会自动去掉。

总结

现在添加机器,直接连上puppetserver机器然后执行几个命令就可以搞定;

1
2
3
4
5
6
HOST=new-host-name 
# 无密钥登录和puppet/mco
PASSWD=new-host-root-password ./prepare.sh $HOST

./pexec.sh $HOST new-hadoop.site
./pexec.sh $HOST gmond.site # 当前需要到web界面确认新节点的数据是否被采集

–END

Comments