参考文档 :
https://www.jianshu.com/p/012ccdff93cc
http://www.cnblogs.com/xiewenming/p/7716660.html
https://www.jianshu.com/p/02c5286f43c6
一,在salt-master上面安装
yum -y install salt-api
# apt-get install salt-api
二,检查cherry包是否安装
[root@linux-node1 ~]# rpm -qa |grep cherry
python-cherrypy-3.2.2-4.el7.noarch
yum install -y python-cherrypy
# apt-get install -y python-cherrypy
三,安装pyOpenSSL包
root@ubuntu16:/etc/salt# pip install pyopenssl
Looking in indexes: http://mirrors.aliyun.com/pypi/simple/
Collecting pyopenssl
Downloading http://mirrors.aliyun.com/pypi/packages/01/c8/ceb170d81bd3941cbeb9940fc6cc2ef2ca4288d0ca8929ea4db5905d904d/pyOpenSSL-19.0.0-py2.py3-none-any.whl (53kB)
100% |████████████████████████████████| 61kB 3.0MB/s
Requirement already satisfied: six>=1.5.2 in /usr/local/lib/python3.5/dist-packages (from pyopenssl) (1.11.0)
Collecting cryptography>=2.3 (from pyopenssl)
Downloading http://mirrors.aliyun.com/pypi/packages/5b/12/b0409a94dad366d98a8eee2a77678c7a73aafd8c0e4b835abea634ea3896/cryptography-2.6.1-cp34-abi3-manylinux1_x86_64.whl (2.3MB)
100% |████████████████████████████████| 2.3MB 66.8MB/s
Collecting asn1crypto>=0.21.0 (from cryptography>=2.3->pyopenssl)
Downloading http://mirrors.aliyun.com/pypi/packages/ea/cd/35485615f45f30a510576f1a56d1e0a7ad7bd8ab5ed7cdc600ef7cd06222/asn1crypto-0.24.0-py2.py3-none-any.whl (101kB)
100% |████████████████████████████████| 102kB 51.1MB/s
Collecting cffi!=1.11.3,>=1.8 (from cryptography>=2.3->pyopenssl)
Downloading http://mirrors.aliyun.com/pypi/packages/62/76/135eeffe0089e6724bdd65c1bf9f1654db9b47783e65b8d9f1454c540d8b/cffi-1.12.3-cp35-cp35m-manylinux1_x86_64.whl (429kB)
100% |████████████████████████████████| 430kB 61.9MB/s
Collecting pycparser (from cffi!=1.11.3,>=1.8->cryptography>=2.3->pyopenssl)
Downloading http://mirrors.aliyun.com/pypi/packages/68/9e/49196946aee219aead1290e00d1e7fdeab8567783e83e1b9ab5585e6206a/pycparser-2.19.tar.gz (158kB)
100% |████████████████████████████████| 163kB 25.9MB/s
Building wheels for collected packages: pycparser
Running setup.py bdist_wheel for pycparser ... done
Stored in directory: /root/.cache/pip/wheels/83/8e/10/30364b3b58ac66ac251ed330e2f6529850a020a383ab2e83fd
Successfully built pycparser
Installing collected packages: asn1crypto, pycparser, cffi, cryptography, pyopenssl
Successfully installed asn1crypto-0.24.0 cffi-1.12.3 cryptography-2.6.1 pycparser-2.19 pyopenssl-19.0.0
You are using pip version 18.1, however version 19.1.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
四,配置自签名证书,生产环境我们可以购买证书
root@ubuntu16:/etc/salt# salt-call --local tls.create_self_signed_cert
local:
Created Private Key: "/etc/pki/tls/certs/localhost.key." Created Certificate: "/etc/pki/tls/certs/localhost.crt."
root@ubuntu16:/etc/salt#
五,在salt-master上,打开include功能方便管理
vi /etc/salt/master
default_include: master.d/*.conf
六,添加api配置到salt-master配置文件
cd /etc/salt/master.d
vi api.conf
root@ubuntu16:/etc/salt/master.d# cat api.conf
rest_cherrypy:
host: 0.0.0.0
port: 8008
ssl_crt: /etc/pki/tls/certs/localhost.crt
ssl_key: /etc/pki/tls/certs/localhost.key
或者:
vi tornado.conf
root@ubuntu16:/etc/salt/master.d# cat tornado.conf
rest_tornado:
port: 8007
address: 0.0.0.0
backlog: 128
ssl_crt: /etc/pki/tls/certs/localhost.crt
ssl_key: /etc/pki/tls/private/localhost_nopass.key
debug: False
disable_ssl: False
webhook_disable_auth: False
cors_origin: null
七,创建用户 -M不创建家目录 ,并设置密码 saltapi
root@ubuntu16:/etc/salt/master.d# useradd -M -s /sbin/nologin saltapi
root@ubuntu16:/etc/salt/master.d# passwd saltapi
root@ubuntu16:/etc/salt/master.d# passwd saltapi
Enter new UNIX password: # 输入密码-egg:saltapi
Retype new UNIX password:
passwd: password updated successfully
八,在salt-master配置文件里添加验证,在include的目录下创建新文件
[root@linux-node1 master.d]# pwd
/etc/salt/master.d
[root@linux-node1 master.d]# vi auth.conf
[root@linux-node1 master.d]# cat auth.conf
external_auth:
pam:
saltapi: # 用户
- .* # 该配置文件给予saltapi用户所有模块使用权限,出于安全考虑一般只给予特定模块使用权限
- '@wheel'
- '@runner'
- '@jobs'
九,重启salt-master和启动salt-api
root@ubuntu16:/etc/salt/master.d# systemctl restart salt-master
root@ubuntu16:/etc/salt/master.d# systemctl restart salt-api
root@ubuntu16:/etc/salt/master.d# netstat|grep 8008
tcp 0 0 localhost:53326 localhost:8008 TIME_WAIT
root@ubuntu16:/etc/salt/master.d#
十,查看salt-api端口监听
[root@linux-node1 master.d]# netstat -an |grep 8000
tcp 0 0 192.168.56.11:8000 0.0.0.0:* LISTEN
tcp 0 0 192.168.56.11:45196 192.168.56.11:8000 TIME_WAIT
十一,验证login登陆,获取token字符串
curl -k https://172.16.0.19:8001/login -H "Accept: application/x-yaml" -d username='saltapi' -d password='salt2017' -d eauth='pam'
root@ubuntu16:/etc/salt/master.d# curl -k https://0.0.0.0:8008/login -H "Accept: application/x-yaml" -d username='saltapi' -d password='saltapi' -d eauth='pam'
return:
- eauth: pam
expire: 1557355167.136909
perms:
- .*
- '@wheel'
- '@runner'
- '@jobs'
start: 1557311967.136907
token: 18a26cef51d62b9e40574a1089cfec94aa8509a2
user: saltapi
root@ubuntu16:/etc/salt/master.d#
十二,通过api执行test.ping测试连通性
curl -k https://0.0.0.0:8008/ -H "Accept: application/x-yaml" -H "X-Auth-Token: 18a26cef51d62b9e40574a1089cfec94aa8509a2" -d client='local' -d tgt='*' -d fun='test.ping'
root@ubuntu16:/etc/salt/master.d# curl -k https://0.0.0.0:8008/ -H "Accept: application/x-yaml" -H "X-Auth-Token: 18a26cef51d62b9e40574a1089cfec94aa8509a2" -d client='local' -d tgt='*' -d fun='test.ping'
return:
- ubuntu16: true
root@ubuntu16:/etc/salt/master.d#
十三、获取grains信息
root@ubuntu16:/etc/salt/master.d# curl -sSk https://0.0.0.0:8008/minions/ubuntu16 -H 'Accept: application/x-yaml' -H 'X-Auth-Token: 18a26cef51d62b9e40574a1089cfec94aa8509a2'
return:
- ubuntu16:
SSDs: []
biosreleasedate: 04/01/2014
biosversion: rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org
cpu_flags:
- fpu
- vme
- de
- pse
- tsc
- msr
- pae
- mce
- cx8
- apic
- sep
- mtrr
- pge
- mca
- cmov
- pat
- pse36
- clflush
- mmx
- fxsr
- sse
- sse2
- ss
- syscall
- nx
- pdpe1gb
- rdtscp
- lm
- constant_tsc
- rep_good
- nopl
- eagerfpu
- pni
- pclmulqdq
- ssse3
- fma
- cx16
- pcid
- sse4_1
- sse4_2
- x2apic
- movbe
- popcnt
- tsc_deadline_timer
- aes
- xsave
- avx
- f16c
- rdrand
- hypervisor
- lahf_lm
- abm
- 3dnowprefetch
- fsgsbase
- tsc_adjust
- bmi1
- hle
- avx2
- smep
- bmi2
- erms
- invpcid
- rtm
- mpx
- avx512f
- rdseed
- adx
- smap
- avx512cd
- xsaveopt
- xsavec
- xgetbv1
cpu_model: Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz
cpuarch: x86_64
disks:
- sr0
- vda
- loop0
- loop1
- loop2
- loop3
- loop4
- loop5
- loop6
- loop7
dns:
domain: ''
ip4_nameservers:
- 100.100.2.136
- 100.100.2.138
ip6_nameservers: []
nameservers:
- 100.100.2.136
- 100.100.2.138
options:
- timeout:2
search: []
sortlist: []
domain: ''
fqdn: ubuntu16
fqdn_ip4: []
fqdn_ip6: []
fqdns: []
gid: 0
gpus:
- model: GD 5446
vendor: unknown
groupname: root
host: ubuntu16
hwaddr_interfaces:
docker0: 02:42:b6:b4:9a:a1
eth0: 00:16:3e:08:66:a8
lo: 00:00:00:00:00:00
veth011a5b7: 06:6d:d9:ad:58:8c
veth481223d: 4a:4b:6b:67:aa:42
vethd602627: 5a:e7:c8:9a:10:f1
id: ubuntu16
init: systemd
ip4_gw: 172.31.239.253
ip4_interfaces:
docker0:
- 172.17.0.1
eth0:
- 172.31.239.233
lo:
- 127.0.0.1
veth011a5b7: []
veth481223d: []
vethd602627: []
ip6_gw: false
ip6_interfaces:
docker0: []
eth0: []
lo: []
veth011a5b7: []
veth481223d: []
vethd602627: []
ip_gw: true
ip_interfaces:
docker0:
- 172.17.0.1
eth0:
- 172.31.239.233
lo:
- 127.0.0.1
veth011a5b7: []
veth481223d: []
vethd602627: []
ipv4:
- 127.0.0.1
- 172.17.0.1
- 172.31.239.233
ipv6: []
kernel: Linux
kernelrelease: 4.4.0-105-generic
kernelversion: '#128-Ubuntu SMP Thu Dec 14 12:42:11 UTC 2017'
locale_info:
defaultencoding: UTF-8
defaultlanguage: en_US
detectedencoding: UTF-8
localhost: ubuntu16
lsb_distrib_codename: xenial
lsb_distrib_description: Ubuntu 16.04.3 LTS
lsb_distrib_id: Ubuntu
lsb_distrib_release: '16.04'
machine_id: ec6bb6f4416403d80c9f435159954958
manufacturer: Alibaba Cloud
master: 172.31.239.233
mdadm: []
mem_total: 2000
nodename: ubuntu16
num_cpus: 1
num_gpus: 1
os: Ubuntu
os_family: Debian
osarch: amd64
oscodename: xenial
osfinger: Ubuntu-16.04
osfullname: Ubuntu
osmajorrelease: 16
osrelease: '16.04'
osrelease_info:
- 16
- 4
path: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
pid: 25603
productname: Alibaba Cloud ECS
ps: ps -efHww
pythonexecutable: /usr/bin/python
pythonpath:
- /usr/bin
- /usr/lib/python35.zip
- /usr/lib/python3.5
- /usr/lib/python3.5/plat-x86_64-linux-gnu
- /usr/lib/python3.5/lib-dynload
- /usr/local/lib/python3.5/dist-packages
- /usr/lib/python3/dist-packages
pythonversion:
- 3
- 5
- 2
- final
- 0
saltpath: /usr/local/lib/python3.5/dist-packages/salt
saltversion: 2019.2.0
saltversioninfo:
- 2019
- 2
- 0
- 0
serialnumber: 905c5eee-74a9-4606-9693-1be8be8f195f
server_id: 780065244
shell: /bin/sh
swap_total: 0
systemd:
features: +PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP
+GCRYPT +GNUTLS +ACL +XZ -LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN
version: '229'
uid: 0
username: root
uuid: 905c5eee-74a9-4606-9693-1be8be8f195f
virtual: kvm
zfs_feature_flags: false
zfs_support: false
zmqversion: 4.3.1
root@ubuntu16:/etc/salt/master.d#
1.salt-api必须使用https,生产环境建议使用可信证书
2.当salt-api服务重启后原token失效
编写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', 'fun': method, '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_method, salt_params)
for i in result2.keys():
print i
print result2[i]
print
if __name__ == '__main__':
main()
请求异步执行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, 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
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_method, salt_params)
result2 = salt1.look_jid(jid2)
for i in result2.keys():
print i
print result2[i]
print
if __name__ == '__main__':
main()
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),
'server.socket_queue_size': self.apiopts.get('queue_size', 300),
重启salt-api
systemctl restart salt-api