运维实操——saltstack中job缓存、salt-ssh、salt-syndic与salt-api


前言
server1是saltstack的master端,server2和server3是minion端

1、job

master在下发指令任务时,会附带上产生的jid。minion在接收到指令开始执行时,会在本地的/var/cache/salt/minion/proc目录下产生该jid命名的文件,用于在执行过程中master查看当前任务的执行情况。指令执行完毕将结果传送给master后,删除该临时文件。Job缓存默认保存24小时,有时为了留底,需要把job存到数据库中,分为两种方式

(1)、minion端存入数据库

工作机制如下图,minion端在返回数据给master时,也会给数据库一份
在这里插入图片描述
首先在server1中安装并开启mariadb-service,安全初始化mysql_secure_installation,进入数据库,需要执行创建库和三个表,为了看得清楚,写在了下面的jobs.sql文件中,编写完成后导入数据库即可。

CREATE DATABASE  `salt`							#创建库
  DEFAULT CHARACTER SET utf8
  DEFAULT COLLATE utf8_general_ci;

USE `salt`;

--
-- Table structure for table `jids`
--

DROP TABLE IF EXISTS `jids`;
CREATE TABLE `jids` (							#创建jid表
  `jid` varchar(255) NOT NULL,
  `load` mediumtext NOT NULL,
  UNIQUE KEY `jid` (`jid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#CREATE INDEX jid ON jids(jid) USING BTREE;

--
-- Table structure for table `salt_returns`
--

DROP TABLE IF EXISTS `salt_returns`;
CREATE TABLE `salt_returns` (					#创建salt_returns表
  `fun` varchar(50) NOT NULL,
  `jid` varchar(255) NOT NULL,
  `return` mediumtext NOT NULL,
  `id` varchar(255) NOT NULL,
  `success` varchar(10) NOT NULL,
  `full_ret` mediumtext NOT NULL,
  `alter_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  KEY `id` (`id`),
  KEY `jid` (`jid`),
  KEY `fun` (`fun`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Table structure for table `salt_events`
--

DROP TABLE IF EXISTS `salt_events`;
CREATE TABLE `salt_events` (					#创建salt_events表
`id` BIGINT NOT NULL AUTO_INCREMENT,
`tag` varchar(255) NOT NULL,
`data` mediumtext NOT NULL,
`alter_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`master_id` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `tag` (`tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql -pwestos < jobs.sql将测试文件导入mysql,进入数据库,授权salt用户远程操作salt.*表的所有操作
在这里插入图片描述
修改server2(minion端)的配置文件/etc/slat/minion,重启minion端
在这里插入图片描述

安装MySQL-python.x86_64 0:1.2.5-1.el7。注意:写入的语句是python语言,谁写入数据库谁就需要安装MySQL-python.x86_64 0:1.2.5-1.el7
salt server2 test.ping --return mysqlsalt server2 my_disk.df--return mysql,进行测试
在这里插入图片描述
返回server1看数据库中是否存在刚才的测试信息,如下,配置成功
在这里插入图片描述

(2)、master端存入数据库

工作机制如下图,minion端正常返回数据给master端,master端发给数据库。好处是无需到每个minion端修改策略,只需要在master端设置即可。
在这里插入图片描述
修改配置文件/etc/slat/master,如下
在这里插入图片描述

进入数据库,授权本地用户执行salt.*表的所有操作,重启salt-master,安装MySQL-python
在这里插入图片描述
salt ‘*’ test.ping,进行测试
在这里插入图片描述

成功存入数据库
在这里插入图片描述

2、salt-ssh

假如有些主机无法安装minion端,那该怎么办呢?比如server3关掉minion端。
可以使用salt-ssh的方式,salt-ssh可以独立运行的,不需要minion端。salt-ssh 用的是sshpass进行密码交互的。Ssh方式是串行模式,性能下降,所以只是补充,不是主流,主要还是minion。
在master端yum install -y salt-ssh.noarch,修改配置文件/etc/salt/roster
在这里插入图片描述
master端连接,就可以找到配置文件中写的server3,成功
在这里插入图片描述

3、salt-syndic

syndic其实就是个代理,隔离master与minion。Syndic必须要运行在master上,再连接到另一个topmaster上,Syndic是可以理解为秘书,替top master管理master。Topmaster 下发的状态需要通过syndic来传递给下级master,反过来minion传递给master的数据也是由syndic传递给topmaster,意味着topmaster并不知道有多少个minion。示意图如下
在这里插入图片描述
server1还是master,现在新建一个server4来做顶级master。和前面一样需要给server4配置yum源,安装salt-master。
server4修改配置文件/etc/salt/master,重启salt-master,现在server4就是topmaster了
在这里插入图片描述
Server1安装yum install -y salt-syndic.noarch,vim /etc/salt/master修改配置文件,告诉server1,server4是它的topmaster,重启systemctl restart salt-master.service,开启systemctl start salt-syndic.service
在这里插入图片描述

Server4,salt-key -L查看,salt-key -A添加,topmaster成功捕捉到master,看不到minion
在这里插入图片描述
salt '*' test.ping,测试成功(注意:上个ssh实验关掉了server3的minion,现在要开启,否则server3不成功)
在这里插入图片描述

4、salt-api

SaltStack 官方提供有REST API格式的 salt-api 项目,将使Salt与第三方系统集成变得尤为简单。可以使用python编写

Server1 安装yum install salt-api.noarch,cd /etc/pki/tls/private ,创建密钥openssl genrsa 1024 > localhost.key
在这里插入图片描述
cd /etc/pki/tls/certs,创建证书make testcert
在这里插入图片描述
Vim /etc/salt/master.d/api.conf创建api配置文件
在这里插入图片描述

创建/etc/salt/master.d/auth.conf认证文件,使用pam策略,对saltapi用户的权限全开
在这里插入图片描述

[root@server1 master.d]# useradd saltapi						#创建用户
[root@server1 master.d]# echo westos | passwd --stdin saltapi	#设密码
[root@server1 master.d]# systemctl restart salt-master.service 
[root@server1 master.d]# systemctl start salt-api.service 
[root@server1 master.d]# netstat -antlp | grep 8000				#成功看到api的8000端口
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      30474/salt-api 

注册产生token,然后test测试,连接成功
在这里插入图片描述
之后就可以自己用python开发特殊需要的函数。比如编写saltapi.py文件,内容如下,

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

import urllib2,urllib
import time
import ssl

ssl._create_default_https_context = ssl._create_unverified_context

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.11.1:8000',username='saltapi',password='westos')
    #sapi.token_id()
    print sapi.list_all_key()				#输出所有minion主机名
    #sapi.delete_key('test-01')
    #sapi.accept_key('test-01')
    sapi.deploy('server2','apache')			#给server2部署apache服务
    #print sapi.remote_noarg_execution('test-01','grains.items')

if __name__ == '__main__':
    main()

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值