saltstack api使用詳解
簡述
接觸了saltstack感覺十分強大,非常適合做自動化運維。本文介紹下salt-api的簡單使用。 後續打算用django + saltsatck做一個web介面的自動化運維平臺。
salt-api介紹
saltsatck本身就提供了一套算完整的api,使用 CherryPy 來實現 restful 的 api,供外部的程式呼叫。
salt-api安裝
salt-api需要安裝,然後進行一些配置才可以正常使用,安裝方法有兩種。 方法一: yum安裝,需要的依賴包cherry也會被補全裝上。 安裝salt-api,並設定開機啟動
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密碼,該密碼為之前生成證書時設定的密碼
cd /etc/pki/tls/private/
openssl rsa -in localhost.key -out localhost_nopass.key
複製程式碼
修改檔案許可權
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
複製程式碼
新增使用者
生產環境請使用密碼複雜度高的密碼,這裡我使用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
複製程式碼
建立/etc/salt/master.d/目錄
mkdir -p /etc/salt/master.d/
cd /etc/salt/master.d/
touch eauth.conf
touch api.conf
複製程式碼
編輯eauth.conf,新增下面內容
external_auth:
pam:
saltapi: # 使用者
- .* # 該配置檔案給予saltapi使用者所有模組使用許可權,出於安全考慮一般只給予特定模組使用許可權
複製程式碼
編輯api.conf,新增下面內容
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
複製程式碼
驗證服務
獲得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
複製程式碼
呼叫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認證去請求相應的json檔案。 salt命令在shell中使用方式是salt 客戶端 方法 引數(例子:salt 'client1' cmd.run 'free -m')。 這裡salt命令方法我們已經封裝好了,想使用salt的什麼方法就傳入對應的客戶端、方法、引數即可。 程式碼如下:
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'junxi'
import requests
import json
try:
import cookielib
except:
import http.cookiejar as cookielib
# 使用urllib2請求https出錯,做的設定
import ssl
context = ssl._create_unverified_context()
# 使用requests請求https出現警告,做的設定
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格式時使用這個命令把迴應的內容轉換成字典
# 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','tgt': tgt}
print '命令引數: ',params
result = self.get_data(self.url,params)
return result
def main():
print '=================='
print '同步執行命令'
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)
# 下面只是為了列印結果好看點
result1 = salt.salt_command(salt_client,salt_test)
for i in result1.keys():
print i,': ',result1[i]
result2 = salt.salt_command(salt_client,salt_params)
for i in result2.keys():
print i
print result2[i]
print
if __name__ == '__main__':
main()
複製程式碼
檢視執行結果 第一行請求認證的token。 從結果可以看出來我們請求了兩條命令,test.ping和free -m
==================
同步執行命令
83ad5789cf8046ff06972e1f92bb31f012609a78
命令引數: {'fun': 'test.ping','client': 'local','tgt': '*'}
client1 : True
saltstack : True
命令引數: {'fun': 'cmd.run','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
複製程式碼
請求非同步執行salt命令後的jid結果,首先要修改/etc/salt/master.d/eauth.conf 配置檔案,增加許可權,然後重啟salt-master和salt-api。
cd /etc/salt/master.d/
vi eauth.conf
# 修改內容如下:
external_auth:
pam:
saltapi:
- .*
- '@runner'
- '@wheel'
複製程式碼
python編寫非同步請求模組
def salt_async_command(self,arg=None): # 非同步執行salt命令,根據jid檢視執行結果
"""遠端非同步執行命令"""
if arg:
params = {'client': 'local_async','arg': arg}
else:
params = {'client': 'local_async','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
print '=================='
print '非同步執行命令'
salt1 = SaltApi(salt_api)
salt_client = '*'
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_params)
result2 = salt1.look_jid(jid2)
for i in result2.keys():
print i
print result2[i]
print
if __name__ == '__main__':
main()
複製程式碼
==================
非同步執行命令
{'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二次開發遇到的問題
對salt-api進行了二次開發,通過api控制minion,可能會遇到傳送命令執行緒就進入了等待,然後就是超時。 解決方法: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
修改下面兩行內容
'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),300),複製程式碼
重啟salt-api
systemctl restart salt-api
複製程式碼
##### 未完待續。