> For AI agents: the complete documentation index is available at https://www.tteam.icu/llms.txt, the full documentation bundle is available at https://www.tteam.icu/llms-full.txt.

# saltstack

## 相关链接

[旧文档](https://docs.saltstack.cn/ref/states/all/index.html)

[新文档](https://docs.saltproject.io/en/latest/topics/tutorials/gitfs.html#installing-dependencies)

[下载地址](https://docs.saltproject.io/salt/install-guide/en/latest/)

[Jinja 语法](https://www.tteam.icu/ops/language/jinja.md)

## 命令

### 安装


**centos**

```bash
# 安装saltstack存储库和密钥
curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.repo | tee
/etc/yum.repos.d/salt.repo
# 换源
sed -i 's#https://repo.saltproject.io/#https://mirrors.tuna.tsinghua.edu.cn/saltstack/#g'
/etc/yum.repos.d/salt.repo

dnf -y install salt-master # 主控端安装
dnf -y install salt-ssh # salt-ssh安装
dnf -y install salt-minion # 受控端安装
```


**debian**

```bash
mkdir -p /etc/apt/keyrings
curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee
/etc/apt/keyrings/salt-archive-keyring.pgp
curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee
/etc/apt/sources.list.d/salt.sources
apt update
apt -y install salt-master # 主控端安装
apt -y install salt-ssh # salt-ssh安装
apt -y install salt-minion # 受控端安装
```


| 服务器     | 主机名  | ip            | 身份     | 软件包         |
| ------- | ---- | ------------- | ------ | ----------- |
| centos7 | xue1 | 192.168.70.75 | master | salt-master |
| centos7 | xue2 | 192.168.70.76 | minion | salt-minion |

```bash
# 受控端需要修改(注意:后面需要有一个空格)
vim /etc/salt/minion

# 受控端设置
# 主控端ip
master: 192.168.70.75
# 受控端的名字(自定义)
id: xue2

# 主控端设置(取消注释，默认salt脚本路径和复制文件的路径)
file_roots:
  base:
    - /srv/salt/


# 在主控端可以看有多少请求(主控端需要开启4505和4506端口)
salt-key -L
# 接受需要的受控端
salt-key -a "xue*"
# 接受以后可以测试有没有成功
salt "xue*" test.ping
```

```bash
# salt-key 常用选项
    -L              # 列出所有公钥信息
    -a minion       # 接受指定 minion 等待认证的 key
    -A              # 接受所有 minion 等待认证的 key
    -r minion       # 拒绝指定 minion 等待认证的 key
    -R              # 拒绝所有 minion 等待认证的 key
    -f minion       # 显示指定 key 的指纹信息
    -F              # 显示所有 key 的指纹信息
    -d minion       # 删除指定 minion 的 key
    -D              # 删除所有 minion 的 key
    -y              # 自动回答 yes
```

```bash
# 语法: salt [options] '<target>' <function> [arguments]

# 常用的 options
    --version           # 查看 saltstack 的版本号
    --versions-report   # 查看 saltstack 以及依赖包的版本号
    -h                  # 查看帮助信息
    -c CONFIG_DIR       # 指定配置文件目录(默认为 /etc/salt/)
    -t TIMEOUT          # 指定超时时间(默认是 5s)
    --async             # 异步执行
    -v                  # verbose 模式，详细显示执行过程
    --username=USERNAME # 指定外部认证用户名
    --password=PASSWORD # 指定外部认证密码
    --log-file=LOG_FILE # 指定日志记录文件
    
# 常用 target 参数
    -E              # 正则匹配
    -L              # 列表匹配 
    -S              # CIDR 匹配网段
    -G              # grains 匹配
    --grain-pcre    # grains 加正则匹配
    -N              # 组匹配
    -R              # 范围匹配
    -C              # 综合匹配(指定多个匹配)
    -I              # pillar 值匹配
```

### 编写

具体格式可以参考[官方文档](https://docs.saltstack.cn/ref/states/all/index.html)

创建测试文件 `vi /data/salt/test.sls`:

```bash
# 创建文件夹(注意 file.directory 前面两个空格，- 前面 4 个，- 后面 1 个，True 前面 1 个，最后三行可以指定用户、组、权限)
/data/logs/:
  file.directory:
    - makedirs: True
    - user: fred
    - group: users
    - mode: 755

# 删除 /data 这个目录和下面的所有文件
del:
  file.absent:
    - name: /data/

# 上传单文件到受控端(主控端写相对路径，上传到受控端的绝对路径)
upload:
  file.managed:
    - name: /data/app/1.txt
    - source: salt://1.txt
    - mode: 644

# 上传目录到受控端(主控端写相对路径，上传到受控端的绝对路径，include_empty 空目录也要上传)
# exclude_pat 来排除文件，在 E@ 后面跟正则表达式
# watch 可以监视某个有没有执行成功
upload_res:
  file.recurse:
    - name: /data/data/
    - source: salt://data/
    - dir_mode: 755
    - file_mode: 644
    - exclude_pat: E@(.svn)|(setup-v3.sh)|(setup.sh)
    - include_empty: True
    - watch:
      - file: upload
```

## Salt 使用 Git 作为服务端

### 使用最新的 TLS 版(目前为 3006.5)

```bash
# 新版本的 salt 自带 python
rpm --import https://repo.saltproject.io/salt/py3/redhat/7/x86_64/SALT-PROJECT-GPG-PUBKEY-2023.pub
curl -fsSL https://repo.saltproject.io/salt/py3/redhat/7/x86_64/3006.repo | sudo tee /etc/yum.repos.d/salt.repo

salt -V
```

```bash
Salt Version:
          Salt: 3006.5
 
Python Version:
        Python: 3.10.13 (main, Nov 15 2023, 04:34:27) [GCC 11.2.0]
 
Dependency Versions:
          cffi: 1.16.0
      cherrypy: unknown
      dateutil: 2.8.1
     docker-py: Not Installed
         gitdb: Not Installed
     gitpython: Not Installed
        Jinja2: 3.1.2
       libgit2: 1.7.1
  looseversion: 1.0.2
      M2Crypto: Not Installed
          Mako: Not Installed
       msgpack: 1.0.2
  msgpack-pure: Not Installed
  mysql-python: Not Installed
     packaging: 22.0
     pycparser: 2.21
      pycrypto: Not Installed
  pycryptodome: 3.9.8
        pygit2: 1.13.3
  python-gnupg: 0.4.8
        PyYAML: 6.0.1
         PyZMQ: 23.2.0
        relenv: 0.14.2
         smmap: Not Installed
       timelib: 0.2.4
       Tornado: 4.5.3
           ZMQ: 4.3.4
 
System Versions:
          dist: centos 7.9.2009 Core
        locale: utf-8
       machine: x86_64
       release: 3.10.0-1160.71.1.el7.x86_64
        system: Linux
       version: CentOS Linux 7.9.2009 Core

```

### 安装 pygit2

```bash
yum install python-pygit2 -y

salt-pip install pygit2
```

### 在 master 中配置

```yaml
fileserver_backend:                                # 当前配置为 git 和本地都用，两边有文件时优先使用 git
  - gitfs                                          # 需要在这里写出来才能用
  - roots

gitfs_provider: pygit2                             # 配置 salt 的文件服务器为 pygit2
gitfs_ssl_verify: False                            # 是否校验 ssl(主配置)
gitfs_update_interval: 120                         # 间隔多少秒去拉 git(主配置)
gitfs_user: test                                   # git 的账号(主配置)
gitfs_password: test                               # git 的密码(主配置)
gitfs_insecure_auth: True                          # 默认 False 情况下，Salt 将不会通过 HTTP(非 HTTPS)远程进行身份验证(主配置)
gitfs_remotes:
  - http://xx.xx.xx.xx:8080/root/saltstack.git:    # git 地址
    - user: root                                   # git 的账号(子配置)
    - password: password                           # git 的密码(子配置)
    - ssl_verify: False                            # 是否校验 ssl(子配置)
    - update_interval: 30                          # 间隔多少秒去拉 git(子配置)
    - base: master                                 # 分支(子配置)
```

### 配置 Git 钩子(以 GitLab 为例)

在 `/data/salt/` 新建 `update_fileserver.sls` 文件，可以按照上面的来填写目录和文件名:

```yaml
update_fileserver:
  runner.fileserver.update
```

#### 在 master 中配置

```bash
reactor:
  - 'salt/fileserver/gitfs/update':
    - /data/salt/update_fileserver.sls           # 此配置可以按照上面的来填写目录和文件名
```

#### 配置 GitLab 钩子

15.11 及更高的版本可能在 hooks 目录。

15.10 及更早的版本(当前公司为这个配置):

```bash
# 管理中心 -> 项目 -> saltstack -> 找到 Gitaly 相对路径
# 在服务端中找到对应路径(容器内目录需要加上 /var/opt/gitlab/git-data/repositories)
mkdir custom_hooks && cd custom_hooks && touch post-receive chmod a+x post-receive
vim post-receive         # 注: 下面的脚本最开始的那行最好在容器内执行 which python3 来填写
```

```py file="./saltstack/remote_pull_hooks.py" title="remote_pull_hooks.py"
#!/opt/gitlab/embedded/bin/python3
from pyssh_util.ssh_util import SSHClient

if __name__ == "__main__":
    host = '192.168.1.1'
    password = 'password'
    ssh = SSHClient(host, password)
    command = 'salt-call event.fire_master update salt/fileserver/gitfs/update'
    result_single = ssh.execute_command(command)
    ssh.close()
```

:::tip
需要在 GitLab 容器中安装封装的依赖:

```bash
docker exec -i gitlab /opt/gitlab/embedded/bin/pip3 install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple
docker exec -i gitlab /opt/gitlab/embedded/bin/pip3 install pyssh-util==1.0.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
```

:::

## 其他

### salt-ssh

```bash
# target 的信息
    host:        # 远端主机的 IP 地址或 DNS 域名
    port:        # SSH 端口
    user:        # 登录的用户
    sudo:        # 可以通过 sudo
    priv:        # SSH 密钥的文件路径
    tty:         # 如果设置了 sudo，设置这个参数为 true
    timeout:     # 当建立连接时等待响应时间的秒数
# 可选的部分
    passwd:      # 用户密码，如果不使用此选项，则默认使用密钥方式
    minion_opts: # minion 的位置路径
    thin_dir:    # target 系统的存储目录，默认是 /tmp/salt-<hash>
    cmd_umask:   # 使用 salt-call 命令的 umask 值
    
hdy-xg-server-001:
  host: 154
  port: 22
  user: root
  sudo: true
  passwd: 
  tty: true
  timeout: 60
```

```bash
# 可能需要 py3
salt-ssh -r 'hdy-xg-server-001' 'yum -y install python3'

vim ~/.ssh/config


StrictHostKeyChecking no
```

### salt-proxy

需要在 proxy 端安装 `salt-syndic`。

然后在 proxy 端的 master 增加配置 `order_masters: True` 和 `syndic_master: <master_ip>`。
