前言:
此博文主要以介绍salt配置管理理论为主,关于一些项目的实战将在后续的博文中展开。
Salt配置管理系统介绍
salt的配置管理系统与远程执行都是salt的核心功能,关于远程执行更多的介绍请参考上一篇博文《SaltStack远程执行常用模块使用》。这里我将介绍salt的另一个核心功能,配置管理系统,通过配置管理系统我们可以完成服服器的个性化配置文件管理,复杂的一些应用部署,比如LAMP源码部署,根据系统版本初始化系统配置等更多的功能。
salt配置管理系统依赖于state状态管理,而我们管理需要state状态文件,这些文件必须以 .sls 结尾,需要由我们自己来编写。此文件格式与YAML语法格式相同,并且还可以使用Jinja(Python的模块引擎),通过它我们可以完成一些个性化配置等功能,本文后面将会对YAML,Jinja,还有一点特殊的状态文件以及Salt环境作一些介绍。
环境介绍
环境里面主要就是存放我们的一些状态文件,配置文件等,我们的这些文件可以是生产环境 (Prod),或者开发环境(Dev)等,当然我们可以按我们的服务器种类,来分或者其它方法分,最主要是适用。我们安装好服务端(Salt-master)后默认有一个基础环境(Base),下面我们来自定义我们的环境。
修改服务端配置文件:/etc/salt/master
#在配置文件最后加入以下内容,可以在配置文件里查找“file_roots:”关键字,找到相关例子和说明 file_roots: base: - /srv/salt/base test: - /srv/salt/test
以上配置文件我们定义了2个环境,分别为base,test,其中base环境为必须有的,且名称不可更改,其它我们可以自定义,接来下我们需要创建我们的目录,然后重启服务端服务
mkdir /srv/salt/{base,test} systemctl restart salt-master
YAML语法介绍
关于yaml语法在salt客户端配置文件,服务端配置文件和state状态文件都是采用此讲法结构,所我们很有必要撑握此语法的使用。此语法有以下几个要点
缩进:缩进必须两个空格,不可以使用tab,主要用来表示层级关系
冒号:只要是以冒号结尾的行的下一行必须缩进两个空格,相当于Python里面的key-value。当然如果我们的key只有一个值的话我们可以写成一行,中间空一格即可。如果我们的key的值为一个列表,那么就需要另起一行,并且缩进两个空格以 - 开头
短横线:如上一条所说,一个短模线就相当于一个列表里面的一个元素,我们可以有多个元素。并且短模线的后面必须要有一个空格
例如,我们可以将服务端配置文件里面的file_roots改成如下配置:
file_roots: base: /srv/salt/base test: - /srv/salt/test1 - /srv/salt/test2
将以上内容转换为我们Python的字典如下:
{'file_roots': {'test': ['/srv/salt/test1', '/srv/salt/test2'], 'base': '/srv/salt/base'}} #我们可以使用python的yaml模块(pyyaml包)进行yaml和dict之间的转换测试
top.sls介绍
此文件文件名固定为top.sls,用来定义环境的总入口配置文件,当使用以下命令的时候就会调用
salt [TARGET] state.highstate <ENV>(state模块的highstate方法)时就会自动调用对应环境的top.sls,那么如果不使用state.highstate,而使用salt [TARGET] state.sls [State_File] <ENV>可以指定执行某一个状态文件,这样就不需要调用top.sls这个总入口文件了。如果不指定环境,那么默认调用base环境的状态文件。上面我们讲过所有state状态文件(以.sls结尾)都是使用yaml格式,下面我们看一个例子:
base: #第一行为环境的名称,与file_roots保持一致,如果是test环境那就这里就是test '*': #指定主机,可以使用所有的target,如通配符,regex,grain,pillar,nodegroups等 - init.init_env #要执行的状态文件,以环境根目录开始,父目录与子目录用点分隔,非常像Python的模块调用 'os:CentOS': - match:grain #指定要使用的target - httpd_install
可能你看完这小节感觉不是特别理解,比如什么是target,为什么这样调用state状态文件,state.highstate又是什么意思。关于什么是target,参考另一篇博文《Salt之target介绍》,那么关于剩下的问题我将在本博文后面以一个小例子来让大家明白
init.sls介绍
关于此文件用得不是特别广范,但还是需要给大家介绍我们来看一个例子,先来看看我们的目录结构,这里test环境根目录下面的jdk目录结构。主要用来安装使用源码安装jdk7
jdk/ ├── 7 #根据安装的版本来划分目录,我们还可以安装jdk8等 │ ├── files #用于存放文件的目录 │ │ ├── jdk-7u79-linux-x64.gz #源码包 │ │ └── jdk.sh #环境变量配置文件 │ ├── init.sls #占且称之为目录初始化状态文件 │ └── install.sls #安装状态文件 └── 8 ├── files │ ├── jdk-8u102-linux-x64.tar.gz │ └── jdk.sh └── install.sls
再看看我们init.sls文件的内容
include: #特殊模块,用于包含其它模块 - jdk.7.install #被包含模块的路径,以环境根目录开始
从上面我们可以看出为什么我们jdk8的没有init.sls,这个文件有一个特殊的作用,那可有可无,下面我们将以安装jdk8和jdk7来演示为什么可有可无
安装jdk7
salt "*node1" state.sls jdk.7 saltenv=test
上面的命令我们安装jdk7我们使用的是state.sls,所以我们后面要跟模块的名称,模块名称需要从环境根目录开始,到最终我们使用的模块。但上面我们使用的是jdk.7,而7是一个目录,并不是state状态文件,所以这时候我们的init.sls就起到了这样一个作用,当最后所指的状态文件为一个目录时,那么系统会自动找到该目录下面的init.sls状态文件,而此文件我们包含了我们安装jdk所需要的模块,最后通过此文件来执行,如果该目录下面也没有init.sls那么就会直接报错,找不到可执行的状态文件。saltenv=test表示指定环境为test环境
安装jdk8
salt "*node1" state.sls jdk.8.install saltenv=test test=True
从上面的目录结构我们可以看出jdk/8/这个目录下面并没有init.sls,所以这时候我们需要最终指定一个状态文件,test=True表示不直接执行,而先测试执行过程,确认执行过程正确后再取消此选项真正的执行
注:上面所讲的方法不仅可以用于salt命令行,同样试用于state状态文件之间的引用
Jinja介绍
我们前面的博文中已经讲过salt是完全基于Python开发的自动化运维配置管理工具,Jinja是基于Python的模板引擎,我们可以通过使用jinja模板在state状态配置文件里面实现条件判断,循环,变量引用等一些功能。比如我们要部署Nginx+keepalived负载均衡,那么我们就可以通过jinja的条件判断来实现区分master和slave,又或者我们需要指定Nginx配置文件,但配置文件里面的参数都不固定我们可以通过变量来解决。所以jinja在salt的应用非常的多,很广泛,如果使用得好的话,可以让你的项目可读性,执行效率更高,更加的高大上,更能体能salt自动化的功效,我们首先介绍下几种jinja的语法:
变量
条件判断
下面将以使用salt管理客户端DNS配置文件为例来演示变量和条件判断的使用
cd /srv/salt/test #进入我们的测试环境根目录 mkdir files #新建一个存放文件的目录 touch files/resolv.conf #创建DNS模板文件 touch nameserver.sls #创建状态配置文件
#resolv.conf文件内容如下 dns manager: #任务的ID file.managed: #状态管理模块file的managed方法,用来管理文件 - name: /etc/resolv.conf #每个模块方法都有一个 -name 属性,此属性可写在ID处,代表ID,如果这样的话这里就需要再写 -name属性 - source: salt://files/resolv.conf #源文件 - user: root #定义属主 - group: root #定义属组 - mode: 644 #定义权限 - template: jinja #标记此状态文件为jinja,否则将视为普通状态文件调用 {% if grains['fqdn'] == "kubernetes-node1" %} #第一个条件 DNS_SERVER: 192.168.1.10 #第一个条件为真执行的动作,定义变量 {% elif grains['fqdn'] == "kubernetes-node2" %} #第二个条件 DNS_SERVER: 192.168.1.11 #第二个条件为真执行的动作,定义变量 {% endif %} #条件结束,不管是多分支还是单分支都必须要有结束
#nameserver.sls文件内容如下 # Generated by NetworkManager nameserver {{ DNS_SERVER }} #引用变量
执行命令:
salt "*" state.sls nameserver saltenv=test
当执行完成命令后我们fqdn名称为kubernetes-node1的DNS将设置为192.168.1.10而kubernetes-node2的DNS将设置为192.168.1.11
扩展:在jinja里面的变量我们还可以引用pillar和salt命令执行的结果,方法如下
{{ salt['network.hw_addr']('eth0') }}
{{ pillar['apache']['PORT'] }}
循环
关于循环如果后续有时间将以实现反向代理(Nginx/HAProxy)动态添加后端服务器为例展示
最后:本博文内容不多,主要是以后面实战为主,欢迎大家收藏,关注我的博客,后续有时间会陆续补上一些实战的项目配置