• 《SaltStack技术入门与实践》—— 实践案例 <中小型Web架构>1 初始化和Haproxy


    实践案例 <中小型Web架构>

    本章节参考《SaltStack技术入门与实践》,感谢该书作者: 刘继伟、沈灿、赵舜东

      实践、实践、再实践,这是熟练掌握SaltStack的真理。在运维环境中上线SaltStack后,运维工作从繁杂并且重复的服务部署和配置工作转移到在SaltStack中编写和维护状态文件。通常情况下,状态文件一次编写就可以在大多数环境下执行,所以在编写状态文件时候需要尽可能考虑模块化和通用性。

      为保证读者能够快速地使用SaltStack进行生产环境的配置管理,本章将带领大家通过SaltStack的配置管理来实现一个“中小型Web架构”的自动化部署和配置管理,主要包括以下功能和服务:

    • 系统初始化
    • Haproxy服务
    • Keepalived服务
    • Nginx服务
    • PHP(FastCGI)服务
    • Memcached服务

    案例架构图如图所示:

    在开始编写之前,我们需要进行合理的规划,首选描述本案例的思路,我们将按照系统初始化、功能模块、业务模块这样的设计思路来进行设计和实施:

      1、系统初始化:指的是操作系统安装完毕后,都需要使用到的初始配置,比如安装监控代理、调整内核参数、设置域名解析等。

      2、功能模块:指的是生产使用到的应用,比如Nginx、PHP、Haproxy、Keepalived等这类应用服务的安装和管理,每一个功能我们创建一个目录来存放,我们把这个目录的集合称之为“功能模块”。

      3、业务模块:在功能模块中我们编写了大量基础的功能状态,在业务层面直接进行引用,所以功能模块就是尽可能的全、而且独立。而业务模块,不同的业务类型就可以在Include功能模块里面的安装和部署,每个业务使用自己独特的配置文件等。最终在top.sls里面我们只需要给某个Minion指定一个业务的状态即可。

    环境规划

    这里说的环境规划包含了两种环境:

    • 我们实验案例中的网络和服务器环境。
    • SaltStack中file_roots和pillar_roots定义的SaltStack的环境。

      实验环境设置

        准备两台虚拟机或者物理机,来完成我们整个案例的学习,案例的实验环境:

     

      SaltStack环境设置

        在本案例我们使用两个环境base和prod,base环境用来存放初始化的功能。prod环境用于放置生产的配置管理功能。

    [root@SaltMaster1(10.182.88.136)]$~:>tail -n10 /etc/salt/master
    file_roots:
      base:
        - /srv/salt/base
      prod:
        - /srv/salt/prod
    pillar_roots:
      base:
        - /srv/pillar/base
      prod:
        - /srv/pillar/prod

    参照以上配置在master配置文件的修改,创建相应目录结构并重启salt-master,如下所示:

    mkdir -p /srv/salt/base
    mkdir -p /srv/salt/prod
    mkdir -p /srv/pillar/base
    mkdir -p /srv/pillar/prod
    service salt-master start

    系统初始化

      当我们的服务器上架并安装好操作系统后,都会有一些基础的操作,所以生产环境中使用SaltStack,建议将所有服务器都会涉及的基础配置或者软件部署归类放在Base环境下,比如本例我们在Base环境下创建一个init的目录,将系统初始化配置的SLS均放在Init目录下,我们称为其为“初始化模块”。

    DNS配置

      在生产环境中,一个重要的配置就是DNS解析的设置,强烈建议在内网建立自己的内网DNS服务器,我们只需要使用SaltStack的File状态模块中的Managed方法管理resolv.conf文件即可:

    [root@SaltMaster1(10.182.88.136)]$/srv/salt/base/init:>more dns.sls 
    /etc/resolv.conf:
      file.managed:
        - source: salt://init/files/resolv.conf
        - user: root
        - group: root
        - mode: 644

    注意,编写完毕请将准备好的resolv.conf放置在/srv/salt/base/init/files/目录下。

    History记录时间

      生产非常简单实用的功能就是让History记录时间,这样可以清晰地知道什么用户在什么时间执行了什么命令。我们使用SaltStack的File状态模块的Append方法,在/etc/profile里面追加设置。

    [root@SaltMaster1(10.182.88.136)]$~:>more /srv/salt/base/init/history.sls 
    /etc/profile:
      file.append:
        - text:
          - export HISTTIMEFORMAT="%Y/%m/%d/%H-%M-%S #> "

    命令操作审计

      使用logger将输入的命令写入到messages的一个简单功能,也是使用SaltStack的File模块的Append方法。后期你可以将Memssages日志文件进行统一收集,比如使用ELK Stack(Elasticsearch、LogStash、Kibana)。

    [root@SaltMaster1(10.182.88.136)]$~:>more /srv/salt/base/init/audit.sls
    /etc/bashrc:
      file.append:
        - text:
          - export PROMPT_COMMAND='{ msg=$(history 1 | { read x y; echo $y; });logger "[euid=$(whoami)]":$(who am i):[`pwd`]"$msg"; }'

    内核参数优化

      在进行系统初始化的过程中,需要对默认的内核参数进行调优,SaltStack提供了sysctl状态模块用来进行内核参数的配置,由于默认需要调整的参数过多,下面仅列出了几个例子:

    [root@SaltMaster1(10.182.88.136)]$/srv/salt/base/init:>more /srv/salt/base/init/sysctl.sls 
    net.ipv4.ip_forward:
      sysctl.present:
        - value: 1
    net.ipv4.conf.default.rp_filter:
      sysctl.present:
        - value: 1
    net.ipv4.conf.default.accept_source_route:
      sysctl.present:
        - value: 0
    kernel.sysrq:
      sysctl.present:
        - value: 0
    kernel.core_uses_pid:
      sysctl.present:
        - value: 1
    kernel.msgmnb:
      sysctl.present:
        - value: 65536
    kernel.msgmax:
      sysctl.present:
        - value: 65536
    kernel.shmmax:
      sysctl.present:
        - value: 68719476736
    kernel.shmall:
      sysctl.present:
        - value: 4294967296

    epel仓库

      如果你的系统需要使用epel仓库,那么也可以放在系统初始化配置中。比如我们下面安装Zabbix-Agent就需要epel仓库。这里我们需要使用到SaltStack的pkg状态模块,同时还使用了unless做状态执行的判断。

    提示:强烈建议有条件的用户在生产环境创建内部私有的yum仓库。 

    yum_repo_release:
      pkg.installed:
        - sources:
          - epel-release: http://mirrors.aliyun.com/epel/epel-release-latest-6.noarch.rpm
        - unless: rpm -qa | grep epel-release-latest-6
    
    zabbix_repo_release:
      pkg.installed:
        - sources:
          - zabbix-release: http://mirrors.aliyun.com/zabbix/zabbix/3.0/rhel/6/x86_64/zabbix-release-3.0-1.el6.noarch.rpm  
        - unless: rpm -qa | grep zabbix-release-3.0-1.el6.noarch.rpm

    Zabbix Agent安装

      如果你的监控系统使用的是Zabbix(推荐),那么所有的Minion都应该安装上Zabbix Agent,主要涉及SaltStack的pkg、file、service状态模块以及Pillar的使用。

    提示:如果使用SaltStack进行自动化运维,那么请在自动化安装的步骤中将Salt Minion安装到系统中,并设置好Master IP和开机自动启动。

      通过使用Pillar来设置Zabbix Server的IP地址

    (1)、zabbix-agent.sls状态文件

    [root@SaltMaster1(10.182.88.136)]$~:>more /srv/salt/base/init/zabbix_agent.sls
    zabbix
    -agent: pkg.installed: - name: zabbix-agent file.managed: - name: /etc/zabbix/zabbix_agentd.conf - source: salt://init/file/zabbix_agentd.conf - template: jinja - defaults: Server: {{ pillar['Zabbix_Server'] }} - require: - pkg: zabbix-agent service.running: - enable: True - watch: - pkg: zabbix-agent - file: zabbix-agent

    #Zabbix配置文件目录用来存放用户自定义的配置,接上面

    zabbix_agentd.conf.d:
      file.directory:
        - name: /etc/zabbix/zabbix_agentd.d
        - watch_in:
          - service: zabbix-agent
        - require:
          - pkg: zabbix-agent
          - file: zabbix-agent

     (2) 、配置pillar

    [root@SaltMaster1(10.182.88.136)]$~:>tree /srv/pillar/base/
    /srv/pillar/base/
    |-- top.sls
    |-- zabbix
    `-- zabbix_agent.sls
    
    1 directory, 2 files
    [root@SaltMaster1(
    10.182.88.136)]$~:>more /srv/pillar/base/top.sls base: '*': - zabbix_agent
    [root@SaltMaster1(
    10.182.88.136)]$~:>more /srv/pillar/base/zabbix_agent.sls Zabbix_Server: 10.182.88.136

    (3)、zabbix_agent配置文件

    编写完毕Zabbix Agent的部署后,请将zabbix_agentd.conf文件放置/srv/salt/base/init/files/目录下,同时修改如下:

    [root@SaltMaster1(10.182.88.136)]$~:>more /srv/salt/base/init/file/zabbix_agentd.conf
    PidFile=/var/run/zabbix/zabbix_agentd.pid
    LogFile=/var/log/zabbix/zabbix_agentd.log
    LogFileSize=0
    Server={{ Zabbix_Server }}
    Hostname={{ Hostname }}
    ServerActive=127.0.0.1
    Hostname=Zabbix server
    Include=/etc/zabbix/zabbix_agentd.d/*.conf

    初始化环境引用

      目前我们把所有初始化所需要的功能都写好了,每个小功能都是一个sls文件。统一放置在init目录下,这样归类后很容易解读。那么怎样来使用呢?在top file里面把这些功能都列出了,可不是一个好主意,我们需要再编写一个sls把这些初始化的功能都包含进来:

    [root@linux-node1 /srv/salt/base/init]$ vim init.sls
    include:
      - init.dns
      - init.history
      - init.audit
      - init.sysctl
      - init.epel
      - init.zabbix_agent

      到现在为止,我们已经完成了所有系统初始化状态文件的编写,查看一下目录结构:

    /srv/salt/base/
    `-- init
        |-- CentOS-Base.sls
        |-- audit.sls
        |-- dns.sls
        |-- epel.sls
        |-- file
        |   |-- CentOS-Base.repo
        |   |-- resolv.conf
        |   |-- saltstack.repo
        |   |-- sysctl.conf
        |   `-- zabbix_agent.conf
        |-- history.sls
        |-- init.sls
        |-- sysctl.sls
        `-- zabbix_agent.sls
    
    2 directories, 13 files

    现在我们就可以在top.sls里面给Minion指定状态并执行了:

    [root@linux-node1 /srv/salt/base]$ vim top.sls
    base:
      '*':
        - init.init

    注意,在生产环境中,每次执行状态,强烈建议先进行测试,确定SaltStack会执行哪些操作然后再应用状态到服务器上:

    [root@linux-node1 /srv/salt/base]$ salt 'linux-node2*' state.highstate test=True
    [root@linux-node1 /srv/salt/base]$ salt 'linux-node2*' state.highstate

    执行结果如下(Failed为0表示初始化成功)

    [root@SaltMaster1(10.182.88.136)]$~:>salt '10.182.76.78' state.highstate
    10.182.76.78:
    ----------
              ID: /etc/resolv.conf
        Function: file.managed
          Result: True
         Comment: File /etc/resolv.conf is in the correct state
         Started: 13:15:19.826862
        Duration: 45.426 ms
         Changes:   
    ----------
              ID: /etc/profile
        Function: file.append
          Result: True
         Comment: File /etc/profile is in correct state
         Started: 13:15:19.872549
        Duration: 4.576 ms
         Changes:   
    ----------
              ID: /etc/bashrc
        Function: file.append
          Result: True
         Comment: File /etc/bashrc is in correct state
         Started: 13:15:19.877390
        Duration: 5.029 ms
         Changes:   
    ----------
              ID: net.ipv4.ip_forward
        Function: sysctl.present
          Result: True
         Comment: Sysctl value net.ipv4.ip_forward = 1 is already set
         Started: 13:15:19.884547
        Duration: 167.2 ms
         Changes:   
    ----------
              ID: net.ipv4.conf.default.rp_filter
        Function: sysctl.present
          Result: True
         Comment: Sysctl value net.ipv4.conf.default.rp_filter = 1 is already set
         Started: 13:15:20.052094
        Duration: 163.392 ms
         Changes:   
    ----------
              ID: net.ipv4.conf.default.accept_source_route
        Function: sysctl.present
          Result: True
         Comment: Sysctl value net.ipv4.conf.default.accept_source_route = 0 is already set
         Started: 13:15:20.215910
        Duration: 164.324 ms
         Changes:   
    ----------
              ID: kernel.sysrq
        Function: sysctl.present
          Result: True
         Comment: Sysctl value kernel.sysrq = 0 is already set
         Started: 13:15:20.380586
        Duration: 163.241 ms
         Changes:   
    ----------
              ID: kernel.core_uses_pid
        Function: sysctl.present
          Result: True
         Comment: Sysctl value kernel.core_uses_pid = 1 is already set
         Started: 13:15:20.544154
        Duration: 162.391 ms
         Changes:   
    ----------
              ID: kernel.msgmnb
        Function: sysctl.present
          Result: True
         Comment: Sysctl value kernel.msgmnb = 65536 is already set
         Started: 13:15:20.706891
        Duration: 160.26 ms
         Changes:   
    ----------
              ID: kernel.msgmax
        Function: sysctl.present
          Result: True
         Comment: Sysctl value kernel.msgmax = 65536 is already set
         Started: 13:15:20.867494
        Duration: 163.575 ms
         Changes:   
    ----------
              ID: kernel.shmmax
        Function: sysctl.present
          Result: True
         Comment: Sysctl value kernel.shmmax = 68719476736 is already set
         Started: 13:15:21.031378
        Duration: 162.533 ms
         Changes:   
    ----------
              ID: kernel.shmall
        Function: sysctl.present
          Result: True
         Comment: Sysctl value kernel.shmall = 4294967296 is already set
         Started: 13:15:21.194215
        Duration: 162.737 ms
         Changes:   
    ----------
              ID: yum_repo_release
        Function: pkg.installed
          Result: True
         Comment: All specified packages are already installed
         Started: 13:15:22.407580
        Duration: 2075.602 ms
         Changes:   
    ----------
              ID: zabbix_repo_release
        Function: pkg.installed
          Result: True
         Comment: All specified packages are already installed
         Started: 13:15:24.483582
        Duration: 623.723 ms
         Changes:   
    ----------
              ID: zabbix-agent
        Function: pkg.installed
          Result: True
         Comment: All specified packages are already installed
         Started: 13:15:25.107665
        Duration: 25.241 ms
         Changes:   
    ----------
              ID: zabbix-agent
        Function: file.managed
            Name: /etc/zabbix/zabbix_agentd.conf
          Result: False
         Comment: Unable to manage file: Jinja variable 'Zabbix_Server' is undefined
         Started: 13:15:25.133724
        Duration: 35.486 ms
         Changes:   
    ----------
              ID: zabbix_agentd.conf.d
        Function: file.directory
            Name: /etc/zabbix/zabbix_agentd.d
          Result: False
         Comment: One or more requisite failed: init.zabbix_agent.zabbix-agent
         Started: 13:15:25.172231
        Duration: 0.019 ms
         Changes:   
    ----------
              ID: zabbix-agent
        Function: service.running
          Result: False
         Comment: One or more requisite failed: init.zabbix_agent.zabbix_agentd.conf.d, init.zabbix_agent.zabbix-agent
         Started: 13:15:25.172991
        Duration: 0.016 ms
         Changes:   
    
    Summary for 10.182.76.78
    -------------
    Succeeded: 15
    Failed:     3
    -------------
    Total states run:     18
    Total run time:    4.285 s
    ERROR: Minions returned with non-zero exit code

    公司的docker对一些sysctl参数做了限制,有的设置不了。还有就是我们也不用zabbix,所以就不再单独安装zabbix server了。

    检查Minion配置是否生效

    查看内核参数是否生效

    [root@SaltMinion2(10.182.76.78)]$~:>tail -f /etc/profile
    unset i
    unset -f pathmunge
    export JAVA_HOME=/export/servers/jdk1.8.0_20
    export JAVA_BIN=/export/servers/jdk1.8.0_20/bin
    export PATH=$JAVA_HOME/bin:$PATH
    export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    export  JAVA_OPTS="-Djava.library.path=/usr/local/lib -server -Xms1024m -Xmx2048m -XX:MaxPermSize=256m -Djava.awt.headless=true -Dsun.net.client.defaultReadTimeout=60000 -Djmagick.systemclassloader=no -Dnetworkaddress.cache.ttl=300 -Dsun.net.inetaddr.ttl=300"
    export JAVA_HOME JAVA_BIN PATH CLASSPATH JAVA_OPTS
    export HISTTIMEFORMAT="%Y/%m/%d/%H-%M-%S
    [root@SaltMinion2(10.182.76.78)]$~:>cat /proc/sys/net/ipv4/ip_local_port_range
    32768    60999
    [root@SaltMinion2(10.182.76.78)]$~:>cat /proc/sys/fs/file-max
    20480000

    查看zabbix_agent是否启动成功(公司不用zabbix,这里只演示,不安装)

    [root@SaltMinion2(10.182.76.78)]$~:>netstat -lntup
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name   
    tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      55/sshd             
    tcp        0      0 :::22                       :::*                        LISTEN      55/sshd 

     附加-备份配置文件

    执行top.sls前如果想保存minion端之前的配置文件,可以采用file模块的backup属性。

    [root@linux-node1 /srv/salt/base]# cat init/zabbix_agent.sls 
    zabbix-agent:
      pkg.installed:
        - name: zabbix-agent
      file.managed:
        - name: /etc/zabbix/zabbix_agentd.conf
        - source: salt://init/files/zabbix_agentd.conf
        - backup: minion
        - template: jinja
        - defaults:
          Server: {{ pillar['Zabbix_Server'] }}
          Hostname: {{ grains['fqdn'] }}
        - require:
          - pkg: zabbix-agent
      service.running:
        - enable: True
        - watch:
          - pkg: zabbix-agent
          - file: zabbix-agent
    zabbix_agentd.conf.d:
      file.directory:
        - name: /etc/zabbix/zabbix_agentd.d
        - watch_in:
          - service: zabbix-agent
        - require:
          - pkg: zabbix-agent
          - file: zabbix-agent

    执行后,minion端缓存目录下/var/cache/salt/minion/file_backup 会有zabbix_agentd.conf的备份文件,以时间命名的。

    [root@linux-node2 minion]# tree
    .
    ├── accumulator
    ├── extmods
    ├── extrn_files
    │   └── base
    │       └── mirrors.aliyun.com
    │           ├── epel
    │           │   └── epel-release-latest-7.noarch.rpm
    │           └── zabbix
    │               └── zabbix
    │                   └── 3.0
    │                       └── rhel
    │                           └── 7
    │                               └── x86_64
    │                                   └── zabbix-release-3.0-1.el7.noarch.rpm
    ├── file_backup
    │   └── etc
    │       └── zabbix
    │           └── zabbix_agentd.conf_Fri_Oct_14_16:31:03_697911_2016
    ├── files
    │   └── base
    │       ├── init
    │       │   ├── audit.sls
    │       │   ├── dns.sls
    │       │   ├── epel.sls
    │       │   ├── files
    │       │   │   ├── resolv.conf
    │       │   │   └── zabbix_agentd.conf
    │       │   ├── history.sls
    │       │   ├── init.sls
    │       │   ├── sysctl.sls
    │       │   └── zabbix_agent.sls
    │       └── top.sls
    ├── highstate.cache.p
    ├── module_refresh
    ├── pkg_refresh
    └── proc
    
    20 directories, 16 files

    初始化环境引用

      好的,目前我们把所有初始化所需要的功能都写好了,每个小功能都是一个sls文件。统一放置在init目录下,这样归类后很容易解读。那么怎样来使用呢?在top file里面把这些功能都列出了,可不是一个好主意,我们需要再编写一个sls把这些初始化的功能都包含进来:

    include:
      - init.dns
      - init.history
      - init.audit
      - init.sysctl
      - init.epel
      - init.zabbix_agent

      好了的我们来回顾下所有配置,这里列出了我们初始化模块的目录结构:

    [root@SaltMaster1(10.182.88.136)]$init:>tree /srv/salt/base/
    /srv/salt/base/
    |-- init
    |   |-- CentOS-Base.sls
    |   |-- audit.sls
    |   |-- dns.sls
    |   |-- env_init.sls
    |   |-- epel.sls
    |   |-- file
    |   |   |-- CentOS-Base.repo
    |   |   |-- resolv.conf
    |   |   |-- saltstack.repo
    |   |   |-- sysctl.conf
    |   |   `-- zabbix_agentd.conf
    |   |-- history.sls
    |   |-- init.sls
    |   |-- sysctl.sls
    |   `-- zabbix_agent.sls
    `-- top.sls
    
    2 directories, 15 files

    Haproxy配置管理

      系统初始化完成后,我们就开始编写具体的功能模块了。我们参考图片案例架构图从上往下来进行,首先编写Haproxy和Keeplived的配置管理。

    • Haproxy是一个开源的高性能的反向代理项目,支持四层和七层的负载均衡,多种负载均衡算法和健康检查等。
    • Keepalived是一个高可用集群的项目,它是VRRP协议的完美实现,通过Keepalived来管理Haproxy上面的VIP,当注Haproxy发生故障时,将VIP漂移到备用的Haproxy上来继续提供服务。

      Haproxy和Keepalived使用源码编译安装的方式,将这两个服务放置在prod环境中。

      首先创建目录结构,如下所示:

    [root@SaltMaster1(10.182.88.136)]$~:>mkdir -p /srv/salt/prod/pkg
    [root@SaltMaster1(10.182.88.136)]$~:>mkdir -p /srv/salt/prod/haproxy/files
    [root@SaltMaster1(10.182.88.136)]$~:>mkdir -p /srv/salt/prod/keepalived/files
    [root@SaltMaster1(10.182.88.136)]$~:>mkdir -p /srv/salt/prod/haproxy/package

      在每个服务的目录下均创建一个files目录用来存放源码包和需要的相关启动脚本、配置文件等。

    pkg配置

      首先需要使用pkg模块将源码编译依赖的各种包都安装上,使用pkg状态的installed方法,同时使用names列表,通过列表的方式把需要的安装包都列出来:

    [root@SaltMaster1(10.182.88.136)]$~:>more /srv/salt/prod/pkg/pkg-init.sls 
    pkg-init:
      pkg.installed:
        - names:
          - gcc
          - gcc-c++
          - glibc
          - make
          - autoconf
          - openssl
          - openssl-devel

    Haproxy服务配置

      首先需要将Haproxy的源码包和管理脚本放置在/srv/salt/prod/haproxy/package目录下,通过http://www.haproxy.org/下载软件包,这里使用1.8.12版本。

    [root@SaltMaster1(10.182.88.136)]$~:>cd /srv/salt/prod/haproxy/package/haproxy-1.8.12/examples/
    [root@SaltMaster1(10.182.88.136)]$examples:>sed -i 's#/usr/sbin/$BASENAME#/export/servers/haproxy1.8.12/sbin/$BASENAME#g' haproxy.init
    [root@SaltMaster1(10.182.88.136)]$examples:>grep --color '/export/servers/haproxy1.8.12/sbin/$BASENAME' haproxy.init 
    BIN=/export/servers/haproxy1.8.12/sbin/$BASENAME
    [root@SaltMaster1(10.182.88.136)]$~:>cp /srv/salt/prod/haproxy/package/haproxy-1.8.12/examples/haproxy.init /srv/salt/prod/haproxy/files/

    编写Haproxy安装SLS文件

    编写Haproxy内容如下:

    include:
      - pkg.pkg-init
    
    haproxy-install:
      file.managed:
        - name: /tmp/haproxy-1.8.12.tar.gz
        - source: salt://haproxy/package/haproxy-1.8.12.tar.gz
        - mode: 755
        - user: root
        - group: root
      cmd.run:
        - name: cd /tmp/ && tar -zxf haproxy-1.8.12.tar.gz && cd haproxy-1.8.12 && make TARGET=linux26 PREFIX=/export/servers/haproxy1.8.12 && make install PREFIX=/export/servers/haproxy1.8.12
        - unless: test -d /export/servers/haproxy1.8.12
        - require:
          - pkg: pkg-init
          - file: haproxy-install

    Haproxy的服务管理脚本如下所示:

    /etc/init.d/haproxy:
      file.managed:
        - source: //haproxy/files/haproxy.init
    - mode: 755 - user: root - group: root - require: - cmd: haproxy-install 

    设置可以监听非本地IP:

    net.ipv4.ip_nonlocal_bind:
      sysctl.present:
        - value: 1

    #Haproxy的配置文件存放目录如下:

    haproxy-confi-dir:
      file.directory:
        - name: /etc/haproxy
        - mode: 755
        - user: root
        - group: root

    #设置Haproxy开机自启动

    haproxy-init:
      cmd.run:
        - name: chkconfig -add haproxy
        - unless: chkconfig --list | grephaproxy
        - require:
          - file: /etc/init.d/haproxy

    本文没有把Haproxy的服务管理放置在install.sls里面,因为Haproxy启动需要依赖配置文件,通过两种方法管理Haproxy的配置文件:

    • 直接在需要使用Haproxy的地方引用Haproxy的安装,然后加入Haproxy的配置文件和服务管理。优点:简单明了;缺点:不够灵通用。
    • 使用jinja模板,将Haproxy的基础配置编写完成之后,其他的配置通过Pillar来进行自动生成。优点:灵活通用;缺点:由于需要使用大量的if、for等Jinja模板语法,而且需要配置Pillar来实现配置,比较麻烦,实现起来难度比较大,而且容易出错。

    Haproxy业务引用

      编写一个业务模块Cluster,然后调用Haproxy来完成配置管理,这样做的好处是把基础服务的配置管理和业务分开,例如负载均衡,有可能是对外的,也可能是内部使用,如果都是用Haproxy,那么Haproxy的安装就是基础功能,配置和启动,可以通过放置在业务模块Cluster中来进行集中管理。 

      创建cluster目录,并且在cluster目录下创建config目录,用来存放配置文件:

    [root@SaltMaster1(10.182.88.136)]$package:>mkdir -p /srv/salt/prod/cluster/config

      将haproxy的配置文件放置在/srv/salt/prod/cluster/config目录下,下面列出本次案例使用的最小化配置:

    [root@SaltMaster1(10.182.88.136)]$~:>vim /srv/salt/prod/cluster/files/haproxy-outside.cfg

    #  ------全局配置------
    global
    log 127.0.0.1   local0             #日志输出配置,所有日志都记录在本机,通过local0输出
    log 127.0.0.1   local1 notice
    #log loghost    local0 info
    maxconn 100000                     #最大连接数
    #chroot /usr/share/haproxy         #chroot运行路径
    uid 99                             #所属用户UID
    gid 99                             #所属运行的GID
    daemon                             #以后台形式运行haproxy
    #debug                             #调试模式,输出启动信息到标准输出
    #quiet                             #安静模式,启动时无输出
    
    #------默认配置-----
    
    defaults
    log    global
    mode   http                        #默认模式{tcp|http|health},tcp是4层,http是7层,health只会返回OK
    option httplog                     #日志类别:http日志格式
    option dontlognull                 #不记录健康检查的日志信息
    retries 3                          #3次连接失败就认为服务不可用
    option redispatch                  #ServerID对应的服务器挂掉后,强制定向到其他健康服务器
    maxconn 100000                     #默认最大连接数
    timeout connect      5000          #连接超时
    timeout client      50000          #客户端超时
    timeout server      50000          #服务端超时
    
    #------开启Haproxy Status状态监控,增加验证,如下所示:
    
    listen status                      #监控页面设置
    mode http                          #http的7层模式
    bind 0.0.0.0:8888                  #监听端口
    stats enable                        
    stats hide-version                 #隐藏统计页面上的HAproxy版本信息
    stats uri     /haproxy-status      #监控页面URL
    stats auth    haproxy:saltstack    #监控页面用户名和密码
    stats admin if TRUE                #手工启用、禁用后端服务器
    
    #------前端设置如下:
    
    frontend frontend_www_example_com
    bind 10.182.88.252:80
    mode http
    option httplog
    log global
        default_backend backend_www_example_com
    
    #------后端设置如下:
    
    backend backend_www_example_com
    option forwardfor header X-REAL-IP
    option httpchk HEAD / HTTP/1.0
    balance source
    server  web-node1 10.182.88.136:80 cookie server01 check inter 2000 rise 30 fall 15
    server  web-node2 10.182.76.78:80  cookie server02 check inter 2000 rise 30 fall 15

    ##服务器定义(check指健康状况检查,inter 2000指检测频率;rise 2指从离线状态转换至正常状态需要成功检查的次数;fall 3指失败3次即认为服务器不可用)

    编写Haproxy服务管理的SLS文件

    [root@SaltMaster1(10.182.88.136)]$~:>more /srv/salt/prod/cluster/haproxy-outside.sls 
    include:
      - haproxy.install
    
    haproxy-service:
      file.managed:
        - name: /etc/haproxy/haproxy.cfg
        - source: salt://cluster/files/haproxy-outside.cfg
        - user: root
        - group: root
        - mode: 644
        - makedirs: True
        - unless: test -d /etc/haproxy
      service.running:
        - name: haproxy
        - enable: True
        - reload: True
        - require:
          - cmd: haproxy-install
        - watch:
          - file: haproxy-service

    执行Haproxy状态

    编写完成Haproxy的状态配置后,需要在Top file里面给Minion指定状态。由于本案例只有两台测试机,都需要安装Haproxy,所以直接使用*,生产中请根据实际情况修改,请注意使用Prod环境。代码如下:

    [root@SaltMaster1(10.182.88.136)]$~:>more /srv/salt/base/top.sls 
    #base:
    #  '*':
    #    - init.init
    base:
      '*':
        - init.env_init
    prod:
      '*.example.com':
        - cluster.haproxy-outside

    测试并执行状态如下所示:

    测试验证有点问题,然后开始改,再执行:

    salt '10.182.76.78' state.highstate

     公司办公网到开发测试机环境,只开通了80端口,为展示haproxy-status,故端口8888改成端口80,这里只是作为展示暂时先改过来。

  • 相关阅读:
    The POM for XXX is invalid, transitive dependencies (if any) will not be available解决方案
    Builgen 插件——IntelliJ IDEA和Eclipse Java Bean Builder模式代码生成器-比lombok更符合需求
    java.lang.NoClassDefFoundError: org/apache/curator/RetryPolicy解决方法
    java配置xml报cvc-complex-type.2.3: 元素 'beans' 必须不含字符 [子级], 因为该类型的内容类型为“仅元素”
    Spring Boot中注入配置文件application.properties中的list 对象参数
    Spring Boot 整合Mybatis非starter时,mapper一直无法注入解决
    org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout() mybatis和spring-mybatis版本不匹配问题
    mybatis generator自动生成sqlmap代码的不完善之处以及解决方法
    pagehelper调用mybatis报错java.lang.NoSuchMethodError:org.apache.ibatis.reflection.MetaObject.forObject
    iframe跨域问题:Uncaught DOMException: Blocked a frame with origin解决方法
  • 原文地址:https://www.cnblogs.com/zuoyang/p/9241541.html
Copyright © 2020-2023  润新知