index.md 18 KB

Saltstack

[toc]

简介

线上所有的统一配置管理工具均有saltstack完成 完成的线上任务:

  1. 用于系统的初始化

  2. 用于开源软件的配置管理,包括

    • nginx
    • phpfpm
    • redis
    • mongodb
    • memcache
    • ...
  3. 用于管理c++开发的所有组件配置已经更新

    • roommaster
    • chatroom
    • gateserver
    • secgateserver
    • rediswriter
    • ...

SaltStack介绍

SaltStack,一种全新的基础设施管理方式,部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯。

特性

  1. 具备配置管理
  2. 可以远程执行
  3. 基于python实现
  4. 部署简单方便
  5. 支持API以及自定义模块,通过python可以进行轻松的扩展
  6. 主控端与被控端基于证书认证,安全可靠
  7. 基于ZeroMQ进行消息传输

基本原理

SaltStack采用C/S模式,server端就是salt的salt-master,client端为salt-minion,minion与master之间通过ZeroMQ消息队列通信

minion上线后先与master端联系,把自己的pub key发过去,这时master端通过salt-key -L命令就会看到minion的key,接受该minion-key后,也就是master与minion已经互信

master可以发送任何指令让minion执行了,salt有很多可执行模块,比如说cmd模块,在安装minion的时候已经自带了,它们通常位于你的python库中,locate salt | grep /usr/ 可以看到salt自带的所有东西。

具体步骤如下

  1. Salt stack的Master与Minion之间通过ZeroMq进行消息传递,使用了ZeroMq的发布-订阅模式,连接方式包括tcp,ipc

  2. salt命令,将cmd.run ls命令从salt.client.LocalClient.cmd_cli发布到master,获取一个Jodid,根据jobid获取命令执行结果。

  3. master接收到命令后,将要执行的命令发送给客户端minion。

  4. minion从消息总线上接收到要处理的命令,交给minion._handle_aes处理

  5. minion._handle_aes发起一个本地线程调用cmdmod执行ls命令。线程执行完ls后,调用minion._return_pub方法,将执行结果通过消息总线返回给master

  6. master接收到客户端返回的结果,调用master._handle_aes方法,将结果写的文件中

  7. salt.client.LocalClient.cmd_cli通过轮询获取Job执行结果,将结果输出到终端。

安装

saltstack的包已经加入EPEL源,可以直接通过yum安装

  1. salt-master 安装

    yum install salt-master
    
  2. salt-minion 安装

    wget -O install_salt.sh https://bootstrap.saltstack.com --no-check-certificate && sh install_salt.sh
    

提供的功能

Target

指定执行命令或者模块应用在哪个Minion上

  1. globbing匹配 bash salt 'Dy-JXQ-101' test.ping
  2. RE正则 bash salt -E 'Dy-JXQ-9(1-2)$' test.ping
  3. grains

    salt -G "os:CentOS" test.ping
    
    # 查看所有grains的键值
    salt 'test' grains.items
    # 查看所有grains项
    salt 'test' grains.ls
    # 查看某个grains的值
    salt 'test' grains.item num_cpus
    

    在top file中匹配grains ```bash 'node_type:webserver':

    • match: grain
    • nginx
    • phpfpm
    • ```
  4. nodegroups 是对minion分组

    # /etc/salt/master.d/nodegroup.conf
    nodegroups:
      test1: 'L@test1, test2 or test3'
      test2: 'G@os:CentOS or test2'
    
    salt -N test1 test.ping
    

批量执行

同Target类似例子 使用命令可以执行各种命令

	salt -E 'Dy-JXQ-10[1-9]$' cmd.run "uptime"

多个Master

多个Master,在我们的生产环境中还未正式使用 多Master需要注意的地方:

  1. 2个master之间并不会共享minion key,互相独立
  2. 不会自动同步file_roots,需要手动维护,可以使用git
  3. 不会自动同步Pillar_roots,需要手动维护,可以使用git
  4. master的配置文件是独立

Pillar

Pillar在salt中是非常重要的组成部分,利用它可以完成动态的数据调整,可以使用sls文件编写 适用场景

  1. 比较敏感的数据,如密码,key等
  2. 特殊数据到指定的minion上
  3. 动态内容
查看Minion的pillar信息
	salt '*' pillar.items
	salt '*' pillar.item <key>
	salt '*' pillar.get <key>:<key>
编写pillar数据
  1. 指定pillar_roots,默认是/srv/pillar

  2. 在top file中使用pillar ```bash '*':

    • {{ environment }}.epel
    • {{ environment }}.ntp
    • {{ environment }}.systembase
    • {{ environment }}.openssh
    • {{ environment }}.zabbix_agent
    • {{ environment }}.douyu_sudo ```
  3. 在state中通过jinja使用pillar数据

    {% set zabbix_conf = salt['pillar.get']('zabbix_agent:config_settings', config_map, merge=True) %}
    

Grains

Grains主要提供一种对服务器静态信息的描述,可以对Grains增加自己对服务器节点的描述 grains的解析使用yaml模块进行解析,所以对齐是必须的,否则会出现不可预料的错误

通常Grains所提供的键值对有以下三种:

  1. 针对常用的键值对,比如系统版本号,网卡地址,mac地址,salt有一套原生的grains定义,该定义均由salt官方提供的python脚本提供,这些python脚本均内置到salt中

  2. 通过编写minion端的/etc/salt/grains 加入额外的grains定义

    	environment: live
    	node_type:
    	  - webserver
    	  - memcache
    	  - room_service
    	  - redis
    	  - nginx_lua
    
  3. 通过编写master端的/etc/salt/_grains目录下的python脚本,自定义需要的grains值

    def hello():
    	agrain = {}
    	agrain['hello'] = 'saltstack'
    	return agrain
    

    符合salt自己自定义的要求返回一个字典即可 在三种情况下,会执行_grains目录下的py脚本

    • 重启salt-minion
    • 在master端执行 salt 'test' saltutil.sync_all
    • master端执行 salt 'test' state.highstate 备注:在room_services的state模块中,使用了dy_extends.py脚本对对应的服务器进行了定制化配置

State

它的核心是SLS(salt state file),文件默认是YAML格式,并默认使用jinja模板 该State是salt的配置管理核心,所有的配置定义均由state文件通过salt解析完成

示例文件

选取自ntp中的init.sls

# Include :download:`map file <map.jinja>` of OS-specific package names and
# file paths. Values can be overridden using Pillar.
{% from "ntp/map.jinja" import ntp with context %}
{% set service = {True: 'running', False: 'dead'} %}

ntp:
  pkg.installed:
    - name: {{ ntp.lookup.package }}

{% if 'ntp_conf' in ntp.lookup %}
ntpd_conf:
  file.managed:
    - name: {{ ntp.lookup.ntp_conf }}
    - source: salt://ntp/files/ntp.conf
    - template: jinja
    - context:
      config: {{ ntp.settings.ntp_conf }}
    - require:
      - pkg: ntp
{% endif %}

{% if salt['service.status']('ntpd') != True %}
correct_time:
  cmd.run:
    - name: ntpdate 2.asia.pool.ntp.org
{% endif %}

{% if 'ntpd' in ntp.settings %}
ntpd:
  service.{{ service.get(ntp.settings.ntpd) }}:
    - name: {{ ntp.lookup.service }}
    - enable: {{ ntp.settings.ntpd }}
    - require:
      - pkg: ntp
      {% if salt['service.status']('ntpd') != True %}
      - cmd: correct_time
      {% endif %}
    - watch:
      - file: ntpd_conf
{% endif %}

通过适当的配置,配置管理的功能和便利性会远超puppet

关于salt的render_system

salt默认的渲染器是yaml_jinja,salt处理我们的sls文件时,会先把文件用jinja2处理,然后传给ymal处理器在处理,然后生成的是salt需要的python数据类型。除了yaml_jinja还有yaml_mako,yaml_wempy,py,pydsl yaml_jinja是默认的,而py是用纯python来写的。

线上saltstack的使用

约定

针对我们的业务需求和基于一定的安全考虑 线上的saltstack使用上会区分为

* 北京机房,一个独立的salt-master
* 外网机房,一个独立的salt-master

两个salt-master的代码基本一样,基于room_service和nginx的配置有些微不同 nginx的模块主要是外网代理vhost的不同 room_service外网主要使用MsgRepeater的配置

配置目录的组织

salt的state配置采用归一化的编排,而针对不同环境的不同变量配置采用pillar的动态特性进行区分 具体实施上采用以下的目录结构

├── pillar
│   ├── bj-test
│   │   ├── douyu_sudo.sls
│   │   ├── epel.sls
│   │   ├── init.sls
│   │   ├── memcache.sls
│   │   ├── mongodb.sls
│   │   ├── nginx_lua.sls
│   │   ├── nginx.sls
│   │   ├── ntp.sls
│   │   ├── openssh.sls
│   │   ├── phpfpm.sls
│   │   ├── redis.sls
│   │   ├── room_service.sls
│   │   ├── systembase.sls
│   │   └── zabbix_agent.sls
│   ├── dev
│   │   ├── douyu_sudo.sls
│   │   ├── epel.sls
│   │   ├── init.sls
│   │   ├── memcache.sls
│   │   ├── mongodb.sls
│   │   ├── nginx.sls
│   │   ├── ntp.sls
│   │   ├── openssh.sls
│   │   ├── phpfpm.sls
│   │   ├── redis.sls
│   │   ├── room_service.sls
│   │   ├── systembase.sls
│   │   └── zabbix_agent.sls
│   ├── live
│   │   ├── douyu_sudo.sls
│   │   ├── epel.sls
│   │   ├── init.sls
│   │   ├── memcache.sls
│   │   ├── mongodb.sls
│   │   ├── nginx_lua.sls
│   │   ├── nginx.sls
│   │   ├── ntp.sls
│   │   ├── openssh.sls
│   │   ├── phpfpm.sls
│   │   ├── redis.sls
│   │   ├── room_service.sls
│   │   ├── systembase.sls
│   │   └── zabbix_agent.sls
│   ├── pressure
│   │   ├── douyu_sudo.sls
│   │   ├── epel.sls
│   │   ├── init.sls
│   │   ├── memcache.sls
│   │   ├── mongodb.sls
│   │   ├── nginx.sls
│   │   ├── ntp.sls
│   │   ├── openssh.sls
│   │   ├── phpfpm.sls
│   │   ├── redis.sls
│   │   ├── room_service.sls
│   │   ├── systembase.sls
│   │   └── zabbix_agent.sls
│   ├── prod
│   │   ├── douyu_sudo.sls
│   │   ├── epel.sls
│   │   ├── init.sls
│   │   ├── memcache.sls
│   │   ├── mongodb.sls
│   │   ├── nginx.sls
│   │   ├── ntp.sls
│   │   ├── openssh.sls
│   │   ├── phpfpm.sls
│   │   ├── redis.sls
│   │   ├── room_service.sls
│   │   ├── systembase.sls
│   │   └── zabbix_agent.sls
│   └── top.sls
└── salt
    ├── douyu_sudo
    ├── epel
    ├── _grains
    ├── memcache
    ├── mongodb
    ├── mysql
    ├── nginx
    ├── nginx_lua
    ├── ntp
    ├── openssh
    ├── phpfpm
    ├── redis
    ├── room_service
    ├── systembase
    ├── zabbix_agent
    └── top.sls

区分环境

利用pillar的top.sls入口文件,对符合的主机进行环境区分

  1. 所有主机都必须在/etc/salt/grains中指定 'environment:prod/live/pressure/dev/bj-test‘ 用于标示主机是否属于生产环境或者测试环境

  2. top.sls文件示例 ```python

    top.sls

    {% set environment = salt['grains.get']('environment', '') %} include:

    • {{ environment }} python

      init.sls

      {% set environment = salt['grains.get']('environment', '') %} {{ saltenv if saltenv != None else env }}: '*':

    • {{ environment }}.epel

    • {{ environment }}.ntp

    • {{ environment }}.systembase

    • {{ environment }}.openssh

    • {{ environment }}.zabbix_agent

    • {{ environment }}.douyu_sudo

'node_type:webserver':

- match: grain
- {{ environment }}.nginx
- {{ environment }}.phpfpm

'node_type:nginx':

- match: grain
- {{ environment }}.nginx

'node_type:nginx_lua':

- match: grain
- {{ environment }}.nginx_lua

'node_type:phpfpm':

- match: grain
- {{ environment }}.phpfpm

'node_type:memcache':

- match: grain
- {{ environment }}.memcache

'node_type:redis':

- match: grain
- {{ environment }}.redis

'node_type:mongodb':

- match: grain
- {{ environment }}.mongodb

'node_type:room_service':

- match: grain
- {{ environment }}.room_service

其中的node_type为自定义grains,用来区分主机需要安装的服务类型

#### 典型的salt模块目录组成
salt的所有使用的模块基本是自有,线上所提供的各种开源模块无法符合自身业务的需求
以nginx目录结构为例
```nginx
nginx
├── files
│   ├── conf
│   │   ├── mime.types
│   │   └── nginx.conf
│   ├── initd
│   │   └── nginxd
│   ├── logrotate
│   │   ├── nginxd
│   │   └── nginx_logfile_logrotate.py
│   ├── monitor
│   │   ├── nginx.conf
│   │   ├── nginx_monitor.conf
│   │   └── nginx_status.sh
│   ├── nginx_install.sh
│   ├── ssl_conf
│   │   ├── server.key
│   │   ├── server.pem
│   │   ├── ybadmin.crt
│   │   └── ybadminv1.key
│   ├── tar_package
│   │   ├── nginx-1.8.0.tar.gz
│   │   ├── Nginx-accesskey-2.0.3.tar.gz
│   │   └── ngx_cache_purge-master.zip
│   ├── vhost
│   │   ├── cooperate
│   │   │   ├── backend
│   │   │   │   ├── cooperate.backend.036yx.com.conf
│   │   │   │   ├── cooperate.backend.2144.com.conf
│   │   │   │   └── cooperate.backend.ilongyuan.com.cn.conf
│   │   │   └── edge
│   │   │       ├── cooperate.proxy.036yx.com.conf
│   │   │       ├── cooperate.proxy.2144.com.conf
│   │   │       └── cooperate.proxy.ilongyuan.com.cn.conf
│   │   └── core
│   │       ├── backend
│   │       │   ├── adsys.douyutv.com.conf
│   │       │   ├── api.douyutv.com.conf
│   │       │   ├── file.douyutv.com.conf
│   │       │   ├── ssl.douyutv.com.conf
│   │       │   ├── static2.douyutv.com.conf
│   │       │   ├── staticdn.douyutv.com.conf
│   │       │   ├── staticlive.douyutv.com.conf
│   │       │   ├── uc.douyutv.com.conf
│   │       │   ├── upload.douyutv.com.conf
│   │       │   └── www.douyutv.com.conf
│   │       └── edge
│   │           ├── proxy_adsys.douyutv.com.conf
│   │           ├── proxy_api.douyutv.com.conf
│   │           ├── proxy_ssl.douyutv.com.conf
│   │           ├── proxy_static2.douyutv.com.conf
│   │           ├── proxy_staticlive.douyutv.com.conf
│   │           ├── proxy_uc.douyutv.com.conf
│   │           ├── proxy_www.douyutv.com.conf
│   │           └── proxy_ybadmin.douyutv.com.conf
│   └── web_rsync
│       ├── exclude.txt
│       ├── rsync.pwd
│       └── webrsync.sh
├── init.sls
├── map.jinja
└── states
    ├── config.sls
    ├── install.sls
    ├── logrotate.sls
    ├── monitor.sls
    ├── service.sls
    ├── user.sls
    └── vhost_conf
        ├── cooperate_backend_vhost_group.sls
        ├── cooperate_proxy_vhost_group.sls
        ├── core_backend_vhost_adsys.sls
        ├── core_backend_vhost_fileupload.sls
        ├── core_backend_vhost_group.sls
        ├── core_backend_vhost_ssl.sls
        ├── core_backend_vhost_staticdn.sls
        ├── core_backend_vhost_uc.sls
        ├── core_proxy_vhost_group.sls
        ├── core_proxy_vhost_ssl.sls
        ├── douyu.sls
        └── yuba_proxy_vhost_ybadmin.sls
  1. init.sls 为整个模块的应用入口,用于囊括states目录下面的state定义
  2. map.jinja 为整个模块配置的默认变量设置,可以使用pillar覆盖map里面设置的变量,该件也是其他sls定义文件的变量的源
  3. files目录存放所有需要引入的文件,包括tar包,各种配置文件
  4. states目录存放所有的配置sls文件

使用的模块

现在使用的模块分为

salt
    ├── douyu_sudo		# 控制服务器的sudo权限
    ├── epel			# 控制所有CentOS主机的epel源
    ├── _grains			# 扩展grains
    ├── memcache		# memcache的配置管理
    ├── mongodb			# mongodb的配置管理,暂时未上线
    ├── mysql			# mysql的配置管理,暂时未上线
    ├── nginx			# nginx的配置管理,包括所有在线使用的webserver
    ├── nginx_lua		# nginx_lua环境模块,应php要求新加入的配置管理
    ├── ntp				# ntp配置管理,控制所有服务器的ntp client同步时间
    ├── openssh			# 服务器的ssh服务管理
    ├── phpfpm			# phpfpm进程配置管理,线上使用的配置统一一致,个别phpfpm特殊需求
    ├── redis			# redis的配置管理,负责控制所有redis主从关系
    ├── room_service	# c++组件的配置管理,部分功能未启用
    ├── systembase		# 系统初始化的配置管理,包括安装包,kernel参数优化
    ├── zabbix_agent	# zabbix_agent的配置管理,监控客户端
    └── top.sls			# 入口文件