saltstack之saltssh及其API的应用

一.saltssh简介

1.基本定义

  • salt-ssh是通过ssh协议执行命令进行管理服务器,不需要在服务器端安装minion客户端,如果有安装minion也可以调用minion模块,salt-ssh有点类似ansible无客户端基与ssh协议进行管理服务器,通过roser(/etc/salt/roser)配置文件。

2.应用场景

主要作用是不需要安装minion,只要ssh协议开放,即可远程执行命令,可用作拿到一批新机器,批量配置时使用,也可以直接通过salt-ssh不安装minion进行管理.

  • salt ssh系统并不完全取代salt的通信系统。它只是简单的基于ssh协议不在依赖于ZeroMQ和salt-minion,但是由于salt ssh完全是基于ssh协议的,所以在进行远程行,ssh的执行效率要远远低于ZeroMQ
  • 创建roster系统是因为salt-ssh需要依赖这个名单来确定哪些系统如何连接并且执行。
  • 因为这个roster系统属于“热插拔”类型,它可以增强附着在任何现有的系统中来收集关于哪些服务器目前可用以及可以使用salt-ssh来连接的信息

部署如下:

1.如果在server2和server3上部署了salt-minion需要将其关掉方便ssh的验证

[root@server2 ~]# systemctl stop salt-minion
[root@server3 ~]# systemctl stop salt-minion    ##关掉方便测试ssh

2.在server1(master)上安装salt-ssh,并编写roster文件添加ssh需要连接的主机

[root@server1 salt]# yum install salt-ssh 使用自己搭建的第三方仓库进行安装的,也可以使用安装包进行安装

[root@server1 salt]# vim roster  添加ssh连接的主机
serve2:
  host: 172.25.254.2
  user: root
  passwd: westos

server3:
  host: 172.25.254.3
  user: root
  passwd: westos
[root@server1 salt]# vim master   注释掉数据库的相应内容,否则会有影响

在这里插入图片描述
3.配置完成之后不需要重启salt-master可以直接进行测试
在这里插入图片描述

二.API

saltsatck本身就提供了一套算完整的api,使用 CherryPy 来实现 restful 的 api,供外部的程序调用

部署如下:

1.在server1(master)上安装salt-api,注意本次安装是通过自己搭建的第三方仓库进行安装的,也可以在官网下载安装包进行安装

[root@server1 ~]# yum install -y salt-api

2.在/etc/pki/tls/private目录下生成相应的钥匙

[root@server1 pki]# pwd
/etc/pki
[root@server1 pki]# cd tls/
[root@server1 tls]# ls
cert.pem  certs  misc  openssl.cnf  private
[root@server1 tls]# cd private/  生成钥匙
root@server1 private]# openssl genrsa 1024 > localhost.key

在这里插入图片描述
3.在/etc/pki/tls/certs目录下面生成相应的证书,因为在这个目录下面有makefile文件,该文件里面有生成证书的相应方式,使用钥匙生成证书

[root@server1 certs]# pwd
/etc/pki/tls/certs
[root@server1 certs]# make testcert

在这里插入图片描述
4.在server1上/etc/salt下查看master文件里面有相应的api模块文件的目录及其文件命名格式

[root@server1 certs]# cd /etc/salt/
[root@server1 salt]# vim master

在这里插入图片描述
5.在/etc/salt/master.d目录下编辑api的配置文件添加证书及其钥匙

[root@server1 master.d]# pwd
/etc/salt/master.d
[root@server1 master.d]# vim api.conf
rest_cherrypy:
  port: 8000    在连接时使用的端口
  ssl_crt: /etc/pki/tls/certs/localhost.crt   连接所用到的证书
  ssl_key: /etc/pki/tls/private/localhost.key   连接时所用到的钥匙

6.在/etc/salt/master.d目录下编辑授权文件

[root@server1 master.d]# pwd
/etc/salt/master.d
[root@server1 master.d]# vim auth.conf
external_auth:
  pam:
    saltapi:   用户
      - .*
      - '@wheel'
      - '@runner' 
      - '@jobs'

在这里插入图片描述
7.建立授权用户及其设置密码

[root@server1 master.d]# useradd saltapi  建立授权用户及其设置密码
[root@server1 master.d]# passwd saltapi
[root@server1 master.d]# systemctl restart salt-master  重启相应的服务
[root@server1 master.d]# systemctl start salt-api
[root@server1 master.d]# netstat -tnlp  查看出现8000端口

在这里插入图片描述
8.在物理机端登陆并运行相应命令进行测试

//首先连接获取token
[root@foundation42 ~]# curl -sSk https://172.25.42.1:8000/login -H 'Accept: application/x-yaml' -d username=saltapi -d password=saltapi -d eauth=pam

//使用token运行相应的命令,server2和server3必须保证minion是开启的
[root@foundation42 ~]# curl -sSk https://172.25.42.1:8000 -H 'Accept: application/x-yaml' -H 'X-Auth-Token: b182ffb020daa4110dbcc0815cb678e265a34fa4' -d client=local -d tgt='*' -d fun=test.ping

在这里插入图片描述
在这里插入图片描述
9.在server1上编辑python脚本进行再次测试

[root@server1 ~]# vim saltapi.py

# -*- coding: utf-8 -*-

import urllib2,urllib
import time

try:
    import json
except ImportError:
    import simplejson as json

class SaltAPI(object):
    __token_id = ''
    def __init__(self,url,username,password):
        self.__url = url.rstrip('/')
        self.__user = username
        self.__password = password

    def token_id(self):
        ''' user login and get token id '''
        params = {'eauth': 'pam', 'username': self.__user, 'password': self.__password}
        encode = urllib.urlencode(params)
        obj = urllib.unquote(encode)
        content = self.postRequest(obj,prefix='/login')
	try:
            self.__token_id = content['return'][0]['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

    def list_all_key(self):
        params = {'client': 'wheel', 'fun': 'key.list_all'}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        minions = content['return'][0]['data']['return']['minions']
        minions_pre = content['return'][0]['data']['return']['minions_pre']
        return minions,minions_pre

    def delete_key(self,node_name):
        params = {'client': 'wheel', 'fun': 'key.delete', 'match': node_name}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0]['data']['success']
        return ret

    def accept_key(self,node_name):
        params = {'client': 'wheel', 'fun': 'key.accept', 'match': node_name}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0]['data']['success']
        return ret

    def remote_noarg_execution(self,tgt,fun):
        ''' Execute commands without parameters '''
        params = {'client': 'local', 'tgt': tgt, 'fun': fun}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0][tgt]
        return ret

    def remote_execution(self,tgt,fun,arg):
        ''' Command execution with parameters '''        
        params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0][tgt]
        return ret

    def target_remote_execution(self,tgt,fun,arg):
        ''' Use targeting for remote execution '''
        params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg, 'expr_form': 'nodegroup'}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        jid = content['return'][0]['jid']
        return jid

    def deploy(self,tgt,arg):
        ''' Module deployment '''
        params = {'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        return content

    def async_deploy(self,tgt,arg):
        ''' Asynchronously send a command to connected minions '''
        params = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        jid = content['return'][0]['jid']
        return jid

    def target_deploy(self,tgt,arg):
        ''' Based on the node group forms deployment '''
        params = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup'}
        obj = urllib.urlencode(params)
        self.token_id()
        content = self.postRequest(obj)
        jid = content['return'][0]['jid']
        return jid

def main():
    sapi = SaltAPI(url="https://172.25.42.1:8000",username="saltapi",password="saltapi")
    #sapi.token_id()
    print sapi.list_all_key()  ##打开该端口查看key设为A
    #sapi.delete_key('test-01')
    #sapi.accept_key('test-01')
    sapi.deploy('server3','nginx.service')   打开该端口指定主机安装相应的服务B
    #print sapi.remote_noarg_execution('test-01','grains.items')

if __name__ == '__main__':
       main()

在这里插入图片描述
测试:
//打开该端口查看key的检测

[root@server1 ~]# python saltapi.py 
([u'server2', u'server3'], [])

在这里插入图片描述
//打开该端口指定主机安装相应的服务检测

必须确保在下面目录下有相应的sls安装及其启动服务的文件
[root@server1 salt]# cd /srv/salt/
[root@server1 salt]# ls
apache  _grains  keepalived  _modules  nginx  top.sls
[root@server1 salt]# cd nginx/
[root@server1 nginx]# ls
files  install.sls  service.sls

[root@server1 ~]# python saltapi.py  server3上已经部署nginx并且出现80端口
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值