(五)、用 highstate 复合主机状态

一、用top.sls文件管理拆分过的状态控制文件

  1. 为了解决模块的复用问题和使模块结构化,现在以nginx安装配置为例,把一个大的nginx.sls文件,拆分成尽可能小的可复用单元。


    目录结构
  2. 创建init文件来包含其他文件

# cat nginx/init.sls (点号一定不能去掉)
include:
    - .install_nginx
    - .running_nginx
    - .nginx_conf
    - .vhost_conf
  1. 创建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
  1. 创建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模块

目录结构
  1. 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
  1. 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
  1. 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
  1. top.sls 文件内容
# cat top.sls 
base:
    'node1':
        - httpd
        - php
        - mysqld
执行结果

三、使用highstate实现keepalived + redis 的高可用

设计思路:

  • 主服务器redis挂掉,尝试重启主服务器的redis,重启失败的话关掉主服务器的keepalived,使VIP发生漂移
  • 从服务器变成主,使用脚本断掉主从同步,改变redis角色为主
  • 主服务器正常时,使用脚本开启redis主从同步,改变redis角色为从(VIP不发生漂移,只有当从服务器出问题的时候才发生VIP漂移,以此循环往复)
  1. 拓扑结构
    主服务器:192.168.1.14(node1)
    从服务器:192.168.1.15(node2)
    VIP:192.168.1.100

  2. 编写设置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数据

  1. 编写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 %}
  1. 编写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
  1. 结果测试


    执行结果
  2. 高可用性测试
  • 关闭主服务器的keepalived,VIP成功漂移,redis主从状态成功切换
    node1:


    reids 为主

    VIP正常

    node2:


    redis 为从

    关掉node1的keepalived后
    node1:
    VIP漂移

    redis 角色转变为从

    node2:


    VIP漂移

    redis 角色转变为主

    重新启动node1的keepalived:
    VIP不抢占
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容