saltstack實戰 - 自動化運維管理

實驗環境:
物理機執行: iptables -t nat -I POSTROUTING -s 172.25.254.0/24 -j MASQUERADE
讓server1和server2可以上網。

server1 :172.25.254.1 master端
server2 : 172.25.254.2 minion端
server3 : 172.25.254.3 minion端

一、saltstack 簡介

saltstack 簡介

  • saltstack是一個配置管理系統,能夠維護預定義狀態的遠程節點。
  • saltstack是一個分佈式遠程執行系統,用來在遠程節點上執行命令和查詢數據。
  • saltstack是運維人員提高工作效率、規範業務配置與操作的利器。
  • Salt的核心功能
    • 使命令發送到遠程系統是並行的而不是串行的
    • 使用安全加密的協議
    • 使用最小最快的網絡載荷
    • 提供簡單的編程接口

Salt同樣引入了更加細緻化的領域控制系統來遠程執行,使得系統成爲目標不止可以通過主機名,還可以通過系統屬性。

Salt 和ansible 最大的區別在於salt是具有客戶端的,而 ansible 沒有,salt 直接獲取root權限進行訪問,

saltstack 通訊機制

  • SaltStack 採用 C/S模式,minion與master之間通過ZeroMQ(輕量級)消息隊列通信,默認監聽4505端口。saltstack的優勢就在於這個ZMQ,它運行起來的速度比ansible快很多

在這裏插入圖片描述

  • Salt Master運行的第二個網絡服務就是ZeroMQ REP系統,默認監聽4506端口,就是接受客戶端的回執的。

在這裏插入圖片描述

saltstack 的安裝與配置

我們可以去saltstack官網下載,也可以去阿里雲中下載:
mirrors.aliyun.com

yum install https://mirrors.aliyun.com/saltstack/yum/redhat/salt-repo-latest-2.el7.noarch.rpm

執行這條命令會生成yum源:

[root@server1 images]# cd /etc/yum.repos.d/
[root@server1 yum.repos.d]# ls
redhat.repo  salt-latest.repo  westos.repo
			# 生成這個倉庫
[root@server1 yum.repos.d]# cat salt-latest.repo 
[salt-latest]
name=SaltStack Latest Release Channel for RHEL/Centos $releasever
baseurl=https://repo.saltstack.com/yum/redhat/7/$basearch/latest
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/saltstack-signing-key
## 我們把裏面的路徑改爲指向阿里雲,這樣會更快一些。

[root@server1 yum.repos.d]# sed -i "s/repo.saltstack.com/mirrors.aliyun.com\/saltstack/g" /etc/yum.repos.d/salt-latest.repo
[root@server1 yum.repos.d]# cat salt-latest.repo 

baseurl=https://mirrors.aliyun.com/saltstack/yum/redhat/7/$basearch/latest
				# 這個 	
[root@server1 yum.repos.d]# yum repolist 
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-
              : manager
This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.
repo id            repo name                                              status
HighAvailability   westos.repoHighAvailability                               51
salt-latest/x86_64 SaltStack Latest Release Channel for RHEL/Centos 7Serv    83
##可以列出,說明沒問題 	

然後我們在server2中也做同樣的yum源的配置
master端設置:(server1)
• # yum install -y salt-master	#安裝master端
• # systemctl enable salt-master #設置master自啓動
• # systemctl start salt-master	#啓動master服務
[root@server1 ~]# yum install -y lsof		# 可以用來查看打開的端口
[root@server1 ~]# lsof -i :4505		# 消息隊列
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
salt-mast 3562 root   15u  IPv4  33242      0t0  TCP *:4505 (LISTEN)
[root@server1 ~]# lsof -i :4506			# 接收請求
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
salt-mast 3569 root   23u  IPv4  33287      0t0  TCP *:4506 (LISTEN)
# 此時server2還沒有連接
minion端配置:
• # yum install -y salt-minion		#安裝minion端
• # vim /etc/salt/minion
master: 172.25.0.1		#設置master主機的ip,注意冒號後有空格
• # systemctl enable salt-minion
• # systemctl start salt-minion

在這裏插入圖片描述
此時我們在server1中查看;

[root@server1 ~]# lsof -i :4505
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
salt-mast 3562 root   15u  IPv4  33242      0t0  TCP *:4505 (LISTEN)
## 4505端口沒有變
[root@server1 ~]# lsof -i :4506
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
salt-mast 3569 root   23u  IPv4  33287      0t0  TCP *:4506 (LISTEN)
salt-mast 3569 root   30u  IPv4  37746      0t0  TCP server1:4506->server2:57622 (ESTABLISHED)
## server2 向 server1 發起了一個請求,這時我我們的master端需要通過key去允許,纔可以建立連接,
相當於證書的頒發

在這裏插入圖片描述
-A 允許所有,可以看出server2就到了接受的keys 裏面去了。
這裏我們要注意

[root@server2 salt]# cat minion_id 
server2		這個爲文件裏面記錄了主機名,salt會始終會去文件中的名字,當我們更改了主機名時,要及時的去這個文件中更改,或者刪除文件,重啓minion端

[root@server1 ~]# lsof -i :4505
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
salt-mast 3562 root   15u  IPv4  33242      0t0  TCP *:4505 (LISTEN)
salt-mast 3562 root   17u  IPv4  38484      0t0  TCP server1:4505->server2:36732 (ESTABLISHED)
## 這是我們的主服務就和server2 建立了長連接了。這樣當server1發佈新東西時,這時所有minion端就可以接收到

[root@server1 ~]# lsof -i :4506
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
salt-mast 3569 root   23u  IPv4  33287      0t0  TCP *:4506 (LISTEN)

查看更詳盡的進程信息:

[root@server1 ~]# yum install -y python-setproctitle.x86_64 		# 安裝這個包
[root@server1 ~]# systemctl restart salt-master.service 			# 重啓salt
[root@server1 ~]# ps ax 		# 查看
 5983 ?        Ss     0:00 /usr/bin/python /usr/bin/salt-master ProcessManager
 5990 ?        S      0:00 /usr/bin/python /usr/bin/salt-master MultiprocessingLoggingQueue
 5997 ?        Sl     0:00 /usr/bin/python /usr/bin/salt-master ZeroMQPubServerChannel		# 消息隊列
 6000 ?        S      0:00 /usr/bin/python /usr/bin/salt-master EventPublisher
 6001 ?        S      0:00 /usr/bin/python /usr/bin/salt-master Maintenance
 6002 ?        S      0:00 /usr/bin/python /usr/bin/salt-master ReqServer_ProcessManager		# 請求響應
 6003 ?        Sl     0:00 /usr/bin/python /usr/bin/salt-master MWorkerQueue		# 維護隊列
 6004 ?        R      0:00 /usr/bin/python /usr/bin/salt-master MWorker-0
 6005 ?        R      0:00 /usr/bin/python /usr/bin/salt-master MWorker-1
 6006 ?        R      0:00 /usr/bin/python /usr/bin/salt-master MWorker-2
 6007 ?        R      0:00 /usr/bin/python /usr/bin/salt-master MWorker-3
 6008 ?        Sl     0:00 /usr/bin/python /usr/bin/salt-master FileserverUpdate
 6019 ?        R      0:00 /usr/bin/python /usr/bin/salt-master MWorker-4

master 端測試與minion端的連接:
在這裏插入圖片描述
這裏 * 代表當先目錄下的所有文件,所以我們要加上 ‘’ 來讓他代表slat裏面的所有key(用salt-key -L 可以列出的)。
也可以直接指定key。
在這裏插入圖片描述
這時我們就可以使用遠程命令了,而且我們是超戶哦:

[root@server1 ~]# salt server2 cmd.run df
server2:
    Filesystem            1K-blocks    Used Available Use% Mounted on
    /dev/mapper/rhel-root  17811456 1249308  16562148   8% /
    devtmpfs                 495420       0    495420   0% /dev
    tmpfs                    507512      80    507432   1% /dev/shm
    tmpfs                    507512   13220    494292   3% /run
    tmpfs                    507512       0    507512   0% /sys/fs/cgroup
    /dev/sda1               1038336  135224    903112  14% /boot
    tmpfs                    101504       0    101504   0% /run/user/0
[root@server1 ~]# salt server2 cmd.run pwd
server2:
    /root
    
[root@server1 ~]# salt server2 cmd.run 'touch /tmp/file'
server2:

[root@server2 ~]# ls /tmp/file
/tmp/file

二、 saltstack遠程執行

遠程執行shell命令

Salt命令由三個主要部分構成:

 salt '<target>' <function> [arguments]
 		 目標	 	函數			內容

Targect:

target: 指定哪些minion, 默認的規則是使用glob匹配minion id.
[root@server1 ~]# salt server? test.ping		# 使用通配符
server2:
    True
[root@server1 ~]# salt server[1-3] test.ping
server2:
    True
[root@server1 ~]# salt '*' test.ping
server2:
    True
[root@server1 ~]# salt 'server2' test.ping
server2:
    True
[root@server1 ~]# salt 'server2,server3' test.ping
No minions matched the target. No command was sent, no jid was assigned.
ERROR: No return received
[root@server1 ~]# salt -L 'server2,server3' test.ping		# 使用列表
server2:
    True
server3:
    Minion did not return. [No response]
ERROR: Minions returned with non-zero exit code
[root@server1 ~]# salt -E 'server[1-3]' test.ping			# 使用正則表達式
server2:
    True

Function:

funcation是module提供的功能,Salt內置了大量有效的functions.(其實就是python的各種模塊)
## http://docs.saltstack.cn/	查看中文手冊
[root@server1 ~]# salt '*' cmd.run 'uname -a'		# 遠程執行
server2:
    Linux server2 3.10.0-957.el7.x86_64 #1 SMP Thu Oct 4 20:48:51 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

[root@server1 ~]# salt 'server2' sys.doc pkg			#查看模塊文檔
arguments通過空格來界定參數:
        salt '*' pkg.remove <package name>
        salt '*' pkg.remove <package1>,<package2>,<package3>
        salt '*' pkg.remove pkgs='["foo", "bar"]'

在這裏插入圖片描述
這樣就很簡單的完成了遠程安裝。命令遊4505端口推送,下面的帶顏色的結果由4506端口接收的。
我們還可以去:
http://docs.saltstack.cn/ref/modules/all/index.html
查看salt內置的執行模塊列表,這裏面的使用方式是寫文件時的用法,和命令行不太相同。

salt的數據都會保存在/var/cache/salt 目錄中,(ansible保存在 /tmp 中)

[root@server2 salt]# pwd
/var/cache/salt
[root@server2 salt]# tree .
.
`-- minion
    |-- extmods
    `-- proc

3 directories, 0 files

編寫遠程執行模塊

當系統自帶的模塊不夠時,我們就可以去自己編寫。
默認的文件目錄爲:

[root@server1 ~]# vim  /etc/salt/master
#
#file_roots:
#  base:
#    - /srv/salt		# 在這裏
#
[root@server1 ~]# mkdir /srv/salt				# 這裏就是salt的base目錄,所有的數據都定位到這裏,ansible指定的是當前目錄。
[root@server1 ~]# mkdir /srv/salt		# 這裏是模塊固定存放目錄,
[root@server1 _modules]# vim mydisk.py		# 編寫文件
def df():
    return __salt__['cmd.run']('df -h')
[root@server1 _modules]# salt server2 saltutil.sync_modules		# 同步到server2
server2:
    - modules.mydisk


在server2中查看:
[root@server2 salt]# tree .
.
`-- minion
    |-- extmods
    |   `-- modules
    |       `-- mydisk.py
    |-- files
    |   `-- base			# 這個base就是/srv/salt
    |       `-- _modules
    |           `-- mydisk.py				# 文件就通不過來了
    |-- module_refresh
    `-- proc
##  可以看出文件緩存到了server2中的 /var/cache/salt  目錄中

然後我們就可以調用了:
[root@server1 salt]# salt server2 mydisk.df			# 調用我們剛纔寫的mydisk模塊的df方法。
server2:
    Filesystem             Size  Used Avail Use% Mounted on
    /dev/mapper/rhel-root   17G  1.2G   16G   8% /
    devtmpfs               484M     0  484M   0% /dev
    tmpfs                  496M  100K  496M   1% /dev/shm
    tmpfs                  496M   13M  483M   3% /run
    tmpfs                  496M     0  496M   0% /sys/fs/cgroup
    /dev/sda1             1014M  133M  882M  14% /boot
    tmpfs                  100M     0  100M   0% /run/user/0

瞭解 YAML 語法

編寫模塊時使用的是 YAML 語法,它的使用規則:
在這裏插入圖片描述

配置管理

創建sls文件

  • SLS(代表SaLt State文件)是Salt State系統的核心。SLS描述了系統的目標狀態,由格式簡單的數據構成。這經常被稱作配置管理。

sls文件的寫法有兩種方式;

			vim apache.sls
[root@server1 salt]# cat apache.sls 
httpd:
  pkg.installed			(這種是寫到了一起)

[root@server1 salt]# cat apache.sls 
httpd:				# 聲明(這裏是軟件包的聲明)
  pkg:				# 狀態聲明(模塊)
    - installed		# 函數聲明


[root@server1 salt]# salt server2 state.sls apache		# 指定主機執行

這時在server2上它會先把sls文件推送過來,再去執行安裝。
[root@server2 salt]# tree .
.
`-- minion
    |-- extmods
    |   `-- modules
    |       |-- mydisk.py
    |       `-- mydisk.pyc
    |-- files
    |   `-- base
    |       |-- apache.sls		# 推送過來了
    |       `-- _modules
    |           `-- mydisk.py
    |-- module_refresh
    `-- proc
        `-- 20200608051500237034

當我們需要安裝多個包時:

web:
  pkg.installed:
    - pkgs:
      - httpd			# 這裏指定包,可以接多個
	  - php

推送過去:
[root@server1 salt]# salt server2 state.sls apache
在這裏插入圖片描述
在server2中查看日誌:
在這裏插入圖片描述
它再安裝的時後連依賴性也安裝了。這時候如果我們在刪除的時後就不會卸載到那些依賴性,因爲salt只會把狀態調整到 installed ,中間的過程可能會多樣,所以就造成了這種結果。這不是一種還原機制。


  • Salt 狀態系統的核心是SLS,或者叫SaLt State 文件。
  • SLS表示系統將會是什麼樣的一種狀態,而且是以一種很簡單的格式來包含這些數據,
    常被叫做配置管理。
  • sls文件命名:
    • sls文件以”.sls”後綴結尾,但在調用是不用寫此後綴。
    • 使用子目錄來做組織是個很好的選擇。
    • init.sls 在一個子目錄裏面表示引導文件,也就表示子目錄本身, 所以apache/init.sls 就是
      表示apache.
    • 如果同時存在apache.sls 和 apache/init.sls,則 apache/init.sls 被忽略,apache.sls將被用來
      表示 apache.

當我們的sls文件越寫越多時,爲了方便,我們會在base目錄創建目錄,將一個屬性 sls文件全部放到裏面:

[root@server1 salt]# mkdir apache
[root@server1 salt]# mv apache.sls apache/installed.sls
[root@server1 salt]# ls apache/			# 就好比ansibe中的角色一樣
installed.sls
[root@server1 salt]# salt server2 state.sls apache.installed			# 這時的推送是這樣的,用 . 分隔

這樣有時會出現弊端,那我們還有另一種方式:

[root@server1 apache]# mv installed.sls init.sls			# init.sls 入口文件,每次都會先訪問這個文件
[root@server1 apache]# cd			# 進入根目錄
[root@server1 ~]# salt server2 state.sls apache		# 也可以進行推送了,不必進入base的目錄
server2:								#注意這裏只寫apache,init.sls引導文件就代表apache
----------
          ID: web
    Function: pkg.installed
      Result: True
     Comment: All specified packages are already installed
     Started: 14:12:36.650803
    Duration: 555.309 ms
     Changes:   

Summary for server2
------------
Succeeded: 1
Failed:    0
------------
Total states run:     1
Total run time: 555.309 ms

我們可以把其它的sls文件,用include 寫入到 int.sls 文件中

我們現在用init.sls開啓httpd:

[root@server1 salt]# cat apache/init.sls 
web:
  pkg.installed:
    - pkgs:
      - httpd
      - php
  service.running:
    - name: httpd
[root@server1 salt]# salt server2 state.sls apache

在這裏插入圖片描述
server2中的apache就開起來了.

[root@server1 salt]# cat apache/init.sls 
web:
  pkg.installed:
    - pkgs:
      - httpd
      - php
  service.running:
    - name: httpd
    - enable: True		# 加上開機自啓
[root@server1 salt]# salt server2 state.sls apache

[root@server2 salt]# systemctl is-enabled httpd
enabled
[root@server2 salt]# tree 
.
`-- minion
    |-- accumulator
    |-- extmods
    |   `-- modules
    |       |-- mydisk.py
    |       `-- mydisk.pyc
    |-- files
    |   `-- base
    |       |-- apache
    |       |   |-- init.sls	 # 這裏
    |       |   `-- installed.sls
    |       |-- apache.sls
    |       `-- _modules
    |           `-- mydisk.py
    |-- highstate.cache.p
    |-- module_refresh
    |-- pkg_refresh
    |-- proc
    `-- sls.p

配置文件:

[root@server1 salt]# cat apache/init.sls 
web:
  pkg.installed:
    - pkgs:
      - httpd
      - php
  file.managed:
    - source: salt://apache/files/httpd.conf			#源地址,指/srv/salt/apache/files/httpd.conf
    - name: /etc/httpd/conf/httpd.conf			# 目的地地址

  service.running:
    - name: httpd
    - enable: True


[root@server1 salt]# cd apache/
[root@server1 apache]# mkdir files			# 創建對應目錄
[root@server1 apache]# scp server2:/etc/httpd/conf/httpd.conf ./files		# 拷貝一個文件過來
root@server2's password: 
httpd.conf                                                                           100%   11KB   5.6MB/s   00:00    
[root@server1 apache]# vim httpd.conf

在這裏插入圖片描述
我們將端口改爲8080 端口.以示區別。
在這裏插入圖片描述
在這裏插入圖片描述
server2的配置文件已經更改爲8080端口了。但是此時的netstat 端口還是80端口,所以我們

web:
  pkg.installed:
    - pkgs:
      - httpd
      - php
  file.managed:
    - source: salt://apache/files/httpd.conf
    - name: /etc/httpd/conf/httpd.conf

  service.running:
    - name: httpd
    - enable: True
    - watch:
      - file: web			

用 watch 監控web聲明,這裏應注意,每個聲明底下的模塊只能使用一次,不然就會混亂,比如web地下只能有一個file模塊,如果想再加的話,就再寫一個聲明

[root@server1 salt]# salt server2 state.sls apache

[root@server2 salt]# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      3055/sshd           
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      3149/master         
tcp6       0      0 :::8080                 :::*                    LISTEN      14806/httpd         	#就變成8080端口了
tcp6       0      0 :::22                   :::*                    LISTEN      3055/sshd           
tcp6       0      0 ::1:25                  :::*                    LISTEN      3149/master 

我們還可以這麼寫:

web:
  pkg.installed:
    - pkgs:
      - httpd
      - php

  service.running:
    - name: httpd
    - enable: True
    - watch:
      - file: /etc/httpd/conf/httpd.conf

/etc/httpd/conf/httpd.conf:			# name替換爲聲明
  file.managed:			# 將file獨立出來
    - source: salt://apache/files/httpd.conf

開啓server3,做和server2相同的配置:

[root@server3 packages]# yum install -y salt-minion.noarch 	下載開啓服務,enable。
[root@server3 packages]# vim /etc/salt/minion		# 設置master

[root@server1 salt]# salt-key -L
Accepted Keys:
server2
Denied Keys:
Unaccepted Keys:
server3
Rejected Keys:
[root@server1 salt]# salt-key -A
The following keys are going to be accepted:
Unaccepted Keys:
server3
Proceed? [n/Y] Y
Key for minion server3 accepted.
[root@server1 salt]# salt-key -L
Accepted Keys:
server2
server3
Denied Keys:
Unaccepted Keys:
Rejected Keys:
[root@server1 salt]# lsof -i :4505
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
/usr/bin/ 5997 root   15u  IPv4  40208      0t0  TCP *:4505 (LISTEN)
/usr/bin/ 5997 root   17u  IPv4  42437      0t0  TCP server1:4505->server2:36740 (ESTABLISHED)
/usr/bin/ 5997 root   23u  IPv4  89914      0t0  TCP server1:4505->server3:37524 (ESTABLISHED)

nginx配置

[root@server1 salt]# mkdir nginx
[root@server1 salt]# cd nginx
[root@server1 nginx]# vim init.sls
nginx-install:				# 安裝依賴性
  pkg.installed:
    - pkgs:
      - openssl-devel
      - pcre-devel
      - gcc

  file.managed:		# 源碼包推送過去
    - name: /mnt/nginx-1.17.10.tar.gz
    - source: salt://nginx/files/nginx-1.17.10.tar.gz

  cmd.run:		# 編譯安裝
    - name: cd /mnt/ && tar zxf nginx-1.17.10.tar.gz && cd nginx-1.17.10 && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --prefix=/usr/local/nginx --with-http_ssl_module &> /dev/null && make &> /dev/null && make install &> /dev/null
    - creates: /usr/local/nginx			# cmd會重複執行編譯安裝,這個參數會檢測路徑是否存在,若存在,就不再編譯安裝了

nginx-service:
  file.managed:			#推送文件
    - name: /usr/lib/systemd/system/nginx.service
    - source: salt://nginx/files/nginx.service

  service.running:			# 啓動服務
    - name: nginx


[root@server1 nginx]# mkdir files
[root@server1 nginx]# cd files/
[root@server1 files]# ls
nginx-1.17.10.tar.gz  nginx.service		# 腳本文件和源碼包
[root@server1 files]# cat nginx.service 
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target                       
[root@server1 nginx]# salt server3 state.sls nginx

[root@server3 sbin]# ps ax				# 啓動起來了
 6868 ?        Ss     0:00 nginx: master process ./nginx
 6869 ?        S      0:00 nginx: worker process

加入配置文件:

nginx-install:
  pkg.installed:
    - pkgs:
      - openssl-devel
      - pcre-devel
      - gcc

  file.managed:
    - name: /mnt/nginx-1.17.10.tar.gz
    - source: salt://nginx/files/nginx-1.17.10.tar.gz

  cmd.run:
    - name: cd /mnt/ && tar zxf nginx-1.17.10.tar.gz && cd nginx-1.17.10 && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --prefix=/usr/local/nginx --with-http_ssl_module &> /dev/null && make &> /dev/null && make install &> /dev/null
    - creates: /usr/local/nginx

/usr/local/nginx/conf/nginx.conf:		# 拷貝配置文件過去
  file.managed:
    - source: salt://nginx/files/nginx.conf

nginx-service:
  file.managed:
    - name: /usr/lib/systemd/system/nginx.service
    - source: salt://nginx/files/nginx.service

  service.running:
    - name: nginx
    - enable: True		# 自啓
    - reload: True		# 重新加載
    - watch:			# 監控
      - file: /usr/local/nginx/conf/nginx.conf
[root@server1 files]# vim nginx.conf 
worker_processes  2;		# 設置worker 兩個
[root@server1 files]# salt server3 state.sls nginx
[root@server3 sbin]# ps ax
 6895 ?        Ss     0:00 nginx: master process /usr/local/nginx/sbin/nginx
 6898 ?        S      0:00 [kworker/u2:0]
 6913 ?        S      0:00 [kworker/0:2]
 6916 ?        R      0:00 [kworker/0:0]
 6978 ?        S      0:00 nginx: worker process
 6979 ?        S      0:00 nginx: worker process		# 就有兩個worker進程了

在這裏我們舉例使用一下include:

[root@server1 nginx]# cat init.sls 
nginx-install:
  pkg.installed:
    - pkgs:
      - openssl-devel
      - pcre-devel
      - gcc

  file.managed:
    - name: /mnt/nginx-1.17.10.tar.gz
    - source: salt://nginx/files/nginx-1.17.10.tar.gz

  cmd.run:
    - name: cd /mnt/ ...
    - creates: /usr/local/nginx

include:				# 這就是include的使用方式,默認只讀取接口文件,將另一個文件放入到這個接口文件中,就可以使用了
  - nginx.service				# nginx 目錄下的 service 文件
 
[root@server1 nginx]# cat service.sls 		# 這個文件放的是從init.sls中截取的文件內容
/usr/local/nginx/conf/nginx.conf:
  file.managed:
...

[root@server1 nginx]# salt server3 state.sls nginx		# 推送
server3:
----------
          ID: /usr/local/nginx/conf/nginx.conf
    Function: file.managed
      Result: True
     Comment: File /usr/local/nginx/conf/nginx.conf is in the correct state
     Started: 11:04:36.407291
    Duration: 45.936 ms
     Changes:   
----------
          ID: nginx-service
    Function: file.managed
        Name: /usr/lib/systemd/system/nginx.service
我們發現會優先執行include的內容

top文件

  • 大多數技術系統的基礎架構是由計算機組成,該架構中的每臺計算機都扮演着與其他計算機相似的角色。 這些機器相互協作以創建應用程序的技術棧。
  • 爲了有效地管理這些計算機設備,管理員需要能夠爲這些計算機或計算機分組創建角色。例如,一組爲前端Web流量提供服務的計算機可能具有某些角色,這些角色指示這些計算機都應都安裝了Apache Web服務器軟件包,並且Apache服務應始終處於運行狀態。
  • 在Salt中,包含網絡上的計算機分組與應用於它們的配置角色之間的映射關係的文件稱爲top file文件。
  • 默認情況下,頂級文件的名稱爲top.sls,之所以如此命名是因爲它們始終存在於包含狀態文件的目錄層次結構的“頂部”中。該目錄層次結構稱爲state tree狀態樹。

我們進入base目錄(/srv/salt),創建top.sls文件

[root@server1 salt]# vim top.sls 
[root@server1 salt]# cat top.sls 
base:
  'server2':
    - apache				# 在server2上執行apache的sls文件
  'server3':
    - nginx					 # 在server3上執行 nginx 的sls文件

說明了對於名爲base的環境,server2將應用名爲apache的狀態文件。server3將應用名爲nginx的狀態文件。
Salt將在/srv/salt(base,在master的配置文件中設定)目錄中查找apache.sls或init.sls。
在這裏插入圖片描述
這種高級狀態文件的推送方式爲:

[root@server1 salt]# salt '*' state.highstate
server2:
          ID: web
    Function: service.running
        Name: httpd
      Result: True
     Comment: The service httpd is already running
Summary for server2
------------
Succeeded: 3
Failed:    0
------------
server3:
----------
          ID: nginx-service
    Function: service.running
        Name: nginx
      Result: True
     Comment: The service nginx is already running  

Summary for server3
------------
Succeeded: 6
Failed:    0
------------

而且只會把狀態不同的進行變更。

三、grains與pillar詳解(數據採集系統)

grains和pillar的區別在於:

  • grains:靜態,在minion生效
  • pillar:動態,在server端生效

像上面的操作,我們在推送的時後會把數據緩存到minion端的 /var/cache/salt/ 中,使用pillar方式就不會。

grains

  • Grains是SaltStack的一個組件,存放在SaltStack的minion端。
  • 當salt-minion啓動時會把收集到的數據靜態存放在Grains當中,只有當minion重啓時纔會進行數據的更新。
  • 由於grains是靜態數據,因此不推薦經常去修改它。
  • 應用場景:
    • 信息查詢,可用作CMDB。
    • 在target中使用,匹配minion。
    • 在state系統中使用,配置管理模塊。

信息查詢:
用於查詢minion端的IP、FQDN等信息。

## 默認可用的grains:salt '*' grains.ls
[root@server1 salt]# salt server2 grains.ls
server2:
    - SSDs
    - biosreleasedate
    - biosversion
    - cpu_flags
    - cpu_model
    - cpuarch
    - cwd
    - disks
    - dns
    - domain
    - fqdn
    - fqdn_ip4

## 查看每一項的值:
[root@server1 salt]# salt server3 grains.items
        Red Hat
    master:
        172.25.254.1
    mdadm:
    mem_total:
        991
    nodename:
        server3
## 取單項的值:
[root@server1 salt]# salt server3 grains.item ipv4			# 不是 items 了
server3:
    ----------
    ipv4:
        - 127.0.0.1
        - 172.25.254.3

這些grains,我們可以在minion端的配置文件去靜態指定

grains:
  roles: apache		##指定這個鍵值對
#    - webserver		列表的方式可以通過短槓指定
#    - memcache	
#  deployment: datacenter4
#  cabinet: 13
#  cab_u: 14-15
[root@server2 minion.d]# systemctl restart salt-minion.service 
#重啓salt-minion,否則數據不會更新

[root@server1 salt]# salt server2 grains.item roles
server2:
    ----------
    roles:					# 然後就可以看到了。
        apache

我們還可以去etc/salt/grains中定義:

[root@server3 files]# vim /etc/salt/grains
[root@server3 files]# cat /etc/salt/grains 
roles: nginx

[root@server1 salt]# salt server3 saltutil.sync_grains			#同步數據
server3:
[root@server1 salt]# salt server3 grains.item roles			# 就可以查看了,這種方式不用重啓服務
server3:
    ----------
    roles:
        nginx

還可以通過編寫模塊的方式;

[root@server1 salt]# mkdir /srv/salt/_grains		# 在salt-master端創建_grains目錄
[root@server1 salt]# cd _grains/
[root@server1 _grains]# vim my_grain.py
[root@server1 _grains]# cat my_grain.py 
def my_grain():
    grains = {}
    grains['salt'] = 'stack'
    grains['hello'] = 'world'
    return grains
[root@server1 _grains]# salt '*' saltutil.sync_grains			# 同步到所有結點
server2:
    - grains.my_grain
server3:
    - grains.my_grain

[root@server1 _grains]# salt 'server2' grains.item hello
server2:
    ----------
    hello:
        world
[root@server1 _grains]# salt 'server3' grains.item salt
server3:
    ----------
    salt:
        stack


[root@server2 salt]# tree .
.
`-- minion
    |-- accumulator
    |-- extmods
    |   |-- grains
    |   |   |-- my_grain.py
    |   |   `-- my_grain.pyc
    |   `-- modules
    |       |-- mydisk.py
    |       `-- mydisk.pyc
    |-- files
    |   `-- base
    |       |-- apache
    |       |   |-- files
    |       |   |   `-- httpd.conf
    |       |   |-- init.sls
    |       |   `-- installed.sls
    |       |-- apache.sls
    |       |-- _grains
    |       |   `-- my_grain.py		# 同步過來了

grains匹配運用:

[root@server1 _grains]# salt -G 	roles:apache 	cmd.run hostname
server2:						#這裏是server2中的角色
    server2
-G 通過grains來匹配目標,只要目標有roles是 apache 的就執行 hostname
[root@server1 _grains]# salt -G roles:apache cmd.run hostname
server2:
    server2
[root@server1 _grains]# salt -G roles:nginx cmd.run hostname
server3:
    server3
[root@server1 _grains]# salt -G hello:world cmd.run hostname
server2:
    server2
server3:
    server3

在top文件中匹配:

[root@server1 salt]# vim top.sls 
[root@server1 salt]# cat top.sls 
base:
  'roles:apache':
    - match: grain			# 通過grain匹配roles是apache的主機,相當於標籤,方便了對很多臺主機進行操作
    - apache
  'roles:nginx':
    - match: grain
    - nginx
[root@server1 salt]# salt '*' state.highstate		# 高級推送

pillar

  • pillar和grains一樣也是一個數據系統,但是應用場景不同。
  • pillar是將信息動態的存放在master端,主要存放私密、敏感信息(如用戶名密碼等),而且可以指定某一個minion纔可以看到對應的信息。
  • pillar更加適合在配置管理中運用。

數據不能存放到/srv/salt上,因爲這個目錄裏的數據都推推送到minion端。

定義pillar基礎目錄:
[root@server1 salt]# vim /etc/salt/master
在這裏插入圖片描述
我們可以在這裏進行指定,也可以採用默認,我們採用默認。

[root@server1 salt]# mkdir /srv/pillar
[root@server1 salt]# vim packages.sls
{% if grains['fqdn'] == 'server3' %}			# 如果主機名是server3
package: nginx										# 是這個對印關係
{% elif grains['fqdn'] == 'server2' %}			# 如果
package: httpd
{% endif %}
[root@server1 pillar]# vim top.sls				# 編寫top文件
[root@server1 pillar]# cat top.sls 
base:
  '*':
    - packages
這時我們就可以查看了,因爲是動態的,所以不需要刷新或重啓
[root@server1 pillar]# salt '*' pillar.items
server3:
    ----------
    package:
        nginx			# 獲取到了
server2:
    ----------
    package:
        httpd

[root@server1 pillar]# salt '*' pillar.item package		#但是我們單獨查看的時候
server3:
    ----------
    package:
server2:
    ----------
    package:			# 就訪問不到了
[root@server1 pillar]# salt '*' saltutil.refresh_pillar			# 刷新
server2:	
    True
server3:
    True
[root@server1 pillar]# salt '*' pillar.item package
server2:
    ----------
    package:
        httpd
server3:
    ----------
    package:
        nginx			# 就能訪問了

pillar的數據匹配:

[root@server1 pillar]# salt -I package:nginx cmd.run hostname
server3:
    server3
##  -I 表示用 pillar 的方式查詢 package 對應 nginx 的主機執行 hostname

state系統中使用:

[root@server1 salt]# cd apache/
[root@server1 apache]# ls
files  init.sls
[root@server1 apache]# vim init.sls 
web:
  pkg.installed:
    - pkgs:
      - {{ pillar['package'] }}		這裏本來是 name:httpd,現在在pillar中獲取
      - php
。。。
[root@server1 apache]# salt '*' state.highstate			# 高級推送沒問題
[root@server1 apache]# salt server2 state.sls apache		# 指定推送也沒有問題
[root@server1 apache]# salt server3 state.sls apache		# 推送給server3時就會報錯,因爲3上裝的nginx

# 匹配nginx:
[root@server1 nginx]# ls
files  init.sls
[root@server1 nginx]# vim init.sls
  service.running:
    - name: {{ pillar['package'] }}			# 用pillar去獲取nginx
    - enable: True
    - reload: True
    - watch:
      - file: /usr/local/nginx/conf/nginx.conf
[root@server1 nginx]# salt server3 state.sls nginx			# 推送沒有問題

四、Jinja模板

  • Jinja是一種基於python的模板引擎,在SLS文件裏可以直接使用jinja7模板來做一些操作。
  • 通過jinja模板可以爲不同服務器定義各自的變量。
  • 兩種分隔符: {% … %} 和 {{ … }},前者用於執行諸如 for 循環 或賦值的語句,後者把表達式的結果打印到模板上。

jinja模板的使用方式

Jinja最基本的用法是使用控制結構包裝條件:

[root@server1 salt]# ls
apache  _grains  _modules  nginx top.sls
[root@server1 salt]# vim test.sls 
/mnt/testfile:
  file.append:
    {% if grains['fqdn'] == 'server2' %}
    - text: server2
    {% elif grains['fqdn'] == 'server3' %}			# 通過grains 獲取
    - text: server3
    {% endif %}
[root@server1 salt]# salt '*' state.sls test		# 推送

在server2個serve'r3中查看;
[root@server3 salt]# cat /mnt/testfile 
server3
[root@server2 salt]# cat /mnt/testfile 
server2

Jinja在普通文件的使用:

[root@server1 salt]# cd apache/
[root@server1 apache]# ls
files  init.sls
[root@server1 apache]# vim init.sls 
web:
  pkg.installed:
    - pkgs:
      - {{ pillar['package'] }}
      - php

  service.running:
    - name: httpd
    - enable: True
    - watch:
      - file: /etc/httpd/conf/httpd.conf
 
/etc/httpd/conf/httpd.conf:
  file.managed:
    - source: salt://apache/files/httpd.conf
    - template: jinja		# 使用jinja模板
    - context:					# 直接更改
      bind: 172.25.254.2

[root@server1 apache]# vim files/httpd.conf 		# 在配置文件中更改
Listen {{ bind }}:80		# 監聽server2的80端口。

[root@server1 apache]# salt server2 state.sls apache		# 推送		
server2:

          ID: /etc/httpd/conf/httpd.conf
    Function: file.managed
      Result: True
     Comment: File /etc/httpd/conf/httpd.conf updated
     Started: 23:13:33.279187
    Duration: 32.654 ms
     Changes:   
              ----------
              diff:
                  --- 
                  +++ 
                  @@ -39,7 +39,7 @@
                   # prevent Apache from glomming onto all bound IP addresses.
                   #
                   #Listen 12.34.56.78:80
                  -Listen 8080
                  +Listen 172.25.254.2:80		# 更改了

我們這裏還可以用pillar直接進行調用:

[root@server1 apache]# cd /srv/pillar/
[root@server1 pillar]# ls
packages.sls  top.sls
[root@server1 pillar]# vim packages.sls 
{% if grains['fqdn'] == 'server3' %}
package: nginx
{% elif grains['fqdn'] == 'server2' %}
package: httpd
port: 8080
{% endif %}
[root@server1 pillar]# cd ../salt/apache/files/
[root@server1 files]# vim httpd.conf 

Listen {{ bind }}:{{ pillar['port'] }}		# 更改如這行,使用jinja模板纔可以調用pillar
[root@server1 files]# salt server2 state.sls apache
                   #Listen 12.34.56.78:80
                  -Listen 172.25.254.2:80
                  +Listen 172.25.254.2:8080		# 更改了

引用變量:

[root@server1 files]# vim httpd.conf

在這裏插入圖片描述

[root@server1 files]# salt server2 state.sls apache		# 推送也成功了

在state文件中引用:

[root@server1 files]# vim httpd.conf

在這裏插入圖片描述
直接使用變量,然後去sls文件中更改:

[root@server1 files]# vim ../init.sls 
[root@server1 files]# cat ../init.sls 
...
/etc/httpd/conf/httpd.conf:
  file.managed:
    - source: salt://apache/files/httpd.conf
    - template: jinja
    - context:
      bind: {{ grains['ipv4'][-1] }}		# 直接在這裏引用
      port: {{ pillar['port'] }}

引用變量文件:

[root@server1 salt]# vim lib.sls		# 建立文件
[root@server1 salt]# cat lib.sls 
{%set port = 8000 %}
[root@server1 salt]# vim apache/files/httpd.conf 

在最頂寫上:
在這裏插入圖片描述

root@server1 salt]# cat apache/init.sls 
...
/etc/httpd/conf/httpd.conf:
  file.managed:
    - source: salt://apache/files/httpd.conf
    - template: jinja
    - context:
      bind: {{ grains['ipv4'][-1] }}
      port: {{ pillar['port'] }}			# sls 文件也有port變量

要注意這兩個port 是不同的,下面這個是pillar指定的,而上面時變量文件指定的

[root@server1 salt]# cat lib.sls 
{%set port = 8000 %}		# 變量文件指定8000端口
   
[root@server1 salt]# cat ../pillar/packages.sls 
{% if grains['fqdn'] == 'server3' %}
package: nginx
{% elif grains['fqdn'] == 'server2' %}
package: httpd
port: 8080			# pillar指定8080多口
{% endif %}
[root@server1 salt]# pwd
/srv/salt

那幺到底誰生效哪?這就是優先級的問題,因爲lib.sls文件是最後導進去的,所以這個會生效
推送測試:

[root@server1 salt]# salt server2 state.sls apache

在這裏插入圖片描述
是8000端口吧!
而且這時文件在傳送過去的時候刪除了第一行,因爲我們的apache不識別這種格式:

[root@server2 salt]# vim /etc/httpd/conf/httpd.conf

在這裏插入圖片描述
但是我們在/var/cache 中查看:

[root@server2 salt]# vim /var/cache/salt/minion/files/base/apache/files/httpd.conf 

在這裏插入圖片描述
這裏是有的。這個是從master中緩存過來的。

用JInja 模板做高可用

我們讓server2做master,server3做backup。

[root@server1 salt]# mkdir keepalived
[root@server1 salt]# mkdir files
[root@server1 salt]# cd keepalived/files/
[root@server1 files]# scp server2:/etc/keepalived/keepalived.conf .			#拷貝一份配置文件,可以先裝上keepalived複製一份配置文件在刪除。
[root@server1 files]# vim keepalived.conf 
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 51		
    priority {{ PRI}}		# 變量
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
	172.25.254.100			#
    }
}

然後用pillar指定變量:
[root@server1 keepalived]# vim /srv/pillar/packages.sls 
{% if grains['fqdn'] == 'server3' %}
package: nginx
state: BACKUP			# server3 成爲備用結點
pri: 50
{% elif grains['fqdn'] == 'server2' %}
package: httpd
port: 8080
state: MASTER			# serer2做主節點
pri: 100
{% endif %}


[root@server1 files]# cd ..
[root@server1 keepalived]# vim init.sls 		# 建立引導文件
[root@server1 keepalived]# cat init.sls 
kp-install:			# 安裝(可以先註釋掉下面,讓先安裝,複製一個配置文件過來,後面接上面的scp那條命令)
  pkg.installed:
    - pkgs:
      - keepalived

  file.managed:			# 配置文件(上面獲取到的)
    - name: /etc/keepalived/keepalived.conf
    - source: salt://keepalived/files/keepalived.conf
    - template: jinja
    - context:
      STATE: {{ pillar['state'] }}			# 調用變量
      PRI: {{  pillar['pri'] }}

  service.running:		# 啓動服務
    - name: keepalived
    - enable: True
    - reload: True
    - watch:
      - file: kp-install

測試推送:
[root@server1 keepalived]# salt '*' state.sls keepalived

# server2中查看
[root@server2 ~]# cat /etc/keepalived/keepalived.conf 
。。。
vrrp_instance VI_1 {
    state MASTER		# master結點
    interface eth0
    virtual_router_id 51
    priority 100		# 優先級100
[root@server2 ~]# ip a


2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

    inet 172.25.254.100/32 scope global ens3		# 虛擬IP

# server3中查看;
[root@server3 ~]# cat /etc/keepalived/keepalived.conf 
...
vrrp_instance VI_1 {
    state BACKUP		# 備用結點	
    interface ens3
    virtual_router_id 51
    priority 50			# 優先級50

現在我們去編寫top文件,去高級推送:

[root@server1 salt]# vim top.sls 
[root@server1 salt]# cd /srv/salt/
[root@server1 salt]# vim top.sls 
base:
  'server2':		# server2開啓apache和高可用
    - apache
    - keepalived
  'server3':
    - nginx		# 開啓nginx和高可用
    - keepalived
然後去掉apache目錄的的init.sls和配置文件的監聽地址,只留下監聽端口,這樣才能通過訪問VIP訪問。

在這裏插入圖片描述
在這裏插入圖片描述
這裏都去掉了bind哪一行,只剩下了port。
然後高級推送:

[root@server1 salt]# salt '*' state.highstate
[root@server1 salt]# curl 172.25.254.100
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
	<head>
		<title>Test Page for the Apache HTTP Server on Red Hat Enterprise Linux</title>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<style type="text/css">
## 可以訪問了

我們停掉server2的keepalived:
[root@server2 ~]# systemctl stop keepalived.service

[root@server1 salt]# curl 172.25.254.100
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>		# 就切換到server3的nginx上去了

[root@server2 ~]# systemctl start keepalived.service   # 在開啓
[root@server2 ~]# ip a
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:68:5c:65 brd ff:ff:ff:ff:ff:ff
    inet 172.25.254.2/24 brd 172.25.254.255 scope global ens3
       valid_lft forever preferred_lft forever
    inet 172.25.254.100/32 scope global ens3		# 就又切回到server2上了,因爲優先級高。

五、job 管理

  • master在下發指令任務時,會附帶上產生的jid。
  • minion在接收到指令開始執行時,會在本地的/var/cache/salt/minion/proc目錄下產生該jid命名的文件,用於在執行過程中master查看當前任務的執行情況。
  • 指令執行完畢將結果傳送給master後,刪除該臨時文件。

Job緩存默認保存24小時:,可以在配置文件中設定:

vim /etc/salt/master
在這裏插入圖片描述

master端Job緩存目錄在: /var/cache/salt/master/jobs
在這裏插入圖片描述
這些 job 在企業中是放在數據庫中的,用於日後的回看,進行分析任務執行的情況,所以我們要在這裏把這些本地信息轉爲數據庫的存儲。

方式1:
在這裏插入圖片描述
方式2:
在這裏插入圖片描述

把 Job 存儲到數據庫方式1

http://docs.saltstack.cn/topics/jobs/index.html #在這裏獲取詳細信息

[root@server1 jobs]# yum install -y mariadb-server
[root@server1 jobs]# systemctl start mariadb.service 
[root@server1 jobs]# mysql		# 輸入mysql直接進入,沒有密碼

方式一是所有的minion端作爲returners,主動發送job到數據庫,所以我們在minion端安裝python-mysqldb模塊。

[root@server2 proc]# yum install MySQL-python.x86_64 -y
[root@server2 proc]# vim /etc/salt/minion		# 編輯配置文件

在這裏插入圖片描述
返還給mysql,並設置mysql的主機信息。不加return: mysql 的話在發佈任務時就需要手動指定,例如:

salt '*' test.ping --return mysql

systemctl restart salt-minion.service

而且把這些數據同步到數據庫需要一定的語句結構,所以我們現在去創建salt的數據庫和表:

[root@server1 ~]# vim add.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;
-- CREATE INDEX jid ON jids(jid) USING BTREE;

--
-- 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;
[root@server1 ~]# mysql < add.sql 		# 導入
[root@server1 ~]# mysql

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| salt               |
| test               |
+--------------------+					#導入了庫和表
5 rows in set (0.00 sec)

MariaDB [(none)]> use salt;

MariaDB [salt]> show tables
    -> ;
+----------------+
| Tables_in_salt |
+----------------+
| jids           |
| salt_events    |
| salt_returns   |
+----------------+
3 rows in set (0.00 sec)

MariaDB [salt]> Bye


# 然後我們創建salt用戶
MariaDB [(none)]> grant all on salt.* to salt@localhost identified by 'salt';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> grant all on salt.* to salt@'%' identified by 'salt';		# 授權給所有主機

[root@server1 ~]# salt server2 cmd.run hostname 		# 發佈一個內容
server2:		
    server2
[root@server1 ~]# mysql -usalt -psalt				# 登陸查看
MariaDB [(none)]> use salt;
MariaDB [salt]> select * from salt_returns;

在這裏插入圖片描述
返還故過來了。
這就是minion端的指定,現在我們註釋掉加入/ etc/salt/minion 的參數,去配置master端的job_cache
我們只需要:

[root@server1 ~]# yum install MySQL-python.x86_64 -y  # master端也需要安裝python模塊
[root@server1 ~]# vim /etc/salt/master
master_job_cache: mysql		# 在最後加上這幾行即可緩存到mysql中去
master_job_cache: mysql
mysql.host: 'localhot'		# 因爲數據庫我們裝在本機,這裏可以寫localhost
mysql.user: 'salt'
mysql.pass: 'salt'
mysql.db: 'salt'
mysql.port: 3306

[root@server1 ~]# systemctl restart salt-master.service 
[root@server1 ~]# salt '*' test.ping		# 測試推送
server3:
    True
server2:
    True

在這裏插入圖片描述信息就返回給數據庫了.

[root@server1 ~]# salt-run jobs.list_jobs		#列出當前master jobs cache中所有job
20200609060023786421:
    ----------
    Arguments:
    Function:
        test.ping
    StartTime:
        2020, Jun 09 06:00:23.786421		)
    Target:
        *
    Target-type:
        glob
    User:
        root
20200609060024122606:
    ----------
    Arguments:
    Function:
        test.ping
    StartTime:
        2020, Jun 09 06:00:24.122606
    Target:
        *
    Target-type:
        glob
    User:
        root
[root@server1 ~]# salt-run jobs.active		# 查看所有minion當前正在運行的jobs(在所有minions上運行saltutil.running

[root@server1 ~]# salt-run jobs.lookup_jid 20200609054303349703		#從master jobs cache中查詢指定jid的運行結果
server2:
    server2		# 剛纔推送的是 hostname命令

六、salt-ssh與salt-syndic

salt-ssh

簡介:

  • salt-ssh可以獨立運行的,不需要minion端。
  • salt-ssh 用的是sshpass進行密碼交互的。
  • 以串行模式工作,性能下降。
  • 安裝salt-ssh :
  • yum install -y salt-ssh

當有些主機不允許安裝minion時,這種方法就是可行的。

[root@server1 ~]# yum install -y salt-ssh
[root@server1 ~]# cd /etc/salt/
[root@server1 salt]# ls
cloud         cloud.deploy.d  cloud.profiles.d   master    minion    pki    proxy.d
cloud.conf.d  cloud.maps.d    cloud.providers.d  master.d  minion.d  proxy  roster
# 會出現roster這個文件,我們只需要在這裏面加上想要連接的主機:
[root@server1 salt]# vim roster 
...
server3:
  host: 172.25.254.3
  user: root
  passwd: caoaoyuan
server2:
  host: 172.25.254.2
  user: root
  passwd: caoaoyuan
# 就可以了

[root@server2 proc]# systemctl stop salt-minion.service
[root@server3 proc]# systemctl stop salt-minion.service		# 關閉server2和server3的minion端,
[root@server1 salt]# salt-ssh '*' test.ping -i		# -i 是校驗key,就是我們初次連接時出現的詢問yes/no的選項
server2:
    True
server3:
    True
[root@server1 salt]# salt-ssh server2 cmd.run hostname
server2:
    server2

[root@server2 proc]# systemctl start salt-minion.service
[root@server# proc]# systemctl start salt-minion.service		# 開啓,後面還要用

salt-syndic

在開啓一臺server4: 172.25.254.4 ,我們用它來做頂級master。
簡介:

  • 如果大家知道zabbix proxy的話那就很容易理解了,syndic其實就是個代理,隔離master與minion。
  • Syndic必須要運行在master上,再連接到另一個topmaster上。
  • Topmaster 下發的狀態需要通過syndic來傳遞給下級master,minion傳遞給master的數據也是由syndic傳遞給topmaster。
  • topmaster並不知道有多少個minion。
  • syndic與topmaster的file_roots和pillar_roots的目錄要保持一致。
[root@server2 proc]# scp  /etc/yum.repos.d/salt-latest.repo server4:/etc/yum.repos.d/
[root@server4 ~]# yum install salt-master.noarch -y

在這裏插入圖片描述
隨着minion主機的越來越多,msater結點會有負擔,所以我們對他們進行橫向的擴展,多幾個master結點,爲了不影響master的整體架構,我們在所有的master結點上都安裝syndic結點,通過他們與最頂級的中心master進行通信,topmaster對他們進行統一管理。所有的minion結點的信息還都再master結點上,不再topmaster上,topmaster只有syndic結點的信息,就是各個master。

簡單來說就是,中心master管控下發任務通過syndic給msater,同樣的msater通過syndic傳數據給中心master,就相當於一個代理。

配置;

[root@server4 ~]# vim /etc/salt/master

在這裏插入圖片描述
打開這個參數。

root@server4 ~]# systemctl enable --now salt-master.servic
[root@server1 salt]# yum install salt-syndic -y		# server1作爲sydnic結點安裝sydnic,它沒有配置文件,就是master
[root@server1 salt]# vim /etc/salt/master
# If this master will be running a salt syndic daemon, syndic_master tells
# this master where to receive commands from.
syndic_master: 172.25.254.4			# 這裏指向頂級msater

[root@server1 salt]# systemctl restart salt-master.service
[root@server1 salt]# systemctl start salt-syndic			# 啓動syndic


[root@server4 ~]# salt-key -L			# 查看下級連接授權
Unaccepted Keys:
server1
[root@server4 ~]# salt-key -A			# 授權
Accepted Keys:
server1

然後我們在server4中推送任務:

[root@server4 ~]# salt '*' test.ping
server2:
    True
server3:				# 接收到的回執確是server2 和server3 的
    True

它的數據流向時:
topmaster -> syndic -> msater -> minions -> master -> syndic -> topmaster

七、salt-api配置

salt-api簡介:

  • SaltStack 官方提供有REST API格式的 salt-api 項目,將使Salt與第三方系統
    集成變得尤爲簡單。
  • 官方提供了三種api模塊:
    • rest_cherrypy
    • rest_tornado
    • rest_wsgi
  • 官方鏈接:https://docs.saltstack.com/en/latest/ref/netapi/all/index.html#all-
    netapi-modules

配置

[root@server1 salt]# yum install salt-api.noarch -y
Downloading packages:
(1/2): salt-api-3000.3-1.el7.noarch.rpm           
(2/2): python-cherrypy-5.6.0-3.el7.noarch.rpm        # 自動裝上了cherrypy 模塊
-------------------------------------------------

同時也需要我們生成證書:
[root@server1 salt]# cd /etc/pki/tls/private		# 密鑰存放目錄
[root@server1 private]# openssl genrsa 1024 > localhost.key		#生成密鑰
Generating RSA private key, 1024 bit long modulus
...............++++++
..........++++++
e is 65537 (0x10001)
[root@server1 private]# cd ../certs/
[root@server1 certs]# make testcert			# 生成證書
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:shaanxi
Locality Name (eg, city) [Default City]:Xi'an
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 certs]# ll localhost.crt 
-rw------- 1 root root 1046 Jun  9 15:06 localhost.crt

# 然後我們去/etc/salt/master.d 去編寫配置文件,這時master的輔配置目錄,可以被msater識別

我們調用api是需要認證來獲取token的,創建用戶認證文件:

[root@server1 master.d]# vim auth.conf
external_auth:
  pam:
    saltdev:			# 指定的用戶
      - .*			# 開放權限
      - '@wheel' 	# 允許訪問wheel模塊
      - '@runner' 
      - '@jobs'    
[root@server1 master.d]# useradd saltdev		#生成用戶
[root@server1 master.d]# passwd saltdev
Changing password for user saltdev.
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.

然後激活rest_cherrypy模塊:
[root@server1 master.d]# vim cert.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]# systemctl restart salt-master.service 
[root@server1 master.d]# systemctl start salt-api.service
[root@server1 master.d]# netstat -atnlp | grep 8000
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      30563/salt-api      
tcp        0      0 127.0.0.1:58574         127.0.0.1:8000          TIME_WAIT   -    

使用

獲取認證token:

[root@server1 master.d]# curl -sSk https://172.25.254.1:8000/login \
-H 'Accept: application/x-yaml' \
-d username=saltdev \
-d password=caoaoyuan \
-d eauth=pam		# t拓展認證方式

return:
- eauth: pam
  expire: 1591731223.9624
  perms:
  - .*
  - '@wheel'
  - '@runner'
  - '@jobs'
  start: 1591688023.962399
  token: 1be2665f52e403e2d8d4e457273f9065217da8e3    
  user: saltdev
認證通過後,我們就獲取到了一個token這個token就是訪問api的有效token,裏面是用戶的授權。

推送任務:

[root@server1 ~]# curl -sSk https://172.25.254.1:8000 \
-H 'Accept: application/x-yaml' \
-H 'X-Auth-Token: 1be2665f52e403e2d8d4e457273f9065217da8e3' \
-d client=local -d tgt='*'\
-d fun=test.ping
 
return:
- server2: true
  server3: true		# 返回了

我們哦層嗯github獲取腳本:
https://github.com/binbin91/oms/tree/master/deploy/saltapi.py
我們做以下更改:
開頭:

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

import urllib2,urllib
import time
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

結尾:

def main():
    sapi = SaltAPI(url='https://172.25.254.1:8000',username='saltdev',password='caoaoyuan')
    #sapi.token_id()				# 我們先讓它打引出一個key,就是master授權的主機
    print sapi.list_all_key()
    #sapi.delete_key('test-01')
    #sapi.accept_key('test-01')
    #sapi.deploy('server3','nginx')
    #print sapi.remote_noarg_execution('test-01','grains.items')

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


讓阿曼後我們讓他部署一個服務;
def main():
    sapi = SaltAPI(url='https://172.25.254.1:8000',username='saltdev',password='caoaoyuan')
    sapi.deploy('server3','nginx')

[root@server1 ~]# python saltapi.py 

[root@server3 ~]# systemctl stop nginx.service 
[root@server3 ~]# systemctl status nginx
● nginx.service - The NGINX HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2020-06-09 16:11:26 CST; 3s ago
					# 打開了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章