自动化运维工具php
运维目标有三个阶段,第一是追求稳定性,第二是追求标准化,第三是追求自动化。对于第三阶段来讲,什么是运维自动化呢?简单地讲,运维自动化就是将平常重复性工做按照事先设定好的规则,在必定时间范围内自动化运行,而不须要人工参与。接下来简单介绍经常使用运维自动化工具。html
同类自动化工具GitHub关注程度node
同类的自动化运维工具 | Watch(关注) | Star(点赞) | Fork(复制) | Contributors(贡献者) |
---|---|---|---|---|
Ansible | 1387 | 17716 | 5356 | 1428 |
Saltstack | 530 | 6678 | 3002 | 1520 |
Puppet | 463 | 4044 | 1678 | 425 |
Chef | 383 | 4333 | 1806 | 464 |
Fabric | 379 | 7334 | 1235 | 116 |
技术特性比较python
名称 | Puppet | SaltStack | Ansible |
---|---|---|---|
开发语言 | Ruby | Python | Python |
客户端 | 有 | 有 | 无(也是缺点,机器太多的时候会变慢,串行) |
二次开发 | 不支持 | 支持 | 支持 |
通讯验证 | 是 | 是 | 是 |
同窗加密 | 标准SSL协议 | AES加密 | OpenSSH |
平台支持 | AIX,BSD,HP-UX,Linux,Mac OS X,Solaris,Windows | BSD,Linux,Mac OS X,Solaris,Windows | AIX,BSD,HP-UX,Linux,Mac OS X,Solaris |
配置文件格式 | Ruby语法格式 | YAML | YAML |
Web UI | 提供 | 提供 | 提供(商业版本) |
命令执行 | 不支持(配置模块可实现) | 支持 | 支持 |
优缺点对比mysql
名称 | 优点 | 劣势 | 成本 |
---|---|---|---|
Puppet | 模块由Ruby或Ruby子集编写 push命令能够便可触发变动 Web界面生成处理报表、资源清单、实时节点管理 代理运行端进行详细、深刻的报告和对节点进行配置 |
相对其余工具较复杂,需学习Puppet的DSL或Ruby 安装过程缺乏错误校验和产生错误报表 |
开源软件免费 SaltStack企业版每一年内个节点花费约¥100 |
Saltstack | 状态文件可用简单YAML配置模块或复杂的Python/PyDSL脚本 与客户端能够基于SSH或在被管节点安装代理 Web界面可看到运行的工做、minion状态、事件日志、可在客户端执行命令 扩展能力极强 |
Web界面像毒药竞争产品不稳定与相对不完善 缺少生成深度报告的能力 |
开源软件免费 SaltStack企业版每一年内个节点花费约¥150,随着数量增长相应的会有折扣 |
Ansible | 模块能够用任何语言开发 备管节点不须要安装代理软件 有Web管理界面、可配置用户、组、资源清单和执行Playbook 安装、运行极其简单 |
对备管理节点为Windows有待增强 Web管理界面是内置的Ansible的一部分 需导入资源清单 执行效率较低 |
开源版本免费 Ansible Tower小于10台被管理节点免费 超过10太后没年每台需支付¥100~$250的支持服务费用 |
1.Fabriclinux
Fabric 是一个用 Python 编写的命令行工具库,它能够帮助系统管理员高效地执行某些任务,好比经过 SSH 到多台机器上执行某些命令,远程布署应用等。ios
1.1.安装nginx
yum -y install python-devel 安装python-devel wget https://bootstrap.pypa.io/get-pip.py & python get-pip.py安装pip pip install fabric 安装fabric fab 测试
1.2.例子web
#!/usr/bin/env python # coding: utf-8 """ 查看本地与远程主机信息 经常使用API搜索 local 执行本地命令, local('unamr -a') lcd 切换本地目录, lcd('/home') cd 切换远程目录, cd('/var/log') run 执行远程命令, run('free -m') sudo sudo方式执行远程命令, sudo('service httpd reload') put 上传本地文件到远程主机, put('/home/1.txt', '/data/1.txt') get 从远程主机下载文件到本地, get('/home/1.txt', '/data/1.txt') prompt 获取用户输入信息, prompt('please input user password: ') confirm 获取提示信息确认, confirm('Tests failed.Continue(Y/N)? ') reboot 重启远程主机, reboot() @runs_once 函数装饰符, 标识的函数只会执行一次, 不受多台主机影响 """ from fabric.api import * env.user = 'root' env.hosts = ['192.168.1.7', '192.168.1.8'] env.password = '456852.com' @runs_once #查看本地系统信息, 当有多台主机时,只运行一台 def local_task(): #本地任务函数 local('uname -a') def remote_task(): with cd('/var/log'): #with 的做用是让后面的表达式的语句继承当前状态, 实现 'cd /var/log && ls -l' run('ls -l')
#!/usr/bin/python # -*- coding:utf-8 -*- from fabric.api import * # 设置服务器登陆参数 env.roledefs = { # 操做一致的放一组,一组执行同一个操做 'servers1':['root@linux2:22',], # 第二组 'servers2':['root@linux3:22',] } # 本机操做 def localtask(): local('/usr/local/nginx/nginx') # servers1服务器组操做 @roles('servers1') def task1(): run('/usr/local/tomcat/bin/startup.sh') # servers2 服务器组操做 @roles('servers2') def task2(): run('/usr/local/tomcat/bin/startup.sh') # 执行任务 def doworks(): execute(localtask) execute(task1) execute(task2)
#!/bin/bash # -*- coding: utf-8 -*- import paramiko,os,time,shutil from fabric.api import * from fabric.colors import * env.user = 'root' env.hosts = ['192.168.10.241','192.168.10.242','192.168.10.243','192.168.10.244','192.168.10.245'] env.passwords = { 'root@192.168.10.241:22':'p3mtk', 'root@192.168.10.242:22':'VU6w3', 'root@192.168.10.243:22':'1uP1P', 'root@192.168.10.244:22':'6tznM7', 'root@192.168.10.245:22':'4DXkv5', } os.system("""rm -r -f pid_test.log""") os.system("""date>> /home/post/serverpid/pid.log""") os.system("""date>> /home/post/serverpid/pid_test.log""") os.system("""echo ================================================================================>> /home/post/serverpid/pid.log""") os.system("""echo ================================================================================>> /home/post/serverpid/pid_test.log""") #@runs_once #def clear_log(): # local("""echo ''>>/home/post/serverpid/pid_test.log""") def test(): local("""echo ''>>/home/post/serverpid/pid_test.log""") with settings(hide('running','stdout', 'stderr','warnings','everything')): h2 = "ps -ef|grep home/lcs/web/tomcat-job/bin/bootstrap|grep -v grep|awk '{print $2}'" #192.168.10.245 h3 = "ps -ef|grep robot|grep -v grep|awk '{print $2}'" #192.168.10.241,192.168.10.242,192.168.10.243 h4 = "ps -ef|grep mysql|grep -v grep|awk '{print $2}'" #192.168.10.245 h5 = "ps -ef|grep redis|grep -v grep|awk '{print $2}'" #192.168.10.245 h6 = "ps -ef|grep zookeeper|grep -v grep|awk '{print $2}'" #192.168.10.241,192.168.10.242,192.168.10.243 h7 = "ps -ef|grep IPProxy.py|grep -v grep|awk '{print $2}'" #192.168.10.244 if env.host == '192.168.10.245': result_245_tomcat = run(h2) result_245_redis = run(h4) result_245_mysql = run(h5) if (result_245_tomcat == "") or (result_245_mysql == "") or (result_245_redis == ""): local("""echo '%s'' %s' 执行失败,PID为‘%s’>>/home/post/serverpid/pid.log"""%(env.host,h2,result_245_tomcat)) local("""echo '%s'' %s' 执行失败,PID为‘%s’>>/home/post/serverpid/pid.log"""%(env.host,h4,result_245_mysql)) local("""echo '%s'' %s' 执行失败,PID为‘%s’>>/home/post/serverpid/pid.log"""%(env.host,h5,result_245_redis)) local("""echo '%s'' %s' 执行失败,PID为‘%s’>>/home/post/serverpid/pid_test.log"""%(env.host,h2,result_245_tomcat)) local("""echo '%s'' %s' 执行失败,PID为‘%s’>>/home/post/serverpid/pid_test.log"""%(env.host,h4,result_245_mysql)) local("""echo '%s'' %s' 执行失败,PID为‘%s’>>/home/post/serverpid/pid_test.log"""%(env.host,h5,result_245_redis)) else: local("""echo '%s'' %s' 执行成功,PID为‘%s’>>/home/post/serverpid/pid.log"""%(env.host,h2,result_245_tomcat)) local("""echo '%s'' %s' 执行成功,PID为‘%s’>>/home/post/serverpid/pid.log"""%(env.host,h4,result_245_mysql)) local("""echo '%s'' %s' 执行成功,PID为‘%s’>>/home/post/serverpid/pid.log"""%(env.host,h5,result_245_redis)) local("""echo '%s'' %s' 执行成功,PID为‘%s’>>/home/post/serverpid/pid_test.log"""%(env.host,h2,result_245_tomcat)) local("""echo '%s'' %s' 执行成功,PID为‘%s’>>/home/post/serverpid/pid_test.log"""%(env.host,h4,result_245_mysql)) local("""echo '%s'' %s' 执行成功,PID为‘%s’>>/home/post/serverpid/pid_test.log"""%(env.host,h5,result_245_redis)) #print yellow("%s 执行成功...") %env.host elif env.host == '192.168.10.244': result_244_ipproxy = run(h7) if (result_244_ipproxy == ""): local("""echo '%s'' %s' 执行失败,PID为空>>/home/post/serverpid/pid.log"""%(env.host,h7)) local("""echo '%s'' %s' 执行失败,PID为空>>/home/post/serverpid/pid_test.log"""%(env.host,h7)) #abort(red("错误...")) else: local("""echo '%s'' %s' 执行成功>>/home/post/serverpid/pid.log"""%(env.host,h7)) local("""echo '%s'' %s' 执行成功>>/home/post/serverpid/pid_test.log"""%(env.host,h7)) #print yellow("%s 执行成功...") %env.host else: result_robot = run(h3) result_zookeeper = run(h6) if result_robot.strip('\n') == '': local("""echo '%s'' %s' 执行失败,PID为空>>/home/post/serverpid/pid.log"""%(env.host,h3)) local("""echo '%s'' %s' 执行失败,PID为空>>/home/post/serverpid/pid_test.log"""%(env.host,h3)) elif result_zookeeper.strip('\n') =='': local("""echo '%s'' %s' 执行失败,PID为空>>/home/post/serverpid/pid.log"""%(env.host,h6)) local("""echo '%s'' %s' 执行失败,PID为空>>/home/post/serverpid/pid_test.log"""%(env.host,h6)) else: local("""echo '%s'' %s' 执行成功>>/home/post/serverpid/pid.log"""%(env.host,h3)) local("""echo '%s'' %s' 执行成功>>/home/post/serverpid/pid.log"""%(env.host,h6)) local("""echo '%s'' %s' 执行成功>>/home/post/serverpid/pid_test.log"""%(env.host,h3)) local("""echo '%s'' %s' 执行成功>>/home/post/serverpid/pid_test.log"""%(env.host,h6)) #print yellow("%s 执行成功...") %env.host def go(): test()
alarm_msg = local(zabbix_off,capture=True) 说明:capture=True参数默认值是False,表示输出到终端) 调用:fab -f test.py remote_task 帮助:fab --help
2.Paramikoredis
paramiko模块,基于SSH用于链接远程服务器并执行相关操做。使用该模块能够对远程服务器进行命令或文件操做,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。
2.1.安装paramiko
pip3 install paramiko
2.2.使用paramiko
sshclient
import paramiko # 建立SSH对象 ssh = paramiko.SSHClient() # 容许链接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 链接服务器 ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', password='123') # 执行命令 stdin, stdout, stderr = ssh.exec_command('ls') # 获取命令结果 result = stdout.read() # 关闭链接 ssh.close()
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') # 建立SSH对象 ssh = paramiko.SSHClient() # 容许链接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 链接服务器 ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', key=private_key) # 执行命令 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() # 关闭链接 ssh.close()
sshcilent是传统的链接服务器、执行命令、关闭的一个操做,有时候须要登陆上服务器执行多个操做,好比执行命令、上传/下载文件,方法1则没法实现,能够经过以下方式来操做
# 实例化一个transport对象 trans = paramiko.Transport(('192.168.2.129', 22)) # 创建链接 trans.connect(username='super', password='super') # 将sshclient的对象的transport指定为以上的trans ssh = paramiko.SSHClient() ssh._transport = trans # 执行命令,和传统方法同样 stdin, stdout, stderr = ssh.exec_command('df -hl') print(stdout.read().decode()) # 关闭链接 trans.close() --------------------- 做者:songfreeman 来源:CSDN 原文:https://blog.csdn.net/songfreeman/article/details/50920767 版权声明:本文为博主原创文章,转载请附上博文连接!
# 指定本地的RSA私钥文件,若是创建密钥对时设置的有密码,password为设定的密码,如无不用指定password参数 pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345') # 创建链接 trans = paramiko.Transport(('192.168.2.129', 22)) trans.connect(username='super', pkey=pkey) # 将sshclient的对象的transport指定为以上的trans ssh = paramiko.SSHClient() ssh._transport = trans # 执行命令,和传统方法同样 stdin, stdout, stderr = ssh.exec_command('df -hl') print(stdout.read().decode()) # 关闭链接 trans.close() --------------------- 做者:songfreeman 来源:CSDN 原文:https://blog.csdn.net/songfreeman/article/details/50920767 版权声明:本文为博主原创文章,转载请附上博文连接!
sftpclient
import paramiko transport = paramiko.Transport(('hostname',22)) transport.connect(username='wupeiqi',password='123') sftp = paramiko.SFTPClient.from_transport(transport) # 将location.py 上传至服务器 /tmp/test.py sftp.put('/tmp/location.py', '/tmp/test.py') # 将remove_path 下载到本地 local_path sftp.get('remove_path', 'local_path') transport.close()
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') transport = paramiko.Transport(('hostname', 22)) transport.connect(username='wupeiqi', pkey=private_key ) sftp = paramiko.SFTPClient.from_transport(transport) # 将location.py 上传至服务器 /tmp/test.py sftp.put('/tmp/location.py', '/tmp/test.py') # 将remove_path 下载到本地 local_path sftp.get('remove_path', 'local_path') transport.close()
3.demo
#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko import uuid class SSHConnection(object): def __init__(self, host='172.16.103.191', port=22, username='wupeiqi',pwd='123'): self.host = host self.port = port self.username = username self.pwd = pwd self.__k = None def create_file(self): file_name = str(uuid.uuid4()) with open(file_name,'w') as f: f.write('sb') return file_name def run(self): self.connect() self.upload('/home/wupeiqi/tttttttttttt.py') self.rename('/home/wupeiqi/tttttttttttt.py', '/home/wupeiqi/ooooooooo.py) self.close() def connect(self): transport = paramiko.Transport((self.host,self.port)) transport.connect(username=self.username,password=self.pwd) self.__transport = transport def close(self): self.__transport.close() def upload(self,target_path): # 链接,上传 file_name = self.create_file() sftp = paramiko.SFTPClient.from_transport(self.__transport) # 将location.py 上传至服务器 /tmp/test.py sftp.put(file_name, target_path) def rename(self, old_path, new_path): ssh = paramiko.SSHClient() ssh._transport = self.__transport # 执行命令 cmd = "mv %s %s" % (old_path, new_path,) stdin, stdout, stderr = ssh.exec_command(cmd) # 获取命令结果 result = stdout.read() def cmd(self, command): ssh = paramiko.SSHClient() ssh._transport = self.__transport # 执行命令 stdin, stdout, stderr = ssh.exec_command(command) # 获取命令结果 result = stdout.read() return result ha = SSHConnection() ha.run()
4.实现输入命令立马返回结果的功能
以上操做都是基本的链接,若是咱们想实现一个相似xshell工具的功能,登陆之后能够输入命令回车后就返回结果:
import paramiko import os import select import sys # 创建一个socket trans = paramiko.Transport(('192.168.2.129', 22)) # 启动一个客户端 trans.start_client() # 若是使用rsa密钥登陆的话 ''' default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') prikey = paramiko.RSAKey.from_private_key_file(default_key_file) trans.auth_publickey(username='super', key=prikey) ''' # 若是使用用户名和密码登陆 trans.auth_password(username='super', password='super') # 打开一个通道 channel = trans.open_session() # 获取终端 channel.get_pty() # 激活终端,这样就能够登陆到终端了,就和咱们用相似于xshell登陆系统同样 channel.invoke_shell() # 下面就能够执行你全部的操做,用select实现 # 对输入终端sys.stdin和 通道进行监控, # 当用户在终端输入命令后,将命令交给channel通道,这个时候sys.stdin就发生变化,select就能够感知 # channel的发送命令、获取结果过程其实就是一个socket的发送和接受信息的过程 while True: readlist, writelist, errlist = select.select([channel, sys.stdin,], [], []) # 若是是用户输入命令了,sys.stdin发生变化 if sys.stdin in readlist: # 获取输入的内容 input_cmd = sys.stdin.read(1) # 将命令发送给服务器 channel.sendall(input_cmd) # 服务器返回告终果,channel通道接受到结果,发生变化 select感知到 if channel in readlist: # 获取结果 result = channel.recv(1024) # 断开链接后退出 if len(result) == 0: print("\r\n**** EOF **** \r\n") break # 输出到屏幕 sys.stdout.write(result.decode()) sys.stdout.flush() # 关闭通道 channel.close() # 关闭连接 trans.close() --------------------- 做者:songfreeman 来源:CSDN 原文:https://blog.csdn.net/songfreeman/article/details/50920767 版权声明:本文为博主原创文章,转载请附上博文连接!
5.支持tab命令补全
import paramiko import os import select import sys import tty import termios ''' 实现一个xshell登陆系统的效果,登陆到系统就不断输入命令同时返回结果 支持自动补全,直接调用服务器终端 ''' # 创建一个socket trans = paramiko.Transport(('192.168.2.129', 22)) # 启动一个客户端 trans.start_client() # 若是使用rsa密钥登陆的话 ''' default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') prikey = paramiko.RSAKey.from_private_key_file(default_key_file) trans.auth_publickey(username='super', key=prikey) ''' # 若是使用用户名和密码登陆 trans.auth_password(username='super', password='super') # 打开一个通道 channel = trans.open_session() # 获取终端 channel.get_pty() # 激活终端,这样就能够登陆到终端了,就和咱们用相似于xshell登陆系统同样 channel.invoke_shell() # 获取原操做终端属性 oldtty = termios.tcgetattr(sys.stdin) try: # 将如今的操做终端属性设置为服务器上的原生终端属性,能够支持tab了 tty.setraw(sys.stdin) channel.settimeout(0) while True: readlist, writelist, errlist = select.select([channel, sys.stdin,], [], []) # 若是是用户输入命令了,sys.stdin发生变化 if sys.stdin in readlist: # 获取输入的内容,输入一个字符发送1个字符 input_cmd = sys.stdin.read(1) # 将命令发送给服务器 channel.sendall(input_cmd) # 服务器返回告终果,channel通道接受到结果,发生变化 select感知到 if channel in readlist: # 获取结果 result = channel.recv(1024) # 断开链接后退出 if len(result) == 0: print("\r\n**** EOF **** \r\n") break # 输出到屏幕 sys.stdout.write(result.decode()) sys.stdout.flush() finally: # 执行完后将如今的终端属性恢复为原操做终端属性 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) # 关闭通道 channel.close() # 关闭连接 trans.close() --------------------- 做者:songfreeman 来源:CSDN 原文:https://blog.csdn.net/songfreeman/article/details/50920767 版权声明:本文为博主原创文章,转载请附上博文连接!
3.Saltstack
Salt,一种全新的基础设施管理方式,部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通信。 SaltStack是使用Python语言开发,同时提供Rest API方便二次开发以及和其它平台进行集成。
Salt底层采用动态的链接总线, 使其能够用于远程执行(最先是作远程执行), 配置管理(状态管理),云管理(salt-cloud)和事件驱动等等。
详细介绍 官方文档 saltstack原理
1.安装配置
1.关闭防火墙和selinux
中止: systemctl disable firewalld
禁用: systemctl stop firewalld
vi /etc/selinux/config
将SELINUX=enforcing改成SELINUX=disabled
2.修改master和minion的host(也能够不修改)
192.168.10.231 node1 #master 和minion
192.168.10.232 node2 #minion
3.master和minion添加阿里源
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
或者使用saltstack源
sudo yum install -y https://repo.saltstack.com/yum/redhat/salt-repo-latest-2.el7.noarch.rpm
4.安装saltstack
服务器安装:yum -y install salt-master salt-minion #master服务器端既安装master服务也安装minion服务
客户端安装:yum -y install salt-minion #minion服务器只安装minion服务
5.启动master和minion
systemctl enable /usr/lib/systemd/system/salt-master.service
systemctl start salt-master
systemctl enable /usr/lib/systemd/system/salt-minion.service
systemctl start salt-minion
6.配置
服务器配置:配置文件在/etc/salt下 注意:masterhe和minion的配置文件多一个空格都会报错(注意:服务器端的配置能够不用写,只配置minion端就ok)
[root@node1 ~]# grep -vE "^$|#" /etc/salt/master
interface: 192.168.10.231
客户端配置:
[root@node2 ~]# grep -vE "^$|#" /etc/salt/minion
master: 192.168.10.231 #修改为master的ip,写域名也能够,若是有内部dns的话
id: node2 #能够修改成ip地址,这样就必须以ip地址为惟一性。通常不修改
2.master和minion的公钥交互过程
1.首先咱们来看minion服务器的配置文件
minion服务器 [root@node2 salt]# tree /etc/salt/ . ├── cloud ├── cloud.conf.d ├── cloud.deploy.d ├── cloud.maps.d ├── cloud.profiles.d ├── cloud.providers.d ├── master ├── master.d ├── minion ├── minion.d ├── minion_id #很是重要 ├── pki │ ├── master │ └── minion │ ├── minion.pem #公钥 │ └── minion.pub #私钥 ├── proxy ├── proxy.d └── roster 咱们在上一步已经将minion的配置文件中的id改为主机名。再看id参数的解释时候发现,若是id不设置,minion服务器会获取一个socket.getfqdn()的fqdn的名称,放置在minion_id文件里面,若是刚开始没设置id参数,后来设置的话,须要将minion_id文件删除,至关于删除魂缓存,而后从新启动。 在通常的游戏公司会将id设置成ip地址,来确保惟一性。 pki目录是minion在第一次启动以后生成的机器公钥和私钥,nminion将本身的公钥(minion.pem)发送给matser,先放在master的/etc/salt/pki/minions_pre下,而且以minion配置文件中的id命名(相似:linux-node1.example.com,其中linux-node1是你机器的主机名称) 2.其次查看master服务器的配置文件 master服务器 [root@node1 pki]# tree /etc/salt/pki/ #存放minion服务器发送过来的公钥的目录 . ├── master │ ├── master.pem │ ├── master.pub │ ├── minions #活动的 │ ├── minions_autosign #注册的 │ ├── minions_denied #不容许的 │ ├── minions_pre #存放minio服务器发送过来的公钥 │ │ ├── node1 │ │ └── node2 │ └── minions_rejected #拒绝的 └── minion ├── minion.pem └── minion.pub master在第一次启动的时候会建立master文件夹,里面有如上文件夹,在minion服务器将公钥发过来以后,master要进行认证。使用salt-key命令来认证,其中salt-key -a(容许一个) node* 是支持通配符的,salt-key -A(容许全部) 不支持通配符 [root@node1 master]# salt-key -a node* ,输入y确认 Accepted Keys: #容许的minion Denied Keys: #不容许的minion Unaccepted Keys: #未认证的minion node1 node2 Rejected Keys: #拒绝的minion 3.接下来,看minion服务器的配置文件发生了什么变化 minion服务器 [root@node2 salt]# tree . ├── cloud ├── cloud.conf.d ├── cloud.deploy.d ├── cloud.maps.d ├── cloud.profiles.d ├── cloud.providers.d ├── master ├── master.d ├── minion ├── minion_id #很是重要 ├── minion.d │ └── _schedule.conf ├── pki │ ├── master │ └── minion │ ├── minion_master.pub #master的服务器的公钥 │ ├── minion.pem │ └── minion.pub ├── proxy ├── proxy.d └── roster 咱们能看到/etc/salt/pki/minion目录下多了一个minion_master.pub文件,这个是在刚才master服务器认证命令执行以后,matser发给minion服务器的公钥,这样双方就能够通讯了
4.接下来,看master服务器配置文件发生了什么变化 matser服务器 [root@node1 pki]# tree /etc/salt/pki . ├── master │ ├── master.pem │ ├── master.pub │ ├── minions │ │ ├── node1 │ │ └── node2 │ ├── minions_autosign │ ├── minions_denied │ ├── minions_pre │ └── minions_rejected └── minion ├── minion_master.pub ├── minion.pem └── minion.pub 7 directories, 7 files 咱们能够看到,minions_pre下的公钥转移到了minions,而且,minion本身的minion_master.pub公钥也放到了对应目录, master只能管理/etc/salt/pki/master/minions目录里面的机器,这就是master和minion的验证步骤,很是安全,其中传输过程是经过AES算法来加密的
注意:若是想更改minion配置文件里面的id该如何作那?
1.将要修改的minion服务器从master同一列表里面删除,使用salt-key -d id名
2.在minion服务器上将minion服务停掉
3.删除minion服务器/etc/salt/pki目录
4.删掉/etc/salt/目录下的minion_id文件
5.在配置文件里面修改minion的id
6.从新启动,在master上从新添加minion
接下来咱们查看salt-master安装了那些文件,方便咱们了解saltsatck的往后操做
master上:
[root@centos7-node1 ~]# rpm -ql salt-master
/etc/salt/master #salt-master的配hi文件爱你
/usr/bin/salt #salt-master操做的核心命令
/usr/bin/salt-cp #salt文件传输命令
/usr/bin/salt-key #salt证书管理命令
/usr/bin/salt-master #salt master 服务命令
/usr/bin/salt-run #saltmaster runner 命令
/usr/bin/salt-unity
/usr/lib/systemd/system/salt-master.service #salt-master服务启动脚本
/usr/share/man/man1/salt-cp.1.gz
/usr/share/man/man1/salt-key.1.gz
/usr/share/man/man1/salt-master.1.gz
/usr/share/man/man1/salt-run.1.gz
/usr/share/man/man1/salt-unity.1.gz
/usr/share/man/man7/salt.7.gz
minion:
[root@centos7-node2 salt]# rpm -ql salt-minion
/etc/salt/minion #minion服务器配置文件
/usr/bin/salt-call #minion salt-call命令
/usr/bin/salt-minion #salt minion服务命令
/usr/lib/systemd/system/salt-minion.service #minion服务启动脚本
/usr/share/man/man1/salt-call.1.gz
/usr/share/man/man1/salt-minion.1.gz
master配置文件中重要的参数:
max_open_files :能够根据master将minion的数量进行适当的调整
timeout:能够根据master和minion的网络状态调整
auto_accpet和autosign_file :在大规模部署minion的时候设置自动签证
master_tops和全部以external开头的参数:是saltstack与外部系统进行整合相关配置参数
3.学习saltstack的命令
第一个salt命令,检查通讯是否正常
salt(命令) '*'(匹配目标) test.ping(test模块里面的ping函数,注意:这里面的ping不是icmp的那个ping命令)
[root@node1 pki]# salt '*' test.ping node2: True node1: True [root@node1 pki]#
第二个salt命令。也能够叫超级命令
[root@node1 pki]# salt \* cmd.run 'id'
node2:
uid=0(root) gid=0(root) groups=0(root)
node1:
uid=0(root) gid=0(root) groups=0(root)
[root@node1 pki]#
3.1 salt命令附加
salt -h usage: salt [options] '<target>' <function> [arguments]
options:操做参数 state:salt中的配置管理系统 target:salt中的管理对象或者叫操做目标参数(服务器) -E:正则匹配 --pcre -L:列表匹配 --list -G:grains匹配 --grain -N:组匹配 --nodegroup -R:范围匹配 --range -C:综合匹配,指的多个条件匹配 --compound —I:pillar值匹配 --pillar —S:minion网段匹配 --ipcidr
4.master和minion通讯
在saltstack中使用了zeromq队列来出来master和minion之间的并发执行命令
[root@node1 pki]# lsof -ni:4505
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
salt-mast 7791 root 16u IPv4 5889405 0t0 TCP *:4505 (LISTEN)
salt-mast 7791 root 18u IPv4 5924298 0t0 TCP 192.168.10.231:4505->192.168.10.232:49386 (ESTABLISHED)
salt-mast 7791 root 19u IPv4 5925223 0t0 TCP 192.168.10.231:4505->192.168.10.231:42746 (ESTABLISHED)
salt-mini 9629 root 21u IPv4 5923723 0t0 TCP 192.168.10.231:42746->192.168.10.231:4505 (ESTABLISHED)
[root@node1 pki]#
能够看到master全部的命令都经过监听4505端口,来进行并行(zeromq)处理命令,处理结果经过matser的4506端口来接受
5.salt配置管理
默认saltstack配置管理的配置文件的格式为yaml,类型xml标记语言
数据结构能够用相似大纲的缩排方式呈现,结构经过缩进来表示,连续的项目经过减号“-”来表示,map结构里面的key/value对用冒号“:”来分隔。样例以下:
house: family: name: Doe parents: - John - Jane children: - Paul - Mark - Simone address: number: 34 street: Main Street city: Nowheretown zipcode: 12345
-短横线表明列表
缩进是两个空格,
5.1配置管理
saltstack自带一个文件“File Server settings“设置的小系统,经过设置它,来告诉saltstack来读取配置文件
打开master的配置文件,找到first_root,打开注释(若是只有一个,那么base是必须存在的,开发,运维,测试可使用不一样的文件,就能够按照下面的来建立)
file_roots:
base:
- /srv/salt/base
建立目录: mkdir -p /srv/salt/base/web(最后的文件起什么名字均可以,只是为了和想配置其余服务区分开,若是你要配置mysql,就能够再建立mysql)
从新启动master:systemctl restart master
进入/srv/salt/base/web目录下,建立配置文件(配置文件的后缀名称必须以.sls结尾)
vim apache.sls,进行编辑
apache-install: #在配置文件中顶格写,个人理解是id,就是给你要安装的软件起个名字,用来区分配置文件中其余要安装的软件
pkg.installed: #在配置文件两个空格后开始写,pkg是一个模块,installed是模块中的一个安装方法,pgk的模块会匹配你的操做系统而后使用各个系统的安装方法
- name: sysstat #在配置文件中四个空格后开始写,https是要安装的服务名称
apache-service:
service.running: #service是一个状态模块,running是模块中的一个running性方法
- name: httpd #要运行的服务名称,启动的时候service也会去判断系统,而后使用系统的启动方法
- enable: True #enable是开机自启
注意:必定不要用tab键,和空格数量要确认好
确认配置:
1.master中的File Server settings的配置是
file_roots:
base:
- /srv/salt/base
dev:
- /srv/salt/dev
test:
- /srv/salt/test
prod:
- /srv/salt/prod
2.肯定文件路径
[root@node1 salt]# ll /srv/salt/base/web
total 4
-rw-r--r-- 1 root root 54 Nov 29 05:25 apache.sls
3.肯定内容是否按照yaml标准来执行编写的
肯定执行结果:
salt 'node2' state.sls web.apache saltenv=prod
#salt是命令
#‘node2’是在什么主机上执行
#stata.sls是远程执行命令
#web.apache是在/srv/salt/base/下web目录里面的apache
#saltenv=prod是默认在这个base目录下执行,若是要在/srv/salt/prod目录下执行的话,要加上该句
[root@node1 salt]# salt 'node2' state.sls web.apache
node2:
----------
ID: apache-install
Function: pkg.installed
Name: sysstat
Result: True
Comment: All specified packages are already installed
Started: 05:56:09.247803
Duration: 1505.008 ms
Changes:
Summary for node2
------------
Succeeded: 1
Failed: 0
------------
Total states run: 1
Total run time: 1.505 s
[root@node1 salt]#
5.2top.sls,能体现saltstack的自动化,能指定minion具体作什么
必须写在base目录下,而且文件名字必须为top.sls
vim top.sls
base:
'node1': #表明全部机器
- web.apache #表明使用top.sls执行web目录下的apache.sls,可是要注意,不加.sls后缀名
执行salt '*' state.highstate
[root@node1 base]# salt '*' state.highstate
node2:
----------
ID: states
Function: no.None
Result: False
Comment: No Top file or master_tops data matches found.
Changes:
Summary for node2------------
Succeeded: 0
Failed: 1
------------
Total states run: 1
Total run time: 0.000 ms
node1:
----------
ID: sysstat-install
Function: pkg.installed
Name: sysstat
Result: True
Comment: The following packages were installed/updated: sysstat
Started: 06:21:18.206403
Duration: 9034.407 ms
Changes:
---------
sysstat:
----------
new:
10.1.5-13.el7
old:
Summary for node1
------------
Succeeded: 1 (changed=1)
Failed: 0
------------
Total states run: 1
Total run time: 9.034 s
能够看到node1执行成功,而node2没有执行成功,缘由是:
base目录下的top.sls里面要执行的主机写的是'node1',而不是*,虽然salt '*' state.highstate 高级命令里面指定了‘*’,这只是通知全部的主机将要执行什么操做,可是收到消息的主机能够不执行,觉得你饿在top.sls配置里只是指定了‘node1’须要安装
salt '*' state.highstate test=True 是用做测试可是不执行 很重要的参数
6.saltstack组件(数据存储系统)
(saltstack技术入门与实战:2.2)
Grains 存放着salt minion启动时收集到的信息,运行的过程当中不收集,相对来讲是静态的信息,能够用做收集资产管理,作自动化信息查询
Grains的应用场景
Grains能够在state系统中使用,用于配置管理模块。
Grains能够在target中使用,再用来匹配minion,好比匹配操做系统,使用-G选项。
Grains能够用于信息查询,Grains保存着收集到的客户端的详细信息。
收集自定义的Grains信息
经过minion配置文件
经过grains相关模块定义
经过python脚本定义
查看grains命令
salt 'node2' sys.doc grains 查看全部grains的详细用法
命令详解
1.列出minion可用的Grains名称
Available grains can be listed by using the 'grains.ls' module
salt 'node1' grains.ls
2.列出Grains详细数据
Grains data can be listed by using the 'grains.items' module(超级详细)
salt 'saltstack-node1*' grains.items
只显示item 里的os值,注意item后面没有s
salt '*' grains.item os
3.获取指定的Grains信息
salt 'node1*' grains.get ip4_interfaces
4.在指定的机器上执行操做
salt -G 'os:CentOS' cmd.run 'uptime'
自定义grains
1.经过top.sls来自定义
[root@node1 base]# cat /srv/salt/base/top.sls
base:
'os:CentOS':
- match: grain
- web.apache
这个top.sls的意思就是,经过grains来匹配出全部的os等于CentOS的机器,并执行web目录下的apache.sls
执行top.sls :salt '*' state.highstate
说的简单一点就是在top.sls里面经过grains进行匹配
2.编辑/etc/salt/grains在里面进行自定义
这种配置方式有个优势,能够把自定义的grains抽取出来,把配置写好后,再批量分发给不一样的minion端,这样就能够统一自定义的grains,并且配置还特别简单。
salt '*' saltutil.sync_grains #刷新
验证命令:
#注意写法!test表明测试环境。
[root@saltstack-node1 ~]# vim /etc/salt/grains
cloud: openstack
roles:
- nginx
- php
env: test
#配置完成后,必需要重启minion服务,或者执行: salt 'saltstack-node1*' grains.get cloud
salt 'saltstack-node1*' grains.get roles
salt 'saltstack-node1*' grains.get env
3.能够在/etc/salt/minion的配置文件里面那些,可是这样写比较混乱,不建议这样写
Pillar
能够给指定的minion定义其须要的数据,只有指定的人才能看其数据,通常存放比较重要的数据,觉得你饿pillar比较安全,通常在master上设置
定义pillar
其实pillar与配置管理的File Server settings的配置很像
打开vim /etc/salt/master,搜索pillar_roots,去掉注释
pillar_roots:
base:
- /srv/pillar/base
prod:
- /srv/pillar/prod
建立/srv/pillar/prod和/srv/pillar/base目录,mkdir -p /srv/pillar/{base,prod}
从新启动master,systemctl restart salt-master
文章
7.saltstack的api
import salt.client local = salt.client.LocalClient() result = local.cmd('c2.salt.com', 'cmd.run', ['ifconfig'])
saltstack api 参数详解 参数详解2 参数详解3 参数详解4 参数详解5
client : 模块,python处理salt-api的主要模块,‘client interfaces <netapi-clients>’ local : 使用‘LocalClient <salt.client.LocalClient>’ 发送命令给受控主机,等价于saltstack命令行中的'salt'命令 local_async : 和local不一样之处在于,这个模块是用于异步操做的,即在master端执行命令后返回的是一个jobid,任务放在后台运行,经过产看jobid的结果来获取命令的执行结果。 runner : 使用'RunnerClient<salt.runner.RunnerClient>' 调用salt-master上的runner模块,等价于saltstack命令行中的'salt-run'命令 runner_async : 异步执行runner模块 wheel : 使用'WheelClient<salt.wheel.WheelClient>', 调用salt-master上的wheel模块,wheel模块没有在命令行端等价的模块,但它一般管理主机资源,好比文件状态,pillar文件,salt配置文件,以及关键模块<salt.wheel.key>功能相似于命令行中的salt-key。 wheel_async : 异步执行wheel模块 备注:通常状况下local模块,须要tgt和arg(数组),kwarg(字典),由于这些值将被发送到minions并用于执行所请求的函数。而runner和wheel都是直接应用于master,不须要这些参数。 tgt : minions fun : 函数 arg : 参数 expr_form : tgt的匹配规则 'glob' - Bash glob completion - Default 'pcre' - Perl style regular expression 'list' - Python list of hosts 'grain' - Match based on a grain comparison 'grain_pcre' - Grain comparison with a regex 'pillar' - Pillar data comparison 'nodegroup' - Match on nodegroup 'range' - Use a Range server for matching 'compound' - Pass a compound match string
啦啦啦啦