saltstack

salt-api使用

启用salt-api 服务

这里简单的说明下,SaltStack官方支持三种REST API,分别是rest_cherry; rest_tonado和rest_wsgi, 本文选择使用rest_cherry模块来实现SaltStack的HTTP API。

配置salt-API服务

yum -y install salt-api
useradd -M -s /sbin/nologin saltapi
echo "saltapi" | passwd saltapi --stdin
vim /etc/salt/master
external_auth:
  pam:
    saltapi:
      - .*
      - '@wheel'
      - '@runner'

rest_cherrypy:
  port: 8000
  disable_ssl: Ture
  
  systemctl restart salt-master 
  systemctl restart salt-api 

使用CURL测试salt-API接口

第一步登录获得token,后续的命令使用token直接执行。

curl  -sk http://192.168.56.11:8000/login -H 'Accept: application/x-yaml' -d username='saltapi' -d password='saltapi' -d eauth='pam'

return:
- eauth: pam
  expire: 1522883646.381435
  perms:
  - .*
  - '@wheel'
  - '@runner'
  start: 1522840446.381431
  token: 86e323effd30bed7b2cdbcf4e70744048bbc25ca
  user: saltapi

第二步执行如下命令:salt 'linux-node2' test.ping

curl -sk http://192.168.56.11:8000/ -H 'Accept: application/json' -H 'X-Auth-Token: 86e323effd30bed7b2cdbcf4e70744048bbc25ca' -d client='local' -d tgt='linux-node2' -d fun='test.ping'  | python -mjson.tool  
{
    "return": [
        {
            "linux-node2": true
        }
    ]
}

执行带参数的命令:salt 'linux-node2' cmd.run 'free -m'

curl -sk http://192.168.56.11:8000/ -H 'Accept: application/json' -H 'X-Auth-Token: 86e323effd30bed7b2cdbcf4e70744048bbc25ca' -d client='local' -d tgt='linux-node2' -d fun='cmd.run' -d arg='whoami' | python -mjson.tool
{
    "return": [
        {
            "linux-node2": "root"
        }
    ]
}

salt API /run 接口

运行绕过正常会话处理的命令除此之外,该URL与根URL(/)相同。

curl -sk http://192.168.56.11:8000/run \
    -H 'Accept: application/x-yaml' \
    -H 'Content-type: application/json' \
    -d '[{
        "client": "local",
        "tgt": "linux-node2",
        "fun": "test.ping",
        "username": "saltapi",
        "password": "saltapi",
        "eauth": "pam"
    }]' 
return:
- linux-node2: true

使用python 实现如下命令

salt 'linux-node2' cmd.run 'free -m'
import requests

url='http://192.168.56.11:8000/login'
username = 'saltapi'
password = 'saltapi'

data = {'username': username,'password': password,'eauth': 'pam'}
headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'}
login_req = requests.post(url=url, headers=headers, data=data)
js = login_req.json()
token = js['return'][0].get('token')
print(token)


cmd_headers = {'Accept': 'application/json','Content-type': 'application/x-www-form-urlencoded', 'X-Auth-Token': token}
cmd_data = {'client': 'local', 'tgt': 'linux-node2', 'fun': 'cmd.run', 'arg': 'free -m '}
urls = 'http://192.168.56.11:8000'
req = requests.post(urls,headers=cmd_headers,data=cmd_data)
print(req.status_code)

if req.status_code == 200:
	print(req.json())

执行结果如下:

ab5d9ea0f428367c79f8eaf3dc62d39b1c45b4c9
200
{'return': [{'linux-node2': '              total        used        free      shared  buff/cache   available\nMem:            979         607          76          49         295         172\nSwap:             0           0           0'}]}

使用python编写过程中遇到的问题:

  • curl 请求时,默认会增加Content-type': 'application/x-www-form-urlencoded 的头部,所以在request请求头中也需要加入。

使用saltstack的sls功能

sls文件编写

[root@vm01 ~]# vim /etc/salt/master
#在master配置文件中添加以下内容
file_roots:
base:
– /srv/salt

[root@vm01 ~]# mkdir -p /srv/salt
[root@vm01 ~]# cd /srv/salt/
[root@vm01 salt]# pwd
/srv/salt
[root@vm01 salt]# vim top.sls
base:
‘*’:
– httpd

[root@vm01 salt]# vim httpd.sls
httpd:
pkg:
– installed

[root@vm01 salt]#
[root@vm01 salt]# salt ‘*’ service.available httpd
vm02:
False
[root@vm01 salt]#
[root@vm01 salt]# salt ‘*’ state.highstate -v
Executing job with jid 20160412203923856918
——————————————-

vm02:
———-
ID: httpd
Function: pkg.installed
Result: True
Comment: The following packages were installed/updated: httpd
Started: 20:39:25.356652
Duration: 46945.068 ms
Changes:
———-
httpd:
———-
new:
2.2.15-47.el6.centos.4
old:

Summary
————
Succeeded: 1 (changed=1)
Failed: 0
————
Total states run: 1
[root@vm01 salt]#
[root@vm01 salt]# salt ‘*’ service.available httpd
vm02:
True
[root@vm01 salt]#

#minion端查看httpd是否已经安装成功
[root@vm02 ~]# rpm -q httpd
httpd-2.2.15-47.el6.centos.4.x86_64
[root@vm02 ~]#
#ok,已经安装成功了,就这么简单。

SaltStack使用salt-ssh模式

1.salt-ssh 是 0.17.0 新引入的一个功能,不需要minion对客户端进行管理,也不需要master。

2.salt-ssh 支持salt大部分的功能:如 grains、modules、state 等

3.salt-ssh 没有使用ZeroMQ的通信架构,执行是串行模式

类似 paramiko、pssh、ansible 这类的工具

Roster使用

salt-ssh需要一个名单系统来确定哪些执行目标,Salt的0.17.0版本中salt-ssh引入roster系统

roster系统编译成了一个数据结构,包含了targets,这些targets是一个目标系统主机列表和或如连接到这些targets

配置文件如下
复制代码
# target的信息
    host:        # 远端主机的ip地址或者dns域名
    user:        # 登录的用户
    passwd:      # 用户密码,如果不使用此选项,则默认使用秘钥方式
# 可选的部分
    port:        #ssh端口
    sudo:        #可以通过sudo
    tty:         # 如果设置了sudo,设置这个参数为true
    priv:        # ssh秘钥的文件路径
    timeout:     # 当建立链接时等待响应时间的秒数
    minion_opts: # minion的位置路径
    thin_dir:    # target系统的存储目录,默认是/tmp/salt-<hash>
    cmd_umask:   # 使用salt-call命令的umask值
复制代码

安装配置

一,安装salt-ssh
[root@linux-node1 ~]# yum install salt-ssh
二,修改roster文件,配置要管理的机器
复制代码
[root@linux-node1 ~]# tail -11  /etc/salt/roster 
linux-node1.example.com:
  host: 192.168.56.11
  user: root
  passwd: 123456
  port: 22

linux-node2.example.com:
  host: 192.168.56.12
  user: root
  passwd: 123456
  port: 22
复制代码
三,进行管理测试
[root@linux-node1 ~]# salt-ssh '*' test.ping -i
linux-node1.example.com:
    True
linux-node2.example.com:
    True
四,salt-ssh命令用法
复制代码
-r, –raw, –raw-shell # 直接使用shell命令
–priv #指定SSH私有密钥文件
–roster #定义使用哪个roster系统,如果定义了一个后端数据库,扫描方式,或者用户自定义的的roster系统,默认的就是/etc/salt/roster文件
–roster-file #指定roster文件
–refresh, –refresh-cache #刷新cache,如果target的grains改变会自动刷新
–max-procs #指定进程数,默认为25
-i, –ignore-host-keys #当ssh连接时,忽略keys
–passwd #指定默认密码
–key-deploy #配置keys 设置这个参数对于所有minions用来部署ssh-key认证,
 这个参和–passwd结合起来使用会使初始化部署很快很方便。当调用master模块时,并加上参数 –key-deploy 即可在minions生成keys,下次开始就不使用密码
复制代码
五,salt-ssh执行状态模块
 salt-ssh ‘*’ state.sls web.lamp

总结

1.salt-ssh 是在salt基础上打了一个python包上传到客户端的默认tmp目录下

在客户端上面解压并执行返回结果,最后删除tmp上传的临时文件

2.salt-minion方法是salt-mater先执行语法验证,验证通过后发送到minion

minion收到Msater的状态文件默认保存在/var/cache/salt/minion

注意:也有时候salt-master语法验证通过,在minion上可能因为环境问题会执行失败

3.salt-ssh和salt-minion可以共存,salt-minion不依赖于ssh服务

 

salt之pillar组件

pillar也是salt最重要的组件之一,其作用是定义与被控主机相关的任何数据,定义好的数据可以被其他组件使用,如模板、state、API等。在pillar中定义的数据与不同业务特征的被控主机相关联,这样不同被控主机只能看到自己匹配的数据,因此pillar安全性很高,适用于一些比较敏感的数据,这也是区别于grains最关键的一点,如定义不同业务组主机的用户id、组id、读写权限、程序包等信息,定义的规范是采用Python字典形式,即键/值,最上层的键一般为主机的id或组名称。

pillar的定义:

1、主配置文件定义

salt默认将主控端配置文件中的所有数据都定义到pillar中,而且对所有被控主机开放,可通过修改/etc/salt/master配置中的pillar_opts: True或False来定义是否开户或禁用这项功能,修改后执行salt ‘*’ pillar.data来观察效果。

2、SLS文件定义

pillar支持在slsy文件中定义数据,格式须符合YAML规范,与salt和state组件十分相似,两者文件的配置格式、入口文件top.sls都是一致的。

(1)定义pillar的主目录

修改主配置文件/etc/salt/master的pillar_roots参数,定义pillar的主目录

同时创建pillar目录,执行命令: install -d /srv/pillar

(2)定义入口文件top.sls

入口文件的作用一般是定义pillar的数据覆盖被控主机的有效域范围,”*” 代表任意主机,其中包括了一个data.sls文件,

/srv/pillar/top.sls

base:

‘*’:

– data

/srv/pillar/data.sls

appname: website

flow:

maxconn: 30000

maxmem: 6G

(3)校验pillar

通过 salt ‘myhost’ pillar.data appname flow 命令可以看到多出了上面定义的 data.sls数据项。如果结果不符合预期,可以尝试刷新被控机pillar数据,

运行 salt ‘myhost’ saltutil.refresh_pillar 即可刷新

 

3、pillar的使用

完成pillar配置后,接下来我们可以在state、模板文件中引用,模板格式为 “{{ pillar变量 }}” ,例如:

{{ pillar[‘appname’] }} (一级字典)

{{ pillar[‘flow’][‘maxconn’] }} (二级字典) 或 {{ salt[‘pillar.get’](‘flow: maxconn’),{} }}

 

Python API格式如下:

pillar[‘flow’][‘maxconn’]

pillar.get(‘flow:appname’,{})

 

结合grains处理数据的差异性—-示例:

3.1 创建pillar目录和top.sls文件

1
2
3
4
5
 # mkdir /srv/pillar
 # vi /srv/pillar/top.sls
 base:
   '*':
 - ip

3.2 先通过pillar获取minion主机IP

1
2
 # vi /srv/pillar/ip.sls
 ip: {{ grains['ipv4'][1] }}

#写完后,执行sls命令,可以看到已经获取到IP

1
2
3
4
5
6
7
8
9
 # salt '*' pillar.item ip
 host2:
     ----------
     ip:
         192.168.18.213
 host1:
     ----------
     ip:
         192.168.18.212

 

 

 

 

既然grains与pillar类似,就说下区别:

1.grains是minion每次加载时获取本地系统信息数据,是静态的,固定的,而pillar是动态加载数据,随时变化的,比grains更灵活。

2.grains数据存储在minion本地,pillar存储在master

 

Using salt-ssh to install Salt

In recent articles I covered how I’ve built a Continuous Delivery pipeline for my blog. These articles talk about using Docker to build a container for my blog, using Travis CI to test and build that container, and finally using a Masterless SaltStack configuration to deploy the blog. Once setup, this pipeline enables me to publish new posts by simply managing them within a GitHub repository.

The nice thing about this setup is that not only are blog posts managed hands-free. All of the servers that host my blog are managed hands-free. That means required packages, services and configurations are all deployed with the same Masterless SaltStack configuration used for the blog application deployment.

The only thing that isn’t hands-free about this setup, is installing and configuring the initial SaltStack Minion agent. That is, until today. In this article I am going to cover how to use salt-ssh, SaltStack’s SSH functionality to install and configure the salt-minion package on a new server.

How salt-ssh works

A typical SaltStack deployment consists of a Master server running the salt-master process, and one or more Minion servers running the salt-minion process. The salt-minion service will initiate communication with the salt-master service over a ZeroMQ connection and the Master distributes desired states to the Minion.

With this typical setup, you must first have a salt-master service installed and configured, and every server that you wish to manage with Salt must have the salt-minion service installed and configured. The salt-ssh package however, changes that.

salt-ssh is designed to provide SaltStack with the ability to manage servers in an agent-less fashion. What that means is, salt-ssh gives you the ability to manage a server, without having to install and configure the salt-minion package.

Why use salt-ssh instead of the salt-minion agent?

Why would anyone not want to install the salt-minion package? Well, there are a lot of possible reasons. One reason that comes to mind is that some systems are so performance oriented that there may be a desire to avoid performance degradation by running an agent. While salt-minion doesn’t normally use a lot of resources, it uses some and that some may be too much for certain environments.

Another reason may be due to network restrictions, for example if the Minions are in a DMZ segment of a network you may want to use salt-ssh from the master so that connections are only going from the master to the minion and never the minion to the master like the traditional setup.

For today’s article, the reasoning behind using salt-ssh is that I wish to automate the installation and configuration of the salt-minion service on new servers. These servers will not have the salt-minion package installed by default and I wanted to automate the initial installation of Salt.

Getting started with salt-ssh

Before we can start using salt-ssh to setup our new server we will first need to setup a Master server where we can call salt-ssh from. For my environment I will be using a virtual machine running on my local laptop as the Salt Master. Since we are using salt-ssh there is no need for the Minions to connect to this Master which makes running it from a laptop a simple solution.

Installing SaltStack

On this Salt Master, we will need to install both the salt-master and the salt-ssh packages. Like previous articles we will be following SaltStack’s official guide for installing Salt on Ubuntu systems.

Setup Apt

The official install guide for Ubuntu uses the Apt package manager to install SaltStack. In order to install these packages with Apt we will need to setup the SaltStack repository. We will do so using the add-apt-repository command.

$ sudo add-apt-repository ppa:saltstack/salt
     Salt, the remote execution and configuration management tool.
     More info: https://launchpad.net/~saltstack/+archive/ubuntu/salt
    Press [ENTER] to continue or ctrl-c to cancel adding it

    gpg: keyring `/tmp/tmpvi1b21hk/secring.gpg' created
    gpg: keyring `/tmp/tmpvi1b21hk/pubring.gpg' created
    gpg: requesting key 0E27C0A6 from hkp server keyserver.ubuntu.com
    gpg: /tmp/tmpvi1b21hk/trustdb.gpg: trustdb created
    gpg: key 0E27C0A6: public key "Launchpad PPA for Salt Stack" imported
    gpg: Total number processed: 1
    gpg:               imported: 1  (RSA: 1)
    OK

Once the Apt repository has been added we will need to refresh Apt’s package cache with the apt-get update command.

$ sudo apt-get update
Get:1 http://security.ubuntu.com trusty-security InRelease [65.9 kB]
Ign http://ppa.launchpad.net trusty InRelease                                  
Ign http://archive.ubuntu.com trusty InRelease                                 
Get:2 http://archive.ubuntu.com trusty-updates InRelease [65.9 kB]
Get:3 http://ppa.launchpad.net trusty Release.gpg [316 B]                      
Get:4 http://ppa.launchpad.net trusty Release [15.1 kB]                        
Get:5 http://security.ubuntu.com trusty-security/main Sources [118 kB]         
Fetched 10.9 MB in 7s (1,528 kB/s)                                             
Reading package lists... Done

This update command causes Apt to look through it’s known package repositories and refresh a local inventory of available packages.

Installing the salt-master and salt-ssh packages

Now that we have SaltStack’s Apt repository configured we can proceed with installing the required Salt packages. We will do this with the apt-get install command specifying the two packages we wish to install.

$ sudo apt-get install salt-master salt-ssh
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  git git-man liberror-perl libpgm-5.1-0 libzmq3 python-async python-croniter
  python-dateutil python-git python-gitdb python-jinja2 python-m2crypto
  python-markupsafe python-msgpack python-smmap python-zmq salt-common
Suggested packages:
  git-daemon-run git-daemon-sysvinit git-doc git-el git-email git-gui gitk
  gitweb git-arch git-bzr git-cvs git-mediawiki git-svn python-jinja2-doc
  salt-doc python-mako
The following NEW packages will be installed:
  git git-man liberror-perl libpgm-5.1-0 libzmq3 python-async python-croniter
  python-dateutil python-git python-gitdb python-jinja2 python-m2crypto
  python-markupsafe python-msgpack python-smmap python-zmq salt-common
  salt-master salt-ssh
0 upgraded, 19 newly installed, 0 to remove and 189 not upgraded.
Need to get 7,069 kB of archives.
After this operation, 38.7 MB of additional disk space will be used.
Do you want to continue? [Y/n] Y

In addition to the salt-ssh and salt-master packages Apt will install any dependencies that these packages require. With these packages installed, we can now move on to configuring our Salt master.

Configuring salt-ssh to connect to our target minion

Before we can start using salt-ssh to manage our new minion server we will first need to tell salt-ssh how to connect to that server. We will do this by editing the /etc/salt/roster file.

$ sudo vi /etc/salt/roster

With a traditional SaltStack setup the minion agents would initiate the first connection to the Salt master. This first connection is the way the master service identifies new minion servers. With salt-ssh there is no process for Salt to automatically identify new minion servers. This is where the /etc/salt/roster file comes into the picture, as this file used as an inventory of minions for salt-ssh.

As with other configuration files in Salt, the roster file is a YAML formatted file which makes it fairly straight forwarder to understand. The information required to specify a new minion is also pretty straight forward.

blr1-001:
  host: 10.0.0.2
  user: root

The above information is fairly minimal, the basic definition is a Target name blr1-001, a Hostname or IP address specified by host and then the Username specified by user.

The target name is used when running the salt-ssh command to specify what minion we wish to target. The host key is used by salt-ssh to define where to connect to, and the user key is used to define who to connect as.

In the example above I specified to use the root user. It is possible to use salt-ssh with a non-root user by simply adding sudo: True to the minion entry.

Testing connectivity to our minion

With the minion now defined within the /etc/salt/roster file we should now be able to connect to our minion with salt-ssh. We can test this out by executing a test.ping task against this target with salt-ssh.

$ sudo salt-ssh 'blr1-001' --priv=/home/vagrant/.ssh/id_rsa test.ping
blr1-001:
    ----------
    retcode:
        254
    stderr:
    stdout:
        The host key needs to be accepted, to auto accept run salt-ssh with the -i flag:
        The authenticity of host '10.0.0.2 (10.0.0.2)' can't be established.
        ECDSA key fingerprint is 2c:34:0a:51:a2:bb:88:cc:3b:86:25:bc:b8:d0:b3:d0.
        Are you sure you want to continue connecting (yes/no)?

The salt-ssh command above has a similar syntax to the standard salt command called with a typical Master/Minion setup; the format is salt-ssh <target> <task>. In this case our target was blr1-001 the same name we defined earlier and our task was test.ping.

You may also notice that I passed the --priv flag followed by a path to my SSH private key. This flag is used to specify an SSH key to use when connecting to the minion server. By default, salt-ssh will use SaltStack’s internal SSH key, which means if you wish to use an alternative key you will need to specify the key with the --priv flag.

In many cases it’s perfectly fine to use SaltStack’s internal SSH key, in my case the SSH public key has already been distributed which means I do not want to use Salt’s internal SSH key.

Bypassing Host Key Validation

If we look at the output of the salt-ssh command executed earlier, we can see that the command was not successful. The reason for this is because this master server has not accepted the host key from the new minion server. We can get around this issue by specifying the -i flag when running salt-ssh.

$ sudo salt-ssh 'blr1-001' --priv /home/vagrant/.ssh/id_rsa -i test.ping
blr1-001:
    True

The -i flag tells salt-ssh to ignore host key checks from SSH. We can see from the above salt-ssh execution, when the -i flag is used, everything works as expected.

Specifying a password

In the salt-ssh commands above we used an SSH key for authentication with the Minion server. This worked because prior to setting up Salt, I deployed the public SSH key to the minion server we are connecting with. If we didn’t want to use SSH keys for authentication with the Salt Minion for whatever reason, we could also use password based authentication by specifying the password within the roster file.

$ sudo vi /etc/salt/roster

To add a password for authentication, simply add the passwd key within the target servers specification.

blr1-001:
  host: 10.0.0.2
  user: root
  passwd: example

With the above definition salt-ssh will now connect to our minion by establishing an SSH connection to 10.0.0.2 and login to this system as the root user with the password of example. With a password defined, we can rerun our test.ping this time with the --priv flag omitted.

$ sudo salt-ssh 'blr1-001' -i test.ping
blr1-001:
    True

Now that a test.ping has returned correctly we can move on to our next step of defining the Salt states to install and configure the salt-minion package.

Using Salt to install Salt

In the Master-less Salt Minions article I had two GitHub repositories setup with various Salt state files. One repository contains salt state files that can be used to setup a generic base system, and the other contains custom state files used to setup the environment running this blog.

Breaking down the minion state

Within this second repository is a salt state file that installs and configures the salt-minion service. Let’s take a quick look at this state to understand how the salt-minion package is being installed.

salt-minion:
  pkgrepo:
    - managed
    - humanname: SaltStack Repo
    - name: deb http://repo.saltstack.com/apt/ubuntu/14.04/amd64/latest {{ grains['lsb_distrib_codename'] }} main
    - dist: {{ grains['lsb_distrib_codename'] }}
    - key_url: https://repo.saltstack.com/apt/ubuntu/14.04/amd64/latest/SALTSTACK-GPG-KEY.pub
  pkg:
    - latest
  service:
    - dead
    - enable: False

/etc/salt/minion.d/masterless.conf:
  file.managed:
    - source: salt://salt/config/etc/salt/minion.d/masterless.conf

/etc/cron.d/salt-standalone:
  file.managed:
    - source: salt://salt/config/etc/cron.d/salt-standalone

In the above state we can see that the Salt Apt repository is being added with the pkgrep module. The salt-minion package is being installed with the pkg module and the salt-minion service is being disabled by the service module.

We can also see that two files /etc/salt/minion.d/masterless.conf and /etc/cron.d/salt-standalone are being deployed. For this article, we will use this state as is to perform the initial salt-minion installation and configuration.

Setting up the master

As with the previous article we will use both of these repositories to setup our minion server. We will get started by first using git to clone these repositories into a directory within /srv/salt.

For the first repository, we will clone the contents into a base directory.

$ sudo git clone https://github.com/madflojo/salt-base.git /srv/salt/base
Cloning into '/srv/salt/base'...
remote: Counting objects: 54, done.
remote: Total 54 (delta 0), reused 0 (delta 0), pack-reused 54
Unpacking objects: 100% (54/54), done.
Checking connectivity... done.

The second repository we will clone into /srv/salt/bencane.

$ sudo git clone https://github.com/madflojo/blog-salt.git /srv/salt/bencane
Cloning into '/srv/salt/bencane'...
remote: Counting objects: 46, done.
remote: Total 46 (delta 0), reused 0 (delta 0), pack-reused 46
Unpacking objects: 100% (46/46), done.
Checking connectivity... done.

With all of the salt states now on our local system we can configure Salt to use these state files. To do this we will need to edit the /etc/salt/master configuration file.

$ sudo vi /etc/salt/master

Within the master file the file_roots configuration parameter is used to define where Salt’s state files are located on the master. Since we have two different locations for the two sets of state files we will specify them individually as their own item underneath file_roots.

file_roots:
  base:
    - /srv/salt/base
  bencane:
    - /srv/salt/bencane

With the above defined, we can now use our Salt states to setup a new minion server. To do this we will once again run salt-ssh but this time specifying the state.highstate task.

$ sudo salt-ssh 'blr1-001' -i state.highstate
----------
          ID: salt-minion
    Function: pkgrepo.managed
        Name: deb http://repo.saltstack.com/apt/ubuntu/14.04/amd64/latest trusty main
      Result: True
     Comment: Configured package repo 'deb http://repo.saltstack.com/apt/ubuntu/14.04/amd64/latest trusty main'
     Started: 21:18:54.462571
    Duration: 20440.965 ms
     Changes:   
              ----------
              repo:
                  deb http://repo.saltstack.com/apt/ubuntu/14.04/amd64/latest trusty main
----------
          ID: salt-minion
    Function: pkg.latest
      Result: True
     Comment: The following packages were successfully installed/upgraded: salt-minion
     Started: 21:19:14.903859
    Duration: 16889.713 ms
     Changes:   
              ----------
              dctrl-tools:
                  ----------
                  new:
                      2.23ubuntu1
                  old:
              salt-minion:
                  ----------
                  new:
                      2016.3.1+ds-1
                  old:
----------
          ID: salt-minion
    Function: service.dead
      Result: True
     Comment: Service salt-minion has been disabled, and is dead
     Started: 21:19:32.488449
    Duration: 133.722 ms
     Changes:   
              ----------
              salt-minion:
                  True
----------
          ID: /etc/salt/minion.d/masterless.conf
    Function: file.managed
      Result: True
     Comment: File /etc/salt/minion.d/masterless.conf updated
     Started: 21:19:32.626328
    Duration: 11.762 ms
     Changes:   
              ----------
              diff:
                  New file
              mode:
                  0644
----------
          ID: /etc/cron.d/salt-standalone
    Function: file.managed
      Result: True
     Comment: File /etc/cron.d/salt-standalone updated
     Started: 21:19:32.638297
    Duration: 4.049 ms
     Changes:   
              ----------
              diff:
                  New file
              mode:
                  0644

Summary
-------------
Succeeded: 37 (changed=23)
Failed:     0
-------------
Total states run:     37

From the results of the state.highstate task, we can see that 37 Salt states were verified and 23 of those resulted in changes being made. We can also see from the output of the command above that our salt-ssh execution just resulted in the installation and configuration of the salt-minion package.

If we wanted to verify that this is true even further we can use the cmd.run Salt module to execute the dpkg --list command.

$ sudo salt-ssh 'blr1-001' -i cmd.run "dpkg --list | grep salt"
blr1-001:
    ii  salt-common                        2016.3.1+ds-1                    all          shared libraries that salt requires for all packages
    ii  salt-minion                        2016.3.1+ds-1                    all          client package for salt, the distributed remote execution system

Summary

With the above, we can see that we were successfully able to install the salt-minion agent to a remote system via salt-ssh. While this may seem like quite a bit of work to setup for a single minion. The ability to install Salt with salt-ssh can be very useful when you are setting up multiple minions, as this same methodology works whether you’re installing Salt on 1 or 1,000 minions.

ansible vs saltstack速度测试

salt vs ansible
管理的机器数1500

time salt "*"  cmd.run "hostname"
real    0m3.983s
user    0m3.582s
sys     0m0.252s

time  salt '*' test.ping
real    0m3.856s
user    0m3.454s
sys     0m0.242s

time ansible ... -m ping
real    3m44.632s
user    2m9.356s
sys     1m25.901s

time ansible ... -m shell -a "hostname"
real    1m35.808s
user    1m50.635s
sys     1m26.378s


 

saltstack高效运维

salt介绍

saltstack是由thomas Hatch于2011年创建的一个开源项目,设计初衷是为了实现一个快速的远程执行系统。

salt强大吗

系统管理员日常会进行大量的重复性操作,例如安装软件,修改配置文件,创建用户,批量执行命令等等。如果主机数量庞大,单靠人工维护实在让人难以忍受。

早期运维人员会根据自己的生产环境来写特定脚本完成大量重复性工作,这些脚本复杂且难以维护。系统管理员面临的问题主要是1、系统配置管理,2、远程执行命令,因此诞生了很多开源软件,系统维护方面有fabric、puppet、chef、ansible、saltstack等,这些软件擅长维护系统状态或方便的对大量主机进行批量的命令执行。

salt灵活性强大,可以进行大规模部署,也能进行小规模的系统部署。salt的设计架构适用于任意数量的服务器,从少量本地网络系统到跨越数个数据中心,拓扑架构都是c/s模型,配置简单。

不管是几台、几百台、几千台服务器,都可以使用salt在一个中心节点上进行管控,灵活定位任意服务器子集来运行命令。

Salt是python编写的,支持用户通过python自定义功能模块,也提供了大量的python API接口,用户可以根据需要进行简单快速的扩展。

saltstack的运行方式

  • Local  本地运行,交付管理
  • Master/Minion   <<<   常用方式
  • Salt SSH   不需要客户端

salt部署基本架构

在安装salt之前,先理解salt架构中各个角色,主要区分是salt-master和salt-minion,顾名思义master是中心控制系统,minion是被管理的客户端。

salt架构中的一种就是master > minion。

在远程执行系统中,salt用python通过函数调用完成任务。

运行salt依赖包

复制代码
复制代码
python
zeromq
pyzmp
pycrypto
msgpack-python
yaml
jinja2
复制代码
复制代码

解决依赖包最简单的办法就是用安装包管理器,yum工具

服务器环境准备

服务器环境 centos7(master) centos7(master)
ip地址 192.168.178.131 192.168.178.132
身份 master slave
软件包 salt-master salt-minion

修改虚拟机ip地址为静态地址,并且确保可上网

 master网卡配置
 slave网卡配置
 dns配置文件
 /etc/hosts

 

关闭服务器安全策略

 关闭安全策略

安装saltstack

salt软件包需要epel源的支持,那么下载

EPEL的全称叫 Extra Packages for Enterprise Linux 。EPEL是由 Fedora 社区打造,为 RHEL 及衍生发行版如 CentOS、Scientific Linux 等提供高质量软件包的项目。装上了 EPEL之后,就相当于添加了一个第三方源。

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum clean all #清空缓存
yum makecache #生成yum缓存

安装好epel源就可以开始安装salt了

查看salt包
yum list salt

安装salt-master
yum install salt-master -y
安装salt-minion
yum install salt-minion -y

salt端口

安装好salt之后开始配置,salt-master默认监听两个端口:

4505   publish_port 提供远程命令发送功能
4506   ret_port     提供认证,文件服务,结果收集等功能
确保客户端可以通信服务器的此2个端口,保证防火墙允许端口通过。因此在测试环境直接关闭防火墙。

配置文件

salt-master的配置文件是/etc/salt/master
salt-minion的配置文件是/etc/salt/minion
配置文件中包含了大量可调整的参数,这些参数控制master和minion各个方面

配置salt-master

 常用配置解析

超哥的salt-master文件

复制代码
复制代码
[root@master ~]# grep -v ^# /etc/salt/master|grep -v ^$
interface: 0.0.0.0  #绑定到本地的0.0.0.0地址
publish_port: 4505  #管理端口,命令发送
user: root      #运行salt进程的用户
worker_threads: 5  #salt运行线程数,线程越多处理速度越快,不要超过cpu个数
ret_port: 4506  #执行结果返回端口
pidfile: /var/run/salt-master.pid #pid文件位置
log_file: /var/log/salt/master  #日志文件地址

#自动接收minion的key
auto_accept: False
复制代码
复制代码

复制代码
# minion的识别ID,可以是IP,域名,或是可以通过DNS解析的字符串
id: slave
 
# salt运行的用户权限
user: root
 
# master的识别ID,可以是IP,域名,或是可以通过DNS解析的字符串
master : master
 
# master通信端口
master_port: 4506
 
# 备份模式,minion是本地备份,当进行文件管理时的文件备份模式
backup_mode: minion
 
# 执行salt-call时候的输出方式
output: nested
 
# minion等待master接受认证的时间
acceptance_wait_time: 10
 
# 失败重连次数,0表示无限次,非零会不断尝试到设置值后停止尝试
acceptance_wait_time_max: 0
 
# 重新认证延迟时间,可以避免因为master的key改变导致minion需要重新认证的syn风暴
random_reauth_delay: 60
 
# 日志文件位置
log_file: /var/logs/salt_minion.log
复制代码

超哥的satl-minion文件

复制代码
复制代码
[root@slave ~]# grep -v ^# /etc/salt/minion|grep -v ^$
master: master
master_port: 4506
user: root
id: slave
acceptance_wait_time: 10
log_file: /var/log/salt/minion
复制代码
复制代码

 启动salt-master和salt-minion

复制代码
复制代码
systemctl start salt-minion
systemctl start salt-master

#检查salt状态
systemctl status salt-minion
systemctl status salt-master
复制代码
复制代码

在master上接收minion秘钥

在minion启动后连接master会请求master为其签发证书,等待证书签发完成后,master可以信任minion,并且minion和master之间的通信是加密的。

在salt-master执行

salt-key命令用于管理mionion秘钥

复制代码
复制代码
[root@master ~]# salt-key -L
Accepted Keys:
Denied Keys:
Unaccepted Keys:
slave    #此时已经出现slave
Rejected Keys:
复制代码
复制代码

此时slave已经出现在unaccepted keys中,说明minion已经和master联系,并且master已经获取了minion的公钥,等待下一步指令。

检查master和minion的秘钥匹配

在master上执行

[root@master ~]# salt-key -f slave
Unaccepted Keys:
slave:  0a:b9:97:b5:9a:65:b8:49:a1:50:a5:6a:66:ce:33:ea

然后可以在minion上获取minion的秘钥

[root@slave ~]# salt-call --local key.finger
local:
    0a:b9:97:b5:9a:65:b8:49:a1:50:a5:6a:66:ce:33:ea

因此可确认秘钥匹配,在master上接收秘钥

复制代码
复制代码
[root@master ~]# salt-key -a slave
The following keys are going to be accepted:
Unaccepted Keys:
slave
Proceed? [n/Y] y
Key for minion slave accepted.
复制代码
复制代码

确认接收秘钥后,检验minion秘钥是否被接收

复制代码
复制代码
[root@master ~]# salt-key -L
Accepted Keys:
slave
Denied Keys:
Unaccepted Keys:
Rejected Keys:
复制代码
复制代码

秘钥接收完成后,就可以执行第一条salt啦

salt-key

只有Master接受了Minion Key后,才能进行管理。具体的认证命令为salt-key常用的有如下命令。

复制代码
复制代码
[root@linux-node1 ~]# salt-key -L
Accepted Keys:  #已经接受的key
Denied Keys:    #拒绝的key
Unaccepted Keys:#未加入的key
Rejected Keys:#吊销的key

#常用参数
-L  #查看KEY状态
-A  #允许所有
-D  #删除所有
-a  #认证指定的key
-d  #删除指定的key
-r  #注销掉指定key(该状态为未被认证)

#在master端/etc/salt/master配置
auto_accept: True   #如果对Minion信任,可以配置master自动接受请求
复制代码
复制代码

salt-key的使用

复制代码
复制代码
#列出当前所有的key
[root@salt0-master ~]# salt-key 
Accepted Keys:
salt1-minion.example.com
salt2-minion.example.com
salt3-minion.example.com
salt4-minion.example.com
Denied Keys:
Unaccepted Keys:
Rejected Keys:

#添加指定minion的key
[root@salt0-master ~]# salt-key  -a salt1-minion.example.com -y
#添加所有minion的key
[root@salt0-master ~]# salt-key  -A  -y

#删除指定的key
[root@salt0-master ~]# salt-key -d salt1-minion.example.com -y
#删除所有的key
[root@salt0-master ~]# salt-key -D -y
复制代码
复制代码

 

 

 

日常命令参数

首先知道master和minion都安装了什么文件,然后才知道怎么操作

master端

rpm -ql salt-master
复制代码
复制代码
/etc/salt/master      # salt master主配置文件
/usr/bin/salt           #salt master 核心操作命令
/usr/bin/salt-cp       #salt 文件传输命令
/usr/bin/salt-key    #salt证书管理
/usr/bin/salt-master    #salt master 服务命令
/usr/bin/salt-run          #salt master runner命令
复制代码
复制代码

slave端

[root@slave  ~]$rpm -ql salt-minion
/etc/salt/minion     #minion配置文件
/usr/bin/salt-call    #拉取命令
/usr/bin/salt-minion   #minion服务命令
/usr/lib/systemd/system/salt-minion.service   #minion启动脚本

第一条salt命令

复制代码
复制代码
[root@master ~]# salt '*' test.ping
slave:
    True

# salt 是一个命令 
# * 表示目标主机, 在这里代表所有目标主机 
# test.ping是salt远程执行的一个模块下面的方法。
复制代码
复制代码

这是条很简单的探测minion主机存活命令,也是远程执行命令,我们通过master发送消息给”*”所有的minion,并且告诉他们运行salt内置的命令(也是python模块中的一个函数),返回true表示slave机器监控存活。

 

test模块实际上还有许多其他的函数

 test其他函数

测试下test.echo

[root@master 192.168.199.155 ~]$salt '*' test.echo 'chaoge nb666'
slave:
    chaoge nb666

test.fib生成斐波那契数列

菲波那切数列定义是第0项是0,第1项是1,数列从第3项开始,每一项等于前两项之和。

复制代码
复制代码
[root@master 192.168.199.155 ~]$salt '*' test.fib 50
slave:
    |_
      - 0
      - 1
      - 1
      - 2
      - 3
      - 5
      - 8
      - 13
      - 21
      - 34
    - 1.09672546387e-05
复制代码
复制代码

小结

此前在机器上安装了salt minion和salt master,进行了最简单的连接,然后master接受了minion的秘钥,运行了第一条test.ping命令

salt命令组成结构

在命令行输入的命令都是     执行模块

等到命令写入到文件中,             就叫做状态模块

salt --help #即可查看salt帮助

[root@master 192.168.199.155 ~]$salt –help
Usage: salt [options] ‘<target>’ <function> [arguments]

salt命令 参数 目标 salt模块的函数 远程执行的参数

完整的五部分命令

复制代码
复制代码
#--summary参数显示salt命令的概要
[root@master 192.168.199.155 ~]$salt --summary '*' cmd.run 'hostname'
slave:
    slave


-------------------------------------------
Summary
-------------------------------------------
# of Minions Targeted: 1
# of Minions Returned: 1
# of Minions Did Not Return: 0
-------------------------------------------
复制代码
复制代码

列出所有salt的sys模块

#与系统交互的sys模块
[root@master 192.168.11.72 ~]$salt 'slave' sys.list_modules

远程执行命令模块

cmd是超级模块,所有shell命令都能执行

复制代码
复制代码
[root@master 192.168.11.72 ~]$salt 'slave' cmd.run 'ps -ef|grep python'
slave:
    root        905      1  0 07:31 ?        00:00:02 /usr/bin/python -Es /usr/sbin/tuned -l -P
    root       3843      1  0 11:05 ?        00:00:00 /usr/bin/python /usr/bin/salt-minion
    root       3846   3843  0 11:05 ?        00:00:01 /usr/bin/python /usr/bin/salt-minion
    root       4031      1  0 11:31 ?        00:00:00 /usr/bin/python /usr/bin/salt-minion
    root       4032   4031  0 11:31 ?        00:00:00 /bin/sh -c ps -ef|grep python
    root       4034   4032  0 11:31 ?        00:00:00 grep python
复制代码
复制代码

 

 

远程安装nginx

复制代码
复制代码
#在minion上安装nginx
[root@master 192.168.11.72 ~]$salt 'slave' pkg.install "nginx"
#卸载minion上的nginx
[root@master 192.168.11.72 ~]$salt 'slave' pkg.remove "nginx"
#检查pkg包的版本
[root@master 192.168.11.72 ~]$salt 'slave' pkg.version "nginx"
复制代码
复制代码

远程管理服务模块

管理服务是系统管理员的重要任务,通过salt管理minion服务会很简单,使用service模块

复制代码
复制代码
[root@master 192.168.11.72 ~]$salt 'slave' service.start "nginx"
slave:
    True
[root@master 192.168.11.72 ~]$salt 'slave' service.status "nginx"
slave:
    True
[root@master 192.168.11.72 ~]$salt 'slave' service.stop "nginx"
slave:
    True
复制代码
复制代码

与标准的Linux命令一样,salt的命令一样用法

–out控制salt命令结果输出的格式

JSON

复制代码
复制代码
[root@master 192.168.199.155 ~]$salt --out=json '*' cmd.run_all 'hostname'
{
    "slave": {
        "pid": 2268,
        "retcode": 0,
        "stderr": "",
        "stdout": "slave"
    }
}
复制代码
复制代码

YAML

复制代码
复制代码
[root@master 192.168.199.155 ~]$salt --out=yaml '*' cmd.run_all 'hostname'
slave:
  pid: 2289
  retcode: 0
  stderr: ''
  stdout: slave
复制代码
复制代码

YAML讲解

复制代码
复制代码
在学习saltstack过程中,第一要点就是States编写技巧,简称SLS文件。这个文件遵循YAML语法。初学者看这玩意很容易懵逼,来,超哥拯救你学习YAML语法
json xml yaml 数据序列化格式
yaml容易被解析,应用于配置文件

salt的配置文件是yaml配置文件,不能用tab
saltstack,k8s,ansible都用的yaml格式配置文件


语法规则
    大小写敏感
    使用缩进表示层级关系   
    缩进时禁止tab键,只能空格
    缩进的空格数不重要,相同层级的元素左侧对其即可
    # 表示注释行
yaml支持的数据结构
    对象: 键值对,也称作映射 mapping 哈希hashes 字典 dict    冒号表示 key: value   key冒号后必须有
    数组: 一组按次序排列的值,又称为序列sequence 列表list     短横线  - list1
    纯量: 单个不可再分的值

对象:键值对
yaml
    first_key:
      second_key:second_value

python
    {
        'first_key':{
            'second_key':'second_value',
        }
    }
复制代码
复制代码

 

YAML是YAML Ain't Markup Language的首字母缩写,YAML的语法简单,
结构体通过空格展示
项目使用 '-' 代表
键值对通过 ':' 分割
YAML语法遵循固定的缩进风格,表示数据层级结构关系,saltstack需要每个缩进级别由2个空格组成,禁止用tabs!!!
复制代码
复制代码
Python中的字典是简单的键值对,go语言中称作哈希表map
字典的key通过冒号分割

key在YAML中表现形式是一个冒号结果的字符串
my_key: my_value
转化到python语法中,上述命令为
{'my_key':'my_value'}

value还可以通过缩进和key关联,四个空格!!
my_key:
    my_value 
转化为python语法同样的
{'my_key':'my_value'}

YAML语法中字典是可以嵌套的
one_dict_key:
    two_dict_key:value_dict
转化为python语法

{
‘one_dict_key’:{
‘two_dict_key’:’value_dict’
}
}

复制代码
复制代码
复制代码
复制代码
短横杠
YAML语法表示列表,使用一个横杠加一个空格
多个项使用同样的缩进级别作为同一个列表的部分
- list_value_one
- list_value_two
- list_value_three
列表可以作为一个键值对的value,例如一次性要安装多个软件
my_dict:
  - l1
  - l2
  - l3
转化为python代码理解就是

{
‘my_dict’:[‘l1′,’l2’,;l3]
}

复制代码
复制代码

 目标定位字符串

之前的salt命令我们都是使用 salt ‘*’控制所有minion,并且我们只有一个“slave”,但是生产环境的服务器很可能是成千上百的minion,因此需要灵活地定位所需的服务器并且执行远程命令。

 

1.全局匹配
[root@master 192.168.11.72 ~]$salt '*' test.ping
slave:
    True
复制代码
复制代码
Linux通配符
*               代表任意字符,或空字符串
?               代表一个字符,不可以为空
[a-z] [0-9]     代表任何一个小写字母

[root@master 192.168.11.72 ~]$salt 'slav?' test.ping
slave:
    True

[root@master 192.168.11.72 ~]$salt '[a-z]lave' test.ping
slave:
    True            
salt海支持python的re正则表达式
复制代码
复制代码

state模块定义主机状态

之前执行的远程命令,都是一个过程式的,类似一段shell或者python脚本执行,执行一次触发一次相同的功能。

那么大量的minion上运行远程命令就必须使用salt提供的“状态管理”了,状态是对minion的一种描述和定义,运维不需要关心部署是如何完成的,只需要描述minion需要达到什么状态。

接下来通过state模块部署nginx

master端

复制代码
复制代码
vim /etc/salt/master 
#打开注释,写入以下,必须严格遵循语法,空格
file_roots:
  base:
    - /srv/salt/base
 dev:
   - /srv/salt/dev
 test:
   - /srv/salt/test
 prod:
   - / srv/salt/prod

#此步骤在master和minion都需要执行,都需要文件夹,和nginx.sls文件
[root@master  ~]$mkdir -p /srv/salt/{base,dev,test,prod}

[root@slave   ~]$mkdir -p /srv/salt/{base,dev,test,prod}

复制代码
复制代码
复制代码
复制代码
#这个nginx.sls状态文件,在master和minion上都得有
[root@master /srv/salt/base]$cat nginx.sls
nginx-install:
  pkg.installed:
    - name: nginx

nginx-service:
  service.running:
    - name: nginx
    - enable: True
复制代码
复制代码
解释下nginx.sls描述文件
sls配置文件都遵循YAML语言描述
第一条命令使用了pkg.install安装命令,相对于运行了yum install,而此时state模块会判断nginx是否安装了,如果没有安装就进行安装,安装了就什么都不做。
状态描述都会遵循这个原则,只有检测到真实状态和所需状态不一就会执行此功能,这种性质叫做幂等性。

此时用state模块部署nginx软件,通过我们编写的nginx.sls描述性配置文件,命令行调用state模块的sls函数。

#启动命令,此时slave已经安装且存活了nginx,进行状态管理
[root@master  /srv/salt/base]$salt 'slave' state.sls nginx

可以去slave测试关闭nginx,删除nginx,重新执行命令,一样可以安装启动nginx

通过master检查slave的nginx状态

复制代码
复制代码
[root@master 192.168.199.155 /srv/salt/base]$salt 'slave' cmd.run 'ps -ef|grep nginx'
slave:
    root       8543      1  0 Sep14 ?        00:00:00 nginx: master process /usr/sbin/nginx
    nginx      8544   8543  0 Sep14 ?        00:00:00 nginx: worker process
    root       8592   8591  0 00:03 ?        00:00:00 /bin/sh -c ps -ef|grep nginx
    root       8594   8592  0 00:03 ?        00:00:00 /bin/sh -c ps -ef|grep nginx
复制代码
复制代码

Salt采集静态信息之Grains

如果你入职了,你的老板让你收集公司300台服务器的相关硬件信息,你是一台台登录呢?还是选择用salt收集呢?又或者用python的salt-api写脚本呢

复制代码
复制代码
Grains 是saltstack组件中非常重要之一,在配置部署时候回经常使用,Grains记录minion的静态信息,比如常用属性,CPU、内存、磁盘、网络信息等。
Minions的Grains信息是Minion启动时采集汇报给Master的
Grains是以 key  value形式存储的数据库,可以看做Host的元数据(metadata)
Grains保存着收集到的客户端的详细信息
如果slave机器数据变化,grains就过期了
在生产环境中需要自定义Grains,可以通过
Minion配置文件
Grains相关模块定义
Python脚本定义

salt 'slave' sys.doc grains#查看grains的命令用法
复制代码
复制代码

Grains

复制代码
复制代码
Grains人为是描述minion本身固有的静态属性数据,列出主机所有Grains数据

[root@master 192.168.11.72 ~]$salt ‘slave’ grains.items
slave:
———-
SSDs:
biosreleasedate:
05/19/2017
biosversion:
6.00

信息过长,已经省略

salt ‘slave’ grains.ls  #列出所有grains方法

复制代码
复制代码

检索某些数据

复制代码
复制代码
[root@master 192.168.11.72 ~]$salt 'slave' grains.item os id host
slave:
    ----------
    host:
        slave
    id:
        slave
    os:
        CentOS
复制代码
复制代码

利用Grains静态信息定位主机

超哥以前公司有100+的redhat操作系统,80+的centos,在不知道salt之前很是懵逼。。

除了系统的不同,还有不同的系统版本,redhat6.x centos6.x..

复制代码
复制代码
两种写法:
salt '*' grains.item key1 key2 key3
salt '*' -G

#定位Cenots的机器
[root@master 192.168.11.72 ~]$salt -G 'os:CentOS' test.ping
slave:
    True
#定位操作系统系统是7系列的机器

[root@master 192.168.11.72 ~]$salt -G ‘osrelease:7*’ test.ping
slave:
True

#找出ip地址

salt ‘*’ grains.item fqdn_ip4

复制代码
复制代码

因此用grains.items列出所有的数据匹配主机,以及根据单一信息定位数据,Grains还可以自定义来满足不同的需求。

自定义设置Grains数据

复制代码
复制代码
#设置数据
[root@master 192.168.11.72 ~]$salt 'slave' grains.setval cpu_num 8
slave:
    ----------
    cpu_num:
        8
#查询数据
[root@master 192.168.11.72 ~]$salt 'slave' grains.item cpu_num
slave:
    ----------
    cpu_num:
        8
复制代码
复制代码

在master端设置Grains静态数据,原理会将此数据添加到minion服务器的配置文件的/etc/salt/grains

[root@slave 192.168.11.71 ~]$cat /etc/salt/grains
cpu_num: 8

对于复杂的数据结构,可以添加灵活的JSON语法

复制代码
复制代码
[root@master 192.168.11.72 ~]$salt 'slave' grains.setval cpu_info '["Intel","Xeon","10"]'
slave:
    ----------
    cpu_info:
        - Intel
        - Xeon
        - 10
[root@master 192.168.11.72 ~]$salt 'slave' grains.item cpu_info
slave:
    ----------
    cpu_info:
        - Intel
        - Xeon
        - 10
复制代码
复制代码

此时可以检查minion服务器上的grains文件

复制代码
复制代码
[root@slave 192.168.11.71 ~]$cat /etc/salt/grains
cpu_info:
- Intel
- Xeon
- '10'
cpu_num: 8
复制代码
复制代码

因此Grains数据写入配置文件后,重启salt-minion服务,数据也不会丢失

想要删除可以通过grains.delval命令删除,或者去minion的配置文件删除配置一样完成操作(或者删除文件)

复制代码
复制代码
1.方法一,清空值
[root@master 192.168.11.72 ~]$salt 'slave' grains.delval cpu_info
slave:
    None
[root@master 192.168.11.72 ~]$salt 'slave' grains.delval cpu_num
slave:
    None

2.方法二 删除minion的grains配置文件,重启服务

[root@slave 192.168.11.71 ~]$rm -rf /etc/salt/grains
[root@slave 192.168.11.71 ~]$!sys
systemctl restart salt-minion

检查结果删除成功
复制代码
复制代码

 数据管理中心之Pillar组件

Pillar也是saltstack组件中非常重要的组件之一,称作数据管理中心,经常配合states在大规模的配置管理中使用。

Pillar是动态的,存储在master端,提供和给minion端

Pillar在SaltStack中主要的作用是存储和定义配置管理中需要的一些数据,比如软件版本号,用户账号密码等,保证敏感数据不被其他minion看到

存储格式与Grains类似,都是YAML格式

在master配置文件中有一段Pillar settings选项专门定义Pillar的参数

 

cat /etc/salt/master  
#此配置代表pillar的工作根目录,在/srv/pillar下,然后可以新建sls文件
#pillar_roots:
#  base:
#    - /srv/pillar

默认pillar的工作目录在/srv/pillar目录下,执行如下代码

复制代码
复制代码
mkdir -p /srv/pillar
#指定环境,标记,引用packages.sls和services.sls
vim /srv/pillar/top.sls
base:
  '*':
      - packages
      - services
vim /srv/pillar/packages.sls
nginx:
    packages-name: nginx
    version: 1.12.2

vim /srv/pillar/packages.sls
nginx:
    port: 80
    user: root

复制代码
复制代码

检查我们设置的pillar值

复制代码
复制代码
[root@master 192.168.199.155 /srv/pillar]$salt '*' pillar.item nginx
slave:
    ----------
    nginx:
        ----------
        packages-name:
            nginx
        port:
            80
        user:
            root
        version:
            1.12.2
复制代码
复制代码

Pillar与Grains对比

pillar与Grains对比

类型     数据采集方式   应用场景                   定义位置
Grains   静态         minion启动时收集  数据查询  目标选择  配置管理   minion
Pillar   动态         master进行自定义  目标选择  配置管理  敏感数据   master

Python API调用SaltStack

SaltStack本身提供salt(usr/bin/salt)来交互管理,但是去服务器上敲命令肯定不是一个长远之计,这时候python就体现了nb的功能。

Python API就是给Python提供的API使用,需要在SaltStack master上运行

实例代码

复制代码
复制代码
[root@master  ~]$python
Python 2.7.5 (default, Jul 13 2018, 13:06:57)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import salt.client
>>> local = salt.client.LocalClient()  #<salt.client.LocalClient object at 0x7f886dbdd850>
>>> local.cmd('*','cmd.run',['hostname'])#向所有minion发送命令
{'slave': 'slave'}
复制代码
复制代码

因此python API就是提供了向saltstack发送命令的入口。

通过API获取saltstack的配置文件

获取master配置文件

>>> import salt.config #导入salt配置模块
>>> m_opts=salt.config.client_config('/etc/salt/master') #读取salt配置文件,得到一个字典数据

获取minion配置文件

复制代码
复制代码
Python 2.7.5 (default, Jul 13 2018, 13:06:57)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import salt.client
>>> salt.config.minion_config('/etc/salt/minion') #读取minion配置文件,得到字典数据,通过字典方法可以查看信息
复制代码
复制代码

Python API介绍

复制代码
复制代码
/usr/bin/salt默认使用的接口是LocalClient,该接口只能在salt master上使用
[root@master  ~]$python
Python 2.7.5 (default, Jul 13 2018, 13:06:57)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import salt.client
>>> local = salt.client.LocalClient()  #<salt.client.LocalClient object at 0x7f886dbdd850>
>>> local.cmd('*','cmd.run',['hostname'])#向所有minion发送命令
{'slave': 'slave'}
复制代码
复制代码

逐条返回结果,local.cmd_iter()

复制代码
复制代码
>>> ret=local.cmd_iter('*','test.ping')
>>> ret
<generator object cmd_iter at 0x7f886d455c80>
>>> for i in ret:
...     print i
...
{'slave': {'retcode': 0, 'ret': True}}
复制代码
复制代码

菲波那切数列

>>> local.cmd('*','test.fib',[10])
{'slave': [[0, 1, 1, 2, 3, 5, 8], 2.1457672119140625e-06]}

检查minion服务器信息

>>> local.cmd('*','cmd.run',['hostname'])
{'slave': 'slave'}
>>> local.cmd('*','cmd.run',['ifconfig'])
>>> local.cmd('*','cmd.run',['crontab -l'])
>>> local.cmd('*','cmd.run',['df -h'])

启停minion的服务,如nginx

复制代码
复制代码
>>> local.cmd('*','service.stop',['nginx'])
{'slave': True}
>>> local.cmd('*','service.status',['nginx'])
{'slave': False}
>>> local.cmd('*','service.start',['nginx'])
{'slave': True}
复制代码
复制代码