自动化运维工具——SaltStack(下)

SaltStack

  • 一.自动化安装keepalived
  • 二.job管理
    • 1.minion传递给master
    • 2.master从minion收集
  • 三.salt-ssh
  • 四.salt-syndic
  • 五.salt-api

一.自动化安装keepalived

配置pillar,在 pillar目录下添加自定义模块


[root@server1 srv]# cat pillar/kp.sls 
{% if grains['fqdn'] == 'server2' %}
state: Master
vrid: 51
pri: 100
{% elif grains['fqdn'] == 'server3' %}
state: BACKUP
vrid: 51
pri: 50
{% endif %}



[root@server1 srv]# cat pillar/top.sls 
base:
  '*':

   - pkgs
     - kp


自动化运维工具——SaltStack(下)_第1张图片

编写keepalived脚本

创建目录keepalived

mkdir /etc/salt/keeplived

主配文件模板:

[root@server1 keepalived]# cat keepalived.conf 
! Configuration File for keepalived

global_defs {
   notification_email {
	root@localhost
   }

   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
   #vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state {{ STATE }}
    interface eth0
    virtual_router_id {{ VRID }}
    priority {{ PRI }}
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.25.3.100/24
    }

安装脚本:

[root@server1 keepalived]# cat init.sls 
kp-install:
  pkg.installed:
    - name: keepalived

  file.managed:
    - name: /etc/keepalived/keepalived.conf
    - source: salt://keepalived/keepalived.conf
    - template: jinja
    - context:
      STATE: {{ pillar['state'] }}
      VRID: {{ pillar['vrid' ]}}
      PRI: {{ pillar['pri'] }}

  service.running:
    - name: keepalived
    - reload: true
    - watch:
      - file: kp-install

自动化运维工具——SaltStack(下)_第2张图片

highstate脚本:

[root@server1 salt]# cat top.sls 
          base:
            'roles:apache':
              - match: grain
              - apache
              - keepalived
          
            'roles:nginx':
          
             - match: grain
               - nginx.service
                 - keepalived


自动化运维工具——SaltStack(下)_第3张图片

执行

 salt '*' saltutil.sync_grains

salt '*' state.highstate

自动化运维工具——SaltStack(下)_第4张图片

查看ip

ip addr show

自动化运维工具——SaltStack(下)_第5张图片

测试高可用

[root@server2 ~]# systemctl  stop keepalived.service 
[root@server2 ~]# systemctl  start keepalived.service 
[root@server2 ~]# netstat -antlp

访问vip
在这里插入图片描述

关闭server2上keepalived

systemctl  stop keepalived.service 
ip a

自动化运维工具——SaltStack(下)_第6张图片
访问vip,发现切换到server3默认发布页面:
自动化运维工具——SaltStack(下)_第7张图片
启动server2上keepalived,发现master再次切入至server2

systemctl  start keepalived.service 

自动化运维工具——SaltStack(下)_第8张图片
在这里插入图片描述

二.job管理

job下数据默认存放24小时

1.minion传递给master

server1/2安装 MySQL-python

 yum install -y MySQL-python.x86_64

server1 安装mysql,并安全初始化

 mysql_secure_installation

导入数据备份:

vim salt.sql
mysql -pwestos < salt.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` varchar(255) NOT NULL,
  `load` mediumtext NOT NULL,
  UNIQUE KEY `jid` (`jid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

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

DROP TABLE IF EXISTS `salt_returns`;
CREATE TABLE `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` (
`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
grant all on salt.* to salt@'%' identified by 'salt'; #授权用户网络访问

server2 配置minion

vim minion
return: mysql
mysql.host: '172.25.3.1'
mysql.user: 'salt'
mysql.pass: 'salt'
mysql.db: 'salt'
mysql.port: 3306
systemctl  restart  salt-minion.service

测试:

salt server2 my_disk.df

mysql -pwestos

use salt

 select * from salt_returns\G;

查看结果:

*************************** 1. row ***************************
       fun: saltutil.find_job
       jid: 20210718032447080204
    return: {}
        id: server2
   success: 1
  full_ret: {"fun_args": ["20210718032442068396"], "jid": "20210718032447080204", "return": {}, "retcode": 0, "success": true, "fun": "saltutil.find_job", "id": "server2"}
alter_time: 2021-07-17 23:24:55

2.master从minion收集

被动式:无需配置minion也可以被收集

server1配置master:

vim master
master_job_cache: mysql
mysql.host: 'localhost'
mysql.user: 'salt'
mysql.pass: 'salt'
mysql.db: 'salt'
mysql.port: 3306
systemctl  restart  salt-master.service 

授权本地用户:

mysql -pwestos

grant all on salt.* to salt@localhost identified by 'salt';

测试:

salt '*' my_disk.df  --return mysql

自动化运维工具——SaltStack(下)_第9张图片

查看

select * from salt_returns\G;

获取到server3信息

alter_time: 2021-07-17 23:32:28
*************************** 4. row ***************************
       fun: my_disk.df
       jid: 20210718033228414731
    return: "Filesystem             Size  Used Avail Use% Mounted on\n/dev/mapper/rhel-root   27G  1.3G   26G   5% /\ndevtmpfs               988M     0  988M   0% /dev\ntmpfs                 1000M  140K 1000M   1% /dev/shm\ntmpfs                 1000M  8.6M  991M   1% /run\ntmpfs                 1000M     0 1000M   0% /sys/fs/cgroup\n/dev/vda1             1014M  132M  883M  14% /boot\ntmpfs                  200M     0  200M   0% /run/user/0"
        id: server3
   success: 1
  full_ret: {"fun_args": [], "jid": "20210718033228414731", "return": "Filesystem             Size  Used Avail Use% Mounted on\n/dev/mapper/rhel-root   27G  1.3G   26G   5% /\ndevtmpfs               988M     0  988M   0% /dev\ntmpfs                 1000M  140K 1000M   1% /dev/shm\ntmpfs                 1000M  8.6M  991M   1% /run\ntmpfs                 1000M     0 1000M   0% /sys/fs/cgroup\n/dev/vda1             1014M  132M  883M  14% /boot\ntmpfs                  200M     0  200M   0% /run/user/0", "retcode": 0, "success": true, "cmd": "_return", "_stamp": "2021-07-18T03:32:28.691707", "fun": "my_disk.df", "id": "server3"}
alter_time: 2021-07-17 23:32:28

三.salt-ssh

安装salt-ssh:

yum install -y salt-ssh

vim roster
server3:
   host: 172.25.3.3
   user: root
   passwd: westos

自动化运维工具——SaltStack(下)_第10张图片
测试:

salt-ssh '*' test.ping

自动化运维工具——SaltStack(下)_第11张图片

四.salt-syndic

server4

 yum install -y salt-master

vim master

order_masters: True

自动化运维工具——SaltStack(下)_第12张图片

server1

yum install -y salt-syndic

vim master
syndic_master: 172.25.3.4

自动化运维工具——SaltStack(下)_第13张图片

启动服务:

 systemctl  restart  salt-master.service 
 systemctl  start salt-syndic.service 

注册主机:

 salt-key -L
salt-key -A

自动化运维工具——SaltStack(下)_第14张图片

测试:

 cd /etc/salt/
salt '*' my_disk.df

自动化运维工具——SaltStack(下)_第15张图片

五.salt-api

安装salt-api

yum install -y  slat-api

自动化运维工具——SaltStack(下)_第16张图片

编辑认证及调用配置文件:

[root@server1 ~]# cd /etc/salt/master.d/
[root@server1 master.d]# cat api.conf 
rest_cherrypy:
  port: 8000
  ssl_crt: /etc/pki/tls/certs/localhost.crt
  ssl_key: /etc/pki/tls/private/localhost.key
[root@server1 master.d]# cat auth.conf 
external_auth:
  pam:
    saltapi:
      - .*
      - '@wheel'
      - '@runner'
      - '@jobs'
cd /etc/salt/master.d/

vim auth.conf

vim api.conf

自动化运维工具——SaltStack(下)_第17张图片
auth.conf
自动化运维工具——SaltStack(下)_第18张图片
api.conf
在这里插入图片描述

创建saltapi用户

 useradd saltapi

echo westos |passwd --stdin saltapi

自动化运维工具——SaltStack(下)_第19张图片

生成密钥

cd /etc/pki/tls/private/

openssl genrsa 1024 > localhost.key

自动化运维工具——SaltStack(下)_第20张图片

生成认证文件

cd /etc/pki/tls/certs/

[root@server1 certs]# make testcert
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 
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) []:shannxi
Locality Name (eg, city) [Default City]:xian
Organization Name (eg, company) [Default Company Ltd]:westos
Organizational Unit Name (eg, section) []:linux
Common Name (eg, your name or your server's hostname) []:server1
Email Address []:[email protected]

查看认证文件及密钥

[root@server1 master.d]# ll /etc/pki/tls/private/localhost.key 
-rw-r--r-- 1 root root 887 Jul 18 03:18 /etc/pki/tls/private/localhost.key
[root@server1 master.d]# ll /etc/pki/tls/certs/localhost.crt 
-rw------- 1 root root 1038 Jul 18 03:19 /etc/pki/tls/certs/localhost.crt


启动服务:

systemctl restart  salt-master.service

systemctl  start salt-api.service

自动化运维工具——SaltStack(下)_第21张图片

获取token认证码

 curl -sSk https://172.25.3.1:8000/login -H 'Accept: application/x-yaml' -d username=saltapi   -d password=westos  -d eauth=pam

认证玛内容

    return:
    
    - eauth: pam
      expire: 1626636538.547457
      perms:
      - .*
      - '@wheel'
      - '@runner'
      - '@jobs'
        start: 1626593338.547456
        token: fd2a30e454581056e12493c7ada7c7d97f7b9a3d
        user: saltapi

自动化运维工具——SaltStack(下)_第22张图片

调用api接口:

 curl -sSk https://172.25.3.1:8000 -H 'Accept: application/x-yaml' -H 'X-Auth-Token: fd2a30e454581056e12493c7ada7c7d97f7b9a3d' -d username=saltapi   -d password=westos  -d client=local -d tgt='*' -d fun=test.ping

return:
- server2: true
  server3: true

自动化运维工具——SaltStack(下)_第23张图片

执行saltapi.py

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


[root@server1 ~]# cat 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.3.1:8000',username='saltapi',password='westos')
    sapi.token_id()
    print sapi.list_all_key()
    #sapi.delete_key('test-01')
    #sapi.accept_key('test-01')
    #sapi.deploy('*','httpd.apache')
    #print sapi.remote_noarg_execution('test-01','grains.items')

if __name__ == '__main__':
    main()

主函数调用部分:
自动化运维工具——SaltStack(下)_第24张图片

执行结果:

在这里插入图片描述

你可能感兴趣的:(SaltStack,linux学习,运维)