文章目录

saltstack

安装

master端: 'yum install salt-master -y'

default_include: master.d/*.conf

interface: 0.0.0.0

ipv6: False

publish_port: 4505

cachedir: /data/cache/salt/master

auto_accept: False

file_roots:
  base:
    - /data/salt/salt/

file_ignore_regex:
  - '/\.svn($|/)'
  - '/\.git($|/)'

file_ignore_glob:
  - '*.pyc'
  - '*.swp'

pillar_roots:
  base:
    - /data/salt/pillar


minion端: 'yum install salt-minion -y '
# 记得更改主机名 salt-key 对应主机名
sed -i '16s/#master: salt/master: 10.4.6.13/g' /etc/salt/minion(10.31.6.150 salt管理端的ip地址)

常用命令

# 关于salt-key 的相关原理及替换操作本文不提及 
salt-key -A/a #A接受所有key  a指定接受的key
salt-key -D/d #D删除所有key  d指定删除的key

salt '*' state.highstate #匹配所有主机'*' 匹配安装sls所有对应的安装文件
salt '*' state.sls base #匹配所有主机'*' 安装编写的sls base(为编写调整服务器基础配置的文件)
salt '*' state.sls base.dirs  #匹配所有主机'*' base.dirs 为base目录下的dirs.sls 文件(批量创建文件夹)
salt '*.youngblog' cmd.run 'hostname -i' #匹配(正则)主机名为*.youngblog的主机  执行远程命令 'hostname -i'
salt '*' test.ping #测试minon节点与master的连通性
salt '*' state.sls nginx test=true  测试nginx的sls文件是否正常

salt 'youngblog'  pillar.items #查看youngblog 能获取的变量 pillar 为对应修改的文件变量 自己根据实际需求编写
salt '*' saltutil.refresh_pillar #更改变量后 可能出现变量为及时同步 使用该命令刷新变量

salt '*' grains.items #获取minion所有的静态信息 如操作系统 ip地址 主机名等
salt '*' grains.item ip4_interfaces  #获取minion 的IPV4所有地址 如需要获取eth0 网卡的地址则使用ip4_interfaces:eth0(注意使用:)

官方提供模块大全

// 本文描述自己常用到的一小部分模块 官方提供详细的模块说明
https://docs.saltstack.com/en/latest/ref/states/all/index.html 

文件及sls说明

// 介绍出摘抄于 https://blog.linuxeye.cn/450.html
Master:控制中心,salt命令运行和资源状态管理
Minion : 需要管理的客户端机器,会主动去连接Mater端,并从Master端得到资源状态
信息,同步资源管理信息
States:配置管理的指令集
Modules:在命令行中和配置文件中使用的指令模块,可以在命令行中运行
Grains:minion端的变量,静态的
Pillar:minion端的变量,动态的比较私密的变量,可以通过配置文件实现同步minions定义
highstate:为minion端下发永久添加状态,从sls配置文件读取.即同步状态配置
salt_schedule:会自动保持客户端配置

tree  /data/salt/ -L 2
/data/salt/
├── pillar
│   ├── app
│   ├── consul
│   ├── crontab
│   ├── base //设置基础变量(包含文件描述符,基本内核调优,基础目录创建等等  base目录下的入口文件为 init.sls)
│   ├── mysql
│   ├── nfs
│   ├── nginx
│   ├── rabbitmq
│   ├── redis
│   ├── top.sls //pillar 入口文件 设置minion 对应的变量 
│   ├── users
│   ├── vpn
│   └── zabbix
└── salt
    ├── api
    ├── app
    ├── base // 根据pillar的base 对minion进行基础优化 
    ├── consul //其余为对应安装的软件 file 在对应文件目录下
    ├── crontab
    ├── iptables
    ├── ldap_ssh
    ├── limits
    ├── logrotate
    ├── logstash
    ├── mysql
    ├── nfs
    ├── nginx
    ├── ntpd
    ├── rabbitmq
    ├── redis
    ├── rsyncd
    ├── rsyslog
    ├── ssh
    ├── subversion
    ├── top.sls //salt 入口文件 设置minion 应该需要安装哪些安装包
    ├── users
    ├── vpn
    └── zabbix

常用模块

文件分发
//包含文件分发 及变量替换

/etc/rc.d/init.d/consul:  //目标文件
  file.managed:  
    - source: salt://consul/files/etc/init.d/consul-agent //源文件地址  为salt file_roots的相对路径
    - template: jinja  //指定 文件模板变量替换 此处为文件为consul 启动脚本 使用jinja 写入对应变量替换
    - user: root  //指定文件属主 及文件权限
    - group: root  
    - mode: 755  
    - backup: minion //在minion中备份当前文件 见master配置选项 cachedir
    - defaults: //使用变量 defaults 为固定写法 变量(grains静态从服务端获取  pillar自己根据项目编写的变量 )
      node_name: {{grains['id']}} //分发文件时 替换 {{node_name}} 为{{grains['id']}}(主机名)  salt '*' grains.items 获取对应变量 取值方式与python取字典类似 
      lan_ip: {{ grains['ip_interfaces']['eth0'][0] }}  // 替换 {{lan_ip}} 为eth0网卡的IP地址
      recursor_one: {{pillar['consul']['dns']['recursor_one']}}  // 替换 {{recursor_one}} 为pillar 中的变量 变量编写 pillar/consul/init.sls中 salt '*'  pillar.items 查看能获取到的变量
      recursor_two: {{pillar['consul']['dns']['recursor_two']}}
      service_ip_01: {{pillar['consul']['server_ip']['one']}}
      service_ip_02: {{pillar['consul']['server_ip']['two']}}
      service_ip_03: {{pillar['consul']['server_ip']['three']}}
      dc: {{pillar['consul']['dc']}}

//pillar pillar/consul/init.sls
consul:
  dns:
    recursor_one: 183.60.83.19
    recursor_two: 8.8.8.8
  server_ip:
    one: 10.0.6.44
    two: 10.0.6.158
    three: 10.0.6.2
  dc: sg01

应用管理
// 包含应用安装 基础流程控制   配置文件替换 这里用redis集群举例 

redis:
  pkg: //安装包管理 固定写法
    - name: redis //安装软件名字
    - installed //安装动作
  service: //服务管理 固定写法
    - name: redis //服务名字 如ssh 叫sshd
    - running  //保证服务状态running
    - enable: True //开机启动 enable
    - reload: True //允许reload重启
    - require: //必要条件 需要先安装redis
      - pkg: redis

//流程控制 判断ip地址为master节点 还是slave节点 分发不同的配置文件并替换变量  {% if %}   {% elif %} {% endif %} 为固定写法 

{% if grains['ip_interfaces']['eth0'][0]  == pillar['redis']['Master'] %} 
/etc/redis.conf:
  file.managed:
    - source: salt://redis/files/redis-master.conf
    - template: jinja
    - user: root
    - group: root
    - mode: 775
    - defaults:
      bind: {{pillar['redis']['Master']}}
      port: {{pillar['redis']['Port']}}
    - backup: minion
    - require:
      - pkg: redis
{% elif grains['ip_interfaces']['eth0'][0]  == pillar['redis']['Slave'] %}
/etc/redis.conf:
  file.managed:
    - source: salt://redis/files/redis-slave.conf
    - template: jinja
    - user: root
    - group: root
    - mode: 775
    - defaults:
      bind: {{pillar['redis']['Slave']}}
      port: {{pillar['redis']['Port']}}
      slaveof: {{pillar['redis']['Master']}} {{pillar['redis']['Port']}}
    - backup: minion
    - require:
      - pkg: redis
{% endif %}

/etc/rc.d/init.d/redis:
  file.managed:
    - source: salt://redis/files/etc/init.d/redis
    - template: jinja
    - user: root
    - group: root
    - mode: 777
    - defaults:
      consul_name: redis
      consul_address: {{ grains['ip_interfaces']['eth0'][0] }}
      consul_port: 6379
      {% if grains['ip_interfaces']['eth0'][0]  == pillar['redis']['Master'] %}
      consul_tags: master
      {% endif %}
      {% if grains['ip_interfaces']['eth0'][0]  == pillar['redis']['Slave'] %}
      consul_tags: slave
      {% endif %}
    - backup: minion
权限与用户
// 包含添加用户 loop循环判断等
sudo:
  pkg.installed
  
{% for user, args in pillar['users'].iteritems() %}  // {% for %} {% endfor %} 为固定写法
{{user}}:
  user.present: //添加用户
    - home: /home/{{user}} //用户家目录
    - shell: {{args['shell']}}  //user_shell
    - fullname: {{args['fullname']}} //用户的完整名字
    {% if 'password' in args %}
    - password: {{args['password']}}
    {% endif %}
      
{% if 'sudo' in args %}
{% if args['sudo'] %}
sudoer-{{user}}:
  file.append:
    - name: /etc/sudoers
    - text:
      - '{{user}} ALL=({{args['sudo_command']}}) NOPASSWD: ALL'
    - require:
      - user: {{user}}
{% endif %}
{% endif %}

{% if 'ssh_auth' in args %}
/home/{{user}}/.ssh:
  file.directory:
    - user: {{user}}
    - group: {{args['group']}}
    - mode: 700
    - require:
      - user: {{user}}

/home/{{user}}/.ssh/authorized_keys:
  file.managed:
    - user: {{user}}
    - group: {{args['group']}}
    - mode: 600
    - require:
      - file: /home/{{user}}/.ssh

{{user}}-key:
  ssh_auth.present:
    - user: {{user}}
    - enc: ssh-rsa
    - comment: {{args['ssh_auth']['comment']}}
    - require:
      - file: /home/{{user}}/.ssh/authorized_keys
    - names:
      - {{ args['ssh_auth']['key'] }}
{% endif %}
{% endfor %}

// user.init.sls
include:
  - users.yuan_yang
  - users.xxxxx

// user.yuan_yang.sls 对应init.sls 中的yuan_yang

users:
  yuan.yang:
    group: users
    uid: 10003
    gid: 10000
    fullname: yuan.yang
    password: 
    shell: /bin/bash
    sudo: true
    sudo_command: ALL
    ssh_auth:
      key: AAAAB3NzaC1yc2EAAAABIwAAAQEAnrKtvbm9tqlu1yURhvsGGRj++UzbCFatqCPotlQaj4ElUv+e7mGFoy/2NpFJWuo37pdTLJhGyzvPiItG8Q0tIfcqdxCB/n3KJydTSsgg+Ihoh00Q+yJYkD3PVV/1IqVWMH93F642TacgfaswaUYvCn8eimULy0a1pBD8gg0XSvnvlUV3T68Hnry3yCS9uPZXmb+fEsB8NMBJsYvycx6Cfku6K3rpdWcLKCasfafasHupJdDcXhWqMPESm3FO/GobqatSF/FLehqB9bpOUKN1Kq/IzKhDWCyjpNlw3v/xxx

iptables+hosts+
// hosts 内容管理
{% for hosts in pillar['hosts'] %} //loop 所有hosts文件变量
hosts_{{hosts}}:
  host.present: //插入
    - ip: {{pillar['hosts'][hosts]['lan']}} //从pillar中获取变量
    - order: 1
    - names:
      - {{hosts}}
{% endfor %}

//iptables 操作包括安装 iptables的规则设置(转发规则,开启部分端口,允许网段内的地址访问)

iptables:
  pkg:
    - installed
  service:
    - running
    - watch:
      - pkg: iptables
      
    
allow_from_forward_eth0:
  iptables.insert:
    - position: 1
    - table: filter
    - chain: FORWARD
    - jump: ACCEPT
    - in-interface: eth0
    - save: True 
    
allow_from_forward_eth0_out:
  iptables.insert:
    - position: 1
    - table: filter
    - chain: FORWARD
    - jump: ACCEPT
    - out-interface: eth0
    - save: True
    

allow_staus:
  iptables.insert:
    - position: 1
    - table: filter
    - chain: INPUT
    - jump: ACCEPT
    - connstate: RELATED,ESTABLISHED
    - save: True
    
    
allow_from_lo:
  iptables.insert:
    - position: 1
    - table: filter
    - chain: INPUT
    - jump: ACCEPT
    - in-interface: lo
    - save: True    


allow_ssh:
  iptables.insert:
    - position: 1
    - table: filter
    - chain: INPUT
    - jump: ACCEPT
    - dport: 22
    - proto: tcp
    - save: True

allow_http:
  iptables.insert:
    - position: 1
    - table: filter
    - chain: INPUT
    - jump: ACCEPT
    - dport: 80
    - proto: tcp
    - save: True
    
allow_https:
  iptables.insert:
    - position: 1
    - table: filter
    - chain: INPUT
    - jump: ACCEPT
    - dport: 443
    - proto: tcp
    - save: True
    
allow_from_manage:
  iptables.insert:
    - position: 1
    - table: filter
    - chain: INPUT
    - jump: ACCEPT
    - family: ipv4
    - source: 10.0.6.0/24
    - save: True
 
// 内核参数更改 示例
net.ipv4.tcp_max_tw_buckets:
  sysctl.present:
    - value: 10000

net.ipv4.ip_local_port_range:
  sysctl.present:
    - value: 1024 65535

salt-api使用

// 后面有时间单独写一篇介绍salt-api部署及基本调用

对比

目前有使用主流的工具只有saltstack和ansible 说说自己的感受:
ansible相对于saltstack的目录结构更简单 编写也比较方便 无需安装agent通过ssh管理 比较适合集群规模不大的项目部署及管理
saltstack 官方提供很多模块对操作系统和应用进行操作 提供salt-api接口方便集成运维相关系统 功能比较强大 运行速度快