saltstack 基础平台管理工具---批量执行
简介
SaltStack是一个服务器基础架构集中化管理平台,具备配置管理、远程执行、监控等功能,一般可以理解为简化版的puppet和加强版的func。SaltStack基于Python语言实现,结合轻量级消息队列(ZeroMQ)与Python第三方模块(Pyzmq、PyCrypto、Pyjinjia2、python-msgpack和PyYAML等)构建。
通过部署SaltStack环境,我们可以在成千上万台服务器上做到批量执行命令,根据不同业务特性进行配置集中化管理、分发文件、采集服务器数据、操作系统基础及软件包管理等,SaltStack是运维人员提高工作效率、规范业务配置与操作的利器。
官方网站:https://saltstack.com/
官方文档:https://docs.saltstack.com/en/latest/
GitHub:https://github.com/saltstack
中国saltstack用户组:https://www.saltstack.cn/
特性
(1)、部署简单、方便;
(2)、支持大部分UNIX/Linux及Windows环境;
(3)、主从集中化管理;
(4)、配置简单、功能强大、扩展性强;
(5)、主控端(master)和被控端(minion)基于证书认证,安全可靠;
(6)、支持API及自定义模块,可通过Python轻松扩展。
三种运行方式:
Local,Master/Minion ,Salt SSH
三大功能:
远程执行,配置管理,云管理
操作
安装:
| IP地址 | 角色 |
| 192.168.20.93 | master |
| 192.168.20.172 | minion |
master 端: yum install salt-master salt-minion -y minion端: yum install salt-minion -y
开机自启动:
chkconfig salt-minion on
启动master:
/etc/init.d/salt-master start
编译:vim /etc/salt/minion(master端和minion端都要配置)
配置17行:master 的主机IP地址
master: 192.168.20.93
id:XXXXXXXX #在master端显示的名称。
Master与Minion认证与快速入门
(1)、minion在第一次启动时,会在/etc/salt/pki/minion/(该路径在/etc/salt/minion里面设置)下自动生成minion.pem(private key)和 minion.pub(public key),然后将 minion.pub发送给master。
(2)、master在接收到minion的public key后,通过salt-key命令accept minion public key,这样在master的/etc/salt/pki/master/minions下的将会存放以minion id命名的 public key,然后master就能对minion发送指令了。
minion端: /etc/salt/pki/minion [root@openfire2 minion]# ll total 8 -r-------- 1 root root 1679 May 31 12:57 minion.pem -rw-r--r-- 1 root root 451 May 31 12:57 minion.pub
master端: [root@js-93 master]# pwd /etc/salt/pki/master [root@js-93 master]# ll total 28 -r-------- 1 root root 1679 May 31 13:00 master.pem -rw-r--r-- 1 root root 451 May 31 13:00 master.pub drwxr-xr-x 2 root root 4096 May 31 13:00 minions drwxr-xr-x 2 root root 4096 May 31 13:00 minions_autosign drwxr-xr-x 2 root root 4096 May 31 13:00 minions_denied drwxr-xr-x 2 root root 4096 May 31 13:05 minions_pre drwxr-xr-x 2 root root 4096 May 31 13:00 minions_rejected
在minion_pre 中有一个等待同意的主机名称
[root@js-93 master]# tree
.
├── master.pem
├── master.pub
├── minions
├── minions_autosign
├── minions_denied
├── minions_pre
│ └── openfire2
└── minions_rejected
[root@js-93 master]# salt-key
Accepted Keys:
Denied Keys:
Unaccepted Keys: #未同意的key
openfire2
Rejected Keys:
同意:
—A 同意所有;
[root@js-93 master]# salt-key -a openfire2
The following keys are going to be accepted:
Unaccepted Keys:
openfire2
Proceed? [n/Y] Y
Key for minion openfire2 accepted.
和上面的tree 的结果进行对比发现openfire2 在不同的目录下了。
[root@js-93 master]# tree
.
├── master.pem
├── master.pub
├── minions
│ └── openfire2
├── minions_autosign
├── minions_denied
├── minions_pre
└── minions_rejected
发现客户端也有master的public key
[root@openfire2 minion]# ls
minion_master.pub minion.pem minion.pub
简单操作:
[root@js-93 master]# salt '*' test.ping openfire2: True [root@js-93 master]# salt '*' cmd.run 'uptime' openfire2: 13:17:55 up 255 days, 1:29, 1 user, load average: 0.08, 0.07, 0.05 You have mail in /var/spool/mail/root [root@js-93 master]# salt '*' cmd.run 'df -h' openfire2: Filesystem Size Used Avail Use% Mounted on /dev/sda3 195G 4.6G 181G 3% / tmpfs 1.9G 12K 1.9G 1% /dev/shm /dev/sda1 194M 27M 158M 15% /boot
快速入门:
修改 master端的 /etc/salt/master 文件: #该配置文件里面一定要保持使用空格,如果使用tab键,那么一定会报错。 416 file_roots: 417 base: 418 - /srv/salt 然后查看master端是否有 /srv/salt 这个目录,如果没有则创建。 mkdir /srv/salt
然后重启服务: /etc/init.d/salt-master restart
写一个apache服务的配置:
[root@js-93 salt]# cat apache.sls apache-install: pkg.installed: - names: - httpd - httpd-devel apache-service: service.running:
- name: httpd - enable: True #开机启动 - reload: True
****一定要注意缩进,该缩进按照2个空格进行缩进,每个层级关系在一起,下一个层级关系则会多增加两个空格。一定不要有别的字符,例如:tab
执行Apache.sls 配置。
master端:
[root@js-93 salt]# salt '*' state.sls apache openfire2: ---------- ID: apache-install Function: pkg.installed Name: httpd Result: True Comment: Package httpd is already installed. Started: 14:46:21.941103 Duration: 1343.879 ms Changes: ---------- ID: apache-install Function: pkg.installed Name: httpd-devel Result: True Comment: Package httpd-devel is already installed. Started: 14:46:23.285596 Duration: 1.452 ms Changes: ---------- ID: apache-service Function: service.running Name: httpd Result: True Comment: Service httpd has been enabled, and is running Started: 14:46:23.288696 Duration: 263.856 ms Changes: ---------- httpd: True Summary ------------ Succeeded: 3 (changed=1) Failed: 0 ------------ Total states run: 3
minion 端: [root@openfire2 minion]# ps -ef|grep yum root 6961 6921 4 14:38 ? 00:00:00 /usr/bin/python2.6.6 /usr/bin/yum --quiet check-update
[root@openfire2 minion]# chkconfig --list|grep httpd
httpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
[root@openfire2 minion]# ps -ef|grep httpd
root 7170 1 0 14:46 ? 00:00:00 /usr/sbin/httpd
apache 7172 7170 0 14:46 ? 00:00:00 /usr/sbin/httpd
apache 7173 7170 0 14:46 ? 00:00:00 /usr/sbin/httpd
apache 7174 7170 0 14:46 ? 00:00:00 /usr/sbin/httpd
apache 7175 7170 0 14:46 ? 00:00:00 /usr/sbin/httpd
apache 7176 7170 0 14:46 ? 00:00:00 /usr/sbin/httpd
apache 7177 7170 0 14:46 ? 00:00:00 /usr/sbin/httpd
apache 7179 7170 0 14:46 ? 00:00:00 /usr/sbin/httpd
apache 7180 7170 0 14:46 ? 00:00:00 /usr/sbin/httpd
root 7190 6358 0 14:47 pts/0 00:00:00 grep httpd
saltstack 数据系统
grains数据系统
Grains:存放着minion启动时的数据信息(存储在minion端),只有在minion启动的时候才会收集。重启以后才会重新收集
[root@js-93 salt]# salt '*' grains.ls openfire2: - SSDs - cpu_flags - cpu_model - cpuarch - domain - fqdn - fqdn_ip4 - fqdn_ip6 - gpus - host - hwaddr_interfaces - id - init - ip4_interfaces - ip6_interfaces - ip_interfaces - ipv4 - ipv6 - kernel - kernelrelease - locale_info - localhost - lsb_distrib_codename - lsb_distrib_id - lsb_distrib_release - machine_id - master - mdadm - mem_total - nodename - num_cpus - num_gpus - os - os_family - osarch - oscodename - osfinger - osfullname - osmajorrelease - osrelease - osrelease_info - path - ps - pythonexecutable - pythonpath - pythonversion - saltpath - saltversion - saltversioninfo - selinux - server_id - shell - virtual - zmqversion
[root@js-93 salt]# salt '*' grains.items openfire2: ---------- SSDs: cpu_flags: - fpu - vme - de - pse - tsc - msr - pae - mce - cx8 - apic - sep - mtrr - pge - mca - cmov - pat - pse36 - clflush - dts - mmx - fxsr - sse - sse2 - ss - ht - syscall - nx - rdtscp - lm - constant_tsc - arch_perfmon - pebs - bts - xtopology - tsc_reliable - nonstop_tsc - aperfmperf - unfair_spinlock - pni - pclmulqdq - ssse3 - cx16 - sse4_1 - sse4_2 - x2apic - popcnt - aes - hypervisor - lahf_lm - arat - dts cpu_model: Intel(R) Xeon(R) CPU E5606 @ 2.13GHz cpuarch: x86_64 domain: fqdn: openfire2 fqdn_ip4: - 192.168.20.172 fqdn_ip6: gpus: |_ ---------- model: SVGA II Adapter vendor: unknown host: openfire2 hwaddr_interfaces: ---------- eth1: 00:0c:29:ed:a9:14 lo: 00:00:00:00:00:00 id: openfire2 init: upstart ip4_interfaces: ---------- eth1: - 192.168.20.172 lo: - 127.0.0.1 ip6_interfaces: ---------- eth1: - fe80::20c:29ff:feed:a914 lo: - ::1 ip_interfaces: ---------- eth1: - 192.168.20.172 - fe80::20c:29ff:feed:a914 lo: - 127.0.0.1 - ::1 ipv4: - 127.0.0.1 - 192.168.20.172 ipv6: - ::1 - fe80::20c:29ff:feed:a914 kernel: Linux kernelrelease: 2.6.32-431.el6.x86_64 locale_info: ---------- defaultencoding: UTF8 defaultlanguage: en_US detectedencoding: UTF-8 localhost: openfire2 lsb_distrib_codename: Final lsb_distrib_id: CentOS lsb_distrib_release: 6.5 machine_id: e8c670405579b8d0809d7d1800000022 master: 192.168.20.93 mdadm: mem_total: 3824 nodename: openfire2 num_cpus: 4 num_gpus: 1 os: CentOS os_family: RedHat osarch: x86_64 oscodename: Final osfinger: CentOS-6 osfullname: CentOS osmajorrelease: 6 osrelease: 6.5 osrelease_info: - 6 - 5 path: /sbin:/usr/sbin:/bin:/usr/bin ps: ps -efH pythonexecutable: /usr/bin/python2.6 pythonpath: - /usr/bin - /usr/lib64/python26.zip - /usr/lib64/python2.6 - /usr/lib64/python2.6/plat-linux2 - /usr/lib64/python2.6/lib-tk - /usr/lib64/python2.6/lib-old - /usr/lib64/python2.6/lib-dynload - /usr/lib64/python2.6/site-packages - /usr/lib/python2.6/site-packages - /usr/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg-info pythonversion: - 2 - 6 - 6 - final - 0 saltpath: /usr/lib/python2.6/site-packages/salt saltversion: 2015.5.10 saltversioninfo: - 2015 - 5 - 10 - 0 selinux: ---------- enabled: False enforced: Disabled server_id: 1314904039 shell: /bin/bash virtual: VMware zmqversion: 3.2.5
获取机器单个选项信息: [root@js-93 salt]# salt '*' grains.item fqdn openfire2: ---------- fqdn: openfire2 [root@js-93 salt]# salt '*' grains.get fqdn openfire2: openfire2
[root@js-93 salt]# salt '*' grains.get ip_interfaces
openfire2:
----------
eth1:
- 192.168.20.172
- fe80::20c:29ff:feed:a914
lo:
- 127.0.0.1
- ::1
grains 的操作实例:
指定系统进行远程命令操作;
[root@js-93 salt]# salt -G os:CentOS cmd.run 'free -m' openfire2: total used free shared buffers cached Mem: 3824 2860 964 0 169 1358 -/+ buffers/cache: 1333 2491 Swap: 2047 0 2047 参数:-G 表示用grains 的数据进行匹配。
grains 可以给minion端赋予 roles角色,然后通过salt 远程执行对应的roles角色就行。
minion端: [root@openfire2 minion]# cat /etc/salt/grains #这里面的role名称不能用roles 否则会冲突 web: check12 [root@openfire2 minion]# /etc/init.d/salt-minion restart master端: [root@js-93 master]# salt -G web:check12 cmd.run 'w' openfire2: 17:50:08 up 255 days, 6:01, 1 user, load average: 0.12, 0.08, 0.01 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.16.7 10:55 21.00s 0.58s 0.58s -bash
grains: 在master 的top.sls 里面进行配置minion 的信息,进行执行命令;
master端: [root@js-93 salt]# cat top.sls base: 'web:check12': - match: grain - apache 这里的apache 是/src/salt/apache.sls 里面的信息。
[root@js-93 salt]# salt '*' state.highstate #执行这个命令就会有信息返回
Pillar 数据系统
pillar 数据系统默认是关着的(master上面),因此要使用pillar需要修改 master端的 /etc/salt/master 的 552行 "#pillar_opts: False "改成 pillar_opts: True"
[root@js-93 salt]# /etc/init.d/salt-master restart
[root@js-93 salt]# salt '*' pillar.items #就可以查看到很多信息。
[root@js-93 salt]# salt '*' pillar.items openfire2: ---------- master: ---------- __role: master auth_mode: 1 auto_accept: False cache_sreqs: True cachedir: /var/cache/salt/master cli_summary: False client_acl: ---------- client_acl_blacklist: ---------- cluster_masters: cluster_mode: paranoid con_cache: False conf_file: /etc/salt/master config_dir: /etc/salt cython_enable: False daemon: True default_include: master.d/*.conf enable_gpu_grains: False enforce_mine_cache: False enumerate_proxy_minions: False environment: None event_return: event_return_blacklist: event_return_queue: 0 event_return_whitelist: ext_job_cache: ext_pillar: extension_modules: /var/cache/salt/extmods external_auth: ---------- failhard: False file_buffer_size: 1048576 file_client: local file_ignore_glob: None file_ignore_regex: None file_recv: False file_recv_max_size: 100 file_roots: ---------- base: - /srv/salt fileserver_backend: - roots fileserver_followsymlinks: True fileserver_ignoresymlinks: False fileserver_limit_traversal: False gather_job_timeout: 10 gitfs_base: master gitfs_env_blacklist: gitfs_env_whitelist: gitfs_insecure_auth: False gitfs_mountpoint: gitfs_passphrase: gitfs_password: gitfs_privkey: gitfs_pubkey: gitfs_remotes: gitfs_root: gitfs_user: hash_type: md5 hgfs_base: default hgfs_branch_method: branches hgfs_env_blacklist: hgfs_env_whitelist: hgfs_mountpoint: hgfs_remotes: hgfs_root: id: openfire2 interface: 0.0.0.0 ioflo_console_logdir: ioflo_period: 0.01 ioflo_realtime: True ioflo_verbose: 0 ipv6: False jinja_lstrip_blocks: False jinja_trim_blocks: False job_cache: True keep_jobs: 24 key_logfile: /var/log/salt/key keysize: 2048 log_datefmt: %H:%M:%S log_datefmt_logfile: %Y-%m-%d %H:%M:%S log_file: /var/log/salt/master log_fmt_console: [%(levelname)-8s] %(message)s log_fmt_logfile: %(asctime)s,%(msecs)03.0f [%(name)-17s][%(levelname)-8s][%(process)d] %(message)s log_granular_levels: ---------- log_level: warning loop_interval: 60 maintenance_floscript: /usr/lib/python2.6/site-packages/salt/daemons/flo/maint.flo master_floscript: /usr/lib/python2.6/site-packages/salt/daemons/flo/master.flo master_job_cache: local_cache master_pubkey_signature: master_pubkey_signature master_roots: ---------- base: - /srv/salt-master master_sign_key_name: master_sign master_sign_pubkey: False master_tops: ---------- master_use_pubkey_signature: False max_event_size: 1048576 max_minions: 0 max_open_files: 100000 minion_data_cache: True minionfs_blacklist: minionfs_env: base minionfs_mountpoint: minionfs_whitelist: nodegroups: ---------- open_mode: False order_masters: False outputter_dirs: peer: ---------- permissive_pki_access: False pidfile: /var/run/salt-master.pid pillar_opts: True pillar_roots: ---------- base: - /srv/pillar pillar_safe_render_error: True pillar_source_merging_strategy: smart pillar_version: 2 pillarenv: None ping_on_rotate: False pki_dir: /etc/salt/pki/master preserve_minion_cache: False pub_hwm: 1000 publish_port: 4505 publish_session: 86400 queue_dirs: raet_alt_port: 4511 raet_clear_remotes: False raet_main: True raet_mutable: False raet_port: 4506 range_server: range:80 reactor: reactor_refresh_interval: 60 reactor_worker_hwm: 10000 reactor_worker_threads: 10 renderer: yaml_jinja ret_port: 4506 root_dir: / rotate_aes_key: True runner_dirs: saltversion: 2015.5.10 search: search_index_interval: 3600 serial: msgpack show_jid: False show_timeout: True sign_pub_messages: False sock_dir: /var/run/salt/master sqlite_queue_dir: /var/cache/salt/master/queues ssh_passwd: ssh_port: 22 ssh_scan_ports: 22 ssh_scan_timeout: 0.01 ssh_sudo: False ssh_timeout: 60 ssh_user: root state_aggregate: False state_auto_order: True state_events: False state_output: full state_top: salt://top.sls state_top_saltenv: None state_verbose: True sudo_acl: False svnfs_branches: branches svnfs_env_blacklist: svnfs_env_whitelist: svnfs_mountpoint: svnfs_remotes: svnfs_root: svnfs_tags: tags svnfs_trunk: trunk syndic_dir: /var/cache/salt/master/syndics syndic_event_forward_timeout: 0.5 syndic_jid_forward_cache_hwm: 100 syndic_master: syndic_max_event_process_time: 0.5 syndic_wait: 5 timeout: 5 token_dir: /var/cache/salt/master/tokens token_expire: 43200 transport: zeromq user: root verify_env: True win_gitrepos: - https://github.com/saltstack/salt-winrepo.git win_repo: /srv/salt/win/repo win_repo_mastercachefile: /srv/salt/win/repo/winrepo.p worker_floscript: /usr/lib/python2.6/site-packages/salt/daemons/flo/worker.flo worker_threads: 5 zmq_filtering: False
修改 master端的:/etc/salt/master
#pillar_opts: True 这个再次改成False
pillar_opts: False
pillar_roots: base: - /srv/pillar
[root@js-93 salt]# mkdir /srv/pillar
[root@js-93 salt]# /etc/init.d/salt-master restart #重启
使用:
先创建一个pillar的一个信息文件: [root@js-93 salt]# cat /srv/pillar/apache.sls {% if grains['os'] == 'CentOS' %} apache: httpd {% elif grains['os'] == 'Debian' %} apache: apache2 {% endif %} 然后指定能够读取这个文件的命令或文件: [root@js-93 salt]# cat /srv/pillar/top.sls base: '*': - apache
查看pillar数据系统的信息: [root@js-93 salt]# salt '*' pillar.items openfire2: ---------- apache: httpd 因为 apache.sls 里面指定的是CentOS的信息才会显示上面的内容,不然不会显示。
[root@js-93 salt]# salt -I 'apache:httpd' test.ping openfire2: Minion did not return. [No response] You have mail in /var/spool/mail/root [root@js-93 salt]# salt '*' saltutil.refresh_pillar openfire2: True 当不能使用的时候,要刷新一下。
[root@js-93 salt]# salt -I 'apache:httpd' test.ping
openfire2:
True
| 名称 | 存储位置 | 数据类型 | 采集更新方式 | 应用 |
| Grains | MInion端 | 静态数据 | minion启动时手机,也可以使用saltutil.sync_grains进行刷新 | 存储Minion基本数据。比如用于匹配Minion,自身数据可以用来做资产管理等 |
| Pillar | Master端 | 动态数据 | 在Master端定义,指定给对应的Minion。可以使用saltutil.refresh_pillar刷新 | 存储Master指定的数据,只有指定的Minion可以看到。用于敏感数据保存。 |
远程执行命令详解
远程执行命令三大内容:目标(targeting),模块(Module),返回(Returners)
目标(targeting)
https://docs.saltstack.com/en/latest/topics/targeting/ 所有支持的远程操作命令:主要是看正则表达式;


模块(Module)
https://docs.saltstack.com/en/latest/ref/modules/all/ 官方所有模块配置的地址。
返回(Returners)
https://docs.saltstack.com/en/latest/ref/returners/all/index.html
salt 的访问控制
首先修改/etc/salt/master 的acl控制: vi /etc/salt/master 245 client_acl: 246 ryan: 247 - test.ping 248 - network.* 修改这里表示,ryan 系统用户只能执行 test.ping 以及network.* 的方法。 别的模块及方法则不行 [ryan@js-93 ~]$ salt '*' test.ping openfire2: True [ryan@js-93 ~]$ salt '*' cmd.run 'w' Failed to authenticate! This is most likely because this user is not permitted to execute commands, but there is a small possibility that a disk error occurred (check disk/inode usage).
还可以指定某个用户只能访问某类型的机器,或者指定用户不能使用某个方法,以及不能使用某些模块。
salt 的信息还可以写入到mysql数据库。这个主要用于二次开发,或者收集记录信息等等,可以在官方文档查看到。
saltstack配置管理
top file 是saltstack的入口文件。
首先修改master端的 /etc/salt/master file_roots: base: - /srv/salt/base test: - /srv/salt/test prod: - /srv/salt/prod
重启:
[root@js-93 salt]# /etc/init.d/salt-master restart
[root@js-93 salt]# mkdir /srv/salt/{base,test,prod}
写入一个批量修改reslov.conf的配置:
[root@js-93 base]# pwd /srv/salt/base [root@js-93 base]# cat dns.sls /etc/resolv.conf: file.managed: - source: salt://files/resolv.conf - user: root - group: root - mode: 644 注释 salt:// 这是一个相对路径就相当于:/srv/salt/base的绝对路径一样。 因此,还要在base目录下面创建一个 files目录,用于存放resolv.conf文件;
查看一下需要配置的resolv.conf文件:
[root@js-93 files]# pwd /srv/salt/base/files [root@js-93 files]# cat resolv.conf # Generated by NetworkManager nameserver 202.96.209.133 nameserver 4.4.4.4 nameserver 8.8.8.8 nameserver 114.114.114.114
直接命令行执行:
[root@js-93 base]# salt '*' state.sls dns js-93: ---------- ID: /etc/resolv.conf Function: file.managed Result: True Comment: File /etc/resolv.conf updated Started: 14:12:36.775940 Duration: 41.112 ms Changes: ---------- diff: --- +++ @@ -1,3 +1,5 @@ # Generated by NetworkManager nameserver 202.96.209.133 -#nameserver 114.114.114.114 +nameserver 4.4.4.4 +nameserver 8.8.8.8 +nameserver 114.114.114.114 Summary ------------ Succeeded: 1 (changed=1) Failed: 0 ------------ Total states run: 1 openfire2: ---------- ID: /etc/resolv.conf Function: file.managed Result: True Comment: File /etc/resolv.conf updated Started: 14:05:11.366982 Duration: 38.805 ms Changes: ---------- diff: --- +++ @@ -1,3 +1,5 @@ - -nameserver 192.168.19.1 -nameserver 202.96.209.5 +# Generated by NetworkManager +nameserver 202.96.209.133 +nameserver 4.4.4.4 +nameserver 8.8.8.8 +nameserver 114.114.114.114 Summary ------------ Succeeded: 1 (changed=1) Failed: 0 ------------ Total states run: 1
查看minion端的reslov.conf 是否修改成功:
[root@openfire2 minion]# cat /etc/resolv.conf # Generated by NetworkManager nameserver 202.96.209.133 nameserver 4.4.4.4 nameserver 8.8.8.8 nameserver 114.114.114.114
这上面 命令行执行只是一个低级状态,如果有多个状态,则需要多次执行,因此。可以写一个高级状态,top file文件里面去定义。
[root@js-93 base]# pwd /srv/salt/base [root@js-93 base]# cat dns.sls /etc/resolv.conf: file.managed: - source: salt://files/resolv.conf - user: root - group: root - mode: 644 [root@js-93 base]# cat top.sls base: '*': - dns
执行结果:
执行:salt '*' state.highstate
[root@js-93 base]# salt '*' state.highstate js-93: ---------- ID: /etc/resolv.conf Function: file.managed Result: True Comment: File /etc/resolv.conf updated Started: 14:24:08.642733 Duration: 11.801 ms Changes: ---------- diff: --- +++ @@ -1,2 +1,5 @@ # Generated by NetworkManager nameserver 202.96.209.133 +nameserver 4.4.4.4 +nameserver 8.8.8.8 +nameserver 114.114.114.114 Summary ------------ Succeeded: 1 (changed=1) Failed: 0 ------------ Total states run: 1 openfire2: ---------- ID: /etc/resolv.conf Function: file.managed Result: True Comment: File /etc/resolv.conf updated Started: 14:16:48.282799 Duration: 29.424 ms Changes: ---------- diff: --- +++ @@ -1,2 +1,5 @@ # Generated by NetworkManager nameserver 202.96.209.133 +nameserver 4.4.4.4 +nameserver 8.8.8.8 +nameserver 114.114.114.114 Summary ------------ Succeeded: 1 (changed=1) Failed: 0 ------------ Total states run: 1
案例1:

新系统思想:
1.系统初始化
2.功能模块
3.业务模块
YAML规则语法:
1,缩进;Yaml使用一个固定的缩进放歌表示数据层结构关系。salt需要每个缩进级别有两个空格组成。不要使用tab
2,冒号;每个冒号后面都有一个空格,除了以冒号结尾和路径。
3,短横线;想要表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表的一部分。
jinja 用法:
[root@js-93 base]# cat dns.sls /etc/resolv.conf: file.managed: - source: salt://files/resolv.conf - user: root - group: root - mode: 644 - template: jinja - defaults: DNS_SERVER01: 202.96.209.133 DNS_SERVER02: 114.114.114.114
[root@js-93 base]# cat files/resolv.conf # Generated by NetworkManager nameserver {{DNS_SERVER01}} nameserver {{DNS_SERVER02}}
执行:salt '*' state.highstate
[root@js-93 base]# salt '*' state.highstate openfire2: ---------- ID: /etc/resolv.conf Function: file.managed Result: True Comment: File /etc/resolv.conf updated Started: 14:49:54.703800 Duration: 40.246 ms Changes: ---------- diff: --- +++ @@ -1,5 +1,4 @@ # Generated by NetworkManager nameserver 202.96.209.133 -nameserver 4.4.4.4 -nameserver 8.8.8.8 nameserver 114.114.114.114 + Summary ------------ Succeeded: 1 (changed=1) Failed: 0 ------------ Total states run: 1 js-93: ---------- ID: /etc/resolv.conf Function: file.managed Result: True Comment: File /etc/resolv.conf updated Started: 14:57:40.053564 Duration: 24.137 ms Changes: ---------- diff: --- +++ @@ -1,5 +1,4 @@ # Generated by NetworkManager nameserver 202.96.209.133 -nameserver 4.4.4.4 -nameserver 8.8.8.8 nameserver 114.114.114.114 + Summary ------------ Succeeded: 1 (changed=1) Failed: 0 ------------ Total states run: 1
查看minion结果:
[root@openfire2 minion]# cat /etc/resolv.conf # Generated by NetworkManager nameserver 202.96.209.133 nameserver 114.114.114.114
其中:
- template: jinja 这里表示一个模板;
- defaults:
DNS_SERVER01: 202.96.209.133
DNS_SERVER02: 114.114.114.114
这上面三句话表示变量。
files/resolv.conf 这里面表示变量的引用。模板的名称和文件里面的名称一定要一样。
系统初始化“模块”
配置resolv.conf 文件:
[root@js-93 init]# cat dns.sls /etc/resolv.conf: file.managed: - source: salt://init/files/resolv.conf - user: root - group: root - mode: 644
设置history的操作时间,操作用户:
[root@js-93 init]# cat history.sls /etc/profile: file.append: - text: - export HISTTIMEFORMAT="%F %T `whoami`"
把操作命令已日志的方式记录到 /var/log/message 里面;
export PROMPT_COMMAND='{ msg=$(history 1|{ read x y; echo $y; });logger "[euid=$(whoami)]":$(who am i):[`pwd`]"$msg";}'
写成 sls 文件:
[root@js-93 init]# cat 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";}'
调整内核参数:
[root@js-93 init]# cat sysctl.sls vm.swappiness: #不使用交换分区 sysctl.present: - value: 0 net.ipv4.ip_local_port_range: #本地随机端口号范围 sysctl.present: - value: 10000 65000 fs.file-max: #打开的最大文件数 sysctl.present: - value: 100000
把上面的所有初始化的内容写入到一个sls文件里面:
[root@js-93 init]# cat env_init.sls include: - init.dns - init.history - init.audit - init.sysctl
然后写入 top file文件里面 引用高级状态:
[root@js-93 base]# cat top.sls base: '*': - init.env_init init.env_init:表示init目录下的 env_init.sls 文件。
执行结果:
salt '*' state.highstate test=True #test=True 测试执行,可以查看到需要更高后的结果,但是,并不会真正的改变内容。
[root@js-93 base]# salt '*' state.highstate test=True js-93: ---------- ID: /etc/resolv.conf Function: file.managed Result: True Comment: The file /etc/resolv.conf is in the correct state Started: 16:07:09.456946 Duration: 8.706 ms Changes: ---------- ID: /etc/profile Function: file.append Result: None Comment: File /etc/profile is set to be updated Started: 16:07:09.465787 Duration: 3.052 ms Changes: ---------- diff: --- +++ @@ -80,3 +80,4 @@ export PATH=/application/mysql/bin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin export PATH=/usr/local/mysql/bin:$PATH export PATH=/usr/local/python27/bin:$PATH +export HISTTIMEFORMAT="%F %T `whoami`" ---------- ID: /etc/bashrc Function: file.append Result: None Comment: File /etc/bashrc is set to be updated Started: 16:07:09.468979 Duration: 3.908 ms Changes: ---------- diff: --- +++ @@ -84,3 +84,4 @@ unset pathmunge fi # vim:ts=4:sw=4 +export PROMPT_COMMAND='{ msg=$(history 1|{ read x y; echo $y; });logger "[euid=$(whoami)]":$(who am i):[`pwd`]"$msg";}' ---------- ID: vm.swappiness Function: sysctl.present Result: None Comment: Sysctl option vm.swappiness set to be changed to 0 Started: 16:07:09.474272 Duration: 29.895 ms Changes: ---------- ID: net.ipv4.ip_local_port_range Function: sysctl.present Result: None Comment: Sysctl option net.ipv4.ip_local_port_range set to be changed to 10000 65000 Started: 16:07:09.504508 Duration: 25.928 ms Changes: ---------- ID: fs.file-max Function: sysctl.present Result: None Comment: Sysctl option fs.file-max set to be changed to 100000 Started: 16:07:09.530710 Duration: 28.35 ms Changes: Summary ------------ Succeeded: 6 (unchanged=5, changed=2) Failed: 0 ------------ Total states run: 6 openfire2: ---------- ID: /etc/resolv.conf Function: file.managed Result: True Comment: The file /etc/resolv.conf is in the correct state Started: 15:59:44.178131 Duration: 22.931 ms Changes: ---------- ID: /etc/profile Function: file.append Result: None Comment: File /etc/profile is set to be updated Started: 15:59:44.201484 Duration: 5.118 ms Changes: ---------- diff: --- +++ @@ -83,3 +83,4 @@ PATH=$PATH:$HOME/bin PATH=$PATH:$HOME/bin:/usr/local/python27/bin +export HISTTIMEFORMAT="%F %T `whoami`" ---------- ID: /etc/bashrc Function: file.append Result: None Comment: File /etc/bashrc is set to be updated Started: 15:59:44.206841 Duration: 7.952 ms Changes: ---------- diff: --- +++ @@ -84,3 +84,4 @@ unset pathmunge fi # vim:ts=4:sw=4 +export PROMPT_COMMAND='{ msg=$(history 1|{ read x y; echo $y; });logger "[euid=$(whoami)]":$(who am i):[`pwd`]"$msg";}' ---------- ID: vm.swappiness Function: sysctl.present Result: None Comment: Sysctl option vm.swappiness set to be changed to 0 Started: 15:59:44.218022 Duration: 67.859 ms Changes: ---------- ID: net.ipv4.ip_local_port_range Function: sysctl.present Result: None Comment: Sysctl option net.ipv4.ip_local_port_range set to be changed to 10000 65000 Started: 15:59:44.286496 Duration: 51.831 ms Changes: ---------- ID: fs.file-max Function: sysctl.present Result: None Comment: Sysctl option fs.file-max set to be changed to 100000 Started: 15:59:44.338812 Duration: 51.0 ms Changes: Summary ------------ Succeeded: 6 (unchanged=5, changed=2) Failed: 0 ------------ Total states run: 6
salt '*' state.highstate
[root@js-93 base]# salt '*' state.highstate js-93: ---------- ID: /etc/resolv.conf Function: file.managed Result: True Comment: File /etc/resolv.conf updated Started: 16:22:25.288082 Duration: 11.363 ms Changes: ---------- diff: --- +++ @@ -1,4 +1,4 @@ # Generated by NetworkManager nameserver 202.96.209.133 -nameserver 4.4.4.4 +nameserver 114.114.114.114 ---------- ID: /etc/profile Function: file.append Result: True Comment: Appended 1 lines Started: 16:22:25.299569 Duration: 2.153 ms Changes: ---------- diff: --- +++ @@ -80,3 +80,4 @@ #export PATH=/application/mysql/bin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin export PATH=/usr/local/mysql/bin:$PATH export PATH=/usr/local/python27/bin:$PATH +export HISTTIMEFORMAT="%F %T `whoami`" ---------- ID: /etc/bashrc Function: file.append Result: True Comment: Appended 1 lines Started: 16:22:25.301827 Duration: 3.519 ms Changes: ---------- diff: --- +++ @@ -84,3 +84,4 @@ unset pathmunge fi # vim:ts=4:sw=4 +export PROMPT_COMMAND='{ msg=$(history 1|{ read x y; echo $y; });logger "[euid=$(whoami)]":$(who am i):[`pwd`]"$msg";}' ---------- ID: vm.swappiness Function: sysctl.present Result: True Comment: Updated sysctl value vm.swappiness = 0 Started: 16:22:25.306579 Duration: 34.697 ms Changes: ---------- vm.swappiness: 0 ---------- ID: net.ipv4.ip_local_port_range Function: sysctl.present Result: True Comment: Updated sysctl value net.ipv4.ip_local_port_range = 10000 65000 Started: 16:22:25.341528 Duration: 34.841 ms Changes: ---------- net.ipv4.ip_local_port_range: 10000 65000 ---------- ID: fs.file-max Function: sysctl.present Result: True Comment: Updated sysctl value fs.file-max = 100000 Started: 16:22:25.376573 Duration: 38.181 ms Changes: ---------- fs.file-max: 100000 Summary ------------ Succeeded: 6 (changed=6) Failed: 0 ------------ Total states run: 6 openfire2: ---------- ID: /etc/resolv.conf Function: file.managed Result: True Comment: File /etc/resolv.conf updated Started: 16:14:50.016655 Duration: 28.94 ms Changes: ---------- diff: --- +++ @@ -1,4 +1,4 @@ # Generated by NetworkManager nameserver 202.96.209.133 -nameserver 4.4.4.4 +nameserver 114.114.114.114 ---------- ID: /etc/profile Function: file.append Result: True Comment: Appended 1 lines Started: 16:14:50.045861 Duration: 5.464 ms Changes: ---------- diff: --- +++ @@ -80,3 +80,4 @@ PATH=$PATH:$HOME/bin:/usr/local/python3/bin PATH=$PATH:$HOME/bin PATH=$PATH:$HOME/bin:/usr/local/python27/bin +export HISTTIMEFORMAT="%F %T `whoami`" ---------- ID: /etc/bashrc Function: file.append Result: True Comment: Appended 1 lines Started: 16:14:50.051566 Duration: 8.297 ms Changes: ---------- diff: --- +++ @@ -84,3 +84,4 @@ unset pathmunge fi # vim:ts=4:sw=4 +export PROMPT_COMMAND='{ msg=$(history 1|{ read x y; echo $y; });logger "[euid=$(whoami)]":$(who am i):[`pwd`]"$msg";}' ---------- ID: vm.swappiness Function: sysctl.present Result: True Comment: Updated sysctl value vm.swappiness = 0 Started: 16:14:50.062927 Duration: 68.223 ms Changes: ---------- vm.swappiness: 0 ---------- ID: net.ipv4.ip_local_port_range Function: sysctl.present Result: True Comment: Updated sysctl value net.ipv4.ip_local_port_range = 10000 65000 Started: 16:14:50.131850 Duration: 64.959 ms Changes: ---------- net.ipv4.ip_local_port_range: 10000 65000 ---------- ID: fs.file-max Function: sysctl.present Result: True Comment: Updated sysctl value fs.file-max = 100000 Started: 16:14:50.197403 Duration: 67.141 ms Changes: ---------- fs.file-max: 100000 Summary ------------ Succeeded: 6 (changed=6) Failed: 0 ------------ Total states run: 6
编译安装proxy
状态模块:状态间关系
功 能:条件判断,用于cmd状态模块
常用方法:
onlyif:检查命令,仅当“onlyif”选项指向的命令返回true时才执行name定义的命令
unless:用于检查的命令,仅当“unless”选项指向的命令返回false时才执行name指向的命令。
功能名称:requisites
功 能:处理状态间关系
常用方法:
require #我依赖某个状态
require_in #我被某个状态依赖
watch #我关注某个状态
watch_in #我被某个状态关注
已完成以后的目录结构:
[root@js-93 prod]# tree . ├── haproxy │ ├── files │ │ ├── haproxy-1.6.10.tar.gz │ │ └── haproxy.init │ └── install.sls └── pkg └── pkg-init.sls 3 directories, 4 files
linux安装一个软件之前,首先要安装这个软件所依赖的软件包。因此,写一个批量安装依赖包的sls
[root@js-93 prod]# cat pkg/pkg-init.sls pkg-init: pkg.installed: - names: - gcc - gcc-c++ - glibc - make - autoconf - openssl-devel
安装haproxy:通过saltstack进行远程批量安装,(当然,批量是指,minion端已经和master端进行过认证的服务器)
[root@js-93 prod]# cat haproxy/install.sls include: - pkg.pkg-init haproxy-install: file.managed: - name: /usr/local/src/haproxy-1.6.10.tar.gz - source: salt://haproxy/files/haproxy-1.6.10.tar.gz - user: root - group: root - mode: 755 cmd.run: - name: cd /usr/local/src && tar zxf haproxy-1.6.10.tar.gz && cd haproxy-1.6.10 && make TARGET=linux26 PREFIX=/usr/local/haproxy && make install PREFIX=/usr/local/haproxy - unless: test -d /usr/local/haproxy - require: - pkg: pkg-init - file: haproxy-install haproxy-init: file.managed: - name: /etc/init.d/haproxy - source: salt://haproxy/files/haproxy.init - user: root - group: root - mode: 755 - require: - cmd: haproxy-install cmd.run: - name: chkconfig --add haproxy - unless: chkconfig --list|grep haproxy - require: - file: haproxy-init net.ipv4.ip_nonlocal_bind: sysctl.present: - value: 1 haproxy-config-dir: file.directory: - name: /etc/haproxy - user: root - group: root - mode: 755
在 /usr/local/src 下面需要有haproxy的安装包。并且在 files下面有haproxy的启动脚本,会放在/etc/init.d下面。(启动脚本需要修改:BIN=/usr/local/haproxy/sbin/$BASENAME)
执行:salt 'openfire*' state.sls haproxy.install env=prod (这里一定要指定环境,而且,这个执行的过程比较慢,主要是yum安装依赖包,并且编译安装haproxy的配置文件。)
Saltstack配置管理-业务引用haproxy
首先要有一个haproxy.cfg的配置文件:
[root@js-93 prod]# cat cluster/files/haproxy-outside.cfg global log 127.0.0.1 local3 notice maxconn 4096 uid 0 gid 0 daemon defaults log global mode tcp option tcplog option dontlognull retries 3 maxconn 2000 option redispatch timeout connect 5000 timeout client 50000 timeout server 50000 listen server_haproxy bind *:8066 balance roundrobin mode tcp server server_01 192.168.20.93:8066 weight 3 check server server_02 192.168.20.172:8066 weight 3 check
然后写一个haproxy的文件配置管理,与服务管理:
[root@js-93 prod]# cat 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 service.running: - name: haproxy - enable: True #加入开机自启动 - reload: True - require: - cmd: haproxy-init - watch: #如果检测到文件被改变,则服务会被重启 - file: haproxy-service
这里的逻辑性比较高,需要结合前面的haproxy 的配置进行解释。
然后到base目录下去编写 top file文件:
[root@js-93 salt]# cat base/top.sls base: '*': - init.env_init prod: 'openfire*': - cluster.haproxy-outside 'js-*': - cluster.haproxy-outside
执行: salt ‘*’ state.highstate
因此:salt下的整体目录结构就是:
[root@js-93 salt]# tree . ├── base │ ├── init #系统初始化时需要做的一些事情。 │ │ ├── audit.sls │ │ ├── dns.sls │ │ ├── env_init.sls │ │ ├── files │ │ │ └── resolv.conf │ │ ├── history.sls │ │ └── sysctl.sls │ └── top.sls ├── prod │ ├── cluster #这里主要是配置文件管理,集群安装,服务启动等等 │ │ ├── files │ │ │ └── haproxy-outside.cfg │ │ └── haproxy-outside.sls │ ├── haproxy #这里主要是安装依赖包,安装haproxy的软件 │ │ ├── files │ │ │ ├── haproxy-1.6.10.tar.gz │ │ │ └── haproxy.init │ │ └── install.sls │ └── pkg │ └── pkg-init.sls └── test
安装keepalived
keepalived的目录结构:
[root@js-93 prod]# tree keepalived/ keepalived/ ├── files │ ├── keepalived #启动脚本 ==>/usr/local/src/keepalived-1.3.5/keepalived/etc/init.d/keepalived │ ├── keepalived-1.3.5.tar.gz #安装包 │ ├── keepalived.conf #配置文件 ==> /usr/local/src/keepalived-1.3.5/keepalived/etc/keepalived/keepalived.conf │ └── keepalived.sysconfig #配置文件(编译安装生成以后的文件) ==> ll /usr/local/keepalived/etc/sysconfig/keepalived └── install.sls #saltstack安装keepalived的安装文件
其中上面的启动脚本keepalived 的 “daemon keepalived ${KEEPALIVED_OPTIONS}”要修改成为:“daemon /usr/local/keepalived/sbin/keepalived ${KEEPALIVED_OPTIONS}”
安装keepalived的sls配置文件。
[root@js-93 keepalived]# cat install.sls include: - pkg.pkg-init keepalived-install: file.managed: - name: /usr/local/src/keepalived-1.3.5.tar.gz - source: salt://keepalived/files/keepalived-1.3.5.tar.gz - user: root - group: root - mode: 755 cmd.run: - name: cd /usr/local/src && tar xf keepalived-1.3.5.tar.gz && cd keepalived-1.3.5 &&./configure --prefix=/usr/local/keepalived --disable-fwmark && make && make install - unless: test -d /usr/local/keepalived - require: - pkg: pkg-init - file: keepalived-install keepalived-init: file.managed: - name: /etc/init.d/keepalived - source: salt://keepalived/files/keepalived - user: root - group: root - mode: 755 cmd.run: - name: chkconfig --add keepalived - unless: chkconfig --list|grep keepalived - require: - file: keepalived-init /etc/sysconfig/keepalived: file.managed: - source: salt://keepalived/files/keepalived.sysconfig - user: root - group: root - mode: 644 /etc/keepalived: file.directory: - user: root - group: root
执行: salt '*' state.sls keepalived.install env=prod
业务引用keepalived
keepalived+haproxy 当前的目录结构:
[root@js-93 salt]# tree . ├── base │ ├── ; │ ├── init │ │ ├── audit.sls │ │ ├── dns.sls │ │ ├── env_init.sls │ │ ├── files │ │ │ └── resolv.conf │ │ ├── history.sls │ │ └── sysctl.sls │ └── top.sls ├── prod │ ├── cluster │ │ ├── files │ │ │ ├── haproxy-outside.cfg │ │ │ └── haproxy-outside-keepalived.conf │ │ ├── haproxy-outside-keepalived.sls │ │ └── haproxy-outside.sls │ ├── haproxy │ │ ├── files │ │ │ ├── haproxy-1.6.10.tar.gz │ │ │ └── haproxy.init │ │ └── install.sls │ ├── keepalived │ │ ├── files │ │ │ ├── keepalived │ │ │ ├── keepalived-1.3.5.tar.gz │ │ │ ├── keepalived.conf │ │ │ └── keepalived.sysconfig │ │ └── install.sls │ └── pkg │ └── pkg-init.sls └── test
haproxy-outside-keepalived.conf 的内容为:
[root@js-93 cluster]# cat files/haproxy-outside-keepalived.conf ! Configuration File for keepalived global_defs{ notification_email { saltstack@example.com } notification_email_from keepalived@example.com smtp_server 127.0.0.1 smtp_connect_timeout 39 router_id {{ROUTEID}} } vrrp_instance haproxy_ha{ state {{STATEID}} interface eth1 virutal_router_id 36 priority {{PRIORITYID}} advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.20.249 } }
haproxy-outside.cfg 的内容为:
[root@js-93 cluster]# cat files/haproxy-outside.cfg global maxconn 100000 chroot /usr/local/haproxy uid 99 gid 99 daemon nbproc 1 pidfile /usr/local/haproxy/logs/haproxy.pid log 127.0.0.1 local3 info defaults option http-keep-alive maxconn 100000 mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms listen stats mode http bind 0.0.0.0:8777 stats enable stats uri /haproxy-status stats auth haproxy:saltstack frontend frontend_www_example_com bind 192.168.20.93:80 mode http option httplog log global default_backend backend_www_example_com backend backend_www_example_com option httpchk HEAD / HTTP/1.0 balance roundrobin server js-93 192.168.20.93:8080 check inter 2000 rise 30 fall 15 server openfire2 192.168.20.172:8080 check inter 2000 rise 30 fall 15
haproxy-outside-keepalived.sls 部署keepalived的sls文件:
[root@js-93 cluster]# cat haproxy-outside-keepalived.sls include: - keepalived.install keepalived-service: file.managed: - name: /etc/keepalived/keepalived.conf - source: salt://cluster/files/haproxy-outside-keepalived.conf - user: root - group: root - mode: 644 - template: jinja {% if grains['fqdn'] == 'js-93' %} - ROUTEID: haproxy_ha - STATEID: MASTER - PRIORITYID: 150 {% elif grains['fqdn'] == 'openfire2' %} - ROUTEID: haproxy_ha - STATEID: BACKUP - PRIORITYID: 100 {% endif %} service.running: - name: keepalived - enable: True - watch: - file: keepalived-service
然后写入到 top file 里面:
[root@js-93 cluster]# cat /srv/salt/base/top.sls base: '*': - init.env_init prod: 'openfire*': - cluster.haproxy-outside - cluster.haproxy-outside-keepalived 'js-*': - cluster.haproxy-outside - cluster.haproxy-outside-keepalived
增加zabbix agent
目前为止所有目录结构:
[root@js-93 /]# tree srv srv ├── pillar │ ├── apache.sls │ ├── base │ │ ├── top.sls │ │ └── zabbix.sls │ └── top.sls └── salt ├── base │ ├ │ ├── init │ │ ├── audit.sls │ │ ├── dns.sls │ │ ├── env_init.sls │ │ ├── files │ │ │ ├── resolv.conf │ │ │ └── zabbix_agentd.conf │ │ ├── history.sls │ │ ├── sysctl.sls │ │ └── zabbix_agent.sls │ └── top.sls ├── prod │ ├── cluster │ │ ├── files │ │ │ ├── haproxy-outside.cfg │ │ │ └── haproxy-outside-keepalived.conf │ │ ├── haproxy-outside-keepalived.sls │ │ └── haproxy-outside.sls │ ├── haproxy │ │ ├── files │ │ │ ├── haproxy-1.6.10.tar.gz │ │ │ └── haproxy.init │ │ └── install.sls │ ├── keepalived │ │ ├── files │ │ │ ├── keepalived │ │ │ ├── keepalived-1.3.5.tar.gz │ │ │ ├── keepalived.conf │ │ │ └── keepalived.sysconfig │ │ └── install.sls │ └── pkg │ └── pkg-init.sls └── test
添加zabbix agent 用到了pillar 因此,修改了 /etc/salt/master 的配置文件:
pillar_roots: base: - /srv/pillar/base
其中:zabbix_agent.sls 的配置如下:
[root@js-93 init]# cat /srv/salt/base/init/zabbix_agent.sls zabbix-agent-install: pkg.installed: - name: zabbix-agent file.managed: - name: /etc/zabbix/zabbix_agentd.conf - source: salt://init/files/zabbix_agentd.conf - template: jinja - defaults: Server: {{ pillar['zabbix-agent']['Zabbix_Server'] }} - require: - pkg: zabbix-agent-install service.running: - name: zabbix-agent - enable: True - watch: - pkg: zabbix-agent-install - file: zabbix-agent-install
然后在环境初始化 env_init.sls 添加zabbix_agent:
[root@js-93 init]# cat env_init.sls include: - init.dns - init.history - init.audit - init.sysctl - init.zabbix_agent
zabbix_agent.conf 的配置内容为:
[root@js-93 init]# cat files/zabbix_agentd.conf |egrep -v "^#|^$" PidFile=/var/run/zabbix/zabbix_agentd.pid LogFile=/var/log/zabbix/zabbix_agentd.log LogFileSize=0 Server={{ Server }} #注意这一行,这一行是用到了pillar的变量 ServerActive=116.228.90.94 Hostname=hezitwo UserParameter=mount_disk_discovery,/bin/bash /etc/zabbix/monitor_scripts/mount_disk_discovery.sh mount_disk_discovery
因为现在用了了pillar 修改了pillar的路径:/srv/pillar/base
[root@js-93 base]# cat zabbix.sls zabbix-agent: Zabbix_Server: 192.168.20.212 [root@js-93 base]# cat top.sls base: '*': - zabbix
执行: salt '*' state.highstate 即可完成minion端的 zabbix agent的安装;
github 的文档:包含了 nginx memecached pcre 等等。
https://github.com/unixhot/saltbook-code
架构扩展
[root@js-93 base]# lsof -i:4505 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME salt-mini 19331 root 24u IPv4 17761248 0t0 TCP 192.168.20.93:11393->192.168.20.93:4505 (ESTABLISHED) salt-mast 30477 root 12u IPv4 17759720 0t0 TCP *:4505 (LISTEN) salt-mast 30477 root 14u IPv4 17760302 0t0 TCP 192.168.20.93:4505->openfire2:24389 (ESTABLISHED) salt-mast 30477 root 15u IPv4 17761249 0t0 TCP 192.168.20.93:4505->192.168.20.93:11393 (ESTABLISHED) [root@js-93 base]# lsof -i:4506 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME salt-mini 19331 root 13u IPv4 17759778 0t0 TCP 192.168.20.93:37211->192.168.20.93:4506 (ESTABLISHED) salt-mast 30493 root 20u IPv4 17759741 0t0 TCP *:4506 (LISTEN) salt-mast 30493 root 22u IPv4 17759777 0t0 TCP 192.168.20.93:4506->openfire2:12236 (ESTABLISHED) salt-mast 30493 root 23u IPv4 17759779 0t0 TCP 192.168.20.93:4506->192.168.20.93:37211 (ESTABLISHED)
可以看到 minion端和master端,保持一个长连接的模式。这个模式的好处再于,master处理的信息发送到4505,然后发送到minion端,然后处理后的结果会发送到4506 这个端口。
salt信息显示:
[root@js-93 base]# yum install python-setproctitle #安装这个可以看到python启动的进程信息 [root@js-93 base]# ps -ef|grep salt root 3148 1 0 17:57 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-master -d ProcessManager #salt的中心管理进程 root 3149 3148 9 17:57 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-master -d Maintenance root 3150 3148 0 17:57 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-master -d Publisher root 3159 3148 0 17:57 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-master -d EventPublisher root 3160 3148 0 17:57 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-master -d ReqServer_ProcessManager root 3172 3160 18 17:57 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-master -d MWorker root 3173 3160 18 17:57 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-master -d MWorker root 3174 3160 9 17:57 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-master -d MWorker root 3175 3160 9 17:57 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-master -d MWorker root 3176 3160 9 17:57 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-master -d MWorker root 3181 3160 0 17:57 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-master -d MWorkerQueue root 19331 1 0 May31 ? 00:01:04 /usr/bin/python2.6 /usr/bin/salt-minion -d root 32133 26018 0 16:49 pts/2 00:00:00 /usr/bin/python2.6 /usr/bin/salt * state.highstate
优化1: 把master 的 /etc/salt/master的 timeout修改成为: timeout: 30(如果是公网的可能会数值调大)
salt-syndic
具体使用方法可查看官当文档:Salt Syndic 这一章节

更换master 的方法:
1.先停止 minion端的 服务,以及master服务。
2.清理 minion端所有key:/etc/salt/pki 下面所有的内容,
3.修改 /etc/salt/minion :master: 192.168.20.93(修改改变的master IP地址。)
4.重启:/etc/init.d/salt-minion start
saltstack 二次开发
grains:
注释:grains 是静态的。获取一次就不会改变。
首先要在 file_roots 下面创建 _grains 的目录;然后写一个编写一个 my grains 的python脚本
[root@js-93 _grains]# pwd /srv/salt/base/_grains
[root@js-93 _grains]# cat my_grains.py #!/usr/bin/env python #coding:utf-8 def my_grains(): ''' My Custin Grains ''' grains = { 'key1':'val1','key2':'val2'} return grains
然后执行:salt '*' saltutil.sync_grains 这会把自己写的grians 同步到各个minion上面;
[root@js-93 _grains]# salt '*' saltutil.sync_grains js-93: - grains.my_grains openfire2: - grains.my_grains
上面这一步会同步到minion端,如下:
[root@openfire2 grains]# ll /var/cache/salt/minion/extmods/grains total 8 -rw------- 1 root root 157 Jun 2 19:07 my_grains.py -rw------- 1 root root 382 Jun 2 19:07 my_grains.pyc [root@openfire2 grains]# cat my_grains.py #!/usr/bin/env python #coding:utf-8 def my_grains(): ''' My Custin Grains ''' grains = { 'key1':'val1','key2':'val2'} return grains
获取自己写的 grains:
自己写的grains的结果
模块: modules
安装salt 时,自己的模块存放路径为: /usr/lib/python2.6/site-packages/salt/modules
首先要在 file_roots 下面创建一个 _module 目录,然后写一个模块:
[root@js-93 _modules]# pwd /srv/salt/base/_modules [root@js-93 _modules]# cat my_disk.py #!/usr/bin/env python def list(): cmd = 'df -h' ret = __salt__['cmd.run'](cmd) return ret
同步到minion:
[root@js-93 _modules]# salt '*' saltutil.sync_modules openfire2: - modules.my_disk js-93: - modules.my_disk
minion端查看同步的模块:
[root@openfire2 modules]# pwd /var/cache/salt/minion/extmods/modules [root@openfire2 modules]# cat my_disk.py #!/usr/bin/env python def list(): cmd = 'df -h' ret = __salt__['cmd.run'](cmd) return ret
执行自己写的模块:
[root@js-93 _modules]# salt '*' my_disk.list js-93: Filesystem Size Used Avail Use% Mounted on /dev/md1 1.8T 1.2T 517G 71% / tmpfs 3.9G 16K 3.9G 1% /dev/shm /dev/md0 194M 59M 126M 32% /boot openfire2: Filesystem Size Used Avail Use% Mounted on /dev/sda3 195G 4.7G 181G 3% / tmpfs 1.9G 12K 1.9G 1% /dev/shm /dev/sda1 194M 27M 158M 15% /boot

浙公网安备 33010602011771号