[Saltstack] CentOS下批量部署Nginx
上一篇博文我介绍了如何快速搭建Salt环境, 以及利用相关pillar, state, grains模块进行基本的客户端部署操作.
本篇文档我们会详细介绍如何利用Salt来批量部署安装Nginx, 并自动化配置Nginx的相关属性.
Salt环境部署详见: http://www.showerlee.com/archives/1472
安装环境:
System: Centos 6.3
Salt master: salt-master.example.com
Salt minion: salt-client01.example.com
Salt minion: salt-client02.example.com
一. 主控端配置
1. 配置master基本参数
# vi /etc/salt/master
添加:
nodegroups: webgroup1: 'salt-client01.example.com' webgroup2: 'salt-client02.example.com' file_roots: base: - /srv/salt pillar_roots: base: - /srv/pillar
Tip: 这里的nodegroups里的分组会应用到随后的pillar脚本下, 用来区分不同的salt-minion使用相应的pillar参数, 从而定制不同的minion使用不同的配置方案.
重启服务
# /etc/init.d/salt-master restart
2. 动态配置客户端系统连接数
使用python脚本编写grains_module, 实现动态配置被控主机连接数(CLI可用"limit -n"查询该值), 以便随后的Nginx配置文件中的worker_rlimit_nofile, worker_connections可动态调用脚本中max_open_file的参数值.
Tip: "ulimit -n" 是用来查询当前linux系统的最大打开文件数, 默认为1024
也可用"ulimit -a"来查看其他相关参数
# ulimit -a
core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7819 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 1024 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
暂时修改当前session的参数值
# ulimit -n 2048
永久修改需修改该参数值
# vi /etc/security/limits.conf
添加:
root soft nofile 2048 root hard nofile 2048
# vi /etc/pam.d/common-session
添加:
session required pam_limits.so
重启生效.
脚本具体配置如下:
# mkdir -p /srv/salt/_grains
# vi /srv/salt/_grains/nginx_config.py
#!/usr/bin/env python import os,sys,commands # return Nginx config grains value def NginxGrains(): grains = {} max_open_file=65536 try: getulimit=commands.getstatusoutput('source /etc/profile && ulimit -n') except Exception,e: pass if getulimit[0]==0: max_open_file=int(getulimit[1]) grains['max_open_file'] = max_open_file return grains
Tip: 该脚本会同步到远程后执行, 脚本实际就是获取并返回当前主机的最大打开数值, 最终返回值会赋予字典 grains['max_open_file']
同步grains模块:
# salt '*' saltutil.sync_all
刷新模块(让minion编译模块)
# salt '*' sys.reload_modules
验证max_open_file key的value
# salt '*' grains.item max_open_file
Tip: 这里笔者测试更改客户端最大文件打开值时发现了一个问题, 无论客户端如何更改这个值, 在验证key value时终会显示最早的系统初始值1024, 翻阅了大量文档, 发现minion端会将所有服务端的推送保存在(/var/cache/salt/minion), 这里删除这个缓存目录并重启salt-minion, 让其生成新的缓存目录, 从新同步grains模块, 新的vaule就会生效.
# salt '*' cmd.run 'rm -rf /var/cache/salt/minion && /etc/init.d/salt-minion restart'
3. 配置pillar
1). 定义入口sls
# vi /srv/pillar/top.sls
base: webgroup1: - match: nodegroup - nginx.webserver1 webgroup2: - match: nodegroup - nginx.webserver2
Tip: 这里定义webgroup1的所有minions会使用pillar/nginx/webserver1.sls脚本, webgroup2所有minions使用pillar/nginx/webserver2.sls脚本, match: nodegroup 定义webgroup1, webgroup2匹配nodegroup组.
2). 定义webserver1, webserver2 sls
# mkdir /srv/pillar/nginx
# vi /srv/pillar/nginx/webserver1.sls
nginx: hostname: webserver1 name: nginx root: /www source: salt://nginx/nginx.conf file: /etc/nginx/nginx.conf user: root group: root mode: 644 template: jinja status: installed
# vi /srv/pillar/nginx/webserver2.sls
nginx: hostname: webserver2 name: nginx root: /data source: salt://nginx/nginx.conf file: /etc/nginx/nginx.conf user: root group: root mode: 666 template: jinja status: installed
3). 查看配置结果
# salt '*' pillar.data nginx
salt-client02.example.com: ---------- nginx: ---------- file: /etc/nginx/nginx.conf group: root hostname: webserver2 mode: 666 name: nginx root: /data source: salt://nginx/nginx.conf status: installed template: jinja user: root salt-client01.example.com: ---------- nginx: ---------- file: /etc/nginx/nginx.conf group: root hostname: webserver1 mode: 644 name: nginx root: /www source: salt://nginx/nginx.conf status: installed template: jinja user: root
Tip: 可以通过字典 pillar['nginx']['root'] 在配置文件中调用
4. 配置state
1). 定义入口sls
# vi /srv/salt/top.sls
base: '*': - env - nginx.deploy
2). 定义env, nginx服务状态管理配置sls
通用系统环境配置
# vi /srv/salt/env.sls
policycoreutils: pkg.installed policycoreutils-python: pkg.installed {% if grains['selinux']['enabled'] %} setselinux: selinux.mode: - name: 'permissive' - require: - pkg: policycoreutils - pkg: policycoreutils-python /etc/sysconfig/selinux: file.replace: - pattern: 'SELINUX=\w+' - repl: 'SELINUX=disabled' {% endif %} iptables: pkg: - installed iptables.flush: - table: 'filter' - save: True cmd.run: - name: 'service iptables save' - require: - pkg: iptables
Tip: 使用setenforce需要安装2个python依赖包, 通过判断系统默认的SELINUX是否打开, 从而确定是否关闭SELINUX, 如果不作此判断, 系统SELINUX若关闭, 部署时会报错.
NGINX配置
# mkdir /srv/salt/nginx
# vi /srv/salt/nginx/deploy.sls
{% if 'nginx' in pillar %} {% set item = pillar['nginx'] %} {{ item['name'] }}: pkg: - {{ item['status'] }} file.managed: - source: {{ item['source'] }} - name: {{ item['file'] }} - user: {{ item['user'] }} - group: {{ item['group'] }} - mode: {{ item['mode'] }} - template: {{ item['template'] }} service.running: - enable: True - reload: True - watch: - file: {{ item['file'] }} - pkg: {{ item['name'] }} {{ item['root'] }}: file.directory: - user: {{ item['name'] }} - group: {{ item['name'] }} - mode: 755 - makedirs: True - recurse: - user - group - mode {% endif %}
Tip: "source: {{ item['source'] }}"等价于"source: {{ pillar['nginx']['source'] }}"为配置模板文件位置
"-enable: True" 等价于 "chkconfig nginx on"
"-reload True" 等价于 "service nginx reload", 若不加则默认执行"service nginx restart"
"-wotch -file:" 检查 /etc/nginx/nginx.conf是否发生变化
"-watch -pkg" 确保nginx安装成功.
"{{ item['root'] }}: file.directory:" 等价于mkdir /www
3). 定义Nginx配置文件(引用jinja模板)
# vi /srv/salt/nginx/nginx.conf
# For more information on configuration, see: {% set item = pillar['nginx'] %} user nginx; worker_processes {{ grains['num_cpus'] }}; {% if grains['num_cpus'] == 2 %} worker_cpu_affinity 01 10; {% elif grains['num_cpus'] == 4 %} worker_cpu_affinity 1000 0100 0010 0001; {% elif grains['num_cpus'] >= 8 %} worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000; {% else %} worker_cpu_affinity 1000 0100 0010 0001; {% endif %} worker_rlimit_nofile {{ grains['max_open_file'] }}; error_log /var/log/nginx/error.log; #error_log /var/log/nginx/error.log notice; #error_log /var/log/nginx/error.log info; pid /var/run/nginx.pid; events { worker_connections {{ grains['max_open_file'] }}; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; # Load config files from the /etc/nginx/conf.d directory # The default server is in conf.d/default.conf #include /etc/nginx/conf.d/*.conf; server { listen 80 default_server; server_name _; #charset koi8-r; #access_log logs/host.access.log main; location / { root {{ item['root'] }}; index index.html index.htm; } error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html; } # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } }
Tip:
- worker_processes参数采用grains['num_cpus'] 上报值(与设备CPU核数一致);
- worker_cpu_affinity分配多核CPU根据当前设备核数进行匹配,分别为2\4\8\其它核;
- worker_rlimit_nofile参数与grains['max_open_file'] 获取的系统ulimit -n一致;
- worker_connections 参数理论上为grains['max_open_file'];
- root参数为定制的pillar['nginx']['root']值。
4). 执行最终state配置, 将master的所有nginx配置部署到客户端
# salt '*' state.highstate
Tip: 可使用salt '*' -l debug state.highstate 查看部署过程中是否有错误
salt-client02.example.com: ---------- ID: policycoreutils Function: pkg.installed Result: True Comment: Package policycoreutils is already installed. Started: 14:35:20.183439 Duration: 1165.132 ms Changes: ---------- ID: policycoreutils-python Function: pkg.installed Result: True Comment: Package policycoreutils-python is already installed. Started: 14:35:21.348902 Duration: 0.875 ms Changes: ---------- ID: iptables Function: pkg.installed Result: True Comment: Package iptables is already installed. Started: 14:35:21.349904 Duration: 0.47 ms Changes: ---------- ID: iptables Function: iptables.flush Result: True Comment: Flush iptables rules in filter table chain ipv4 family Started: 14:35:21.351883 Duration: 16.006 ms Changes: ---------- locale: iptables ---------- ID: iptables Function: cmd.run Name: service iptables save Result: True Comment: Command "service iptables save" run Started: 14:35:21.371349 Duration: 50.934 ms Changes: ---------- pid: 3352 retcode: 0 stderr: stdout: iptables: Saving firewall rules to /etc/sysconfig/iptables: ?[60G[?[0;32m OK ?[0;39m] ---------- ID: nginx Function: pkg.installed Result: True Comment: The following packages were installed/updated: nginx Started: 14:35:21.422715 Duration: 19128.275 ms Changes: ---------- nginx: ---------- new: 1.0.15-12.el6 old: ---------- ID: nginx Function: file.managed Name: /etc/nginx/nginx.conf Result: True Comment: File /etc/nginx/nginx.conf updated Started: 14:35:40.560042 Duration: 40.855 ms Changes: ---------- diff: --- +++ @@ -1,42 +1,70 @@ -# For more information on configuration, see: -# * Official English Documentation: http://nginx.org/en/docs/ -# * Official Russian Documentation: http://nginx.org/ru/docs/ - -user nginx; -worker_processes 1; - -error_log /var/log/nginx/error.log; -#error_log /var/log/nginx/error.log notice; -#error_log /var/log/nginx/error.log info; - -pid /var/run/nginx.pid; +# For more information on configuration, see: -events { - worker_connections 1024; -} - - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - - sendfile on; - #tcp_nopush on; - - #keepalive_timeout 0; - keepalive_timeout 65; - - #gzip on; - - # Load config files from the /etc/nginx/conf.d directory - # The default server is in conf.d/default.conf - include /etc/nginx/conf.d/*.conf; - -} +user nginx; +worker_processes 1; + +worker_cpu_affinity 1000 0100 0010 0001; + +worker_rlimit_nofile 1024; + +error_log /var/log/nginx/error.log; +#error_log /var/log/nginx/error.log notice; +#error_log /var/log/nginx/error.log info; + +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + + # Load config files from the /etc/nginx/conf.d directory + # The default server is in conf.d/default.conf + #include /etc/nginx/conf.d/*.conf; + server { + listen 80 default_server; + server_name _; + + #charset koi8-r; + + #access_log logs/host.access.log main; + + location / { + root /data; + index index.html index.htm; + } + + error_page 404 /404.html; + location = /404.html { + root /usr/share/nginx/html; + } + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + + } + +} mode: 0666 ---------- ID: nginx Function: service.running Result: True Comment: Service nginx has been enabled, and is running Started: 14:35:40.608381 Duration: 320.864 ms Changes: ---------- nginx: True ---------- ID: /data Function: file.directory Result: True Comment: Directory /data is in the correct state Started: 14:35:40.929607 Duration: 2.265 ms Changes: Summary ------------ Succeeded: 9 (changed=5) Failed: 0 ------------ Total states run: 9 salt-client01.example.com: ---------- ID: policycoreutils Function: pkg.installed Result: True Comment: Package policycoreutils is already installed. Started: 18:14:48.158376 Duration: 1211.452 ms Changes: ---------- ID: policycoreutils-python Function: pkg.installed Result: True Comment: Package policycoreutils-python is already installed. Started: 18:14:49.370171 Duration: 0.787 ms Changes: ---------- ID: setselinux Function: selinux.mode Name: permissive Result: True Comment: SELinux is already in Permissive mode Started: 18:14:49.372833 Duration: 0.652 ms Changes: ---------- ID: /etc/sysconfig/selinux Function: file.replace Result: True Comment: No changes needed to be made Started: 18:14:49.377284 Duration: 2.507 ms Changes: ---------- ID: iptables Function: pkg.installed Result: True Comment: Package iptables is already installed. Started: 18:14:49.379941 Duration: 0.597 ms Changes: ---------- ID: iptables Function: iptables.flush Result: True Comment: Flush iptables rules in filter table chain ipv4 family Started: 18:14:49.381900 Duration: 21.393 ms Changes: ---------- locale: iptables ---------- ID: iptables Function: cmd.run Name: service iptables save Result: True Comment: Command "service iptables save" run Started: 18:14:49.406906 Duration: 342.078 ms Changes: ---------- pid: 3124 retcode: 0 stderr: stdout: iptables: Saving firewall rules to /etc/sysconfig/iptables: ?[60G[?[0;32m OK ?[0;39m] ---------- ID: nginx Function: pkg.installed Result: True Comment: The following packages were installed/updated: nginx Started: 18:14:49.749415 Duration: 23737.719 ms Changes: ---------- nginx: ---------- new: 1.0.15-12.el6 old: ---------- ID: nginx Function: file.managed Name: /etc/nginx/nginx.conf Result: True Comment: File /etc/nginx/nginx.conf updated Started: 18:15:13.490651 Duration: 52.469 ms Changes: ---------- diff: --- +++ @@ -1,42 +1,70 @@ -# For more information on configuration, see: -# * Official English Documentation: http://nginx.org/en/docs/ -# * Official Russian Documentation: http://nginx.org/ru/docs/ - -user nginx; -worker_processes 1; - -error_log /var/log/nginx/error.log; -#error_log /var/log/nginx/error.log notice; -#error_log /var/log/nginx/error.log info; - -pid /var/run/nginx.pid; +# For more information on configuration, see: -events { - worker_connections 1024; -} - - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - - sendfile on; - #tcp_nopush on; - - #keepalive_timeout 0; - keepalive_timeout 65; - - #gzip on; - - # Load config files from the /etc/nginx/conf.d directory - # The default server is in conf.d/default.conf - include /etc/nginx/conf.d/*.conf; - -} +user nginx; +worker_processes 1; + +worker_cpu_affinity 1000 0100 0010 0001; + +worker_rlimit_nofile 1024; + +error_log /var/log/nginx/error.log; +#error_log /var/log/nginx/error.log notice; +#error_log /var/log/nginx/error.log info; + +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + + # Load config files from the /etc/nginx/conf.d directory + # The default server is in conf.d/default.conf + #include /etc/nginx/conf.d/*.conf; + server { + listen 80 default_server; + server_name _; + + #charset koi8-r; + + #access_log logs/host.access.log main; + + location / { + root /www; + index index.html index.htm; + } + + error_page 404 /404.html; + location = /404.html { + root /usr/share/nginx/html; + } + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + + } + +} ---------- ID: nginx Function: service.running Result: True Comment: Service nginx has been enabled, and is running Started: 18:15:13.550329 Duration: 424.431 ms Changes: ---------- nginx: True ---------- ID: /www Function: file.directory Result: True Comment: Directory /www is in the correct state Started: 18:15:13.975177 Duration: 2.586 ms Changes: Summary ------------- Succeeded: 11 (changed=5) Failed: 0 ------------- Total states run: 11
Tip: 笔者为了验证效果, 事先手动关闭了client02的SELINUX配置, 这里可以看到client02跳过SELINUX配置项, client01则正常执行.
这样我们就可以从返回信息查看Nginx的配置文件参数是否正确调用, 以及最终是否部署成功.
最终/srv目录下的树状结构
# cd /srv && tree .
. |-- pillar | |-- nginx | | |-- webserver1.sls | | `-- webserver2.sls | `-- top.sls `-- salt |-- env.sls |-- _grains | `-- nginx_config.py |-- nginx | |-- deploy.sls | `-- nginx.conf |-- nginx.sls.bak `-- top.sls 5 directories, 9 files
至此, 一个模拟生产环境的WEB服务配置集中管理部署平台已经搭建并测试完成, 大家可以拓展思路, 利用该平台扩展到其他应用业务当中.
本文链接:http://www.showerlee.com/archives/1538
继续浏览:Saltstack
还没有评论,快来抢沙发!