配置管理(3) salt-api安装、配置、使用

salt-api也用了一段时间了,现在从安装、配置、使用三个方面梳理下知识。
1、安装
采用pip安装方便快捷,当然编译安装也很nice。
安装pip采用的编译安装的方式,版本当前最新1.5.6,下载、解压、编译、安装是不变的法则。

[root@saltstack ~]#wget https://pypi.python.org/packages/source/p/pip/pip-1.5.6.tar.gz#md5=01026f87978932060cc86c1dc527903e --no-check-certificate
[root@saltstack ~]#tar xvfz pip-1.5.6.tar.gz
[root@saltstack ~]#cd pip-1.5.6
[root@saltstack pip-1.5.6]#python setup.py build
[root@saltstack pip-1.5.6]#python setup.py install
#安装完成后可以用pip freeze查看已安装的packages
[root@saltstack pip-1.5.6]#pip freeze

安装CherryPy,版本3.2.3

[root@saltstack ~]#pip install cherrypy==3.2.3

安装salt-api,版本0.8.3

[root@saltstack ~]#pip install salt-api==0.8.3

2、配置

[root@saltstack ~]# cd /etc/pki/tls/certs
[root@saltstack certs]# make testcert
umask 77 ; \
    /usr/bin/openssl genrsa -aes128 2048 > /etc/pki/tls/private/localhost.key
Generating RSA private key, 2048 bit long modulus
...+++
..................................................................+++
e is 65537 (0x10001)
Enter pass phrase:    #键入加密短语,4到8191个字符
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) []:Shanghai
Locality Name (eg, city) [Default City]:Shanghai
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:1989051805@qq.com
[root@saltstack certs]# cd ../private/
[root@saltstack private]# openssl rsa -in localhost.key -out localhost_nopass.key
Enter pass phrase for localhost.key:    #输入之前的加密短语
writing RSA key

如果遇到这样的错误

[root@saltstack certs]# make testcert
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
unable to load Private Key
139696733648712:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:703:Expecting: ANY PRIVATE KEY
make: *** [/etc/pki/tls/certs/localhost.crt]

删掉文件/etc/pki/tls/private/localhost.key文件,然后再make testcert。
为salt-api创建用户并设定密码,用户名没有特别要求,我就用saltapi好了。

[root@saltstack ~]#useradd -M -s /sbin/nologin saltapi
#由于是测试,故采用了弱密码"password",正式环境必须采用强密码,多用特殊字符
[root@saltstack ~]# passwd saltapi

新增加配置文件/etc/salt/master.d/api.conf和/etc/salt/master.d/eauth.conf

#该配置文件给予saltapi用户所有模块使用权限,出于安全考虑一般只给予特定模块使用权限
[root@saltstack master.d]# cat eauth.conf
external_auth:
  pam:
    saltapi:
      - .*
[root@saltstack master.d]#
[root@saltstack master.d]# cat api.conf
rest_cherrypy:
  port: 8888
  ssl_crt: /etc/pki/tls/certs/localhost.crt
  ssl_key: /etc/pki/tls/private/localhost_nopass.key
[root@saltstack master.d]#

寻找salt-api的启动脚本,我比较懒就不自己写了,在页面https://github.com/saltstack/salt-api/releases下载salt-api的tar.gz包,启动脚本在解压包的这个位置./pkg/rpm/salt-api。
不过提供的脚本貌似有个小的bug,就是使用restart参数时,salt-api能够stop但是不能start,如下:

[root@saltstack ~]# /etc/init.d/salt-api restart
Stopping salt-api daemon:                                  [确定]
Starting salt-api daemon:                                  [失败]

我估计可能是有些相关资源在下次启动前没有来得及释放造成的,解决方法很简单在脚本的restart函数的stop和start之间加上sleep语句。

restart() {
   stop
   sleep 1
   start
}

然后重启就没有问题了

[root@saltstack ~]# /etc/init.d/salt-api restart
Stopping salt-api daemon:                                  [确定]
Starting salt-api daemon:                                  [确定]
[root@saltstack ~]#

最后重启salt-master在启动salt-api并将salt-api加入开机启动,安装就完成了。

[root@saltstack ~]# chkconfig salt-api on
[root@saltstack ~]# /etc/init.d/salt-master restart
Stopping salt-master daemon:                               [确定]
Starting salt-master daemon:                               [确定]
[root@saltstack ~]# /etc/init.d/salt-api restart
Stopping salt-api daemon:                                  [确定]
Starting salt-api daemon:                                  [确定]
[root@saltstack ~]#

3、使用(基本的使用方法)
登录获取token

[root@syndic02 ~]# curl -k https://192.168.186.134:8888/login -H "Accept: application/x-yaml" -d username='saltapi' -d password='password' -d eauth='pam'
return:
- eauth: pam
  expire: 1416324685.2597771
  perms:
  - .*
  start: 1416281485.2597761
  token: 6171a922a9718ccb40e94ee7c8eb8768f4eea4e5
  user: saltapi

获取token后就可以使用token通信

#相当于在salt-master本地执行salt \* test.ping
[root@syndic02 ~]# curl -k https://192.168.186.134:8888/ -H "Accept: application/x-yaml" -H "X-Auth-Token: 6171a922a9718ccb40e94ee7c8eb8768f4eea4e5" -d client='local' -d tgt='*' -d fun='test.ping'
return:
- syndic01: true
  syndic01-minion02: true
  syndic02: true
  syndic02-minion02: true

#相当于在salt-master本地执行salt \* test.echo 'hello world'
[root@syndic02 ~]# curl -k https://192.168.186.134:8888/ -H "Accept: application/x-yaml" -H "X-Auth-Token: 6171a922a9718ccb40e94ee7c8eb8768f4eea4e5" -d client='local' -d tgt='*' -d fun='test.echo' -d arg='hello world'
return:
- syndic01: hello world
  syndic01-minion02: hello world
  syndic02: hello world
  syndic02-minion02: hello world
[root@syndic02 ~]#

运维开发这样使用还是不方便的,下面写的是一个salt-api的类(其它的文章也提到过)可以参考。

#!/usr/bin/env python
#coding=utf-8

import urllib2, urllib, json, re

class saltAPI:
    def __init__(self):
        self.__url = 'https://192.168.186.134:8888'       #salt-api监控的地址和端口如:'https://192.168.186.134:8888'
        self.__user =  'saltapi'             #salt-api用户名
        self.__password = 'password'          #salt-api用户密码
        self.__token_id = self.salt_login()

    def salt_login(self):
        params = {'eauth': 'pam', 'username': self.__user, 'password': self.__password}
        encode = urllib.urlencode(params)
        obj = urllib.unquote(encode)
        headers = {'X-Auth-Token':''}
        url = self.__url + '/login'
        req = urllib2.Request(url, obj, headers)
        opener = urllib2.urlopen(req)
        content = json.loads(opener.read())
        try:
            token = content['return'][0]['token']
            return token
        except KeyError:
            raise KeyError

    def postRequest(self, obj, prefix='/'):
        url = self.__url + prefix
        headers = {'X-Auth-Token'   : self.__token_id}
        req = urllib2.Request(url, obj, headers)
        opener = urllib2.urlopen(req)
        content = json.loads(opener.read())
        return content['return']

    def saltCmd(self, params):
        obj = urllib.urlencode(params)
        obj, number = re.subn("arg\d", 'arg', obj)
        res = self.postRequest(obj)
        return res

def main():
    #以下是用来测试saltAPI类的部分
    sapi = saltAPI()
    params = {'client':'local', 'fun':'test.ping', 'tgt':'*'}
    #params = {'client':'local', 'fun':'test.ping', 'tgt':'某台服务器的key'}
    #params = {'client':'local', 'fun':'test.echo', 'tgt':'某台服务器的key', 'arg1':'hello'}
    #params = {'client':'local', 'fun':'test.ping', 'tgt':'某组服务器的组名', 'expr_form':'nodegroup'}
    test = sapi.saltCmd(params)
    print test

if __name__ == '__main__':
    main()

测试效果

[root@syndic02 ~]# python salt-api.py
[{u'syndic02': True, u'syndic02-minion02': True, u'syndic01': True, u'syndic01-minion02': True}]
[root@syndic02 ~]#

以上只是一些基本的实例,salt-api还可以实现更多功能。
文章出处:http://www.xiaomastack.com/2014/11/18/salt-api/

22 Comments

 Add your comment
  1. 获取到了token后,测试返回:
    return:
    – {}

  2. 你的代码我看看,返回这种值情况太多呵,是不是salt-api挂了还是调用的key不对。

  3. [root@odb-1 ~]# curl -k https://192.168.1.175:8888/login -H “Accept: application/x-yaml” -d username=’salt’ -d password=’test’ -d eauth=’pam’
    return:
    – eauth: pam
    expire: 1418237429.3646691
    perms:
    – .*
    – ‘@wheel’
    – ‘@runner’
    start: 1418194229.3646679
    token: fcd8917dcdbae1d64c0de61001ba7e4613af2f4f
    user: salt
    [root@odb-1 ~]# curl -k https://192.168.1.175:8888/ -H “Accept: application/x-yaml” -H “X-Auth-Token: d54bf0c64e05fd664fec71cad3f11443c5b55cc1” -d client=’local’ -d tgt=’*’ -d fun=’test.ping’
    return:
    – {}

  4. 用你最新获取的token呵,貌似你下面的那个token是你以前获取的吧。

  5. token没有错,贴到你博客,好像不全

  6. 你贴的是两个40位的token,没有不全哦。

  7. 当你用同一个用户名获取一个新的token时,上次获取的token就失效了呵。

  8. 在你的salt-master的那台机器上执行 salt \* test.ping看看有没有返回信息。

  9. 请问下马哥,我的这个问题怎能解决呢?
    [root@YZSJHL19-71 ~]# curl -k https://10.4.19.71:8000/login -H “Accept: application/x-yaml” -d username=’10.4.19.71′ -d password=’123.com’ -d eauth=’pam’

    401 Unauthorized

    #powered_by {
    margin-top: 20px;
    border-top: 2px solid black;
    font-style: italic;
    }

    #traceback {
    color: red;
    }

    401 Unauthorized
    Could not authenticate using provided credentials

    Powered by CherryPy 3.2.2

  10. 认证失败,检查下你相关的配置文件如eauth.conf等的缩进有没有问题。

  11. 问问。api的参数 tgt 。能不能批定几台主机。tgt好像只能带 * 号 或是一台主机。

  12. 比如 tgt=”*” 或 tgt=”10.0.0.1″。能不能带几台机器呢?

  13. 可以给主机分组,然后指定组名即可。

  14. 小马哥,你这个syndic01是使用多级的master吗?多级master直接在top上面执行 syndic-master下的minion也能返回结果?还是需要在配置一下什么?
    [root@syndic02 ~]# curl -k https://192.168.186.134:8888/ -H “Accept: application/x-yaml” -H “X-Auth-Token: 6171a922a9718ccb40e94ee7c8eb8768f4eea4e5” -d client=’local’ -d tgt=’*’ -d fun=’test.ping’
    return:
    – syndic01: true
    syndic01-minion02: true
    syndic02: true
    syndic02-minion02: true

  15. 可以的,不过跨机房的话,有超时的问题。

  16. 我的是指返回 top 自身的minion,syndic-minion 无法返回结果,就很奇怪呢,也么有任何log
    我的结果是这样的:
    curl -k https://192.168.186.134:8888/ -H “Accept: application/x-yaml” -H “X-Auth-Token: 6171a922a9718ccb40e94ee7c8eb8768f4eea4e5″ -d client=’local’ -d tgt=’*’ -d fun=’test.ping’
    return:
    – syndic01: true
    syndic02: true

    还有你是怎么传递pillar值的呢,就像cli中 使用pillar=‘XXXXX’ 在api中传递,使用什么参数呢

  17. 我没有用api传递过pillar值。

  18. 你可以设置 expr_form=‘list’,然后目标机器使用逗号分隔就可以执行多台机器了

  19. 老兄解决了么

  20. 找到了用这个方法,或者用列表
    local.cmd(‘*’, ‘state.show_sls’, kwarg={
    ‘mods’: ‘base.cptepillara’,
    ‘pillar’: {
    ‘name’: ‘Foo data’,
    },
    })

  21. curl -k https://10.129.9.120:8888/ -X POST -H “Acceptpplication/json” -H “X-Auth-Token: 28bc78f3bb84331d2cd62426a58160c9a4bc5f24” -H “Content-Type: application/json” -d ‘[
    {
    “client”: “local”,
    “tgt”: “win02en”,
    “fun”: “state.show_sls”,
    “kwarg”: {“mods”: “base.cptepillara”, “pillar”: {“name”:”11111111111aaaaa”} }
    }
    ]’

  22. 请教下,如果是执行salt mine命令,怎么调用salt-api ?
    譬如实现下面这个功能
    salt ‘*’ mine.get ‘*’ cmd.run

发表评论:

你的电子邮件地址将不会被公开.

39 ÷ = 13