saltstack-api使用詳解

簡述

接觸了saltstack感覺十分強大,非常適合做自動化運維。本文介紹下salt-api的簡單使用。
后續(xù)打算用django + saltsatck做一個web界面的自動化運維平臺。

salt-api介紹

saltsatck本身就提供了一套算完整的api,使用 CherryPy 來實現(xiàn) restful 的 api,供外部的程序調(diào)用。

salt-api安裝

salt-api需要安裝,然后進行一些配置才可以正常使用,安裝方法有兩種。
方法一:
yum安裝,需要的依賴包cherry也會被補全裝上。
安裝salt-api,并設(shè)置開機啟動

yum -y install salt-api pyOpenSSL 
systemctl enable salt-api

方法二:
pip安裝,首先要確認機器上有沒有安裝pip模塊。

rpm -ivh https://mirrors.aliyun.com/epel/7/x86_64/s/salt-api-2015.5.10-2.el7.noarch.rpm
pip install cherrypy==3.2.3
pip install cherrypy
pip install salt-api
配置自簽名證書
cd /etc/pki/tls/certs/
make testcert



Enter pass phrase:    ===>  輸入加密短語,這里我使用salt2017
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密碼,該密碼為之前生成證書時設(shè)置的密碼

cd /etc/pki/tls/private/
openssl rsa -in localhost.key -out localhost_nopass.key

修改文件權(quán)限

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
添加用戶

生產(chǎn)環(huán)境請使用密碼復(fù)雜度高的密碼,這里我使用salt2017

useradd -M -s /sbin/nologin saltapi
passwd saltapi        
配置salt-api

修改/etc/salt/master文件

sed -i '/#default_include/s/#default/default/g' /etc/salt/master

創(chuàng)建/etc/salt/master.d/目錄

mkdir -p /etc/salt/master.d/
cd /etc/salt/master.d/
touch eauth.conf
touch api.conf

編輯eauth.conf,添加下面內(nèi)容

external_auth:
  pam:
    saltapi:   # 用戶
      - .*     # 該配置文件給予saltapi用戶所有模塊使用權(quán)限,出于安全考慮一般只給予特定模塊使用權(quán)限

編輯api.conf,添加下面內(nèi)容

rest_cherrypy:
  port: 8001
  ssl_crt: /etc/pki/tls/certs/localhost.crt
  ssl_key: /etc/pki/tls/private/localhost_nopass.key
啟動salt-api
systemctl restart salt-master
systemctl start salt-api
ps -ef|grep salt-api
netstat -lnput|grep 8001
驗證服務(wù)

獲得token

curl -k https://172.16.0.19:8001/login -H "Accept: application/x-yaml"  -d username='saltapi'  -d password='salt2017'  -d eauth='pam'
return:
- eauth: pam
  expire: 1494365711.173652
  perms:
  - .*
  start: 1494322511.173652
  token: f40623825ea02606bfc558c982dbbfbb923c7570
  user: saltapi

調(diào)用test.ping

curl -k https://172.16.0.19:8001/ -H "Accept: application/x-yaml" -H "X-Auth-Token: f40623825ea02606bfc558c982dbbfbb923c7570" -d client='local' -d tgt='*' -d fun='test.ping'
return:
- client1: true
  saltstack: true

編寫python腳本請求salt api接口

自定義一個類,首先初始化時候獲得token,然后使用token認證去請求相應(yīng)的json文件。
salt命令在shell中使用方式是salt 客戶端 方法 參數(shù)(例子:salt 'client1' cmd.run 'free -m')
這里salt命令方法我們已經(jīng)封裝好了,想使用salt的什么方法就傳入對應(yīng)的客戶端、方法、參數(shù)即可。
代碼如下:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'junxi'


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

# 使用urllib2請求https出錯,做的設(shè)置
import ssl
context = ssl._create_unverified_context()

# 使用requests請求https出現(xiàn)警告,做的設(shè)置
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


salt_api = "https://172.16.0.19:8001/"


class SaltApi:
    """
    定義salt api接口的類
    初始化獲得token
    """
    def __init__(self, url):
        self.url = url
        self.username = "saltapi"
        self.password = "salt2017"
        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格式時使用這個命令把回應(yīng)的內(nèi)容轉(zhuǎn)換成字典
        # 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):
        """遠程執(zhí)行命令,相當于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 '命令參數(shù): ', params
        result = self.get_data(self.url, params)
        return result

def main():
    print '=================='
    print '同步執(zhí)行命令'
    salt = SaltApi(salt_api)
    print salt.token
    salt_client = '*'
    salt_test = 'test.ping'
    salt_method = 'cmd.run'
    salt_params = 'free -m'
    # print salt.salt_command(salt_client, salt_method, salt_params)
    # 下面只是為了打印結(jié)果好看點
    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]
        print

if __name__ == '__main__':
    main()

查看運行結(jié)果
第一行請求認證的token。
從結(jié)果可以看出來我們請求了兩條命令,test.ping和free -m

==================
同步執(zhí)行命令
83ad5789cf8046ff06972e1f92bb31f012609a78
命令參數(shù):  {'fun': 'test.ping', 'client': 'local', 'tgt': '*'}
client1 :  True
saltstack :  True
命令參數(shù):  {'fun': 'cmd.run', 'client': 'local', 'tgt': '*', 'arg': 'free -m'}
client1
              total        used        free      shared  buff/cache   available
Mem:            220         153           7           2          59          31
Swap:          2046         129        1917

saltstack
              total        used        free      shared  buff/cache   available
Mem:            976         516          83          24         376         260
Swap:          2046           0        2046

請求異步執(zhí)行salt命令后的jid結(jié)果,首先要修改/etc/salt/master.d/eauth.conf 配置文件,增加權(quán)限,然后重啟salt-master和salt-api。

cd /etc/salt/master.d/
vi eauth.conf
# 修改內(nèi)容如下:
external_auth:
  pam:
    saltapi:
      - .*
      - '@runner'
      - '@wheel'

python編寫異步請求模塊

def salt_async_command(self, tgt, method, arg=None):  # 異步執(zhí)行salt命令,根據(jù)jid查看執(zhí)行結(jié)果
    """遠程異步執(zhí)行命令"""
    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):  # 根據(jù)異步執(zhí)行命令返回的jid查看事件結(jié)果
    params = {'client': 'runner', 'fun': 'jobs.lookup_jid', 'jid': jid}
    print params
    result = self.get_data(self.url, params)
    return result

查看執(zhí)行結(jié)果

def main():
    print
    print '=================='
    print '異步執(zhí)行命令'
    salt1 = SaltApi(salt_api)
    salt_client = '*'
    salt_method = 'cmd.run'
    salt_params = 'df -hT'
    # 下面只是為了打印結(jié)果好看點
    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]
        print


if __name__ == '__main__':
    main()
==================
異步執(zhí)行命令
{'fun': 'jobs.lookup_jid', 'jid': u'20170525095342243770', 'client': 'runner'}
saltstack :  True
client1 :  True
{'fun': 'jobs.lookup_jid', 'jid': u'20170525095342994269', 'client': 'runner'}
client1
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/sda2      xfs        17G   13G  4.1G  77% /
devtmpfs       devtmpfs   97M     0   97M   0% /dev
tmpfs          tmpfs     111M   12K  111M   1% /dev/shm
tmpfs          tmpfs     111M  4.7M  106M   5% /run
tmpfs          tmpfs     111M     0  111M   0% /sys/fs/cgroup
/dev/sda1      xfs       297M  202M   96M  68% /boot

saltstack
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/sda2      xfs        17G  7.2G  9.9G  43% /
devtmpfs       devtmpfs  475M     0  475M   0% /dev
tmpfs          tmpfs     489M   16K  489M   1% /dev/shm
tmpfs          tmpfs     489M  6.9M  482M   2% /run
tmpfs          tmpfs     489M     0  489M   0% /sys/fs/cgroup
/dev/sda1      xfs       297M  202M   96M  68% /boot

salt-api二次開發(fā)遇到的問題

對salt-api進行了二次開發(fā),通過api控制minion,可能會遇到發(fā)送命令線程就進入了等待,然后就是超時。
解決方法:salt.netapi.rest_cherrypy包里面有一個app.py方法,修改'server.thread_pool': self.apiopts.get('thread_pool', 100)為200,修改'server.socket_queue_size': self.apiopts.get('queue_size', 30)為300 。重啟salt-api 再次測試,OK。

vi /usr/lib/python2.7/site-packages/salt/netapi/rest_cherrypy/app.py
修改下面兩行內(nèi)容
'server.thread_pool': self.apiopts.get('thread_pool', 100),
'server.socket_queue_size': self.apiopts.get('queue_size', 30),
為
'server.thread_pool': self.apiopts.get('thread_pool', 200),
'server.socket_queue_size': self.apiopts.get('queue_size', 300),

重啟salt-api

systemctl restart salt-api

<br />

未完待續(xù)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,881評論 18 139
  • 學(xué)習(xí)地址[http://tech.mainwise.cn/?p=438] 更新于 3.25 23:16 salt簡...
    J書越來越垃圾了閱讀 30,909評論 9 36
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,941評論 6 342
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,113評論 25 708
  • 我覺得我好想對你要求太多 對你總是期待 接著就是等待 日復(fù)一日 夜復(fù)一夜 我 又重蹈覆轍了 嗎?
    誰能愛自己閱讀 257評論 0 0