设为首页收藏本站

追梦Linux

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 931|回复: 0

【Saltstack】saltstack-api基础使用

[复制链接]

482

主题

485

帖子

16万

积分

CEO

Rank: 9Rank: 9Rank: 9

积分
169037

最佳新人活跃会员热心会员推广达人宣传达人灌水之王突出贡献优秀版主荣誉管理论坛元老

QQ
发表于 2018-6-1 11:56:33 | 显示全部楼层 |阅读模式
salt环境:master、minion、api均在一台机器:192.168.2.192,python3.6

安装Master、monion等服务:
[Bash shell] 纯文本查看 复制代码
yum install salt-master salt-minion salt-ssh  salt-syndic salt-cloud -y

设置服务自启并启动
[Bash shell] 纯文本查看 复制代码
systemctl enable salt-master
systemctl enable salt-minion
systemctl start salt-master
systemctl start salt-master

配置Master、minion,默认全注释的,这里只做简单配置
/etc/salt/master 添加本地ip、user、auto_accept自动接收minion的key ,该项默认的话,minion配置完成后需要手动执行salt-key -a minion-01 将minion-01 加进来。

[Bash shell] 纯文本查看 复制代码
master: 192.168.2.192
user: root
auto_accept :True 

/etc/salt/minion 添加Master端ip、本机标识id、user
[Bash shell] 纯文本查看 复制代码
interface: 192.168.2.192
id: minion-01
user: root

配置完成重启Master、minion

执行简单命令以做验证
[Bash shell] 纯文本查看 复制代码
# salt 'minion-01' test.ping
minion-01:
    True
# salt 'minion-01' cmd.run 'ip addr'
minion-01:
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
        link/ether 00:0c:29:98:2e:3c brd ff:ff:ff:ff:ff:ff
        inet 192.168.2.192/24 brd 192.168.2.255 scope global ens33
           valid_lft forever preferred_lft forever
        inet 192.168.2.196/24 scope global secondary ens33
           valid_lft forever preferred_lft forever
        inet6 fe80::4a0f:de95:9761:a31c/64 scope link 
           valid_lft forever preferred_lft forever
    3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
        link/ether 02:42:22:d2:1b:3c brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 scope global docker0
           valid_lft forever preferred_lft forever

以上则表示OK,下面开始Api


salt-api介绍
saltsatck本身就提供了一套算完整的api,使用 CherryPy 来实现 restful 的 api,供外部的程序调用。
salt-api安装
salt-api需要安装,然后进行一些配置才可以正常使用,安装方法有两种。
salt环境:
方法一:
yum安装,需要的依赖包cherry也会被补全装上。
安装salt-api,并设置开机启动
[Bash shell] 纯文本查看 复制代码
yum -y install salt-api pyOpenSSL 
systemctl enable salt-api

方法二:
pip安装,首先要确认机器上有没有安装pip模块。
[Bash shell] 纯文本查看 复制代码
rpm -ivh [url=https://mirrors.aliyun.com/epel/7/x86_64/s/salt-api-2015.5.10-2.el7.noarch.rpm]https://mirrors.aliyun.com/epel/ ... 10-2.el7.noarch.rpm[/url]
pip install cherrypy==3.2.3
pip install cherrypy
pip install salt-api

配置自签名证书
[Bash shell] 纯文本查看 复制代码
cd /etc/pki/tls/certs/
make testcert



Enter pass phrase:    ===>  输入加密短语,这里我使用salt2018
Verifying - Enter pass phrase:    ===>  确认加密短语
umask 77 ; \
/usr/bin/openssl req -utf8 -new -key /etc/pki/tls/private/localhost.key -x509 -days 365 -out /etc/pki/tls/certs/localhost.crt -set_serial 0
Enter pass phrase for /etc/pki/tls/private/localhost.key:    ===>  再次输入相同的加密短语
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:BeiJing
Locality Name (eg, city) [Default City]:BeiJing
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:

解密key文件,生成无密码的key文件, 过程中需要输入key密码,该密码为之前生成证书时设置的密码
[Bash shell] 纯文本查看 复制代码
cd /etc/pki/tls/private/
openssl rsa -in localhost.key -out localhost_nopass.key
修改文件权限
[Bash shell] 纯文本查看 复制代码
chmod 755 /etc/pki/tls/certs/localhost.crt 
chmod 755 /etc/pki/tls/private/localhost.key 
chmod 755 /etc/pki/tls/private/localhost_nopass.key

添加用户
生产环境请使用密码复杂度高的密码,这里我使用salt2018
[Bash shell] 纯文本查看 复制代码
useradd -M -s /sbin/nologin saltapi
passwd saltapi  

配置salt-api
修改/etc/salt/master文件
[Bash shell] 纯文本查看 复制代码
sed -i '/#default_include/s/#default/default/g' /etc/salt/master

创建/etc/salt/master.d/目录,编辑eauth.conf,添加下面内容
[Bash shell] 纯文本查看 复制代码
mkdir -p /etc/salt/master.d/
cd /etc/salt/master.d/
touch eauth.conf
touch api.conf

cat eauth.conf
external_auth:
  pam:
    saltapi:   # 用户
      - .*     # 该配置文件给予saltapi用户所有模块使用权限,出于安全考虑一般只给予特定模块使用权限
      - '@wheel'
      - '@runner'

编辑api.conf,添加下面内容
[Bash shell] 纯文本查看 复制代码
rest_cherrypy:
  port: 8001
  ssl_crt: /etc/pki/tls/certs/localhost.crt
  ssl_key: /etc/pki/tls/private/localhost_nopass.key
[Bash shell] 纯文本查看 复制代码
# 备注:
    注意所有的缩进都是两个空格,要注意':'后面都有一个空格,不使用SSL的话把ss_crt、ssl_key注释掉即可。
  

# salt-api 配置文件详解
port : 必须填写,salt-api启动的端口
host :默认启动于0.0.0.0,可以不填写
debug : 默认为False,True开启后,会输出debug日志
log_access_file : HTTP访问日志的路径,在2016.11.0版本添加的
log_error_file : HTTP错误日志路径,在2016.11.0版本添加的
ssl_crt : SSL证书的绝对路径
ssl_key: SSK证书的私钥绝对路径
ssl_chain : 在使用PyOpenSSL时可选参数,将证书出递给' Context.load_verify_locations '
disable_ssl : 禁用SSL标识。认证证书将会被送进clear
webhook_disable_auth : False
webhook_url : /hook
thread_pool : 100
socket_queue_size : 30
expire_responses : True
max_request_body_size : 1048576
collect_stats : False
stats_disable_auth : False

更多详细参数请见:https://github.com/saltstack/sal ... est_cherrypy/app.py
启动salt-api
[Bash shell] 纯文本查看 复制代码
systemctl restart salt-master
systemctl start salt-api
ps -ef|grep salt-api
netstat -lnput|grep 8001

验证服务
获得token
[Bash shell] 纯文本查看 复制代码
curl -k [url=https://192.168.2.192:8001/login]https://192.168.2.192:8001/login[/url] -H "Accept: application/x-yaml"  -d username='saltapi'  -d password='salt2018'  -d eauth='pam'

返回如下
[Bash shell] 纯文本查看 复制代码
- eauth: pam
  expire: 1527868401.215029
  perms:
  - .*
  - '@wheel'
  - '@runner'
  start: 1527825201.215028
  token: d2db4945feb5bf33b80e1bd18530830695a6a894
  user: saltapi

调用test.ping
[Bash shell] 纯文本查看 复制代码
curl -k [url=https://192.168.2.192:8001/]https://192.168.2.192:8001/[/url] -H "Accept: application/x-yaml" -H "X-Auth-Token: d2db4945feb5bf33b80e1bd18530830695a6a894" -d client='local' -d tgt='*' -d fun='test.ping' 
return:
- minion-01: true
[Bash shell] 纯文本查看 复制代码
参数解释:
client : 模块,python处理salt-api的主要模块,‘client interfaces <netapi-clients>’
    local : 使用‘LocalClient <salt.client.LocalClient>’ 发送命令给受控主机,等价于saltstack命令行中的'salt'命令
    local_async : 和local不同之处在于,这个模块是用于异步操作的,即在master端执行命令后返回的是一个jobid,任务放在后台运行,通过产看jobid的结果来获取命令的执行结果。
    runner : 使用'RunnerClient<salt.runner.RunnerClient>' 调用salt-master上的runner模块,等价于saltstack命令行中的'salt-run'命令
    runner_async : 异步执行runner模块
    wheel : 使用'WheelClient<salt.wheel.WheelClient>', 调用salt-master上的wheel模块,wheel模块没有在命令行端等价的模块,但它通常管理主机资源,比如文件状态,pillar文件,salt配置文件,以及关键模块<salt.wheel.key>功能类似于命令行中的salt-key。
    wheel_async : 异步执行wheel模块
    备注:一般情况下local模块,需要tgt和arg(数组),kwarg(字典),因为这些值将被发送到minions并用于执行所请求的函数。而runner和wheel都是直接应用于master,不需要这些参数。
tgt : minions
fun : 函数
arg : 参数
expr_form : tgt的匹配规则
    'glob' - Bash glob completion - Default
    'pcre' - Perl style regular expression
    'list' - Python list of hosts
    'grain' - Match based on a grain comparison
    'grain_pcre' - Grain comparison with a regex
    'pillar' - Pillar data comparison
    'nodegroup' - Match on nodegroup
    'range' - Use a Range server for matching
    'compound' - Pass a compound match string
至此salt-api配置完成。

编写python脚本请求salt api接口自定义一个类,首先初始化时候获得token,然后使用token认证去请求相应的json文件。
salt命令在shell中使用方式是salt 客户端 方法 参数(例子:salt 'minion-01' cmd.run 'free -m')
这里salt命令方法我们已经封装好了,想使用salt的什么方法就传入对应的客户端、方法、参数即可。
代码如下:
[Bash shell] 纯文本查看 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/5/29 17:37
# @Author  : hardyxia
# @File    : salt_api.py

import requests
import json

try:
    import cookielib
except:
    import http.cookiejar as cookielib

# 使用urllib2请求https出错,做的设置
import ssl

context = ssl._create_unverified_context()

# 使用requests请求https出现警告,做的设置
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

salt_api = "https://192.168.2.192:8001/"


class SaltApi:
    """
    定义salt api接口的类
    初始化获得token
    """

    def __init__(self, url):
        self.url = url
        self.username = "saltapi"
        self.password = "salt2018"
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36",
            "Content-type": "application/json"
            # "Content-type": "application/x-yaml"
        }
        self.params = {'client': 'local', 'fun': '', 'tgt': ''}
        # self.params = {'client': 'local', 'fun': '', 'tgt': '', 'arg': ''}
        self.login_url = salt_api + "login"
        self.login_params = {'username': self.username, 'password': self.password, 'eauth': 'pam'}
        self.token = self.get_data(self.login_url, self.login_params)['token']
        self.headers['X-Auth-Token'] = self.token

    def get_data(self, url, params):
        send_data = json.dumps(params)
        request = requests.post(url, data=send_data, headers=self.headers, verify=False)
        # response = request.text
        # response = eval(response)     使用x-yaml格式时使用这个命令把回应的内容转换成字典
        # print response
        # print request
        # print type(request)
        response = request.json()
        result = dict(response)
        # print(result)
        return result['return'][0]

    def salt_command(self, tgt, method, arg=None):
        """远程执行命令,相当于salt 'client1' cmd.run 'free -m'"""
        if arg:
            params = {'client': 'local', 'fun': method, 'tgt': tgt, 'arg': arg}
        else:
            params = {'client': 'local', 'fun': method, 'tgt': tgt}
        print('命令参数: ', params)

        result = self.get_data(self.url, params)
        return result

    def salt_async_command(self, tgt, method, arg=None):  # 异步执行salt命令,根据jid查看执行结果
        """远程异步执行命令"""
        if arg:
            params = {'client': 'local_async', 'fun': method, 'tgt': tgt, 'arg': arg}
        else:
            params = {'client': 'local_async', 'fun': method, 'tgt': tgt}
        jid = self.get_data(self.url, params)['jid']
        return jid

    def look_jid(self, jid):  # 根据异步执行命令返回的jid查看事件结果
        params = {'client': 'runner', 'fun': 'jobs.lookup_jid', 'jid': jid}
        print(params)

        result = self.get_data(self.url, params)
        return result


def main():
    print('同步执行命令')
    salt = SaltApi(salt_api)
    print('token :', salt.token)

    salt_client = '*'
    salt_test = 'test.ping'
    salt_method = 'cmd.run'
    salt_params = 'df -h'

    # 下面只是为了打印结果好看点
    result1 = salt.salt_command(salt_client, salt_test)
    for i in result1.keys():
        print('主机', i, ': ', result1[i])

    result2 = salt.salt_command(salt_client, salt_method, salt_params)

    for i in result2.keys():
        print(i)
        print(result2[i])


def async_main():
    print('异步执行命令')

    salt1 = SaltApi(salt_api)
    salt_client = '*'
    salt_test = 'test.ping'
    salt_method = 'cmd.run'
    salt_params = 'df -hT'
    # 下面只是为了打印结果好看点
    jid1 = salt1.salt_async_command(salt_client, salt_test)
    result1 = salt1.look_jid(jid1)
    for i in result1.keys():
        print(i, ': ', result1[i])

    jid2 = salt1.salt_async_command(salt_client, salt_method, salt_params)
    result2 = salt1.look_jid(jid2)
    for i in result2.keys():
        print(i)
        print(result2[i])


if __name__ == '__main__':
    main()
    async_main()

执行结果如下:
[Bash shell] 纯文本查看 复制代码
同步执行命令
token : d32442fa4522b813a7172a20367b477b43384107
命令参数:  {'client': 'local', 'fun': 'test.ping', 'tgt': '*'}
主机 minion-01 :  True
命令参数:  {'client': 'local', 'fun': 'cmd.run', 'tgt': '*', 'arg': 'df -h'}
minion-01
Filesystem           Size  Used Avail Use% Mounted on
/dev/mapper/cl-root   17G  5.1G   12G  30% /
devtmpfs             901M     0  901M   0% /dev
tmpfs                912M   16K  912M   1% /dev/shm
tmpfs                912M   89M  823M  10% /run
tmpfs                912M     0  912M   0% /sys/fs/cgroup
/dev/sda1           1014M  214M  801M  22% /boot
/dev/sdb1            3.0G  169M  2.9G   6% /var/lib/ceph/osd/ceph-1
tmpfs                183M     0  183M   0% /run/user/0
异步执行命令
{'client': 'runner', 'fun': 'jobs.lookup_jid', 'jid': '20180601004114928856'}
minion-01 :  True
{'client': 'runner', 'fun': 'jobs.lookup_jid', 'jid': '20180601004119117398'}
minion-01
Filesystem          Type      Size  Used Avail Use% Mounted on
/dev/mapper/cl-root xfs        17G  5.1G   12G  30% /
devtmpfs            devtmpfs  901M     0  901M   0% /dev
tmpfs               tmpfs     912M   16K  912M   1% /dev/shm
tmpfs               tmpfs     912M   89M  823M  10% /run
tmpfs               tmpfs     912M     0  912M   0% /sys/fs/cgroup
/dev/sda1           xfs      1014M  214M  801M  22% /boot
/dev/sdb1           xfs       3.0G  169M  2.9G   6% /var/lib/ceph/osd/ceph-1
tmpfs               tmpfs     183M     0  183M   0% /run/user/0




小黑屋|手机版|Archiver|追梦Linux    点击这里给我发消息

GMT+8, 2021-6-20 04:46 , Processed in 0.772000 second(s), 31 queries .

Powered by 追梦Linux! X3.3 Licensed

© 2015-2017 追梦Linux!.

快速回复 返回顶部 返回列表