自動化運維工具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
啦啦啦啦