什么是 state

SLS(代表 SaLt State 文件)是 Salt State 系统的核心。SLS 描述了系统的目标状态,由格式简单的数据构成。这经常被称作配置管理。salt 有众多的 modules,state 是使用频率最高的。它有点像是 ansible 的 playbook。可以像剧本一样执行一系列的命令。可以通过下面的链接查找 state 支持的所有 functions。
https://docs.saltstack.com/en/latest/ref/states/all/index.html

SLS 文件语法

master 节点默认识别/srv/salt 下面所有的以 sls 为后缀名的文件为 state 可调用的文件。 这些文件是 YAML 格式的。例如:

kubeadm: # 唯一标识的ID,一般写一个比较好理解的名字。后面require关键字会用到
   pkg.installed: # pkg是一个state的module,这个模块代表了使用本地包管理器来管理接下来的应用(例如centos是yum),installed是这个模块的function,代表了这个应用的状态, 意思是要保持这个应用是处于被安装的状态。 也就是说如果salt发现这个kubeadm这个工具在系统中不存在就会去安装它,如果存在就什么都不做。
    - name: kubeadm # name是这个function的一个参数,表示要安装的包是什么。 相当于yum install kubeadm
    - require: # 依赖,表名依赖于其他的服务。必须等到这些服务运行完后才运行
      - file: kubeadm.repo # require的参数。 这里要填写的是module的ID。 这里表明依赖一个file 的module, 当这个文件准备妥当以后才可运行 。 这里表明的是依赖ID为kubeadm.repo的file module。

kubeadm.repo: # 唯一标识的ID, 上面ID为kubeadm的state在require中指明了要依赖这个ID
  file.managed: # file是state的另外一个module。意思是文件管理。会把master节点的一个文件复制到minion上去。 上面的kubeadm在require中声明了要依赖一个file的module
    - name: /etc/yum.repos.d/kubernetes.repo # 表明minion的目标文件路径
    - source: salt://utils/k8s/kubernetes.repo # master节点上要复制源路径
    - user: root # 以下都是设置文件的权限信息。
    - group: root
    - mode: 644

上面是一个安装 kubeadm(k8s 的部署工具) 的 state 文件。 每一句的解释都放在了注释里。 state 翻译过来是状态, 它设计的初衷就是让服务器达到某种状态 (必须安装某些服务或者卸载某些服务等等), 所以在 pkg.installed 里才有如果存在才安装,不存在就什么都不做的逻辑,因为它判断出来服务器已经处于已安装的状态。理解这个概念很重要。 同样的还有 pkg.removed。意思是要保证当前服务器上一定不能有哪些服务,如果存在就卸载,不存在就什么都不做。 例如:

remove docker:
  pkg.removed:
    - pkgs:
      - docker
      - docker-common
      - docker-selinux
      - docker-engine

这是安装 docker-ce 之前的步骤,我们都知道现在 docker 安装包已经修改为 docker-ce 了。 老版本的 docker 还有 docker-engine 都会跟 docker-ce 冲突。 包括 docker-common 和 docker-selinux 也一样。 所以在安装 docker-ce 之前要保证这些包不能存在服务器上。

在使用 pkg 和 file 这种好用的 module 之余,也可以自己定制操作。例如我们想要服务器的 iptables 是保持干净的,不希望有些规则堵死网络。那么我们做如下设置:

init_iptalbes:
  cmd.run:
    - name: iptables -P INPUT ACCEPT; iptables -F; iptables -X; iptables -Z
    - require:
      - pkg: install kubeadm

cmd module 就是用来给我们写 shell 的地方。高频使用的 module。 接下来还有一个比较常用的指令是 include, 我们写代码的时候都有这种模块引入功能达到代码复用的作用。state 也是有的。如下:

include:
  - init_kubeadm
  - tools

上面代表引入 init_kubeadm.sls 和 tools.sls 中的所有内容

salt '节点名称' state.sls set_k8smaster(这里是sls的文件名称,注意不能带后缀名)

给 state 传参

salt 还有一个 module 叫 pillar。 通过它的一个特性我们可以动态的在运行命令的时候为 state 传递参数。假如我们想要安装一个 k8s 的从节点。 需要知道 master 节点的地址和 token。 这些是不能写死在 state 里面的。所以我们要参数化它。例如:

{% set k8s_token = pillar.get("token", "token") %}
{% set master_node = pillar.get("master_node", "token") %}

join_master:
  cmd.run:
    - name: kubeadm reset; kubeadm join --token {{k8s_token}} {{master_node}}:6443
    - require:
      - cmd: k8s_images_init
      - pkg: install kubeadm

我去掉了一些不必要的步骤 ,只留下了 kubeadm join 的这一段。 可以看到在 join 的时候需要知道 k8s 的 token 和 节点地址。 在脚本一开始的时候我们通过 jinja2 的语法去获取参数。 使用的就是 salt 的 pillar。 这样我们在调用 salt 命令的时候就可以这么写:

salt '172.27.130.32' state.sls join_k8smaster pillar='{"token":"97baa4.e0305e566bb15db8", "master_node": "m7-qa-test01"}'

结尾

这里介绍了 state 的最常用的语法, 当我们准备好 state 文件以后就可以用下面的命令运行了。


↙↙↙阅读原文可查看相关链接,并与作者交流