1、Saltstack介绍
Salt是这样的一个软件:
- 一个配置管理系统,能够将远程节点维护在一个预定义的状态(例如,确保安装特定的软件包并运行特定的服务)
- 一个分布式远程执行系统,用于在远程节点上单独或通过任意选择标准来执行命令和查询数据
它的开发是为了将远程执行领域中发现的最佳解决方案结合在一起,使其更好,更快,更具延展性。 Salt通过简单易用的界面快速处理大量信息,而不仅仅是数十个甚至数千个单独的服务器。
以下是Salt的几项核心功能:
- 使管理命令能够并行地而不是串行地在远程系统中执行
- 使用安全和加密的协议
- 使用尽可能最小和最快的网络负载
- 提供简单的编程接口
Salt还为远程执行领域引入了更精细的控件,允许系统不仅可以通过主机名,还可以通过其系统属性进行定位。
2、Saltstack原理
1、Salt架构模型+通信原理
Salt使用server-agent通信模型。 服务器端组件被称为Salt master,agent被称为Salt minion。Salt master主要负责向Salt minions发送命令,然后聚合并显示这些命令的结果。 一个Salt master可以管理数千个系统。使用发布 - 订阅模式与受管系统进行通信。 连接由Salt minion发起,这意味着你不需要在这些系统上打开任何传入端口(从而减少攻击向量)。 Salt master使用端口4505和4506,必须打开端口才能接收访问连接。
Publisher (端口4505)所有Salt minions都需要建立一个持续连接到他们收听消息的发布者端口。 命令是通过此端口异步发送给所有连接,这使命令可以在大量系统上同时执行。
Request Server (端口4506)Salt minions根据需要连接到请求服务器,将结果发送给Salt master,并安全地获取请求的文件或与特定minion相关的数据值(称为Salt pillar)。 连接到这个端口的连接在Salt master和Salt minion之间是1:1(不是异步)。
2、Salt minion 认证
当minion第一次启动时,它会在网络中搜索一个名为salt的系统(尽管这可以很容易地更改为IP或不同的主机名)。 当发现时,minion发起握手,然后将公钥发送给Salt master。
在初始连接之后,Salt minions的公钥存储在服务器上,并且必须使用salt-key命令(或通过某种自动机制)在Salt master上接受。 这可能是让新用户混淆的原因,因为Salt不会提供解密消息所需的安全密钥,直到Salt minions的公钥被接受(这意味着Salt minions在被接受其密钥之前不会运行任何命令)。
在minion密钥被接受后,Salt主机会返回其公钥以及旋转的AES密钥,该密钥用于加密和解密由Salt master发送的消息。 返回的AES密钥使用Salt minion最初发送的公钥进行加密,因此只能由该Salt minion解密。
3、安全通信
Salt master和Salt minion之间的所有进一步通信都使用AES密钥进行加密。 AES加密密钥根据最新公认的TLS版本使用明确的初始化向量和CBC块链接算法。
AES密钥用于加密Salt master发送给Salt minion的作业,并加密与Salt master文件服务器的连接。 每次Salt master重新启动或者每次使用salt-key命令删除Salt minion密钥时,都会生成并使用新密钥。在密钥发生轮换后,所有的Salt minions必须重新认证才能收到更新后的钥匙。 这使得AES密钥可以在不中断连接的情况下更换。Salt原理中文网站
3、Saltstack部署(yum方式)
阿里云镜像源部署(我的系统版本 CentOS Linux release 7.9.2009 (Core))
sudo rpm --import https://repo.saltproject.io/py3/redhat/7/x86_64/latest/SALTSTACK-GPG-KEY.pub
curl -fsSL https://repo.saltproject.io/py3/redhat/7/x86_64/latest.repo | sudo tee /etc/yum.repos.d/salt.repo
官方镜像源部署
sudo rpm --import https://repo.saltproject.io/py3/redhat/8/x86_64/latest/SALTSTACK-GPG-KEY.pub
curl -fsSL https://repo.saltproject.io/py3/redhat/8/x86_64/latest.repo | sudo tee /etc/yum.repos.d/salt.repo
yum clean all
yum makecache
#salt-master机器
yum install salt-master salt-minion salt-ssh salt-syndic salt-cloud salt-api -y
#salt-minion机器
yum install -y salt-minion
启动服务:
#master机器
[root@vm1 ~]# systemctl start salt-master
[root@vm1 ~]# systemctl enable salt-master
Created symlink from /etc/systemd/system/multi-user.target.wants/salt-master.service to /usr/lib/systemd/system/salt-master.service.
#minion机器
[root@k8s-1 salt]# systemctl start salt-minion
[root@k8s-1 salt]# systemctl enable salt-minion
Created symlink from /etc/systemd/system/multi-user.target.wants/salt-minion.service to /usr/lib/systemd/system/salt-minion.service.
在minion的机器上配置/etc/salt/minion,然后重启重启salt-minion
interface: 192.168.31.201 #本地IP
master: 192.168.31.210 #master监听的IP
在salt-master上添加minion的公钥
[root@vm1 salt]# salt-key -L
Accepted Keys:
Denied Keys:
Unaccepted Keys: #此时公钥未被接受
k8s-1
Rejected Keys:
#接受k8s-1的公钥
[root@vm1 salt]# salt-key -a k8s-1 -y
The following keys are going to be accepted:
Unaccepted Keys:
k8s-1
Key for minion k8s-1 accepted.
[root@vm1 salt]# salt-key -L
Accepted Keys:
k8s-1
Denied Keys:
Unaccepted Keys:
Rejected Keys:
测试:
[root@vm1 ~]# salt 'k8s-1' test.ping
k8s-1:
True
master公钥接收:
[root@vm1 salt]# salt-key -L
Accepted Keys: #已经接受的Key
Denied Keys: #拒绝的Key
Unaccepted Keys: #未接受的Key
Rejected Keys: #拒绝或注销的Key
#常用参数
-L #查看KEY状态
-A #允许所有
-D #删除所有
-a #认证指定的key
-d #删除指定的key
-r #注销掉指定key(该状态为未被认证)
#配置master自动接受请求认证(master上配置 /etc/salt/master)
auto_accept: True
4、Saltstack配置信息
SlatStack的配置文件存放在/etc/salt目录下master为salt-master的配置文件,minion为salt-minion的配置文件,Salt官网配置(在进行操作之前建议先进行备份)
1、salt-master基础配置
#以下配置均为默认情况
interface: 0.0.0.0 #监听本地IP地址
publish_port: 4505 #发布端口
ret_port: 4506 #结果返回端口
user: root #指定master进程的运行用户
timeout: 5 #minion超时时间,如果网络不好,建议调大。
keep_jobs: 24 #minion执行结果返回master, master会缓存到本地的cachedir目录,该参数指定缓存多长时间,可查看之间执行结果会占用磁盘空间(默认为24h)
job_cache: True #master是否缓存执行结果,如果规模庞大(超过5000台),建议使用其他方式来存储jobs,关闭本选项(默认为True)
file_recv: False #是否允许minion传送文件到master 上(默认是Flase)
file_recv_max_size: 100 #接收文件的大小
log_level: warning #日志等级
log_level_logfile: warning
#日志文件路径
log_file: /var/log/salt/master
log_file: file:///dev/log
log_file: udp://loghost:10514
log_file: /var/log/salt/master
key_logfile: /var/log/salt/key
file_roots: #指定file server目录
base:
- /srv/salt/
dev:
- /srv/salt/dev/services
- /srv/salt/dev/states
prod:
- /srv/salt/prod/services
- /srv/salt/prod/states
2、salt-minion基础配置
#以下配置均为默认情况
master: #master的IP
master_port: 4506 #master的结果端口
id: #本机的hostname或者IP
user: #指定运行minion的用户(默认root)
cache_jobs: False #minion是否缓存执行结果
backup_mode: minion #在文件操作(file.managed 或file.recurse) 时, 如果文件发送变更,指定备份目录.当前有效
providers: #指定模块对应的providers, 如在RHEL系列中, pkg对应的providers 是yumpkg5
renderer: jinja|yaml #指定配置管理系统中的渲染器
file_client: remote #指定file clinet 默认去哪里(remote 或local) 寻找文件
log_level: warning #指定日志级别
tcp_keepalive: True #minion 是否与master 保持keepalive 检查
注:配置修改完成后需要重启服务。
5、Saltstack远程执行命令
salt命令的结构语法
salt [options] '<target>' <function> [arguments]
option:命令
target:目标机器
function:执行的命令模块和方法
arguments:额外参数
1、Option+Target
-L 列表匹配
[root@vm1 ~]# salt -L 'k8s-1,k8s-2,k8s-3' test.ping
-E 正则匹配
[root@vm1 ~]# salt -E 'k8s-[1-2]' test.ping
-S 路由匹配
[root@vm1 ~]# salt -S '192.168.31.201' test.ping
[root@vm1 ~]# salt -S '192.168.31.0/24' test.ping
-C 复合匹配
[root@vm1 ~]# salt -C 'E@k8s-[1-6] and S@192.168.31.201' test.ping
-G Grains匹配
[root@vm1 ~]# salt -G 'os:CentOS' test.ping
-N 分组匹配
[root@vm1 ~]# tail -4 /etc/salt/master
nodegroups:
master-server: 'k8s-1,k8s-2,k8s-3'
node-server: 'k8s-4,k8s-5,k8s-6'
etcd-server: 'k8s-1,k8s-2,k8s-3'
[root@vm1 ~]# salt -N 'etcd-server' test.ping
2、Function
Function= 执行的模块+命令官网模块列表
test:模块多用于测试
cmd: 模块可以执行任意shell命令
user:模块用于用户管理
pkg:模块用于软件包管理
file:模块多用于配置文件
service:模块用于服务管理
network:模块用于查看机器网络信息
dig:模块用于DNS相关查询
git:模块用于git提交代码
test模块:
[root@vm1 ~]# salt 'k8s-1' test.ping
k8s-1:
True
#查看模块帮助手册
[root@vm1 ~]# salt 'k8s-1' test
cmd模块:
#执行uptime查看系统运行时间和负载信息
[root@vm1 ~]# salt 'k8s-1' cmd.run 'uptime'
k8s-1:
16:58:44 up 6:22, 1 user, load average: 0.00, 0.01, 0.05
#查看/home/下的所有目录
[root@vm1 ~]# salt 'k8s-1' cmd.run 'ls -l /home/'
k8s-1:
total 0
drwx------. 3 fong fong 95 Jun 9 17:29 fong
user模块:
[root@vm1 ~]# salt 'k8s-1' user.add 'testuser'
k8s-1:
True
[root@vm1 ~]# salt 'k8s-1' user.delete 'testuser'
k8s-1:
True
pkg模块:
功能:软件包状态管理,会根据操作系统不同,选择对应的安装方式(如CentOS系统默认使用yum,Debian系统默认使用apt-get)
#安装httpd包
[root@vm1 ~]# salt 'k8s-1' pkg.install 'httpd'
#移除httpd包
[root@vm1 ~]# salt 'k8s-1' pkg.remove 'httpd'
#下载最新版本
[root@vm1 ~]# salt 'k8s-1' pkg.latest_version 'httpd'
#更新
[root@vm1 ~]# salt 'k8s-1' pkg.upgrade 'httpd'
file模块:
功能:被控主机常见的文件操作,包括文件读写、权限、查找、校验
[root@vm1 ~]# salt 'k8s-1' file.get_mode '/etc/salt/minion'
k8s-1:
0644
6、saltstack数据系统
1、grains
1、简介
1、Salt提供了一个接口来获取关于底层系统的信息。这被称为grains接口,因为它为Salt提供了大量信息。Grains包括操作系统、域名、IP地址、内核、操作系统类型、内存和许多其他系统属性。grain接口对Salt模块和组件可用,这样就可以在正确的系统上自动使用正确的Salt minion命令。grains是相对静态的,采集动作只在启动客户端或有新的Grains添加时触发,Grains采集上报的数据可以作为资产管理的元数据。 2、如果需要自定义grains,需要添加到Salt Minion的/etc/salt/grains文件中(配置文件中定义的默认路径),也可以直接写在配置文件/etc/salt/minion中。官网grains文档
3、Grains是静态的,因为它们不经常更换,它们在更新时需要主动进行刷新。 这可以通过调用:salt minion saltutil.refresh_modules来完成此操作。
#grains所有模块
[root@vm1 ~]# salt 'k8s-1' grains.ls
#minion机器所有状态信息
[root@vm1 ~]# salt 'k8s-1' grains.items
#机器ipv4地址
[root@vm1 ~]# salt 'k8s-1' grains.item fqdn_ip4
#更新grains数据操作
[root@vm1 ~]# salt '*' saltutil.refresh_modules
2、grains添加自定义items
1、修改minion机器的配置文件/etc/salt/minion
grains:
roles:
- webserver
- memcache
deployment: datacenter4
cabinet: 13
cab_u: 14-15
welcome:
- fong
#重启salt-minion
[root@vm1 ~]# salt 'k8s-1' grains.get welcome
k8s-1:
- fong
2、将default_include: minion.d/*.conf配置项打开,然后将自定义grains的以.conf结尾的配置文件放到minion.d这个目录中。
#配置/etc/salt/minion
default_include: minion.d/*.conf
在minion.d目录中添加并编辑grains.conf文件(文件名随意)
grains:
welcome: fong
#重启salt-minion
[root@vm1 ~]# salt 'k8s-1' grains.get welcome
k8s-1:
fong
3、在master端添加
在配置文件file_roots指定的目录(默认是/srv/salt)下创建_grains目录,编写可以返回一个字典的py文件。我这里配置的是/home/salt/srv/base
file_roots:
base:
- /home/salt/srv/base
dev:
- /home/salt/dev/services
- /home/salt/dev/states
prod:
- /home/salt/prod/services
- /home/salt/prod/states
例如grains添加自定义item(disk_size)返回磁盘的大小,注意python脚本返回值是一个字典。
[root@vm1 salt]# cat /home/salt/srv/base/_grains/disk.py
#coding=utf-8
import os
def disk_size():
''' get disk size '''
disk = os.statvfs("/")
capacity = disk.f_bsize * disk.f_blocks
ret = int(float(capacity)/1000/1000/1000)
if ret > 1000:
obj = ret/1000.0
disk_size = ("%.1f" % obj) + 'T'
else:
ret = str(ret)
disk_size = ret + 'G'
return {'disk_size': disk_size}
用saltutil.sync_grains或者saltutil.sync_all将自定义的grains item同步到minion端,如果只同步grains建议使用saltutil.sync_grains。
同步完成后在minion端的以下目录中可以找到master下发的grains文件
[root@k8s-1 ~]# ls /var/cache/salt/minion/extmods/grains/
disk.py __pycache__
查看是否同步成功
[root@vm1 _grains]# salt 'k8s-1' grains.item disk_size
k8s-1:
----------
disk_size:
53G
4、在master端直接用grains.setval为指定minion的grains设定一个item 设定welcome的值为hello world
[root@vm1 ~]# salt 'k8s-2' grains.setval welcome 'hello world'
k8s-2:
----------
welcome:
hello world
[root@vm1 ~]# salt 'k8s-2' grains.get welcome
k8s-2:
hello world
2、Pillar
1、简介
Pillar是Salt的一个接口,旨在提供可以分发给下属的全局值,Pillar数据的管理方式跟salt state类似。Pillar是动态的,存储在master上,提供给minion,主要记录一些加密信息,可以确保这些敏感数据不被其他minion看到。比如:软件版本号、用户名密码等。存储格式都是YAML格式官网Pillar文档
2、在Master端定义Pillar
在/etc/salt/master中配置
pillar_roots:
base:
- /home/salt/pillar
在/home/salt/pillar下编写top.sls入口
[root@vm1 pillar]# cat top.sls
base:
'k8s-1':
- etcd
在/home/salt/pillar目录下编写需要的sls文件
[root@vm1 pillar]# cat etcd.sls
etcd_server: 192.168.31.201
etcd_name: k8s-1
刷新
[root@vm1 pillar]# salt 'k8s-1' saltutil.refresh_pillar
k8s-1:
True
获取相关的数据
[root@vm1 pillar]# salt 'k8s-1' pillar.item etcd_server
k8s-1:
----------
etcd_server:
192.168.31.201
[root@vm1 pillar]# salt 'k8s-1' pillar.item etcd_name
k8s-1:
----------
etcd_name:
k8s-1
3、Pirrar与Grains对比
| 类型 | 数据类型 | 数据采集更新方式 | 定义位置 | 存放位置 | 应用 |
|---|---|---|---|---|---|
| Grains | 静态数据 | minion启动时收集,也可以使用salt '*' saltutil.sync_grains进行刷新 | 目标选择 | minion端 | 存储Minion基本护具,比如用于匹配Minion,自身收据可以用来做资产管理等 |
| Pillar | 动态数据 | master进行自定义,指定给对应的Minion,可以使用salt '*' saltutil.refresh_pillar刷新 | 配置管理 | master端 | 存储Master指定 数据,只有指定Minion可以看到,用于敏感数据保存 |
7、Salt State File
1、简介
SLS(代表SaLt State文件)是Salt State系统的核心。SLS描述了系统的目标状态,由格式简单的数据构成。这经常被称作配置管理。在使用sls之前,需要先指定环境配置的根目录,不然后面执行的时候会出现找不到文件的提示。环境配置文件为master节点的/etc/salt/master
file_roots:
base:
- /home/salt/srv/base
dev:
- /home/salt/dev/services
- /home/salt/dev/states
prod:
- /home/salt/prod/services
- /home/salt/prod/states
file_roots配置salt配置的存放目录, 其中base环境是必要的, 指定top.sls存放的位置。默认没指定环境时则从base目录获取文件,其它则是一些自定义的, 可以通过环境变量指定.这样可以逻辑上隔离一些环境配置.每一个环境都可以定义多个目录, 优先级关系由定义目录的顺序决定。
file_roots:
base:
- /home/salt/srv/foo
- /home/salt/srv/bar
如果寻找 salt://file.sls, 如果都存在/home/salt/srv/foo/file.sls和/home/salt/srv/bar/file.sls,则使用第一个找到的。
SLS文件的默认渲染器是YAML渲染器。YAML是一种具有强大功能的标记语言。而Saltstack就是使用一部分YAML来映射非常常用的数据结构,例如列表和字典。YAML渲染器的工作就是采用YAML数据结构将其编译为Python数据结构供Saltstack使用。 关于YAML标记语言需记住四个基本规则:
规则一、缩进:
YAML使用固定缩进来表示数据层之间的关系,要求每个级别的缩进刚好两个空格(缩进不允许使用tab、只能使用空格)。
规则二、冒号:
字典键在YAML中表示由冒号分割的字符串。值有冒号后面的字符串表示,由空格分割。
规则三、破折号:
为了表示项目列表,使用单个短划线后跟空格。多个项目是同一个列表的一部分,具有同级别的缩进。
规则四、大小写:
YAML对大小写字符敏感。
2、创建一个sls文件
在master上,在上一步中取消注释的目录(默认情况下为/srv/salt)中,创建一个名为top.sls的新文件并添加以下内容:
[root@vm1 base]# cat top.sls
base:
'*':
- webserver
在和 top file 文件同一个目录中, 创建一个名为 webserver.sls 的文件, 包含以下内容:
[root@vm1 webserver]# cat webserver.sls
httpd: # ID declaration
pkg: # state declaration
- installed # function declaration
第一行称为ID声明,可以是一个任意标识符。 在上面的这种情况下,它定义了要安装的包的名称。
第二行称为state声明,它定义了我们正在使用哪些Salt States。 在此示例中,我们使用pkg state来确保安装了给定的包。
第三行称为Function声明,它定义了在pkg state模块中要调用的函数。
[root@vm1 base]# salt 'k8s-1' state.apply webserver.sls
你可以在ID声明下指定多个State声明。 例如,快速修改我们的webserver.sls,检查如果Apache服务没有运行,则启动Apache:
制作httpd的安装任务,添加一个HTML文件来定制网站。 拥有一个没有网络服务器的网站并不是很有用所以我们不希望Salt在安装和运行Apache之前部署我们的HTML文件。 在webserver/init.sls文件的底部包含以下内容:
httpd:
pkg.installed: []
service.running:
- require:
- pkg: httpd
/var/www/html/index.html: # ID declaration
file: # state declaration
- managed # function
- source: salt://webserver/index.html # function arg
- require: # requisite declaration
- pkg: httpd # requisite reference
第7行 是 ID 声明。在此示例中,它是我们要安装自定义HTML文件的位置。
第8行 是state声明。 此示例使用的是Salt file state。
第9行 是Function声明。 managed function将从master服务器下载文件并将其安装在指定的位置。
第10行 是一个Function arg的声明,在本例中,它将source参数传递给managed函数。
第11行 是 Requisite的声明。
第12行 是Requisite的参数,指向了一个state和一个ID。 在这个例子中,它引用了第1部分中的示例中的ID声明。该声明告诉Salt在安装httpd服务之前不要安装HTML文件。
接下为, 创建 index.html 文件并把它保存在 webserver 目录中:
<!DOCTYPE html>
<html>
<head><title>Salt rocks</title></head>
<body>
<h1>This file brought to you by Salt</h1>
</body>
</html>
最后, 再次调用state.apply,minion将从master获取数据并执行highstate,以及从Salt的文件服务器获取我们的HTML文件:
[root@vm1 webserver]# salt 'k8s-1' state.apply webserver.init
k8s-1:
----------
ID: httpd
Function: pkg.installed
Result: True
Comment: All specified packages are already installed
Started: 21:46:46.377213
Duration: 568.05 ms
Changes:
----------
ID: httpd
Function: service.running
Result: True
Comment: The service httpd is already running
Started: 21:46:46.946674
Duration: 34.924 ms
Changes:
----------
ID: /var/www/html/index.html
Function: file.managed
Result: True
Comment: File /var/www/html/index.html updated
Started: 21:46:46.987634
Duration: 31.249 ms
Changes:
----------
diff:
New file
mode:
0644
Summary for k8s-1
------------
Succeeded: 3 (changed=1)
Failed: 0
------------
Total states run: 3
Total run time: 634.223 ms
检查一下Apache是否可以正确地为我们自定义的HTML网页提供服务。
[root@k8s-1 ~]# curl 192.168.31.201
<!DOCTYPE html>
<html>
<head><title>Salt rocks</title></head>
<body>
<h1>This file brought to you by Salt</h1>
</body>
</html>