saltstack的api安装以及使用解释

Posted 抛物线.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了saltstack的api安装以及使用解释相关的知识,希望对你有一定的参考价值。

首先,贴上官方地址:https://docs.saltstack.cn/

salt,一种全新的基础设施管理方式,部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯。
salt底层采用动态的连接总线, 使其可以用于编配, 远程执行, 配置管理等等.

一、什么是saltstack
什么是saltstack

• Saltstack是基于python开发的一套C/S架构配置管理工具

• 使用SSL证书签方的方式进行认证管理

• 底层使用ZeroMQ消息队列pub/sub方式通信

    – 号称世界上最快的消息队列ZeroMQ能快速在成千上万台主机上进行各种操作

    – 采用RSA Key方式确认身

Salt 是:

一个配置管理系统,能够维护预定义状态的远程节点(比如,确保指定的报被安装,指定的服务在运行)

一个分布式远程执行系统,用来在远程节点(可以是单个节点,也可以是任意规则挑选出来的节点)

上执行命令和查询数据

开发其的目的是为远程执行提供最好的解决方案,并使远程执行变得更好,更快,更简单

既要考虑大规模部署,又要考虑小规模系统,提供适应多种场合的应用让人沮丧,但Salt非常容易设置和维护,

而不用考虑项目的大小。从数量可观的本地网络系统,到跨数据中心的互联网部署,

Salt设计为在任意数量的server下都可工作。

salt的拓扑使用简单的server/client模式,需求的功能内建在一组daemon中。

salt在几乎不改动配置的情况下就可以工作,也可以调整从而满足特定的需求。
二、官网的介绍:

Salt的核心功能:

  • 使命令发送到远程系统是并行的而不是串行的

  • 使用安全加密的协议

  • 使用最小最快的网络载荷

  • 提供简单的编程接口

  • Salt同样引入了更加细致化的领域控制系统来远程执行,使得系统成为目标不止可以通过主机名,还可以通过系统属性。

三、主要功能
主要功能

• Saltstack最主要的两个功能是:配置管理与远程执行

• Saltstack不只是一个配置管理工具,还是一个云计算与数据中心架构编排的利器

• Saltstack已经支持Docker相关模块

• 在友好地支持各大云平台之后,配合Saltstack的Mine实时发现功能可以实现各种云平台业务的自动扩展
四、Saltstack架构
• Saltstack基于C/S架构

    – 服务器端称作Master

    – 客户端称作Minion

• 可以实现传统处理方式,即:客户端发送请求给服务器,服务器收到请求后处理请求,再将结果返回

• 也可以使用消息队列中的发布与订阅(pub/sub)服务模式

五、Saltstack工作机制
  • Master和Minion都以守护进程的方式运行

  • Master监听配置文件里定义的ret_port(接收minion请求),和publish_port(发布消息)的端口

  • 当Minion运行时,它会自动连接到配置文件里定义的Master地址ret_port端口进行连接认证

  • 当Master和Minion可以正常通信后,就可以进行各种各样的配置管理工作了

六、安装salt api

[root@master ~]#  yum -y install salt-api pyOpenSSL  
[root@master ~]#  systemctl restart salt-api

1) 创建用户,saltapi认证使用
[root@master ~]#  useradd -M -s /sbin/nologin wmm  
[root@master ~]#  echo 'wmm' | passwd wmm --stdin  

2) 添加salt api配置
Last login: Sat Sep  7 19:08:35 2019 from 192.168.10.1
[root@master ~]# cat /etc/salt/master.d/api.conf 
rest_cherrypy:
  port: 8888
  #ssl_crt: /etc/pki/tls/certs/localhost.crt
  #ssl_key: /etc/pki/tls/certs/localhost.key
  disable_ssl: True
external_auth:
  pam:
    wmm:
      - .*
      - '@wheel'
      - '@runner'
[root@master ~]# 

3) 不使用ssl
rest_cherrypy:
  port: 8000
  #ssl_crt: /etc/pki/tls/certs/localhost.crt
  #ssl_key: /etc/pki/tls/private/localhost.key
  disable_ssl: True
external_auth:
  pam:
    wmm:
      - .*
      - '@wheel'
      - '@runner'

4) 生成自签名证书
[root@master ~]# salt-call tls.create_self_signed_cert
local:
    Certificate "localhost" already exists

提示已经存在时,可以删除/etc/pki/tls/certs/localhost.crt /etc/pki/tls/certs/localhost.key重新生成

如果这里报异常,请先确认下有没有未认证的主机:

[root@master ~]# salt-key -L
Accepted Keys:
minion-01
minion-02
Denied Keys:
Unaccepted Keys:
Rejected Keys:
[root@master ~]# 
5)获取token
[oot@master ~]# curl -k https://192.168.10.12:8000/login  -H "Accept: application/x-yaml" -d username='wmm' -d password='wmm' -d eauth='pam'
return:
- eauth: pam
  expire: 1480714218.787106
  perms:
  - .*
  - '@wheel'
  - '@runner'
  start: 1480671018.787106
  token: ab3749a9a0fe83386b8a5d558d10e346c252e336
  user: wmm

重启salt-api后token会改变

6)执行models,test.ping测试minion连通性
[root@master ~]# curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: ab3749a9a0fe83386b8a5d558d10e346c252e336" -d client='local' -d tgt='*' -d fun='test.ping'  
return:
- minion-02: true

7)远程执行命令
[root@master ~]# curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: ab3749a9a0fe83386b8a5d558d10e346c252e336" -d client='local' -d tgt='*' -d fun='cmd.run'   -d arg='free -m'
return:
- minion-02: '             total       used       free     shared    buffers     cached
    Mem:           988        932         56          1         19        107
    -/+ buffers/cache:        805        182
    Swap:         1983        382       1601'

8)远程执行多个minion命令
[root@master ~]# curl -k https://192.168.62.200:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: ab3749a9a0fe83386b8a5d558d10e346c252e336"  -d client='local' -d tgt='operation,slave01'  -d expr_form='list'  -d fun='cmd.run' -d arg='free -m'
return:
- minion-02: '             total       used       free     shared    buffers     cached
    Mem:           988        925         63          1         21         81
    -/+ buffers/cache:        821        166
    Swap:         1983        393       1590'
  minion-01: '             total       used       free     shared    buffers     cached
    Mem:          1870        622       1248          6         79        300
    -/+ buffers/cache:        242       1628
    Swap:         2047          0       2047'
[root@master ~]#

9)执行wheel

查看minion key状态

[root@master ~]#curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: ab3749a9a0fe83386b8a5d558d10e346c252e336" -d client='wheel'  -d fun='key.list_all'
return:
- data:
    _stamp: '2019-09-14S09:30:35.235660'
    fun: wheel.key.list_all
    jid: '20190914173034905379'
    return:
      local:
      - master.pem
      - master.pub
      minions:
      - minion-01
      - minion-02
      minions_denied: []
      minions_pre: []
      minions_rejected: []
    success: true
    tag: salt/wheel/20161202173034905379
    user: wmm
  tag: salt/wheel/20161202173034905379

10)查看sls模块信息 wheel.file_roots.list_roots
[root@master ~]# curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: 2ea1a20373900c311cf4ab1a707da5de4c9c44fc" -d client='wheel'  -d fun='file_roots.list_roots'
return:
- data:
    _stamp: '2019-09-14S09:30:35.235951'
    fun: wheel.file_roots.list_roots
    jid: '20190914173034906684'
    return:
      app:
      - /data/salt/app:
          memcached:
            file:
              install_memcached-1.4.15.tar.gz: f
            init.sls: f
            install.sls: f
          nginx:
            conf.sls: f
            file:
              nginx: f
              nginx-1.2.5.tar.gz: f
              nginx.conf: f
              nginx_log_cut.sh: f
              vhost.conf: f
            init.sls: f
            install.sls: f
            vhost.sls: f

11)执行runner

查看saltenv环境配置

[root@master ~] # curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: 2ea1a20373900c311cf4ab1a707da5de4c9c44fc" -d client='runner'  -d fun='fileserver.envs'
return:
- - app
  - base
  - online

查看minion运行状态

[root@master ~]# curl -k https://192.168.62.200:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: ab3749a9a0fe83386b8a5d558d10e346c252e336" -d client='runner'  -d fun='manage.status'
return:
- down:
  - minion-01
  up:
  - minion-02

异步执行命令job:

# curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: 14e719b94839b680e7860bfa34db7a385070dd53" -d client="local_async" -d expr_form="glob" -d tgt="minion-01"   -d fun="cmd.run" -d  arg="free -m"
return:
- jid: '20190914111629216443'
  minions:
  - operation
 
 
# curl -k https://192.168.10.12:8000/jobs/20161205111629216443 -H "Accept: application/x-yaml" -H "X-Auth-Token: 14e719b94839b680e7860bfa34db7a385070dd53"
info:
- Arguments:
  - free -m
  Function: cmd.run
  Minions:
  - minion-01
  Result:
    minion-01:
      return: '             total       used       free     shared    buffers     cached
 
        Mem:           988        928         59          1         17         75
 
        -/+ buffers/cache:        836        152
 
        Swap:         1983        330       1653'
  StartTime: 2019, Dec 14 11:16:29.216443
  Target: minion-01
  Target-type: glob
  User: wmm
  jid: '20190914111629216443'
return:
- minion-01: '             total       used       free     shared    buffers     cached
 
    Mem:           988        928         59          1         17         75
 
    -/+ buffers/cache:        836        152
 
    Swap:         1983        330       1653'

这里之前查阅资料过前辈们概括的整个大致过程:

 首先是服务端认证,通过每个请求传递会话令牌来执行身份验证,token通过Login URL生成。

token认证采用两种方法发送:一种是hearder头添加认证token,另一种作为会话cookie。

用法:

  请求主体必须是一组命令。使用此工作流程来构建命令:

    1. 选择一个客户端界面。

    2. 选择一个功能。

    3.填写所选客户端所需的其余参数。

client字段是对Salt的python api中使用的主要python类的引用。

  local:向本地发送命令的“本地”使用。等同于salt 命令。

  runner:调用master的runner 模块。等同于salt-run命令。

  wheel:调用master的wheel模块。wheel没有知己额的CLI命令,它通常广利Master-side资源,例如状态文件,支柱文件,salt配置文件,以及salt-key类似的功能。

 

在执行LocalClient,它需要将命令转发给Minions,所以需要tgt参数来指定minionid.

           也需要arg(数组)和kwarg(之前)参数,这些值被发送到minions并用作请求函数的参数。

RunnerClient和WheelClient直接在Master上执行,因此不需要接受这些参数。

header头设置:

  REST接口在接受什么样的数据格式以及它将返回什么格式(例如,JSON,YAML,urlencoded)方面是灵活的

    通过包含Content-type头来指定请求正文中的数据格式。

    使用Accept头指定相应主体所需的数据格式。

关于CherryPy的并发:

  CherryPy服务器是一个生成就绪的线程HTTP服务器,用Python编写。它使用线程池来处理HTTP请求,所以不适合维护大量的并发同步连接,在配置默认设置的中等硬件上,他最高大约3050个并发连接。

  注意:每个salt的命令运行都会启动一个实例化的进程(LocalClient),它将自己的监听器实例化为salt事件总线,并发出自己的周期性salturil.find_job查询来确定Minion是否仍在运行该命令,不完全是一个轻量级操作。

超时:

  CherryPy还可以设置HTTP超时时间。LocalClient和RunnerClient都可以在顶级关键字(timeout)中设置自己的超时参数。

异步操作:

  由于性能开销和HTTP超时,长时间运行上述操作,可以使用local_asyn,runner_asyn,wheel_asyn进行异步方式运行更能节省开销。执行结果可以通过 /jobs/<jid> URL 从缓存中获取,也可以使用salt的Rerutner 系统收集到数据存储中。

  /events URL专门用户处理长时间运行的HTTP请求,并包含了作业返回的salt事件总线,但该操作具有不同步性。

性能调整:

  设置thread_pool和socket_queue_size 可以用来增加处理传入请求的rest_cherrypy的能力。设置这些配置时需要留意RAM的使用情况以及可用文件句柄。由于salt-api是基于salt使用,同时还需要考虑salt的性能。

下面是一些运维平台中,有关资产管理的一些常用API:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = '40kuai'
__version__ = 'v0.0.1'
"""
1. 整合 salt-api 功能
2. 获取token多次使用,发现token过期后重新获取token从当前失败任务重新继续执行
3. 可选:出现接口或服务异常(501),本次操作尝试几次重新执行
arg 为模块需要传入的参数,kwargs为pillar或grains参数。

分为以下几个类:
    1. salt-api 方法类
    2. 发送请求的类
"""

from urlparse import urljoin
import requests


class Salt_Api():
    def __init__(self, url, username, password):
        self.url = url
        self._username = username
        self._password = password
        self.get_token()

    def get_token(self, eauth='pam', ):
        """获取salt-api使用的token"""
        get_token_url = urljoin(self.url, 'login')
        json_data = 'username': self._username, 'password': self._password, 'eauth': eauth
        token_obj = requests.post(get_token_url, json=json_data, verify=False)
        if token_obj.status_code != 200:
            raise Exception(token_obj.status_code)
        self.token = token_obj.json()['return'][0]['token']

    def post(self, prefix='/', json_data=None, headers=None):
        post_url = urljoin(self.url, prefix)
        if headers is None:
            headers = 'X-Auth-Token': self.token, 'Accept': 'application/json'
        else:
            headers = 'X-Auth-Token': self.token, .update(headers)
        post_requests = requests.post(post_url, json=json_data, headers=headers, verify=False)
        return post_requests.json()

    def get(self, prefix='/', json_data=None, headers=None):
        post_url = urljoin(self.url, prefix)
        if headers is None:
            headers = 'X-Auth-Token': self.token, 'Accept': 'application/json'
        else:
            headers = 'X-Auth-Token': self.token, .update(headers)
        get_requests = requests.get(post_url, json=json_data, headers=headers, verify=False)
        return get_requests.json()

    def get_all_key(self):
        """获取所有minion的key"""
        json_data = 'client': 'wheel', 'fun': 'key.list_all'
        content = self.post(json_data=json_data)
        minions = content['return'][0]['data']['return']['minions']
        minions_pre = content['return'][0]['data']['return']['minions_pre']
        return minions, minions_pre

    def accept_key(self, minion_id):
        """认证minion_id,返回Ture or False"""
        json_data = 'client': 'wheel', 'fun': 'key.accept', 'match': minion_id
        content = self.post(json_data=json_data)
        return content['return'][0]['data']['success']

    def delete_key(self, node_name):
        """删除minion_id,返回Ture or False"""
        json_data = 'client': 'wheel', 'fun': 'key.delete', 'match': node_name
        content = self.post(json_data=json_data)
        return content['return'][0]['data']['success']

    def host_remote_module(self, tgt, fun, arg=None):
        """根据主机执行函数或模块,模块的参数为arg"""
        json_data = 'client': 'local', 'tgt': tgt, 'fun': fun, 
        if arg:
            json_data.update('arg': arg)
        content = self.post(json_data=json_data)
        return content['return']

    def group_remote_module(self, tgt, fun, arg=None):
        """根据分组执行函数或模块,模块的参数为arg"""
        json_data = 'client': 'local', 'tgt': tgt, 'fun': fun, 'expr_form': 'nodegroup'
        if arg:
            json_data.update('arg': arg)
        content = self.post(json_data=json_data)
        return content['return']

    def host_sls_async(self, tgt, arg):
        '''主机异步sls '''
        json_data = 'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg
        content = self.post(json_data=json_data)
        return content['return']

    def group_sls_async(self, tgt, arg):
        '''分组异步sls '''
        json_data = 'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup'
        content = self.post(json_data=json_data)
        return content['return']

    def server_hosts_pillar(self, tgt, arg, **kwargs):
        '''针对主机执行sls and pillar '''
        print kwargs
        kwargs = 'pillar': kwargs['kwargs']
        json_data = "client": "local", "tgt": tgt, "fun": "state.sls", "arg": arg, "kwarg": kwargs
        content = self.post(json_data=json_data)
        return content['return']

    def server_group_pillar(self, tgt, arg, **kwargs):
        '''分组进行sls and pillar'''
        kwargs = 'pillar': kwargs['kwargs']
        json_data = 'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup',
                     'kwarg': kwargs
        content = self.post(json_data=json_data)
        return content['return']

    def jobs_all_list(self):
        '''打印所有jid缓存'''
        json_data = "client": "runner", "fun": "jobs.list_jobs"
        content = self.post(json_data=json_data)
        return content['return']

    def jobs_jid_status(self, jid):
        '''查看jid运行状态'''
        json_data = "client": "runner", "fun": "jobs.lookup_jid", "jid": jid
        content = self.post(json_data=json_data)
        return content['return']

    def keys_minion(self, hostname):
        """Show the list of minion keys or detail on a specific key"""
        content = self.get('keys/%s' % hostname)
        return content


if __name__ == '__main__':
    url = 'https://local:8000/'
    obj = Salt_Api(url, 'username', 'password')
    print obj.keys_minion('minionid')

salt-api

我在运维平台中针对于IP地址的获取,使用的是这样的思路,因为大家可以看到:

[root@master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    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 foreve

以上是关于saltstack的api安装以及使用解释的主要内容,如果未能解决你的问题,请参考以下文章

saltstack api安装使用

SaltStack安装,添加主机,基本命令

Saltstack API以及对应的Python模板

Saltstack API 配置管理

SaltStack RESTful API的调用

Saltstack-API