puppetmaster 自带了 webrick 作为自身的 web server,但是 webrick 的执行效率相对比较低下,需要考虑使用更加专业的 web server 进行替换,解决并发问题。

网上简单搜索后的解决办法通常分如下几种,如下:
1、apache + passenger
2、nginx + mongrel
3、nginx + unicorn

由于不会apache,故考虑使用后两种方法,实际尝试替换过程中,mongrel没有正常安装上(安装时没有安装ruby-dev和build-essential导致无法gem install mongrel),unicorn安装上了,故考虑使用第三种方法进行webrick替换。以下为简单安装过程。

1、安装unicorn

安装完 puppetmaster,会自动安装 ruby、gem 等依赖包。故可考虑直接使用 gem 命令安装 unicorn。由于 gem 包安装需要进行编译,故考虑先安装 build-essential

1
$ apt-get install build-essential ruby-dev && gem install unicorn --verbose

安装完成后,查看是否正常安装unicorn:

1
2
3
4
5
6
7
8
$ gem list

*** LOCAL GEMS ***

kgio (2.9.2)
rack (1.5.2)
raindrops (0.13.0)
unicorn (4.8.3)

2、安装nginx

1
2
$ puppet resource package nginx ensure=present
#实际还是会调用apt-get install nginx

安装完成关闭nginx

1
2
$ puppet resource service nginx ensure=stopped
# service nginx stop

3、配置unicorn

增加rake配置文件

1
$ cp /etc/puppet/ && wget https://raw.githubusercontent.com/puppetlabs/puppet/master/ext/rack/config.ru

增加unicorn.conf配置文件

/etc/puppet/unicorn.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
worker_processes 8
working_directory "/etc/puppet"
listen '/var/run/puppet/puppetmaster_unicorn.sock', :backlog => 512
timeout 120
pid "/var/run/puppet/puppetmaster_unicorn.pid"

preload_app true
if GC.respond_to?(:copy_on_write_friendly=)
GC.copy_on_write_friendly = true
end

before_fork do |server, worker|
old_pid = "#{server.config[:pid]}.oldbin"
if File.exists?(old_pid) && server.pid != old_pid
begin
Process.kill("QUIT", File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
# someone else did our job for us
end
end
end

增加puppetmaster-unicoron服务管理脚本

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#/etc/init.d/puppetmaster-unicorn
内容如下:


#!/bin/bash
# unicorn-puppet
lockfile=/var/lock/puppetmaster-unicorn
pidfile=/var/run/puppet/puppetmaster_unicorn.pid

RETVAL=0
DAEMON=/usr/local/bin/unicorn
DAEMON_OPTS="-D -c /etc/puppet/unicorn.conf"
USER=root

start() {
sudo -u $USER $DAEMON $DAEMON_OPTS
RETVAL=$?
[ $RETVAL -eq 0 ] && touch "$lockfile"
echo
return $RETVAL
}

stop() {
sudo -u $USER kill `cat $pidfile`
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f "$lockfile"
return $RETVAL
}

restart() {
stop
sleep 1
start
RETVAL=$?
echo
[ $RETVAL -ne 0 ] && rm -f "$lockfile"
return $RETVAL
}

condrestart() {
status
RETVAL=$?
[ $RETVAL -eq 0 ] && restart
}

status() {
ps ax | egrep -q "unicorn (worker|master)"
RETVAL=$?
return $RETVAL
}

usage() {
echo "Usage: $0 {start|stop|restart|status|condrestart}" >&2
return 3
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
condrestart)
condrestart
;;
status)
status
;;
*)
usage
;;
esac

exit $RETVAL

4、nginx增加配置

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
#/etc/nginx/sites-enable/puppetmaster
内容如下:


upstream puppetmaster_unicorn {
server unix:///var/run/puppet/puppetmaster_unicorn.sock fail_timeout=0;
}

server {
listen 8140;

ssl on;
ssl_session_timeout 5m;
ssl_certificate /var/lib/puppet/ssl/certs/master.pem;
ssl_certificate_key /var/lib/puppet/ssl/private_keys/master.pem;
ssl_client_certificate /var/lib/puppet/ssl/ca/ca_crt.pem;
ssl_ciphers SSLv2:-LOW:-EXPORT:RC4+RSA;
ssl_verify_client optional;

root /usr/share/empty;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Client-Verify $ssl_client_verify;
proxy_set_header X-Client-DN $ssl_client_s_dn;
proxy_set_header X-SSL-Issuer $ssl_client_i_dn;
proxy_read_timeout 120;

location / {
proxy_pass http://puppetmaster_unicorn;
proxy_redirect off;
}
}

启动nginx

5、修改pupetmaster配置

1
2
3
4
5
6
7
8
9
10
11
#/etc/puppet/puppet.conf
内容如下:

[master]
# These are needed when the puppetmaster is run by passenger
# and can safely be removed if webrick is used.
#ssl_client_header = SSL_CLIENT_S_DN
#ssl_client_verify_header = SSL_CLIENT_VERIFY

ssl_client_header = HTTP_X_CLIENT_DN
ssl_client_verify_header = HTTP_X_CLIENT_VERIFY

6、启动服务

启动puppet-unicoron

1
2
$ /etc/init.d/puppets-unicorn start
# service puppets-unicorn start

启动nginx

1
2
$ puppet resource service nginx ensure=running
# service nginx start

7、收尾工作

取消 puppetmaster 的开机自启动
增加 puppetmaster-unicorn 的开机自启动
增加 nginx 的开机自启动(nginx安装完成就会开机自启动)

简单原理:

nginx 使用 ssl 监听 puppet 原有 8140 端口,将 web 请求分发到 puppetmaster_unicorn.sock文件,unicorn 监听该 sock 文件,有 sock 请求后,分发到 puppetmaster 进行请求分析、返回。由于nginx 自身负载能力较强,并且 rake 的多 work 并发,执行效率相对原有 webrick 更高。

扩展阅读: