SaltStack--基础篇

975 阅读16分钟

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,必须打开端口才能接收访问连接。

image-20210618143302295

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。

image-20210622101403943

在初始连接之后,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>