+++
date = "2018-12-15T09:52:59+08:00"
title = "Saltstack"
categories = ["linux"]
tags = ["linux"]
toc = true
author = "younglinuxer"
comments = true
author_homepage = "https://blog.youngblog.cc/"
+++
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接口方便集成运维相关系统 功能比较强大 运行速度快