python 上下文管理器

python上下文管理器

  1. 简介

    1
    2
    3
    * 规定对象的使用范围,超越范围则"采取处理"
    格式: with...as.. 代码块
    * 任何定义了"__enter__()"和"__exit__()"方法的对象都可以用于上下文管理器
  2. 示例

    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
    //普通文件打开方式
    [root@dev test]# cat 1.py
    #!/usr/bin/env python
    f = open('new.text','w')
    print(f.closed)
    f.write('Hello,world!')
    f.close()
    print(f.closed)

    [root@dev test]# python 1.py
    False
    True

    //使用上下文管理器打开文件
    [root@dev test]# cat 2.py
    #!/usr/bin/env python
    with open('new.txt','w') as f:
    print(f.closed)
    f.write('haha')
    print(f.closed)

    [root@dev test]# python 2.py
    False
    True

    //自定义上下文管理器
    [root@dev test]# cat 3.py
    #!/usr/bin/env python
    class Vow(object):
    def __init__(self,text):
    self.text = text

    def __enter__(self):
    self.text = "enter : " + self.text
    return self # 注意,这里返回的是 对象!!!

    def __exit__(self,exc_type,exc_value,traceback):
    self.text = self.text + ' now __exit__ !'

    with Vow('hello') as myvow:
    print(myvow.text) # 此时进入的是__enter__()
    print(myvow.text) # 此时进入的是__exit__()

    [root@dev test]# python 3.py
    enter : hello
    enter : hello now __exit__ !
  3. 上下文管理器理解

    1
    2
    3
    4
    5
    6
    7
    8
    with EXPR as VAR:
    相当于:
    VAR = EXPR
    VAR = VAR.__enter__()
    try:
    BLOCK
    finally:
    VAR.__exit__()

python library time datetime calendar

python library time datetime calendar

  1. 时间模块简介

    1
    Python处理时间和日期方面的模块,主要有: time,datetime和calendar 三个模块
  2. time模块
    time module

    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
    >>> import time       #导入模块

    >>> t = time.time() #获取当前时间戳
    >>> t
    1502700231.32274

    >>> t_tuple = time.localtime(t) #由时间戳转换为时间元组
    >>> t_tuple
    time.struct_time(tm_year=2017, tm_mon=8, tm_mday=14, tm_hour=16, tm_min=43, tm_sec=51, tm_wday=0, tm_yday=226, tm_isdst=0)

    >>> t_people = time.ctime(t) #由时间戳转换为"友好显示"
    >>> t_people
    'Mon Aug 14 16:43:51 2017'

    >>> t = time.mktime(t_tuple) #由时间元组转换为时间戳
    >>> t
    1502700231.0

    >>> t_people = time.asctime(t_tuple) #由时间元组转换为"友好显示"
    >>> t_people
    'Mon Aug 14 16:43:51 2017'

    >>> t_1 = time.strftime('%Y-%m-%d %X',t_tuple) #由时间元组转换为自定义显示格式
    >>> t_1
    '2017-08-14 16:43:51'

    >>> t_2 = time.strptime(t_1,'%Y-%m-%d %X') #由自定义时间转换为时间元组显示
    >>> t_2
    time.struct_time(tm_year=2017, tm_mon=8, tm_mday=14, tm_hour=16, tm_min=43, tm_sec=51, tm_wday=0, tm_yday=226, tm_isdst=-1)
  3. datetime模块
    datetime module

    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
    >>> import datetime     #导入datetime模块

    >>> dt = datetime.datetime.now() #获取当前时间
    >>> dt
    datetime.datetime(2017, 8, 14, 16, 59, 56, 358531)

    >>> dt.year #获取当前年份
    2017
    >>> dt.month #获取当前月份
    8
    >>> dt.day #获取当前月第几天
    14

    >>> dt.date() #获取年月日
    datetime.date(2017, 8, 14)
    >>> dt.time() #获取时间
    datetime.time(16, 59, 56, 358531)

    >>> dt.weekday() #获取今天是周几,默认周一为0
    0
    >>> dt.isoweekday() #获取今天是周几,默认周一为1
    1

    >>> dt.isocalendar() #获取日历,年,一年中第几周,周几
    (2017, 33, 1)

    >>> dt.toordinal() #计算到公元元年过了多少天
    736555
    >>> dt.fromordinal(54) #以元年为起点,获取指定某天的时间
    datetime.datetime(1, 2, 23, 0, 0)

    >>> dt.today() #获取当前时间
    datetime.datetime(2017, 8, 14, 17, 6, 29, 46188)
    >>> dt.utcnow() #获取utc当前时间
    datetime.datetime(2017, 8, 14, 9, 6, 49, 240196)

    >>> dt.isoformat() #获取时间字符串
    '2017-08-14T16:59:56.358531'

    >>> dt.ctime() #将时间转换为友好显示
    'Mon Aug 14 17:16:49 2017'

    >>> dt.strftime('%Y-%m-%d %X') #转换为指定格式
    '2017-08-14 17:16:49'

    >>> dt.strptime('2017-08-14 17:16:49','%Y-%m-%d %X') #指定格式转换为datetime格式
    datetime.datetime(2017, 8, 14, 17, 16, 49)
  4. calendar模块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> import calendar   #导入模块

    >>> calendar.isleap(2017) #判断是否是闰年
    False
    >>> calendar.isleap(2020)
    True

    >>> calendar.leapdays(1990,2020) #返回闰年在1990-2020之间出现的次数
    7

zabbix install distributed

zabbix install distributed

  1. 基础环境安装

    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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    //系统信息
    [root@localhost ~]# cat /etc/redhat-release
    CentOS Linux release 7.0.1406 (Core)

    //修改主机名
    zabbix-server-company:
    [root@localhost ~]# hostname zabbix-server-company && echo zabbix-server-company | tee /etc/hostname
    [root@localhost ~]# $SHELL
    [root@zabbix-server-company ~]#

    zabbix-server-mysql:
    [root@localhost ~]# hostname zabbix-server-mysql && echo zabbix-server-mysql | tee /etc/hostname
    [root@localhost ~]# $SHELL
    [root@zabbix-server-mysql ~]#

    //格式化磁盘(ALL)
    [root@[ALL] ~]# mkfs.xfs /dev/vdb
    [root@[ALL] ~]# echo '/dev/vdb /mnt xfs defaults 0 0' | tee -a /etc/fstab
    [root@[ALL] ~]# mount -a

    //修改最大文件数(ALL)
    [root@[ALL] ~]# echo '* - nproc 65535' | tee -a /etc/security/limits.conf
    [root@[ALL] ~]# echo '* - nofile 65535' | tee -a /etc/security/limits.conf
    [root@[ALL] ~]# ls /etc/security/limits.d/|xargs rm -f

    //YUM源设置(ALL)
    [root@[ALL] ~]# mkdir /etc/yum.repos.d/backup && mv /etc/yum.repos.d/{*,backup}
    [root@[ALL] ~]# curl -o /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo
    [root@[ALL] ~]# curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    [root@[ALL] ~]# curl -O https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
    [root@[ALL] ~]# rpm --import RPM-GPG-KEY-CentOS-7
    [root@[ALL] ~]# rm -f RPM-GPG-KEY-CentOS-7
    [root@[ALL] ~]# yum clean all
    [root@[ALL] ~]# yum makecache

    //安装基础软件包(ALL)
    [root@[ALL] ~]# yum -y groupinstall "Development Tools"
    [root@[ALL] ~]# yum -y install \
    make cmake \
    bison-devel \
    bzip2-devel \
    zlib zlib-devel \
    openssl openssl-devel openssl-libs \
    pcre pcre-devel pcre-static \
    ncurses ncurses-devel ncurses-libs \
    bzip2-devel\
    openldap openldap-devel \
    readline readline-devel readline-static \
    libssh2 libssh2-devel \
    unixODBC unixODBC-devel \
    sqlite sqlite-devel \
    tcl tcl-devel \
    perl-Digest-SHA1 \
    python-libs python-devel python2-pip python-crypto \
    perl-libs \
    GeoIP GeoIP-devel \
    gperftools gperftools-devel gperftools-libs \
    libatomic_ops-devel \
    gtest gtest-devel \
    gdk-pixbuf2 gdk-pixbuf2-deve \
    libffi libffi-devel \
    libcurl libcurl-devel \
    http-parser http-parser-devel
    [root@[ALL] ~]# yum -y install fop lftp ntp ntpdate vim wget telnet dstat tree lrzsz net-tools nmap-ncat nmap sysstat

    //关闭selinux(ALL)
    [root@[ALL] ~]# setenforce 0
    [root@[ALL] ~]# sed -i s/'SELINUX=enforcing'/'SELINUX=disabled'/g /etc/selinux/config

    //关闭防火墙(ALL)
    [root@[ALL] ~]# systemctl stop firewalld && systemctl disable firewalld

    //设置时区和时间(ALL)
    [root@[ALL] ~]# [ -f /etc/localtime ] && cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    [root@[ALL] ~]# [ -f /etc/sysconfig/clock ] && echo 'ZONE="Asia/Shanghai"' | tee /etc/sysconfig/clock
    [root@[ALL] ~]# [ -f /etc/timezone ] && echo 'Asia/Shanghai' | tee /etc/timezone
    [root@[ALL] ~]# [ -f /etc/sysconfig/ntpd ] && echo 'SYNC_HWCLOCK=yes' | tee -a /etc/sysconfig/ntpd
    [root@[ALL] ~]# ntpdate cn.pool.ntp.org
    [root@[ALL] ~]# cp -f /etc/{ntp.conf,ntp.conf.bak}
    [root@[ALL] ~]# cat > /etc/ntp.conf <<EOF
    > driftfile /var/lib/ntp/drift
    > restrict default nomodify notrap nopeer noquery
    > restrict 127.0.0.1
    > restrict ::1
    > server cn.pool.ntp.org prefer
    > server 0.centos.pool.ntp.org iburst
    > server 1.centos.pool.ntp.org iburst
    > server 2.centos.pool.ntp.org iburst
    > server 3.centos.pool.ntp.org iburst
    > includefile /etc/ntp/crypto/pw
    > keys /etc/ntp/keys
    > disable monitor
    > EOF
    [root@[ALL] ~]# cp -f /etc/ntp/{step-tickers,step-tickers.bak}
    [root@[ALL] ~]# cat > /etc/ntp/step-tickers <<EOF
    > cn.pool.ntp.org
    > 0.centos.pool.ntp.org
    > 1.centos.pool.ntp.org
    > 2.centos.pool.ntp.org
    > 3.centos.pool.ntp.org
    > EOF
    [root@[ALL] ~]# systemctl start ntpd && systemctl enable ntpd

    //设置PIP源(ALL)
    [root@[ALL] ~]# mkdir ~/.pip
    [root@[ALL] ~]# cat > ~/.pip/pip.conf <<EOF
    > [global]
    > trusted-host=mirrors.aliyun.com
    > index-url=http://mirrors.aliyun.com/pypi/simple/
    > [list]
    > format=columns
    > EOF

    //python安装(ALL)
    [root@[ALL] ~]# git clone https://github.com/yyuu/pyenv.git /usr/local/pyenv
    [root@[ALL] ~]# echo 'export PYENV_ROOT=/usr/local/pyenv' | tee /etc/profile.d/pyenv.sh
    [root@[ALL] ~]# echo 'export PATH="$PYENV_ROOT/bin:$PATH"' | tee -a /etc/profile.d/pyenv.sh
    [root@[ALL] ~]# echo 'eval "$(pyenv init -)"' | tee -a /etc/profile.d/pyenv.sh
    [root@[ALL] ~]# source /etc/profile
    [root@[ALL] ~]# exec $SHELL
    [root@[ALL] ~]# mkdir -p ${PYENV_ROOT}/cache
    [root@[ALL] ~]# v=2.7.13;wget -P /usr/local/pyenv/cache/ http://mirrors.sohu.com/python/$v/Python-$v.tar.xz
    [root@[ALL] ~]# pyenv install 2.7.13
    [root@[ALL] ~]# pyenv rehash
    [root@[ALL] ~]# pyenv local 2.7.13
    [root@ALL Python-2.7.13]# python -V
    Python 2.7.13
    [root@ALL Python-2.7.13]# pip -V
    pip 9.0.1 from /usr/local/python27/lib/python2.7/site-packages (python 2.7)

    //设置开机启动文件权限
    [root@[ALL] ~]# chmod +x /etc/rc.d/rc.local

    //创建基础目录(ALL)
    [root@[ALL] ~]# mkdir -p /mnt/{app,data,log,web,ops/{app,data,cron}}
  2. 修改内核

    1
    2
    3
    4
    5
    6
    7
    [root@[ALL] ~]# cat >> /etc/sysctl.conf <<EOF
    kernel.shmmax=30000000000
    kernel.shmall=7000000
    kernel.msgmax=65535
    kernel.msgmnb=65535
    EOF
    [root@[ALL] ~]# sysctl -p
  3. zabbix-server-mysql 数据库安装

    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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    [root@zabbix-server-mysql app]# useradd -s /sbin/nologin mysql
    [root@zabbix-server-mysql app]# tar xzf mysql-5.6.35.tar.gz
    [root@zabbix-server-mysql app]# cd mysql-5.6.35
    [root@zabbix-server-mysql mysql-5.6.35]# cmake \
    > -DCMAKE_INSTALL_PREFIX=/mnt/app/mysql \
    > -DWITH_MYISAM_STORAGE_ENGINE=1 \
    > -DWITH_INNOBASE_STORAGE_ENGINE=1 \
    > -DENABLED_LOCAL_INFILE=1 \
    > -DWITH_PARTITION_STORAGE_ENGINE=1 \
    > -DEXTRA_CHARSETS=all \
    > -DDEFAULT_CHARSET=utf8 \
    > -DDEFAULT_COLLATION=utf8_general_ci \
    > -DENABLE_DOWNLOADS=1
    [root@zabbix-server-mysql mysql-5.6.35]# make
    [root@zabbix-server-mysql mysql-5.6.35]# make install

    [root@zabbix-server-mysql mysql-5.6.35]# echo 'export MYSQL_BASE=/mnt/app/mysql' |tee /etc/profile.d/mysql.sh
    [root@zabbix-server-mysql mysql-5.6.35]# echo 'export MYSQL_BIN=$MYSQL_BASE/bin' |tee -a /etc/profile.d/mysql.sh
    [root@zabbix-server-mysql mysql-5.6.35]# echo 'export PATH=$MYSQL_BIN:$PATH' |tee -a /etc/profile.d/mysql.sh
    [root@zabbix-server-mysql mysql-5.6.35]# source /etc/profile

    [root@zabbix-server-mysql mysql-5.6.35]# mkdir -p /mnt/{data,log}/mysql/3306
    [root@zabbix-server-mysql mysql-5.6.35]# touch /mnt/log/mysql/3306/mysqld.log
    [root@zabbix-server-mysql mysql-5.6.35]# chown -R mysql.mysql /mnt/{data,log}/mysql

    [root@zabbix-server-mysql mysql-5.6.35]# chmod +x scripts/*
    [root@zabbix-server-mysql mysql-5.6.35]# ./scripts/mysql_install_db --basedir=/mnt/app/mysql/ --datadir=/mnt/data/mysql/3306/ --user=mysql

    [root@zabbix-server-mysql mysql-5.6.35]# mkdir -p /mnt/app/mysql/conf
    [root@zabbix-server-mysql mysql-5.6.35]# cat > /mnt/app/mysql/conf/3306.M.cnf <<EOF
    [mysqld]
    user = mysql
    port = 3306
    basedir = /mnt/app/mysql
    datadir = /mnt/data/mysql/3306
    socket = /mnt/data/mysql/3306/mysql.sock
    default-storage-engine = InnoDB
    character_set_server = utf8
    max_connections = 100000
    skip-name-resolve
    sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

    server-id = 82
    max_allowed_packet = 32m
    max_heap_table_size = 256m
    read_rnd_buffer_size = 16m
    sort_buffer_size = 8m
    join_buffer_size = 8m
    query_cache_type = 1
    query_cache_size = 1024m
    query_cache_limit = 8m
    innodb_open_files = 30000
    innodb_buffer_pool_size = 24G
    innodb_file_per_table = 1

    [mysqld_safe]
    log-error=/mnt/log/mysql/3306/mysqld.log
    pid-file =/mnt/app/mysql/mysqld.3306.pid

    [client]
    default-character-set=utf8
    socket=/mnt/data/mysql/3306/mysql.sock

    [mysql]
    default-character-set=utf8
    socket=/mnt/data/mysql/3306/mysql.sock
    EOF

    [root@zabbix-server-mysql mysql-5.6.35]# cat > /etc/init.d/mysql.3306M <<EOF
    #!/bin/bash

    if [ $# != 1 ];then
    echo "Please input:
    /etc/init.d/$0 start
    /etc/init.d/$0 stop
    /etc/init.d/$0 status
    "
    exit 0
    fi

    STATUS=$1
    ROLE='mysql'
    PORT=3306
    SQLAPP="/mnt/app/${ROLE}/bin/mysqld_safe"
    SQLSHT="/mnt/app/${ROLE}/bin/mysqladmin"
    SOCKET="/mnt/data/${ROLE}/${PORT}/mysql.sock"
    COFIG="/mnt/app/${ROLE}/conf/${PORT}.M.cnf"


    if [ $STATUS == "start" ];then
    ${SQLAPP} --defaults-file=${COFIG} &
    if [ $? == 0 ];then
    echo "$ROLE $PORT start success."
    else
    echo "$ROLE $PORT start fail."
    fi
    fi

    if [ $STATUS == "stop" ];then
    ${SQLSHT} -S ${SOCKET} shutdown
    if [ $? == 0 ];then
    echo "$ROLE $PORT stoped success."
    else
    echo "$ROLE $PORT stoped fail."
    fi
    fi

    if [ $STATUS == "kill" ];then
    PID=$(ps -ef|grep -w ${ROLE}|grep ${PORT}|grep -v grep|grep -v bash|awk '{print $2}'|tr '\n' ' ')
    kill -9 $PID
    if [ $? == 0 ];then
    echo "$ROLE $PORT killed success."
    else
    echo "$ROLE $PORT killed fail."
    fi
    fi


    if [ $STATUS == "status" ];then
    NUM=$(ps -ef|grep -w ${ROLE}|grep ${PORT}|grep root|grep -v grep|grep -v bash|awk '{print $2}'|wc -l)

    if [ $NUM == 0 ];then
    echo "$ROLE $PORT is stopped."
    exit 0
    fi

    if [ $NUM != 1 ];then
    echo "Please check $ROLE, There are $NUM processes."
    fi

    PID=$(ps -ef|grep -w ${ROLE}|grep ${PORT}|grep -v grep|grep -v bash|awk '{print $2}'|tr '\n' ' ')
    echo "$ROLE $PORT is running. PID: $PID"
    fi
    EOF
    [root@zabbix-server-mysql ~]# chmod +x /etc/init.d/mysql.3306M
    [root@zabbix-server-mysql ~]# chown -R mysql.mysql /mnt/app/mysql
    [root@zabbix-server-mysql ~]# /etc/init.d/mysql.3306M start
    [root@zabbix-server-mysql ~]# echo '/etc/init.d/mysql.3306M start' | tee -a /etc/rc.local
  4. zabbix-server-company zabbix安装

    1
    2
    3
    4
    [root@zabbix-server-company ~]# rpm -ivh http://repo.zabbix.com/zabbix/3.2/rhel/7/x86_64/zabbix-release-3.2-1.el7.noarch.rpm

    [root@zabbix-server-company ~]# yum -y install zabbix-server-mysql zabbix-web-mysql httpd
    [root@zabbix-server-company ~]# yum -y install zabbix-java-gateway zabbix-sender zabbix-get
  5. 创建zabbix-server数据库

    1
    2
    3
    4
    5
    6
    7
    8
    //安装完zabbix-server-mysql后,将数据库表结构拷贝到zabbix-server-mysql上
    [root@zabbix-server-company ~]# scp /usr/share/doc/zabbix-server-mysql-3.2.7/create.sql.gz root@zabbix-server-mysql:/mnt/ops/app/

    [root@zabbix-server-mysql app]# mysql -S /mnt/data/mysql/3306/mysql.sock
    mysql> create database zabbix_server character set utf8 collate utf8_bin;
    mysql> grant all privileges on zabbix_server.* to zabbix@192.168.10.81 identified by 'zabbix';
    mysql> flush privileges;
    [root@zabbix-server-mysql app]# zcat create.sql.gz | mysql -S /mnt/data/mysql/3306/mysql.sock -B zabbix_server
  6. 修改zabbix-server配置文件

    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
    [root@zabbix-server-company ~]# vim /etc/zabbix/zabbix_server.conf
    ListenPort=10051
    LogType=file
    LogFile=/var/log/zabbix/zabbix_server.log
    LogFileSize=512
    DebugLevel=3
    PidFile=/var/run/zabbix/zabbix_server.pid
    DBHost=192.168.10.82
    DBName=zabbix_server
    DBUser=zabbix
    DBPassword=UPCLfTHSj72a
    DBPort=3306
    StartPollers=500
    StartIPMIPollers=0
    StartPollersUnreachable=50
    StartTrappers=50
    StartPingers=30
    StartDiscoverers=80
    StartHTTPPollers=30
    StartTimers=100
    StartEscalators=30
    SNMPTrapperFile=/var/log/snmptrap/snmptrap.log
    StartSNMPTrapper=0
    HousekeepingFrequency=1
    MaxHousekeeperDelete=500000
    SenderFrequency=60
    CacheSize=2G
    CacheUpdateFrequency=300
    StartDBSyncers=50
    HistoryCacheSize=2G
    HistoryIndexCacheSize=2G
    TrendCacheSize=2G
    ValueCacheSize=5G
    Timeout=20
    TrapperTimeout=300
    UnreachablePeriod=300
    UnavailableDelay=300
    UnreachableDelay=30
    AlertScriptsPath=/etc/zabbix/zabbix_alert
    ExternalScripts=/usr/lib/zabbix/zabbix_exec
    FpingLocation=/usr/sbin/fping
    LogSlowQueries=1000
    StartProxyPollers=50
    ProxyConfigFrequency=300
    ProxyDataFrequency=30
    [root@zabbix-server-company ~]# systemctl start zabbix-server
    [root@zabbix-server-company ~]# systemctl enable zabbix-server
  7. 设置 httpd zabbix

    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
    [root@zabbix-server-company ~]# cat > /etc/httpd/conf.d/zabbix.conf <<EOF
    #
    # Zabbix monitoring system php web frontend
    #

    Alias /zabbix /usr/share/zabbix

    <Directory "/usr/share/zabbix">
    Options FollowSymLinks
    AllowOverride None
    Require all granted

    <IfModule mod_php5.c>
    php_value max_execution_time 300
    php_value memory_limit 2048M
    php_value post_max_size 512M
    php_value upload_max_filesize 200M
    php_value max_input_time 300
    php_value always_populate_raw_post_data -1
    php_value date.timezone Asia/Shanghai
    </IfModule>
    </Directory>

    <Directory "/usr/share/zabbix/conf">
    Require all denied
    </Directory>

    <Directory "/usr/share/zabbix/app">
    Require all denied
    </Directory>

    <Directory "/usr/share/zabbix/include">
    Require all denied
    </Directory>

    <Directory "/usr/share/zabbix/local">
    Require all denied
    </Directory>
    EOF
    [root@zabbix-server-company ~]# systemctl start httpd
    [root@zabbix-server-company ~]# systemctl enable httpd
  8. 打开浏览器进行设置

    1
    URL: http://192.168.10.81/zabbix/   默认账号/密码:Admin/zabbix

salt install distributed

salt multiple master/syndic/minion

  1. 基础环境安装

    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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    //机器信息
    192.168.13.217 saltmaster1 # CentOS 7.0
    192.168.13.218 saltmaster2 # CentOS 7.0
    192.168.13.212 saltsyndic1 # CentOS 7.0
    192.168.13.187 saltminion1 # CentOS 6.5
    192.168.13.188 saltminion2 # CentOS 7.0

    说明: 192.168.13.217 和 192.168.13.218 互为主备

    //修改主机名
    saltmaster1:
    [root@localhost ~]# hostname saltmaster1 && echo saltmaster1 |tee /etc/hostname
    [root@localhost ~]# $SHELL
    [root@saltmaster1 ~]#

    saltmaster2:
    [root@localhost ~]# hostname saltmaster2 && echo saltmaster2 |tee /etc/hostname
    [root@localhost ~]# $SHELL
    [root@saltmaster2 ~]#

    saltsyndic1:
    [root@localhost ~]# hostname saltsyndic1 && echo saltsyndic1 |tee /etc/hostname
    [root@localhost ~]# $SHELL
    [root@saltsyndic1 ~]#

    saltminion1:
    [root@localhost ~]# hostname saltminion1 && echo saltminion1 |tee /etc/hostname
    [root@localhost ~]# sed -i s/'localhost.localdomain'/saltminion1/g /etc/sysconfig/network
    [root@localhost ~]# $SHELL
    [root@saltminion1 ~]#

    saltminion2:
    [root@localhost ~]# hostname saltminion2 && echo saltminion2 |tee /etc/hostname
    [root@localhost ~]# $SHELL
    [root@saltminion2 ~]#

    //格式化磁盘(ALL)
    [root@[ALL] ~]# mkfs.xfs /dev/vdb
    [root@[ALL] ~]# echo '/dev/vdb /mnt xfs defaults 0 0' | tee -a /etc/fstab
    [root@[ALL] ~]# mount -a

    //修改最大文件数(ALL)
    [root@[ALL] ~]# echo '* - nproc 65535' | tee -a /etc/security/limits.conf
    [root@[ALL] ~]# echo '* - nofile 65535' | tee -a /etc/security/limits.conf
    [root@[ALL] ~]# ls /etc/security/limits.d/|xargs rm -f

    //YUM源设置(ALL)
    [root@[ALL] ~]# mkdir /etc/yum.repos.d/backup && mv /etc/yum.repos.d/{*,backup}

    CentOS6:
    [root@[ALL] ~]# curl -o /etc/yum.repos.d/epel-6.repo http://mirrors.aliyun.com/repo/epel-6.repo
    [root@[ALL] ~]# curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
    [root@[ALL] ~]# curl -O https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-6
    [root@[ALL] ~]# rpm --import RPM-GPG-KEY-CentOS-6
    [root@[ALL] ~]# rm -f RPM-GPG-KEY-CentOS-6
    CentOS7:
    [root@[ALL] ~]# curl -o /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo
    [root@[ALL] ~]# curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    [root@[ALL] ~]# curl -O https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
    [root@[ALL] ~]# rpm --import RPM-GPG-KEY-CentOS-7
    [root@[ALL] ~]# rm -f RPM-GPG-KEY-CentOS-7

    [root@[ALL] ~]# yum clean all
    [root@[ALL] ~]# yum makecache

    //安装基础软件包(ALL)
    CentOS6:
    [root@[ALL] ~]# yum -y groupinstall "Development Tools"
    [root@[ALL] ~]# yum -y install \
    cmake \
    bison-devel\
    bzip2 bzip2-devel bzip2-libs \
    zlib zlib-devel \
    openssl openssl-devel openssl-static \
    pcre pcre-devel pcre-static \
    ncurses ncurses-devel ncurses-libs ncurses-static \
    bzip2 bzip2-devel bzip2-libs \
    openldap openldap-devel \
    readline readline-devel readline-static \
    libssh2 libssh2-devel \
    unixODBC unixODBC-devel \
    sqlite sqlite-devel \
    tcl tcl-devel \
    perl-Digest-SHA1 \
    python-libs python-devel python-pip python-crypto \
    perl-libs \
    GeoIP GeoIP-devel \
    gperftools gperftools-devel gperftools-libs \
    libatomic_ops-devel \
    gtest gtest-devel \
    gdk-pixbuf2 gdk-pixbuf2-devel \
    libffi libffi-devel \
    libcurl libcurl-devel \
    http-parser http-parser-devel
    [root@[ALL] ~]# yum -y install fop lftp ntp ntpdate vim wget telnet dstat tree lrzsz net-tools nmap-ncat nmap sysstat

    CentOS7:
    [root@[ALL] ~]# yum -y groupinstall "Development Tools"
    [root@[ALL] ~]# yum -y install \
    make cmake \
    bison-devel \
    bzip2-devel \
    zlib zlib-devel \
    openssl openssl-devel openssl-libs \
    pcre pcre-devel pcre-static \
    ncurses ncurses-devel ncurses-libs \
    bzip2-devel\
    openldap openldap-devel \
    readline readline-devel readline-static \
    libssh2 libssh2-devel \
    unixODBC unixODBC-devel \
    sqlite sqlite-devel \
    tcl tcl-devel \
    perl-Digest-SHA1 \
    python-libs python-devel python2-pip python-crypto \
    perl-libs \
    GeoIP GeoIP-devel \
    gperftools gperftools-devel gperftools-libs \
    libatomic_ops-devel \
    gtest gtest-devel \
    gdk-pixbuf2 gdk-pixbuf2-deve \
    libffi libffi-devel \
    libcurl libcurl-devel \
    http-parser http-parser-devel
    [root@[ALL] ~]# yum -y install fop lftp ntp ntpdate vim wget telnet dstat tree lrzsz net-tools nmap-ncat nmap sysstat

    //关闭selinux(ALL)
    [root@[ALL] ~]# setenforce 0
    [root@[ALL] ~]# sed -i s/'SELINUX=enforcing'/'SELINUX=disabled'/g /etc/selinux/config

    //关闭防火墙(ALL)
    CentOS6:
    [root@[ALL] ~]# /etc/init.d/iptables stop && chkconfig iptables off
    CentOS7:
    [root@[ALL] ~]# systemctl stop firewalld && systemctl disable firewalld

    //设置时区和时间(ALL)
    [root@[ALL] ~]# [ -f /etc/localtime ] && cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    [root@[ALL] ~]# [ -f /etc/sysconfig/clock ] && echo 'ZONE="Asia/Shanghai"' | tee /etc/sysconfig/clock
    [root@[ALL] ~]# [ -f /etc/timezone ] && echo 'Asia/Shanghai' | tee /etc/timezone
    [root@[ALL] ~]# [ -f /etc/sysconfig/ntpd ] && echo 'SYNC_HWCLOCK=yes' | tee -a /etc/sysconfig/ntpd
    [root@[ALL] ~]# ntpdate cn.pool.ntp.org
    [root@[ALL] ~]# cp -f /etc/{ntp.conf,ntp.conf.bak}
    [root@[ALL] ~]# cat > /etc/ntp.conf <<EOF
    > driftfile /var/lib/ntp/drift
    > restrict default nomodify notrap nopeer noquery
    > restrict 127.0.0.1
    > restrict ::1
    > server cn.pool.ntp.org prefer
    > server 0.centos.pool.ntp.org iburst
    > server 1.centos.pool.ntp.org iburst
    > server 2.centos.pool.ntp.org iburst
    > server 3.centos.pool.ntp.org iburst
    > includefile /etc/ntp/crypto/pw
    > keys /etc/ntp/keys
    > disable monitor
    > EOF
    [root@[ALL] ~]# cp -f /etc/ntp/{step-tickers,step-tickers.bak}
    [root@[ALL] ~]# cat > /etc/ntp/step-tickers <<EOF
    > cn.pool.ntp.org
    > 0.centos.pool.ntp.org
    > 1.centos.pool.ntp.org
    > 2.centos.pool.ntp.org
    > 3.centos.pool.ntp.org
    > EOF

    CentOS6:
    [root@[ALL] ~]# /etc/init.d/ntpd start && chkconfig ntpd on
    CentOS7:
    [root@[ALL] ~]# systemctl start ntpd && systemctl enable ntpd

    //设置PIP源(ALL)
    [root@[ALL] ~]# mkdir ~/.pip
    [root@[ALL] ~]# cat > ~/.pip/pip.conf <<EOF
    > [global]
    > trusted-host=mirrors.aliyun.com
    > index-url=http://mirrors.aliyun.com/pypi/simple/
    > [list]
    > format=columns
    > EOF

    //设置开机启动文件权限
    [root@[ALL] ~]# chmod +x /etc/rc.d/rc.local

    //创建基础目录(ALL)
    [root@[ALL] ~]# mkdir -p /mnt/{app,data,log,web,ops/{app,data,cron}}
  2. python版本安装(ALL)

    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
    [root@ALL app]# wget https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tar.xz
    [root@ALL app]# xz -d Python-2.7.13.tar.xz
    [root@ALL app]# tar xf Python-2.7.13.tar
    [root@ALL app]# cd Python-2.7.13
    [root@ALL Python-2.7.13]# ./configure --prefix=/usr/local/python27
    [root@ALL Python-2.7.13]# make -j 4
    [root@ALL Python-2.7.13]# make -j 4 install

    [root@ALL Python-2.7.13]# wget https://bootstrap.pypa.io/get-pip.py
    [root@ALL Python-2.7.13]# /usr/local/python27/bin/python get-pip.py

    [root@ALL Python-2.7.13]# echo 'export PYTHON_PATH=/usr/local/python27' |tee /etc/profile.d/python27.sh
    [root@ALL Python-2.7.13]# echo 'export PYTHON_BIN=$PYTHON_PATH/bin' |tee -a /etc/profile.d/python27.sh
    [root@ALL Python-2.7.13]# echo 'export PATH=$PYTHON_BIN:$PATH' |tee -a /etc/profile.d/python27.sh
    [root@ALL Python-2.7.13]# source /etc/profile

    CentOS6:
    [root@ALL Python-2.7.13]# rm -f /usr/bin/{python,pip}
    [root@ALL Python-2.7.13]# sed -i s/python/python2.6/g /usr/bin/yum

    CentOS7:
    [root@ALL Python-2.7.13]# rm -f /usr/bin/{python,pip}
    [root@ALL Python-2.7.13]# sed -i s/python/python2.7/g /usr/bin/yum
    [root@ALL Python-2.7.13]# sed -i s/python/python2.7/g /usr/libexec/urlgrabber-ext-down

    [root@ALL Python-2.7.13]# python -V
    Python 2.7.13
    [root@ALL Python-2.7.13]# pip -V
    pip 9.0.1 from /usr/local/python27/lib/python2.7/site-packages (python 2.7)
  3. saltmaster1 和 saltmaster2 挂载一块共享磁盘

    1
    2
    3
    4
    5
    [root@saltmaster[X] ~]# yum -y install nfs-utils

    [root@saltmaster[X] ~]# mkdir -p /salt
    [root@saltmaster[X] ~]# echo '192.168.13.201:/mnt/data/nfs /salt nfs nfsvers=3 0 0' | tee -a /etc/fstab
    [root@saltmaster[X] ~]# mount -a
  4. salt 安装(ALL)

    1
    [root@[ALL] ~]# pip install salt
  5. saltmaster[X] 和 saltsyndic[X] pygit2 install

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    [root@saltmaster[X] app]# wget https://codeload.github.com/libgit2/libgit2/tar.gz/v0.26.0
    [root@saltmaster[X] app]# tar xzf v0.26.0 && rm -f v0.26.0
    [root@saltmaster[X] app]# cd libgit2-0.26.0/
    [root@saltmaster[X] libgit2-0.26.0]# cmake .
    [root@saltmaster[X] libgit2-0.26.0]# make
    [root@saltmaster[X] libgit2-0.26.0]# make install
    [root@saltmaster[X] libgit2-0.26.0]# echo '/usr/local/lib' | tee /etc/ld.so.conf.d/libgit2.conf
    [root@saltmaster[X] libgit2-0.26.0]# ldconfig

    [root@saltmaster[X] app]# wget https://codeload.github.com/libgit2/pygit2/tar.gz/v0.26.0
    [root@saltmaster[X] app]# tar xzf v0.26.0 && rm -f v0.26.0
    [root@saltmaster[X] app]# cd pygit2-0.26.0
    [root@saltmaster[X] pygit2-0.26.0]# python setup.py build
    [root@saltmaster[X] pygit2-0.26.0]# python setup.py install

    [root@saltmaster[X] pygit2-0.26.0]# pip list |grep pygit2
    pygit2 0.26.0

  1. saltmaster[X] 创建salt目录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    [root@saltmaster[X] ~]# mkdir -p /etc/salt
    [root@saltmaster[X] ~]# mkdir -p /salt/master.d
    [root@saltmaster[X] ~]# ln -s /salt/master.d /etc/salt/master.d

    [root@saltmaster[X] ~]# mkdir -p /salt/{file,pillar}/{base,dev,prod}

    [root@saltmaster[X] ~]# mkdir -p /salt/pki
    [root@saltmaster[X] ~]# ln -s /salt/pki /etc/salt/pki

    [root@saltmaster[X] ~]# mkdir -p /mnt/data/salt/cache
    [root@saltmaster[X] ~]# ln -s /mnt/data/salt/cache /var/cache/salt

    [root@saltmaster[X] ~]# mkdir -p /mnt/data/salt/run
    [root@saltmaster[X] ~]# ln -s /mnt/data/salt/run /var/run/salt

    [root@saltmaster[X] ~]# mkdir -p /mnt/log/salt
    [root@saltmaster[X] ~]# ln -s /mnt/log/salt /var/log/salt
  2. saltmaster[X] 配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    注意: 由于配置文件创建master.conf在"/salt"(共享磁盘),所以saltmaster1和saltmaster2共享配置

    [root@saltmaster[X] ~]# echo 'default_include: master.d/*.conf' | tee /etc/salt/master
    [root@saltmaster[X] ~]# cat > /etc/salt/master.d/master.conf <<EOF
    ...
    order_masters: True #主要是将它打开
    ...
    EOF
  3. saltmaster[X] 启动/关闭程序

    1
    2
    [root@saltmaster[X] ~]# salt-master -c /etc/salt -d  #启动程序
    [root@saltmaster[X] ~]# pkill salt-master #关闭程序

  1. saltsyndic[X] 创建salt目录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    [root@saltsyndic[x] ~]# mkdir -p /mnt/data/salt
    [root@saltsyndic[x] ~]# ln -s /mnt/data/salt /salt

    [root@saltsyndic[x] ~]# mkdir -p /etc/salt
    [root@saltsyndic[x] ~]# mkdir -p /salt/master.d
    [root@saltsyndic[x] ~]# ln -s /salt/master.d /etc/salt/master.d

    [root@saltsyndic[x] ~]# mkdir -p /salt/{file,pillar}/{base,dev,prod}

    [root@saltsyndic[x] ~]# mkdir -p /salt/pki
    [root@saltsyndic[x] ~]# ln -s /salt/pki /etc/salt/pki

    [root@saltsyndic[x] ~]# mkdir -p /mnt/data/salt/cache
    [root@saltsyndic[x] ~]# ln -s /mnt/data/salt/cache /var/cache/salt

    [root@saltsyndic[x] ~]# mkdir -p /mnt/data/salt/run
    [root@saltsyndic[x] ~]# ln -s /mnt/data/salt/run /var/run/salt

    [root@saltsyndic[x] ~]# mkdir -p /mnt/log/salt
    [root@saltsyndic[x] ~]# ln -s /mnt/log/salt /var/log/salt
  2. saltsyndic[X] 配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [root@saltsyndic[x] ~]# echo 'default_include: master.d/*.conf' | tee /etc/salt/master
    [root@saltsyndic[x] ~]# cat > /etc/salt/master.d/master.conf <<EOF
    ...
    # order_masters: True
    syndic_master: #指定salt-master IP
    - 192.168.13.217
    - 192.168.13.218
    syndic_master_port: 4506
    syndic_pidfile: /var/log/salt/salt-syndic.pid
    syndic_log_file: /var/log/salt/syndic
    syndic_failover: random
    syndic_wait: 20
    ...
    EOF
  3. saltsyndic[X] 启动/关闭程序

    1
    2
    3
    4
    5
    [root@saltsyndic[x] ~]# salt-master -c /etc/salt -d   #先启动salt-master
    [root@saltsyndic[x] ~]# salt-syndic -c /etc/salt -d #在启动salt-syndic

    [root@saltsyndic[x] ~]# pkill salt-syndic #先关闭salt-syndic
    [root@saltsyndic[x] ~]# pkill salt-master #在关闭salt-master
  4. saltsyndic[X] 与 saltmaster[X] 建立认证

    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
    方式一: 自动认证(配置文件中已经开启"auto_accept: True")
    [root@saltmaster[X] ~]# salt-key -L
    minions:
    - saltsyndic1
    minions_denied:
    minions_pre:
    minions_rejected:


    方式二: 手动认证(配置文件中已经关闭"auto_accept: False")
    [root@saltmaster[X] ~]# salt-key -L # 查看当前Key信息
    minions:
    minions_denied:
    minions_pre:
    - saltsyndic1
    minions_rejected:

    [root@saltmaster[X] ~]# salt-key -A # 认证全部
    The following keys are going to be accepted:
    minions_pre:
    - saltsyndic1
    Proceed? [n/Y] y
    Key for minion saltsyndic1 accepted.

    [root@saltmaster[X] ~]# salt-key -L # 认证结果查看
    minions:
    - saltsyndic1
    minions_denied:
    minions_pre:
    minions_rejected:

  1. saltminion[X] 创建salt目录

    1
    [root@saltminion[x] ~]# mkdir -p /etc/salt/minion.d
  2. saltminion[X] 配置文件

    1
    2
    3
    4
    5
    6
    7
    [root@saltminion[x] ~]# echo 'default_include: minion.d/*.conf'|tee /etc/salt/minion
    [root@saltminion[x] ~]# cat > /etc/salt/minion.d/minion.conf <<EOF
    ...
    master: saltsyndic1 #注意这里的master指向 satlsyndic
    id: saltminion1
    ...
    EOF
  3. saltminion[X] 启动/关闭程序

    1
    2
    [root@saltminion[x] ~]# salt-minion -c /etc/salt -d  #启动程序
    [root@saltminion[x] ~]# pkill salt-minion #关闭程序
  4. saltminion[X] 与 saltsyndic[X] 建立认证

    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
    方式一: 自动认证(配置文件中已经开启"auto_accept: True")
    [root@saltsyndic[X] ~]# salt-key -L
    minions:
    - saltminion1
    - saltminion2
    minions_denied:
    minions_pre:
    minions_rejected:


    方式二: 手动认证(配置文件中已经关闭"auto_accept: False")
    [root@saltsyndic[X] ~]# salt-key -L # 查看当前Key信息
    minions:
    minions_denied:
    minions_pre:
    - saltminion1
    - saltminion2
    minions_rejected:

    [root@saltsyndic[X] ~]# salt-key -A # 认证全部
    The following keys are going to be accepted:
    minions_pre:
    - saltminion1
    - saltminion2
    Proceed? [n/Y] y
    Key for minion saltminion1 saltminion2 accepted.

    [root@saltmaster[X] ~]# salt-key -L # 认证结果查看
    minions:
    - saltsyndic1
    minions_denied:
    minions_pre:
    minions_rejected:
  5. 补充说明

    1
    2
    注意:
    salt-syndic上面只运行了salt-master和salt-syndic,不要运行salt-minion.如果在salt-syndic上有运行salt-minion, id最好不要与salt-syndic一样,或者 禁止启动 salt-minion

  1. saltmaster[X] 通过 saltsyndic[X] 管理 saltminion[X]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //在saltsyndic[X]测试:
    [root@saltsyndic[X] ~]# salt '*' test.ping
    saltminion1:
    True
    saltminion2:
    True

    //在saltmaster[X]测试:
    [root@saltmaster[X] ~]# salt '*' test.ping
    saltminion2:
    True
    saltminion1:
    True

hmonitor install

hmonitor install

  1. 基础环境

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [root@alarmcenter ~]# python -V
    Python 2.7.13

    [root@alarmcenter ~]# pip -V
    pip 9.0.1 from /usr/local/python27/lib/python2.7/site-packages (python 2.7)

    [root@alarmcenter ~]# mysql -V
    mysql Ver 14.14 Distrib 5.6.36, for Linux (x86_64) using EditLine wrapper

    注意:数据库要添加动态库:
    echo '/mnt/app/mysql/lib' | tee /etc/ld.so.conf.d/mysql.conf
    ldconfig
  2. hmonitor install

    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
    //下载
    [root@alarmcenter ~]# cd /mnt/web/
    [root@alarmcenter web]# git clone https://github.com/smallasa/hmonitor.git

    //安装依赖包
    [root@alarmcenter web]# cd hmonitor/
    [root@alarmcenter hmonitor]# cat requirements.txt
    # python version : 2.7.13
    # pip version : 9.0.1
    tornado>=4.2
    torndb==0.3
    requests>=2.7.0
    six>=1.9.0
    stevedore>=1.5.0
    MySQL-python>=1.2.5
    [root@alarmcenter hmonitor]# pip install -r requirements.txt

    //初始化数据库
    [root@alarmcenter hmonitor]# mysql -S /mnt/data/mysql/mysql.sock < db.sql
    [root@alarmcenter hmonitor]# mysql -S /mnt/data/mysql/mysql.sock -e "show tables in hmonitor;"
    +-----------------------+
    | Tables_in_hmonitor |
    +-----------------------+
    | ALERT_FILTER |
    | ALERT_MSG |
    | AUTOFIX_BINDING |
    | AUTOFIX_LOG |
    | HM_TRIGGER |
    | TRIGGER_EVENTS |
    | USERS |
    | USERS_TRIGGER_BINDING |
    +-----------------------+

    //数据库授权
    [root@alarmcenter hmonitor]# mysql -S /mnt/data/mysql/mysql.sock
    mysql> grant all privileges on hmonitor.* to 'hmonitor'@'127.0.0.1' identified by 'hmonitor' with grant option;
    mysql> flush privileges;
    [root@alarmcenter hmonitor]# mysql -uhmonitor -phmonitor -h127.0.0.1
    mysql>


    // hmonitor 安装
    [root@alarmcenter hmonitor]# python setup.py build
    [root@alarmcenter hmonitor]# python setup.py install
  3. hmonitor 配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //hmonitor.py
    [root@alarmcenter hmonitor]# vim hmonitor.py
    #MySQL
    define("port", default=8888, help="run on the given port", type=int)
    define("mysql_host", default="{127.0.0.1:3306}", help="hmonitor database host")
    define("mysql_database", default="{hmonitor}", help="hmonitor database name")
    define("mysql_user", default="{hmonitor}", help="hmonitor database user")
    define("mysql_password", default="{htmonitor}", help="hmonitor database password")
    #Zabbix
    define("zabbix_user", default="{Admin}", help="Zabbix user name")
    define("zabbix_password", default="{zabbix}", help="Zabbix password")
    define("zabbix_url", default="{http://zabbix.domain.cn}", help="Zabbix URL")
    #Executor
    define("executor_driver", default="ssh", help="remote executor driver")
    define("executor_user", default="stack", help="remote executor user")

htmonitor install

htmonitor install

  1. tornado install

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [root@alarmcenter ~]# python -V
    Python 2.7.13
    [root@alarmcenter ~]# pip -V
    pip 9.0.1 from /usr/local/python27/lib/python2.7/site-packages (python 2.7)

    [root@alarmcenter ~]# cat > requirements.txt <<EOF
    > tornado>=4.2
    > torndb==0.3 # 0.3 is ok, not sure if other versions can work.
    > requests>=2.7.0
    > six>=1.9.0
    > stevedore>=1.5.0
    > EOF
    [root@alarmcenter ~]# pip install -r requirements.txt
  2. mysql install

    1
    2
    3
    [root@alarmcenter ~]# yum -y install mariadb-server
    [root@alarmcenter ~]# systemctl start mariadb
    [root@alarmcenter ~]# systemctl enable mariadb
  3. 下载htmonitor

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [root@alarmcenter ~]# cd /mnt/web/
    [root@alarmcenter web]# git clone https://github.com/smallasa/hmonitor.git

    [root@alarmcenter web]# cd hmonitor/
    [root@alarmcenter hmonitor]# mysql < db.sql
    [root@alarmcenter hmonitor]# mysql -e "show tables in hmonitor;"
    +-----------------------+
    | Tables_in_hmonitor |
    +-----------------------+
    | ALERT_FILTER |
    | ALERT_MSG |
    | AUTOFIX_BINDING |
    | AUTOFIX_LOG |
    | HM_TRIGGER |
    | TRIGGER_EVENTS |
    | USERS |
    | USERS_TRIGGER_BINDING |
    +-----------------------+

    [root@alarmcenter hmonitor]# mysql
    MariaDB [(none)]> grant all privileges on hmonitor.* to 'hmonitor'@'localhost' identified by 'htmonitor' with grant option;
    MariaDB [(none)]> flush privileges;

python tornado install

python tornado install

  1. python install

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    [root@alarmcenter app]# wget https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tar.xz
    [root@alarmcenter app]# xz -d Python-2.7.13.tar.xz
    [root@alarmcenter app]# tar xf Python-2.7.13.tar
    [root@alarmcenter app]# cd Python-2.7.13
    [root@alarmcenter Python-2.7.13]# ./configure --prefix=/usr/local/python27
    [root@alarmcenter Python-2.7.13]# make
    [root@alarmcenter Python-2.7.13]# make install
    [root@alarmcenter Python-2.7.13]# wget https://bootstrap.pypa.io/get-pip.py
    [root@alarmcenter Python-2.7.13]# /usr/local/python27/bin/python get-pip.py
    [root@alarmcenter Python-2.7.13]# echo 'export PYTHON_PATH=/usr/local/python27' |tee /etc/profile.d/python27.sh
    [root@alarmcenter Python-2.7.13]# echo 'export PYTHON_BIN=$PYTHON_PATH/bin' |tee -a /etc/profile.d/python27.sh
    [root@alarmcenter Python-2.7.13]# echo 'export PATH=$PYTHON_BIN:$PATH' |tee -a /etc/profile.d/python27.sh
    [root@alarmcenter Python-2.7.13]# source /etc/profile
    [root@alarmcenter Python-2.7.13]# rm -f /usr/bin/{python,pip}
    [root@alarmcenter Python-2.7.13]# sed -i s/python/python2.7/g /usr/bin/yum
    [root@alarmcenter Python-2.7.13]# python -V
    Python 2.7.13
    [root@alarmcenter Python-2.7.13]# pip -V
    pip 9.0.1 from /usr/local/python27/lib/python2.7/site-packages (python 2.7)
  2. pip源设置

    1
    2
    3
    4
    5
    6
    7
    8
    [root@alarmcenter ~]# mkdir ~/.pip
    [root@alarmcenter ~]# cat > ~/.pip/pip.conf <<EOF
    > [global]
    > trusted-host=mirrors.aliyun.com
    > index-url=http://mirrors.aliyun.com/pypi/simple/
    > [list]
    > format=columns
    > EOF
  3. tornado install

    1
    [root@alarmcenter ~]# pip install tornado

salt raet

salt raet

  1. 简介

    1
    salt raet 是继 Salt-Zeromq,Salt-Ssh 之后的第三套通信体系,全名为"Reliable Asynchronous Event Transport"(即基于事件的可靠异步传输协议)
  2. 为什么研发salt raet?

    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
    现代大规模的分布式应用架构,其组件均是分布在互联网上的多个主机和多个CPU内核,往往是基于一个消息或事件总线,允许不同的分布式组件之间相互异步通信.
    通常情况下,消息总线是某种形式的消息队列服务,如: AMQP 或 ZeroMQ.
    消息总线支持通常被称为"发布/订阅"模式的信息交互方式

    一个具备完整功能的消息队列服务拥有很多的优点,然而,其存在的缺陷之一便是"大规模应用环境下的性能问题"

    一个消息队列服务完成两个独立而互补的功能:
    第一个是,在互联网上消息的异步传输
    第二个是,消息队列管理,这便是通过队列实现的诸如:消息识别,跟踪,存储,以及发布者和订阅者相互之间的消息分发

    对于众多应用程序而言,一个消息队列服务的优势之一便是通过API能很好的隐藏服务背后的细节,也就是其来自各个客户端的消息队列管理的复杂性.但是,消息队列服务存在的主要缺陷便是"大规模应用环境下的扩展性",其消息的容量,消息的定时以及内存,网络和CPU处理能力相关的需求往往成为关键,而客户端对于服务性能的调整往往显得无能为力.MQ服务在分布式的应用环境下通常会成为瓶颈所在,而更复杂的MQ服务,如 AMQP,则会在高负载下变得不可靠

    异步事件的网络传输 和 消息队列管理之间功能的分离,使得每个功能模块可以独立的调整各自大规模环境下的性能

    绝大部分的MQ服务是基于TCP/IP网络传输协议.TCP/IP对于网络通信有显著的"延迟效应",因而不太适合用于分布式事件驱动式应用程序交互的异步特性.这其中主要的原因便是在于"TCP/IP为了支持流传输针对'连接的建立'和'连接的关闭'以及'失败连接'的处理".从根本上来说,"TCP/IP是基于大规模的连续数据流作出了诸多优化,而不太适用于大量小规模异步事件或消息的传输".其在小规模应用系统下不成问题,而一旦达到一定规模,相关的通信特征的差异问题将会凸显.

    UDP/IP低延迟和无连接的特性注定它更适用于许多小规模异步消息的传输.UDP/IP本身的缺点在于它是不可靠的传输协议.这里所需要的便是一个适配的针对UDP/IP协议增添可靠性,而同时无损其低延迟及扩展性的传输协议.一个事务型协议,比流协议更适用于为异步事件提供可靠传输.进一步来说,由于大部分的MQ服务是基于TCP/IP协议,他们也更倾向于使用HTTP或者保证安全通信的TLS/SSL.虽然使用HTTP能够轻松的提供基于Web的集成系统,但是长远来说它也会成为高性能系统的瓶颈所在,TLS对于一个安全系统而言,其性能和漏洞两方面也同样存在问题.

    椭圆曲线加密,另一方面来说,在相对于其他实现方法更低的性能需求的前提下增强了系统的安全性.LibSodium提供了一个开源的椭圆曲线加密库,用于验证和加密支持.CurveCP协议基于LibSodium提供了一个引导安全网络信息交互的握手协议.最后,在分布式并发事件驱动的应用环境下管理和协调处理器资源(CPU,内存,网络)的一个最佳途径便是使用一种称为微线程的东西.一个微线程应该说是一个程序语言级的特性,它在不比函数调用消耗更多资源的情况下实现了代码逻辑上的并发.

    微线程使用协同工作的多任务处理来取代线程和/或进程,其避免了许多诸如资源竞争,上下文切换,和进程间通信的复杂性,同时提供了更高的性能.由于所有协同工作的微线程均运行于一个进程,也就造成一个简单的微线程应用的资源调用被限制在一个CPU核心.为了使得所有的CPU核心均得到充分的利用,应用程序需要能够为每个CPU核心运行至少一个进程.这就需要同一台主机的进程间通信.但是不同于传统的多进程处理方式,即一个进程完成一个逻辑并发的功能,一个基于微线程的多进程程序不再使用一个微线程处理一个逻辑并发功能的模式,而微线程的总数是取决于总的进程的最小数目的限制,并且其不超过CPU的核心数量.这将优化CPU的处理能力,同时最大限度地减少进程上下文切换的开销.

    一个使用这样的"微线程-多进程"架构平台的典型例子便是Erlang.事实上,Erlang模式的成功为RAET方案的可行性提供了强有力的支持.进一步来说,一个潜在的问题可能是:我们为什么不使用Erlang呢? 很不幸的是,Erlang生态系统跟Python相比较而言有些时候显得有些局限性,而它本身则使用了一种不太友好的语法结构. RAET的设计实现目标之一便是充分集成现有的Python生态系统丰富的类库和知识集,同时又能够方便的开发一个基于"微线程-多进程"架构模型的分布式应用程序.我们的终极目标便是想两全其美.

    RAET设计用于借助"微线程-多进程"应用框架提供在互联网上安全可靠的,可扩展的异步消息/事件传输,其使用UDP协议来完成主机间的通信,LibSodium来完成认证,加密,CurveCP握手协议来达成安全引导.相应的队列管理和微线程应用程序的支持由Ioflo提供.RAET可以算作是Ioflo的一个互补项目,它使得多个Ioflo程序可以通过网络结合在一起,作为一个分布式程序的一部分协同工作.

    导致开发RAET的一个主要驱动因素便是"使得Saltstack具备更好的扩展性的需求".Saltstack是一个使用Python编写的远程执行和配置管理平台.Saltstack使用Zeromq作为它的消息总线或者说消息队列服务.Zeromq是基于TCP/IP传输协议实现的,因而也存在上述相应的TCP/IP基础架构下的延迟及非同步性问题.此外,因为Zeromq是通过一个特殊的"套接字"将队列管理和传输集成在一起,其大规模应用环境下的队列的独立传输性能也成为问题所在,甚至于跟踪Bug也存在一定的困难.
  3. raet安装

    1
    pip install raet
  4. Raet支持两种通信方式

    1
    2
    3
    Raet支持两种通信方式:
    * 主机间通过UDP/IP协议套接字通信
    * 通过Unix域(UXD)套接字实现的同一主机进程间通信

RaetMetaphor

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
如上图:
Road,Estates,Main Estate:
* UPD通道便是一个"Road"
* 一个Road的成员便是"Estates"(就像现实中房屋前方的道路)
* 每个Estate拥有一个唯一的UDP主机端口地址"ha",一个唯一的字符串"name"和一个唯一的数字ID"eid"
* 一个Road上的Estate便称为"Main Estate"
* Main Estate允许其他Estates通过Join方法(key交换)加入到Road上并且允许(CurveCP)相互之间的信息交易
* Main Estate同样负责担任其他Estates的消息路由

Lane,Yards,Main Yard:
* 每个Estate都可以是一个"Lane",这便是一个UXD通道
* 一个Lane的成员便是"Yard"(简单来说便是一个Estate的细分点)
* 一个Lane的每个Yard成员都有一个唯一的UXD文件名称,主机地址"ha"和一个唯一的字符串"name".这个类通常也有一个Yard的数字ID"yid"用于生成Yard name但是它不是Yard实例的属性之一
* Lane name和Yard name结合起来便可以形成一个唯一的文件名,它是UXD的主机地址"ha"
* 一个Lane上的Yard便是一个Main Yard
* Main Yard负责形成Lane并且允许其他Yards加入到该lane;在此之前这还没有一个正式的处理过程.当前这会设置一个由Main yard维护的标志,其将会把任何事先未在Yards列表里的Yard发送过来的数据包Drop掉.另外,文件权限的设置可以用来阻止伪Yards与Main Yard交互
* Main Yard还负责其他Lane上的Yards之间的消息路由

运行IoFlo:
* 每个Estate UDP接口运行于一个在单个IoFlo House上下文中工作的RoadStack(UDP套接字),因此可以把运行UDP Stack的House看作是Estate组成的庄园别墅
* 每个Yard UXD接口运行于一个在单个IoFlo House上下文中工作的 LaneStack(Unix域套接字),因此可以把运行UXD Stack的House看作是Estate的附属Houses、Tents或Shacks
* "庄园"House的特殊之处在于其可以运行在针对Estate的UDP Stack和针对Main Yard的UXD Stack两套环境下运行
* Main Estate UDP Stack的House可以被认为是Mayor's House;
* 在上下文中,一个House便是一个数据存储.共享的数据存储可以被以一个点号分隔路径的唯一共享名称定位

路由
鉴于上面所描述的Ioflo运行架构,其依照如下方式完成路由:
* 为了定位一个特定的Estate,Estate name需要相应的指定
* 为了定位一个Estate下的特定Yard,Yard name需要相应的指定
* 为了定位一个House下的特定Queue,Share name需要相应的指定

UDP stack 将Estate name映射到UDP主机地址和Estate ID,而UXD stack 将Yard name映射到UXD主机地址,任意IoFlo行为的存储将Share name映射到共享引用.因此,路由是从: 在一个源Share、源Yard或是一个源Estate中的队列定义好的一个源节点到,一个源Share、源Yard或是一个源Estate中的队列定义好的目的节点

这里需要两个三选一的节点,一个是源节点,另一个则是目标节点:
* 源节点(Estate name,Yard name,Share name)
* 目标节点(Estate name,Yard name,Share name)
如果三合一中的任一元素均是None或者空,那么便会使用默认参数值

salt advanced topic

salt高级话题

  1. salt job管理

    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
    // job概念
    slat每次运行任务时都会将作业任务发布到pub-sub总线,minion会对任务做出响应.为区分不同任务,salt-master每次发布一个任务都会为该任务创建一个jobid,不同的jobid对应一个独立的操作任务,master端默认会缓存24小时内的所有job详细操作

    master 缓存目录: /var/cache/salt/master/jobs
    minion 缓存目录: /var/cache/salt/minion/proc,创建以jobid为名的文件,文件内容是对本次任务的缓存,任务执行完后文件会被删除.使用"strings /var/cache/salt/minion/proc/2017080912124243524"进行查看缓存文件内容

    例如:
    在master上长时间执行一个命令:
    [root@saltserver ~]# salt '*' cmd.run 'sleep 1000;echo hello'
    在minion上查看:
    [root@saltminion ~]# ls /var/cache/salt/minion/proc/20170807162006823661
    /var/cache/salt/minion/proc/20170807162006823661
    [root@saltminion ~]# strings /var/cache/salt/minion/proc/20170807162006823661
    tgt_type
    glob
    20170807162006823661
    user
    root
    sleep 1000;echo hello
    cmd.run


    // 管理job
    通过 salt-run 命令来管理job,这种方式其实是通过runner系统对job进行管理;另一种管理job的方式是通过 saltutil模块

    例如: 执行过程中 中断
    [root@saltserver ~]# salt '*' cmd.run 'sleep 1000;echo hello'
    ^C
    Exiting gracefully on Ctrl-c
    This job's jid is: 20170807162218636420
    The minions may not have all finished running and any remaining minions will return upon completion. To look up the return data for this job later, run the following command:
    salt-run jobs.lookup_jid 20170807162218636420

    综上,我们看到jobid是20170807162218636420
    在minion上查看:
    [root@saltminion ~]# ls /var/cache/salt/minion/proc/20170807162218636420
    /var/cache/salt/minion/proc/20170807162218636420

    通过saltutil进行查看:
    [root@saltserver ~]# salt '*' saltutil.find_job 20170807162218636420
    192.168.13.187:
    ----------
    arg:
    - sleep 1000;echo hello
    fun:
    cmd.run
    jid:
    20170807162218636420
    pid:
    30823
    ret:
    tgt:
    *
    tgt_type:
    glob
    user:
    root

    通过kill指令杀死job:
    [root@saltserver ~]# salt '*' saltutil.kill_job 20170807162218636420
    192.168.13.187:
    Signal 9 sent to job 20170807162218636420 at pid 30823

    查看master上cache的所有job:
    [root@saltserver ~]# salt '*' saltutil.runner jobs.list_jobs
  2. runner系统

    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
    前面通过salt master通过执行模块管理salt minion,除此之外,salt还为我们提供了runners系统,runner和salt的模块类似,不同点是salt的模块在minion上执行,runner在sat master上执行,而salt master可以在任意minion执行任务.
    所以,通过runner可以控制不同minion的执行顺序,这一点是state模块无法做到的.通过salt-run可以调用salt的runner功能

    //minion管理
    探测主机是否存活:
    [root@saltserver ~]# salt '*' test.ping
    192.168.13.187:
    True
    通过runner也可以达到同样效果,不同的是runner不需要匹配目标minion:
    [root@saltserver ~]# salt-run manage.up
    - 192.168.13.187
    这条命令实质上是runner调用master并对所有minion进行test.ping,不同的是runner只在master上执行,没有和任何minion进行通信

    [root@saltserver ~]# salt-run manage.down
    这条命令也是通过master对所有minion调用test.ping函数,然后和已经注册的minion做比较,找出现在已经不能连接的minion,然后进行输出

    //job管理
    查看所有和job管理相关的命令:
    [root@saltserver ~]# salt-run -d |grep job

    列出24小时内所有job:
    [root@saltserver ~]# salt-run jobs.list_jobs

    查看某一个特定的job:
    [root@saltserver ~]# salt-run jobs.list_job 20170807162218636420

    //orchestrate
    runner可以控制不同minion的执行顺序,runner有一项功能用于管理多台minion的状态:orchestrate runner.
    例如:
    [root@saltserver ~]# vim /srv/salt/orch.sls
    mysql_mod:
    salt.state:
    - tgt: 'minion-one'
    - tgt_type: list
    - sls: mysql
    web_mod:
    salt.state:
    - tgt: 'minion-two'
    - tgt_type: list
    - sls: httpd
    - require:
    - salt: mysql_mod

    执行:
    [root@saltserver ~]# salt-run state.orchestrate orch

    综上,通过这样的模块顺序控制使得minion-one必须先安装mysql后,才能让minion-two再安装httpd
  3. event系统和reactor系统

    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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    //event系统
    event是salt通信的核心,每一个event可以认为是salt的一个执行单元,比job要宽泛,job可以看成一种特殊的event

    例如: 写一个脚本用于监听master的event
    * 编写脚本:
    [root@saltserver ~]# vim eventlisten.py
    #-*- coding:utf-8 -*-
    """
    This script is a generic tool to test event output
    """

    # import python libs
    from __future__ import absolute_import,print_function
    import optparse
    import pprint
    import time
    import os

    # import salt libs
    import salt.utils.event

    # import 3rd-party libs
    import salt.ext.six as six

    def parse():
    """
    Parse the script command line inputs
    """
    parser = optparse.OptionParser()
    parser.add_option(
    '-s',
    '--sock-dir',
    dest='sock_dir',
    default='/var/run/salt',
    help=('statically define the directory holding the salt unix sockets for communication')
    )
    parser.add_option(
    '-n',
    '--node',
    dest='node',
    default='master',
    help=('state if this listener will attach to a master or a minion daemon,pass "master" or "minion"')
    )
    parser.add_option(
    '-f',
    '--func_count',
    default='',
    help=('Return a count of the number of minions which hava replied to a job with a ggiven func.')
    )
    parser.add_option(
    '-i',
    '--id',
    default='',
    help=('if connection to a live master or minion,pass in the id')
    )
    parser.add_option(
    '-t',
    '--transport',
    default='zeromq',
    help=('Transport to use. Default:\'zeromq\'')
    )

    options, args = parser.parse_args()

    opts = {}

    for k,v in six.iteritems(options.__dict__):
    if v is not None:
    opts[k] = v

    opts['sock_dir'] = os.path.join(opts['sock_dir'],opts['node'])

    if 'minion' in options.node:
    if args:
    opts['id'] = args[0]
    return opts
    if options.id:
    opts['id'] = options.id
    else:
    opts['id'] = options.node
    return opts

    def check_access_and_print_warning(sock_dir):
    """
    check if this user is able to access the socket directory and print a warning if not
    """
    if (os.access(sock_dir,os.R_OK) and
    os.access(sock_dir,os.W_OK) and
    os.access(sock_dir,os.X_OK)):
    return
    else:
    print('Warning: Events will not be reported "(not able to access {0})".format(sock_dir)')


    def listen(opts):
    """
    attach to the pub socket and grab messges
    """
    event = salt.utils.event.get_event(
    opts['node'],
    sock_dir = opts['sock_dir'],
    transport = opts['transport'],
    opts = opts,
    listen = True
    )
    check_access_and_print_warning(opts['sock_dir'])
    print(event.puburi)
    jid_counter = 0
    found_minions = []
    while True:
    ret = event.get_event(full=True)
    if ret is None:
    continue
    if opts['func_count']:
    data = ret.get('data',False)
    if data:
    if 'id' in six.iterkeys(data) and data.get('id',False) not in found_minions:
    if data['fun'] == opts['func_count']:
    jid_counter += 1
    found_minions.append(data['id'])
    print('Reply received from [{0}]. Total replies now:[{1}].'.format(ret['data']['id'],jid_counter))
    continue
    else:
    print('Event fired at {0}'.format(time.asctime()))
    print('*' * 25)
    print('Tag: {0}'.format(ret['tag']))
    print('Data:')
    pprint.pprint(ret['data'])

    if __name__ == '__main__':
    opts = parse()
    listen(opts)

    * 在salt-master上执行脚本:
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc

    * 在打开一个salt-master终端进行执行:
    [root@saltserver ~]# salt '*' test.ping
    192.168.13.187:
    True

    * 在salt-master上查看输出信息:
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc
    Event fired at Tue Aug 8 10:06:47 2017
    *************************
    Tag: 20170808100647714897
    Data:
    {'_stamp': '2017-08-08T02:06:47.715514', 'minions': ['192.168.13.187']}
    Event fired at Tue Aug 8 10:06:47 2017
    *************************
    Tag: salt/job/20170808100647714897/new
    Data:
    {'_stamp': '2017-08-08T02:06:47.716171',
    'arg': [],
    'fun': 'test.ping',
    'jid': '20170808100647714897',
    'minions': ['192.168.13.187'],
    'tgt': '*',
    'tgt_type': 'glob',
    'user': 'root'}
    Event fired at Tue Aug 8 10:06:47 2017
    *************************
    Tag: salt/job/20170808100647714897/ret/192.168.13.187
    Data:
    {'_stamp': '2017-08-08T02:06:47.797479',
    'cmd': '_return',
    'fun': 'test.ping',
    'fun_args': [],
    'id': '192.168.13.187',
    'jid': '20170808100647714897',
    'retcode': 0,
    'return': True,
    'success': True}

    综上,event输出包含两部分:
    部分一: tag,类似于一个url
    salt/job/20170808100647714897/new
    这条tag从左到右说明了:类型,任务ID,任务标识
    部分二: 数据字典,包含:时间戳,调用函数,jid,minion信息



    //salt为我们提供了event.send模块可自定义event,例如:
    * 在master端执行
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc
    * 在minion端执行
    [root@saltminion ~]# salt-call event.send myco/mytag foo=Foo bar=Bar
    local:
    True
    * 在master端查看
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc
    Event fired at Tue Aug 8 10:21:41 2017
    *************************
    Tag: salt/auth
    Data:
    {'_stamp': '2017-08-08T02:21:41.187922',
    'act': 'accept',
    'id': '192.168.13.187',
    'pub': '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnZHnTfGzMpKiNqPmwM1Q\nrgnRGSrA8eNghWRBECq+raT3qG99xvY7sjP1at8Ul/fnEMCC/K1W4CJz/6TN2lG/\n1jVh77zk9W/PbABGv5i00ZpmxZBtgNywRj4wL9IPPDmalSqm13HnjnVQ7+1I4MK7\naQDmkihGWynSh5U/CGLpApWNowcGw2Xui0d3jdrhGjngvmFuwooCLHlXDOXE3kLY\n1/5oE1+NpM4+6Hbg09XQ6wXtAnM7zNW1GFBfuNTh9ZymkicUso8uqZXCH2dUrf+e\n8VViFb01jBOBgThXm4hmqyF+NfbrjlFmcfSMJ73pJBC1VvmfQ4+F9oSksJGVufkl\n7QIDAQAB\n-----END PUBLIC KEY-----',
    'result': True}
    Event fired at Tue Aug 8 10:21:41 2017
    *************************
    Tag: minion/refresh/192.168.13.187
    Data:
    {'Minion data cache refresh': '192.168.13.187',
    '_stamp': '2017-08-08T02:21:41.311715'}
    Event fired at Tue Aug 8 10:21:41 2017
    *************************
    Tag: myco/mytag
    Data:
    {'_stamp': '2017-08-08T02:21:41.396306',
    'cmd': '_minion_event',
    'data': {'__pub_fun': 'event.send',
    '__pub_jid': '20170808102141379062',
    '__pub_pid': 31706,
    '__pub_tgt': 'salt-call',
    'bar': 'Bar',
    'foo': 'Foo'},
    'id': '192.168.13.187',
    'tag': 'myco/mytag'}
    Event fired at Tue Aug 8 10:21:41 2017
    *************************
    Tag: salt/job/20170808102141404168/ret/192.168.13.187
    Data:
    {'_stamp': '2017-08-08T02:21:41.405667',
    'arg': ['myco/mytag', 'foo=Foo', 'bar=Bar'],
    'cmd': '_return',
    'fun': 'event.send',
    'fun_args': ['myco/mytag', 'foo=Foo', 'bar=Bar'],
    'id': '192.168.13.187',
    'jid': '20170808102141404168',
    'retcode': 0,
    'return': True,
    'tgt': '192.168.13.187',
    'tgt_type': 'glob'}

    综上,我们看到新产生的event的tag正是我们自己触发的Event.我们既然可以获取这么多的Event,如果能对这些event做定制化的相应会使salt更加灵活强大. salt为我们设计了Reactor系统,可以对event做出相应


    //reactor系统
    reactor分两部分来配置:
    部分一: 在master配置文件中,定义哪些event触发哪些reactor文件
    部分二: reactor的SLS配置文件,定义对事件作出相应时采取哪些操作

    例如:(修改master配置)
    * 修改master配置文件
    [root@saltserver ~]# vim /etc/salt/master
    reactor:
    - 'myco/*':
    - salt://reactor.sls

    * 重启salt-master
    [root@saltserver ~]# pkill salt-master
    [root@saltserver ~]# salt-master -c /etc/salt -d

    * 定义reactor.sls文件
    [root@saltserver ~]# vim /srv/salt/reactor.sls
    my_first_reactor:
    local.cmd.run:
    - tgt: '192.168.13.187'
    - arg:
    - 'touch /tmp/my_first_reactor'

    * 在master上执行
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc

    * 在minion上执行
    [root@saltminion ~]# salt-call event.send myco/mytag foo=Foo bar=Bar
    local:
    True

    * 在master上观察输出结果
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: salt/auth
    Data:
    {'_stamp': '2017-08-08T02:32:51.543849',
    'act': 'accept',
    'id': '192.168.13.187',
    'pub': '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnZHnTfGzMpKiNqPmwM1Q\nrgnRGSrA8eNghWRBECq+raT3qG99xvY7sjP1at8Ul/fnEMCC/K1W4CJz/6TN2lG/\n1jVh77zk9W/PbABGv5i00ZpmxZBtgNywRj4wL9IPPDmalSqm13HnjnVQ7+1I4MK7\naQDmkihGWynSh5U/CGLpApWNowcGw2Xui0d3jdrhGjngvmFuwooCLHlXDOXE3kLY\n1/5oE1+NpM4+6Hbg09XQ6wXtAnM7zNW1GFBfuNTh9ZymkicUso8uqZXCH2dUrf+e\n8VViFb01jBOBgThXm4hmqyF+NfbrjlFmcfSMJ73pJBC1VvmfQ4+F9oSksJGVufkl\n7QIDAQAB\n-----END PUBLIC KEY-----',
    'result': True}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: minion/refresh/192.168.13.187
    Data:
    {'Minion data cache refresh': '192.168.13.187',
    '_stamp': '2017-08-08T02:32:51.669152'}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: myco/mytag
    Data:
    {'_stamp': '2017-08-08T02:32:51.755789',
    'cmd': '_minion_event',
    'data': {'__pub_fun': 'event.send',
    '__pub_jid': '20170808103251736557',
    '__pub_pid': 31742,
    '__pub_tgt': 'salt-call',
    'bar': 'Bar',
    'foo': 'Foo'},
    'id': '192.168.13.187',
    'tag': 'myco/mytag'}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: salt/job/20170808103251765140/ret/192.168.13.187
    Data:
    {'_stamp': '2017-08-08T02:32:51.768086',
    'arg': ['myco/mytag', 'foo=Foo', 'bar=Bar'],
    'cmd': '_return',
    'fun': 'event.send',
    'fun_args': ['myco/mytag', 'foo=Foo', 'bar=Bar'],
    'id': '192.168.13.187',
    'jid': '20170808103251765140',
    'retcode': 0,
    'return': True,
    'tgt': '192.168.13.187',
    'tgt_type': 'glob'}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: 20170808103251827538
    Data:
    {'_stamp': '2017-08-08T02:32:51.829254', 'minions': ['192.168.13.187']}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: salt/job/20170808103251827538/new
    Data:
    {'_stamp': '2017-08-08T02:32:51.829749',
    'arg': ['touch /tmp/my_first_reactor'],
    'fun': 'cmd.run',
    'jid': '20170808103251827538',
    'minions': ['192.168.13.187'],
    'tgt': '192.168.13.187',
    'tgt_type': 'glob',
    'user': 'root'}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: salt/auth
    Data:
    {'_stamp': '2017-08-08T02:32:51.890407',
    'act': 'accept',
    'id': '192.168.13.187',
    'pub': '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnZHnTfGzMpKiNqPmwM1Q\nrgnRGSrA8eNghWRBECq+raT3qG99xvY7sjP1at8Ul/fnEMCC/K1W4CJz/6TN2lG/\n1jVh77zk9W/PbABGv5i00ZpmxZBtgNywRj4wL9IPPDmalSqm13HnjnVQ7+1I4MK7\naQDmkihGWynSh5U/CGLpApWNowcGw2Xui0d3jdrhGjngvmFuwooCLHlXDOXE3kLY\n1/5oE1+NpM4+6Hbg09XQ6wXtAnM7zNW1GFBfuNTh9ZymkicUso8uqZXCH2dUrf+e\n8VViFb01jBOBgThXm4hmqyF+NfbrjlFmcfSMJ73pJBC1VvmfQ4+F9oSksJGVufkl\n7QIDAQAB\n-----END PUBLIC KEY-----',
    'result': True}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: salt/job/20170808103251827538/ret/192.168.13.187
    Data:
    {'_stamp': '2017-08-08T02:32:51.984504',
    'cmd': '_return',
    'fun': 'cmd.run',
    'fun_args': ['touch /tmp/my_first_reactor'],
    'id': '192.168.13.187',
    'jid': '20170808103251827538',
    'retcode': 0,
    'return': '',
    'success': True}

    * 在minion上查看
    [root@saltminion ~]# ls -1 /tmp/my_first_reactor
    /tmp/my_first_reactor
  4. salt api

    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
    salt 提供了大量的 python API 来供第三方程序调用,这些python API可以让我们将Salt强大的功能通过几行代码嵌入到自己的脚本和程序中来完成复杂的任务

    // salt配置文件信息获取
    >>> import salt.config
    >>> master_opts = salt.config.client_config('/etc/salt/master')
    >>> master_opts

    >>> minion_opts = salt.config.client_config('/etc/salt/minion')
    >>> minion_opts

    // salt loader API
    通过Loader API我们加载salt的执行模块,还可以获取salt的grains等数据信息
    >>> import salt.config
    >>> import salt.loader
    >>> __opts__ = salt.config.minion_config('/etc/salt/minion')
    >>> __grains__ = salt.loader.grains(__opts__)
    >>> __grains__

    加载执行模块:
    >>> import salt.config
    >>> import salt.loader
    >>> __opts__ = salt.config.minion_config('/etc/salt/minion')
    >>> __salt__ = salt.loader.minion_mods(__opts__)
    >>> __salt__['cmd.run']("ls /")

    //LocalClient
    LocalClient是最常用的Salt API之一,通过LocalClient的cmd等方法我们可以实现salt执行远程模块的功能
    * 用local.cmd批量执行远程模块
    >>> import salt.client
    >>> local = salt.client.LocalClient()
    >>> local.cmd('*','test.fib','10')
    * 用local.cmd_async批量异步执行远程模块
    >>> import salt.client
    >>> local = salt.client.LocalClient()
    >>> local.cmd_async('*','test.sleep',[30])
    '20170808104645529446'
    [root@saltserver ~]# salt-run jobs.list_job 20170808104645529446
    Arguments:
    - 30
    Function:
    test.sleep
    Minions:
    - 192.168.13.187
    Result:
    ----------
    192.168.13.187:
    ----------
    return:
    True
    StartTime:
    2017, Aug 08 10:46:45.529446
    Target:
    *
    Target-type:
    glob
    User:
    root
    jid:
    20170808104645529446

salt highstate

salt 用highstate复合主机状态

  1. 简介

    1
    2
    3
    4
    通过Jinjia2和grain,pillar数据来扩展状态配置,使状态管理更加灵活.但都是单一状态的管理.
    通过highstate你将学会如何组织主机状态,把多个主机状态配置根据不同的规则进行复合,进而对整个服务器集群进行整体管控

    之前都是使用state.sls来运行一个状态文件,接下来使用highstate模块进行组织和管理单一的状态文件
  2. top.sls文件管理状态文件

    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
    top.sls文件将pillar文件定位到不同的minion;也可以用来在状态系统中将不同状态文件定位到不同的minion中
    highstate函数正式通过top.sls文件作为入口对模块和主机进行管理的

    例如:
    创建状态文件目录:
    [root@saltserver ~]# mkdir -p /srv/salt/lamp
    [root@saltserver ~]# mkdir -p /srv/salt/nginx
    编写相应的state模块文件:
    [root@saltserver ~]# tree /srv/salt/{lamp,nginx}
    /srv/salt/lamp
    ├── httpd.conf
    ├── lamp.sls
    ├── my.cnf
    └── php.ini
    /srv/salt/nginx
    ├── nginx.j2
    ├── nginx.sls
    └── test_vhost.conf
    通过top.sls将lamp和nginx进行整合:
    [root@saltserver ~]# vim /srv/salt/top.sls
    [root@saltserver ~]# cat /srv/salt/top.sls
    base:
    'minion-one':
    - nginx.nginx
    'minion-two':
    - match: list
    - lamp.lamp
    执行指令:
    [root@saltserver ~]# salt '*' state.highstate
  3. 状态文件的拆分和复用

    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
    80
    81
    * 将模块目录结构化
    [root@saltserver ~]# mkdir -p /srv/salt/nginx/{templates,file}
    [root@saltserver ~]# tree /srv/salt/nginx/
    /srv/salt/nginx/
    ├── file
    │   └── test_vhost.conf
    ├── nginx.sls
    └── templates
    └── nginx.j2

    * 对nginx.sls进行拆分
    删除nginx.sls配置文件:
    [root@saltserver ~]# rm -f /srv/salt/nginx/nginx.sls

    创建独立的SLS文件:
    [root@saltserver ~]# touch /srv/salt/nginx/{init,nginx_install,nginx_conf,nginx_running,vhost_conf}.sls
    [root@saltserver ~]# tree /srv/salt/nginx/
    /srv/salt/nginx/
    ├── file
    │   └── test_vhost.conf
    ├── init.sls
    ├── nginx_conf.sls
    ├── nginx_install.sls
    ├── nginx_running.sls
    ├── templates
    │   └── nginx.j2
    └── vhost_conf.sls

    用init文件作入口文件(包含其它文件):
    [root@saltserver ~]# vim /srv/salt/nginx/init.sls
    include:
    - .nginx_install
    - .nginx_running
    - .nginx_conf
    - .vhost_conf

    nginx软件安装:
    [root@saltserver ~]# vim /srv/salt/nginx/nginx_install.sls
    nginx_install:
    pkg.installed:
    - name: nginx

    nginx服务管理:
    [root@saltserver ~]# cat /srv/salt/nginx/nginx_running.sls
    nginx_running:
    service.running:
    - name: nginx
    - enable: True
    - require:
    - pkg: nginx_install
    - watch:
    - file: nginx_conf
    - file: vhost_conf

    nginx配置模板文件管理:
    [root@saltserver ~]# cat /srv/salt/nginx/nginx_conf.sls
    nginx_conf:
    file.managed:
    - name: /etc/nginx/conf/nginx.conf
    - source: salt://nginx/templates/nginx.j2
    - user: root
    - group: root
    - template: jinja
    - mode: 644

    nginx虚拟主机文件管理:
    [root@saltserver ~]# cat /srv/salt/nginx/vhost_conf.sls
    vhost_conf:
    file.managed:
    - name: /etc/nginx/conf/conf.d/nginx.conf
    - source: salt://nginx/file/test_vhost.conf
    - user: root
    - group: root
    - mode: 644

    修改top.sls文件:
    [root@saltserver ~]# cat /srv/salt/top.sls
    base:
    'minion-one':
    - nginx
    注意: nginx模块文件夹里面有init.sls文件,salt会默认加载init.sls,不需要写成nginx.init这种形式
  4. 多环境的配置和管理

    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
    通过top.sls配置文件和模块拆分已经可以对多种状态和多组minion进行同时管理.
    只需要执行"salt '*' state.highstate"就能完成base环境内的minion管理

    [root@saltserver ~]# vim /etc/salt/master
    # file_roots:
    # base:
    # - /srv/salt/
    # dev:
    # - /srv/salt/dev/services
    # - /srv/salt/dev/states
    # prod:
    # - /srv/salt/prod/services
    # - /srv/salt/prod/states

    file_roots这个配置项指明了我们的环境目录在哪里,salt执行对应的SLS状态文件都会默认的目录去寻找.
    一般企业都会有开发环境,测试环境,生产环境.对不同的环境配置不同的目录,我们修改:
    [root@saltserver ~]# vim /etc/salt/master
    file_roots:
    base:
    - /srv/salt/
    dev:
    - /srv/salt/dev/
    prod:
    - /srv/salt/prod/

    重启salt-server:
    [root@saltserver ~]# pkill salt-master
    [root@saltserver ~]# salt-master -c /etc/salt -d

    管理top.sls文件:
    [root@saltserver ~]# vim /srv/salt/top.sls
    base:
    'minion-one':
    - nginx
    dev:
    "test-*":
    - httpd
    prod:
    "prod-*":
    - match: list
    - httpd
    - php
    - mysql