一、用top.sls文件管理拆分過的狀態控制文件
-
為了解決模塊的復用問題和使模塊結構化,現在以nginx安裝配置為例,把一個大的nginx.sls文件,拆分成盡可能小的可復用單元。
目錄結構 創建init文件來包含其他文件
# cat nginx/init.sls (點號一定不能去掉)
include:
- .install_nginx
- .running_nginx
- .nginx_conf
- .vhost_conf
- 創建nginx的各個子配置模塊
# cat nginx/install_nginx.sls (安裝nginx)
install_nginx:
pkg.installed:
- name: nginx
# cat nginx/running_nginx.sls(啟動nginx)
running_nginx:
service.running:
- name: nginx
- enable: True
- require:
- pkg: install_nginx
- watch:
- file: nginx_conf
- file: vhost_conf
# cat nginx/nginx_conf.sls (下發 nginx.conf 配置文件)
nginx_conf:
file.managed:
- name: /etc/nginx/nginx.conf
- source: salt://nginx/templates/nginx.j2
- user: root
- group: root
- mode: 644
- template: jinja
# cat nginx/vhost_conf.sls (下發虛擬主機配置文件)
vhost_conf:
file.managed:
- name: /etc/nginx/conf.d/default.conf
- source: salt://nginx/templates/vhost.j2
- user: root
- group: root
- mode: 644
- template: jinja
- 創建top.sls文件(nginx文件夾下有init.sls文件,salt默認會加載init.sls文件,所以不需要寫成nginx.init這種形式)
沒有top.sls文件時,可以執行 salt node1 state.sls nginx
# cat top.sls
base:
'node1':
- nginx
執行結果
二、拆分lamp.sls文件為httpd、mysqld和php模塊
目錄結構
- httpd 模塊
# cat init.sls # 入口文件
include:
- .install_httpd
- .running_httpd
- .httpd_conf
# cat install_httpd.sls # httpd 軟件安裝
install_httpd:
pkg.installed:
- name: httpd
# cat running_httpd.sls # httpd 服務管理
running_httpd:
service.running:
- name: httpd
- enable: True
- require:
- pkg: install_httpd
- watch:
- file: httpd_conf
- file: php_conf
# cat httpd_conf.sls # httpd 配置文件管理
httpd_conf:
file.managed:
- name: /etc/httpd/conf/httpd.conf
- source: salt://httpd/templates/httpd.j2
- user: root
- group: root
- mode: 644
- template: jinja
- mysqld 模塊
# cat init.sls # 入口文件
include:
- .install_mysqld
- .running_mysqld
- .mysqld_conf
# cat install_mysqld.sls # mysqld 軟件安裝
install_mysqld:
pkg.installed:
- pkgs:
- mysql-server
- mysql-devel
- mysql
# cat running_mysqld.sls # mysqld 服務管理
running_mysqld:
service.running:
- name: mysqld
- enable: True
- require:
- pkg: install_mysqld
- watch:
- file: mysqld_conf
# cat mysqld_conf.sls # mysqld 配置文件管理
mysqld_conf:
file.managed:
- name: /etc/my.cnf
- source: salt://mysqld/templates/my.j2
- user: root
- group: root
- mode: 644
- template: jinja
- php 模塊
# cat init.sls # 入口文件
include:
- .install_php
- .php_conf
$ cat install_php.sls # PHP 服務安裝
install_php:
pkg.installed:
- pkgs:
- php
- php-common
- php-gd
- php-mbstring
- php-mcrypt
- php-devel
- php-xml
- php-soap
- require:
- pkg: install_httpd
# cat php_conf.sls # PHP 配置文件管理
php_conf:
file.managed:
- name: /etc/php.ini
- source: salt://php/templates/php.ini
- user: root
- group: root
- mode: 644
- require:
- pkg: install_php
- top.sls 文件內容
# cat top.sls
base:
'node1':
- httpd
- php
- mysqld
執行結果
三、使用highstate實現keepalived + redis 的高可用
設計思路:
- 主服務器redis掛掉,嘗試重啟主服務器的redis,重啟失敗的話關掉主服務器的keepalived,使VIP發生漂移
- 從服務器變成主,使用腳本斷掉主從同步,改變redis角色為主
- 主服務器正常時,使用腳本開啟redis主從同步,改變redis角色為從(VIP不發生漂移,只有當從服務器出問題的時候才發生VIP漂移,以此循環往復)
拓撲結構
主服務器:192.168.1.14(node1)
從服務器:192.168.1.15(node2)
VIP:192.168.1.100編寫設置redis主從服務器的pillar數據
# node1的pillar數據
# cat /srv/pillar/minion_node1_key.sls
role: redis_master
vip: '192.168.1.100'
master_ip: '192.168.1.15'
# node2的pillar數據
# cat /srv/pillar/minion_node2_key.sls
role: redis_slave
vip: '192.168.1.100'
master_ip: '192.168.1.14'
# cat /srv/pillar/top.sls
base:
'node1':
- minion_node1_key
'node2':
- minion_node2_key
執行 salt -L 'node1,node2' saltutil.refresh_pillar
刷新pillar數據
- 編寫redis模塊
# 入口文件
# cat /srv/salt/redis/init.sls
include:
- .install_redis
- .running_redis
- .redis_conf
# 安裝 redis
# cat /srv/salt/redis/install_redis.sls
install_redis:
pkg.installed:
- name: redis
# 啟動redis
# cat /srv/salt/redis/running_redis.sls
running_redis:
service.running:
- name: redis
- enable: True
- require:
- pkg: install_redis
- file: make_pidfile_dir
- watch:
- file: redis_conf
# 配置redis
# cat /srv/salt/redis/redis_conf.sls
redis_conf:
file.managed:
- name: /etc/redis.conf
- source: salt://redis/templates/redis.conf
- user: root
- group: root
- mode: 644
- template: jinja
- require:
- pkg: install_redis
# 創建 pid 文件目錄
make_pidfile_dir:
file.directory:
- name: /var/run/redis
- user: root
- group: root
- dir_mode: 755
- make_dirs: True
# /srv/salt/redis/templates/redis.conf
# $ egrep -v "^$|^#" templates/redis.conf
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /var/run/redis/redis.pid
loglevel notice
logfile /var/log/redis/redis.log
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
requirepass redis_pass
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
# 只有以下位置不同
{% if pillar['role'] == 'redis_slave' %}
slaveof {{ pillar['master_ip'] }} 6379
masterauth redis_pass
{% endif %}
- 編寫keepalived模塊
# 入口文件
# cat /srv/salt/keepalived/init.sls
include:
- .install_keepalived
- .running_keepalived
- .keepalived_conf
- .keepalived_script
# 安裝keepalived
# cat /srv/salt/keepalived/install_keepalived.sls
install_keepalived:
pkg.installed:
- name: keepalived
# 啟動keepalived
# cat /srv/salt/keepalived/running_keepalived.sls
running_keepalived:
service.running:
- name: keepalived
- enable: True
- require:
- pkg: install_keepalived
- watch:
- file: keepalived_conf
# 配置keepalived
# cat /srv/salt/keepalived/keepalived_conf.sls
keepalived_conf:
file.managed:
- name: /etc/keepalived/keepalived.conf
- source: salt://keepalived/templates/keepalived.conf
- user: root
- group: root
- mode: 644
- template: jinja
make_log_dir:
file.directory:
- name: /etc/keepalived/logs
- user: root
- group: root
- mode: 755
- makedirs: True
# keepalived使用的腳本文件
# cat /srv/salt/keepalived/keepalived_script.sls
{% for file in ['notify_backup.sh','notify_master.sh','check_redis.sh'] %}
keepalived_{{ file }}:
file.managed:
- name: /etc/keepalived/{{ file }}
- source: salt://keepalived/templates/{{ file }}
- mode: 755
- user: root
- group: root
- template: jinja
- require:
- pkg: install_keepalived
{% endfor %}
# 配置文件內容keepalived.conf
# cat /srv/salt/keepalived/templates/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id {{ grains['host'] }}
}
vrrp_script chk_redis {
script "/etc/keepalived/check_redis.sh" # 監測 redis 狀態的腳本
interval 5
}
vrrp_instance VI_1 {
state BACKUP # 主從服務器狀態都設置為BACKUP,依靠priority大小來決定誰是主誰是備(數值小的自動選舉為主),
# 不這樣設置的主服務器出問題后再正常的話會搶占備服務器的VIP
{% if pillar['role'] == 'redis_master' %}
priority 99
{% else %}
priority 100
{% endif %}
interface eth0
virtual_router_id 51
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_redis
}
notify_stop /etc/keepalived/notify_backup.sh # keepalived 停掉時執行的腳本
notify_backup /etc/keepalived/notify_backup.sh # keepalived 角色轉變為 backup 時執行的腳本
notify_master /etc/keepalived/notify_master.sh # keepalived 角色轉變為 master 時執行的腳本
virtual_ipaddress {
{{ pillar['vip'] }}
}
nopreempt #采用VIP不自動搶占的功能
}
###############################keepalived使用的腳本###############################
# cat /srv/salt/keepalived/templates/check_redis.sh
#!/bin/sh
###檢查redis可用性:進程和是否能夠掛載
/sbin/service redis status &>/dev/null
if [ $? -ne 0 ];then
###如果服務狀態不正常,先嘗試重啟服務
/sbin/service redis restart
/sbin/service redis status &>/dev/null
if [ $? -ne 0 ];then
###若重啟redis服務后,仍不正常
/sbin/service keepalived stop
fi
fi
################################################################
# cat /srv/salt/keepalived/templates/notify_master.sh
#!/bin/bash
time=`date "+%F %H:%M:%S"`
echo -e "$time ------notify_{{ pillar['role'] }}------\n" >> /etc/keepalived/logs/notify_master.log
# 取消redis的主從復制,轉變redis角色為主
sed -i '/^slaveof/d' /etc/redis.conf
sed -i '/^masterauth/d' /etc/redis.conf
sleep 5
/sbin/service redis restart &>> /etc/keepalived/logs/notify_{{ pillar['role'] }}.log
echo -e "\n" >> /etc/keepalived/logs/notify_{{ pillar['role'] }}.log
################################################################
# cat /srv/salt/keepalived/templates/notify_backup.sh
#!/bin/bash
time=`date "+%F %H:%M:%S"`
echo -e "$time ------notify_{{ pillar['role'] }}------\n" >> /etc/keepalived/logs/notify_{{ pillar['role'] }}.log
# 檢查redis狀態和防止多次寫入主從同步信息(slaveof和masterauth)
/sbin/service redis status && ! grep -q "^slaveof" /etc/redis.conf && ! grep -q "^masterauth" /etc/redis.conf &>/dev/null
# 當keepalived服務停止或者角色轉變為backup時,redis角色轉變為從
if [[ $? -eq 0 ]];then
echo "slaveof {{ pillar['master_ip'] }} 6379" >> /etc/redis.conf
echo "masterauth redis_pass" >> /etc/redis.conf
sleep 2
/sbin/service redis restart
fi
echo -e "\n" >> /etc/keepalived/logs/notify_{{ pillar['role'] }}.log
-
結果測試
執行結果 - 高可用性測試
-
關閉主服務器的keepalived,VIP成功漂移,redis主從狀態成功切換
node1:
reids 為主
VIP正常
node2:
redis 為從
關掉node1的keepalived后
node1:
VIP漂移
redis 角色轉變為從
node2:
VIP漂移
redis 角色轉變為主
重新啟動node1的keepalived:
VIP不搶占