SaltStack配置管理(1) – 函数

salt state函数

salt state函数就是指在salt state中所做的实际工作,是saltstack配置管理最重要的东西。
函数用来安装和配置应用,创建用户,分发文件和关于你配置你系统的所有其它事情。
在我们调用函数之前,我们来看一下salt state函数的语法。

语法

salt state使用YAML来描述系统状态,YAML是描述结构化数据(类似JSON,但更人性化)的简单语言。
下面的图表显示salt state的声明格式:
运维自动化
salt state第一行声明是是一个ID。
ID下面是你调用一个或多个salt state函数的地方。

  • ID和函数的行以冒号结尾。每个函数调用在ID的下行缩进两个空格。参数以列表形式传递给函数。函数的下面每行一个参数,先缩进两个空格,然后一个连字符,再一个空格,之后就是参数名称和值了。
  • 如果参数只有一个值,那么参数名称和值在同一行,以冒号和一个空格分隔。如果参数值是一个列表,那么列表在下一行开始,缩进两个空格。
  • 函数示例

    最好学习salt state函数的方法是学习一个示例。我们再次使用之前搭建的demo环境来学习这个示例http://devops.webres.wang/2016/11/saltstack-demo-environment/。
    打开终端,切换到salt-vagrant-demo-master目录,执行vagrant up命令。
    当环境启动后,创建一个名称为salt-vagrant-demo-master/saltstack/salt/examples.sls的文件,以便你能运行这么示例。

    安装软件包

    把下面的代码复制到刚才创建的examples.sls文件:

    1. install vim:
    2.   pkg.installed:
    3.     – name: vim

    ssh到salt master服务器:

    1. vagrant ssh master

    用如下命令应用examples.sls state:

    1. sudo salt ‘minion1’ state.apply examples

    运维自动化

    创建目录

    下面是创建目录的示例。

    1. create my_new_directory:
    2.  file.directory:
    3.    – name: /opt/my_new_directory
    4.    – user: root
    5.    – group: root
    6.    – mode: 755

    运行服务

    下面的state用来确保一个服务正在运行在salt minion:

    1. Make sure the mysql service is running:
    2.   service.running:
    3.     – name: mysql

    每一个state声明以一个state ID来区分。state ID必须是唯一的,它们能包含空格和数字。
    你可以在一个state ID下添加多个salt state函数:

    1. Install mysql and make sure the mysql service is running:
    2.   pkg.installed:
    3.     – name: mysql
    4.   service.running:
    5.     – name: mysql

    开始启动服务

    当你调用一个函数时,确保你把函数的参数全部看一遍,因为通常你仅需传递额外的参数就可以完成许多事件。通过传递enable: True到service.running函数,saltstack就会确保服务开机启动。

    1. Make sure the mysql service is running and enable it to start at boot:
    2.   service.running:
    3.     – name: mysql
    4.     – enable: True

    下载GIT仓库

    每个函数都有一个name参数。如果你没有设置,那么salt就使用state的ID。在这个示例中,name参数为https://github.com/saltstack/salt.git:

    1. https://github.com/saltstack/salt-bootstrap:
    2.   git.latest:
    3.     – rev: develop
    4.     – target: /tmp/salt

    使用ID作为name参数值的确省了敲打一些字符,不过还是推荐都设置一个name,如下:

    1. Clone the SaltStack bootstrap script repo:
    2.   pkg.installed:
    3.     – name: git # make sure git is installed first!
    4.   git.latest:
    5.     – name: https://github.com/saltstack/salt-bootstrap
    6.     – rev: develop
    7.     – target: /tmp/salt

    这样能让你的state更明了,更容易维护。

    添加用户

    1. user account for pete:
    2.   user.present:
    3.     – name: pete
    4.     – shell: /bin/bash
    5.     – home: /home/pete
    6.     – groups:
    7.       – sudo

    参数groups的值是一个列表,所以放到下一行,缩进两个空格再加一个短破折号。

    添加条目到hosts文件

    1. myserver in hosts file:
    2.   host.present:
    3.     – name: myserver
    4.     – ip: 192.168.0.42

    平台规范化的一个很好的例子。即使每个平台配置的hosts方式有所不同,salt state仍然能正确地在各个系统配置hosts(不需要关心salt实现的细节)。

    调用执行函数

    service.restart和其它执行函数可以在salt state调用。

    1. restart vsftpd:
    2.   module.run:
    3.     – name: service.restart
    4.     – m_name: vsftpd  # m_name gets passed to the execution module as "name"

    salt执行和salt state函数的区别

    你可能好奇为什么不使用service state函数而使用service执行函数,为什么salt state和salt执行函数看起来类似有很多重叠的地方。
    如果你比较salt执行函数与salt state函数的名称,如service.restart和service.running,你可能会注意到重要的区别。salt state函数设计用来只在必要的时候应用配置,没有必要时不做任何更改。salt执行函数在每次调用时都执行。
    当你调用service.running state函数时,函数首先先查看服务是否已经运行,如果没有就启动,否则不做任何事情。当你调用service.restart执行函数时,始终会重启服务。

    test=True

    在目标系统应用一个salt state会发生许多更改。salt state函数提供了一个机制来测试显示在运行期间将会做怎样的变更。

    1. sudo salt ‘minion1’ state.apply examples test=True

    SaltStack基础(6) – 使用highstate应用多个state文件

    有没有注意到上一篇文章我们创建的salt state没有包含哪个minion应该接收我们发送过去的配置?salt state设计为通用的,只描述了一个配置如何实现配置。在这篇文章中我们学习一个称为Top的文件,来描述哪些minions应该应用配置。
    states和Top文件一起组成了saltstack配置管理的核心功能。

    Top文件介绍

    在highstate期间Top文件用来应用多个state文件到salt minions。state被应用哪台minion是由Top文件中的target字段决定。

    什么是highstate?
    highstate使所有的目录minions下载/srv/salt/top.sls文件并尝试找到与target匹配的state。如果找到匹配的target,minion就应用这个target下面列出的所有state。许多用户定时地运行highstate,以确保系统保持正确状态。

    创建Top文件

    在创建Top文件之前,花点时间考虑一下你的系统的配置应该是怎样的。考虑你设置的系统的不同的类型,哪一个是共同的,哪一个是与其它不一样的。例如你简单的Top文件如下:
    运维自动化
    在saltstack的范例中,Top文件的列表的每一项是一个state,Top文件中的targets用来定义哪个minion应该应用配置。
    下面的例子展示Top文件是如何翻译成YAML文件的。
    运维自动化
    一旦Top文件被minion解析后,它们就执行与target匹配的所有state。例如一个系统的salt minion ID为atl-web4-prod会应用vim,script,user,apache,python和django states。
    现在我们理解了Top文件的目的,我们继续创建一个。如果你用的是Vagrant demo文件你会注意到在saltstack/salt目录已经有一个top.sls文件,所以我们只需要更改它。否则你需要创建一个新文件。添加如下内容到你的top.sls文件:

    1. base:
    2.   ‘*’:
    3.     – common
    4.   ‘minion1’:
    5.     – nettools

    在salt master命令行下执行如下命令来应用top.sls文件:

    1. salt ‘*’ state.apply
    2. #calling state.apply with no arguments starts a highstate.

    如你所想,minion1和minion2两个都会应用common state,且minion1也应用nettools state。

    SaltStack基础(5) – 创建salt state

    远程执行给我们省了很多时间,但它有一些不足。你执行的大多数任务是由许多命令,测试和操作组成,每个都有自己细微差别和故障点。通常是尝试把这些命令放到一个shell脚本中,但这很快会变得难管理。
    为了解决这个问题,saltstack配置管理让你创建一个称为state的可复用的配置模板,描述把系统组件或应用放进一个已知配置所需的一切。
    当你看到state内容,你会觉得这很容易理解。state使用很容易创建和阅读的YAML描述。
    为了简化操作,我们的Vagrant文件映射salt master的/srv/salt目录到本地的salt-vagrant-demo-master/saltstack/salt目录。意味着你只需要修改本地的salt文件,它就会同步到salt master。
    使用文本编辑器创建一个文件并添加如下行:

    1. install_network_packages:
    2.   pkg.installed:
    3.     – pkgs:
    4.       – rsync
    5.       – lftp
    6.       – curl

    state调用pkg.installed state函数,传入pkgs参数的三个软件包名称。
    把这个文件保存到salt-vagrant-demo-master/saltstack/salt/nettools.sls
    让我们测试继续state。下一篇文章我们将会学习应用state更强大的方法,称为highstate,但现在我们可以使用state.apply来直接从命令行应用state。
    在salt master的命令行下应用nettools state:

    1. salt ‘minion2’ state.apply nettools
    2. #state.apply was added in 2015.5, so if you are using an earlier version call state.sls instead.

    如果一切正常,将输出类似的结果。
    运维自动化
    如果再次执行同一个命令,将输出:
    运维自动化
    Salt确定系统已经处于正确的状态,所以没有什么改变。

    SaltStack基础(4) – 指定目标minions

    指定目标服务器最简单的是使用minion ID。这个ID值是在minion的配置文件中设置,可以在bootstrap脚本中使用-i选项指定。

    1. salt ‘minion1’ disk.usage

    通配符

    通配符可以用在minion的ID上:

    1. salt ‘minion*’ disk.usage

    指定目标的多种方法

    在理想的环境中,你环境中的每个系统都有一个结构化的名称,告诉你需要了解的有关硬件,操作系统和系统角色的所有信息。在我们等待那个世界的同时,SaltStack提供了一个强大的定位系统,可以帮助你根据静态和自定义数据查找和过滤系统。
    目标可以基于使用Grains系统得到的salt minion系统信息:

    1. salt -G ‘os:Ubuntu’ test.ping

    目标可以使用正则表达式过滤:

    1. salt -E ‘minion[0-9]’ test.ping

    目标可以是一个指定的列表:

    1. salt -L ‘minion1,minion2’ test.ping

    或者是多种目标类型连在一起:

    1. salt -C ‘G@os:Ubuntu and minion* or [email protected].*’ test.ping

    SaltStack基础(3) – 执行命令

    安装saltstack后,已经可以执行shell命令,更新软件包和同时分发文件到所有minions。minions执行命令后会以一致地和可配置的格式返回结果,这样你就可以很容易地查看执行了什么和工作正不正常。

    执行shell命令

    你可以使用cmd.run在salt master上向所有的minion发送一个shell命令来执行:

    1. salt ‘*’ cmd.run ‘ls -l /etc’

    所有的minion将同时执行这个命令并立即返回结果给salt master。
    运维自动化

    salt执行函数

    使用cmd.run执行shell命令当然是有用的,不过saltstack强大的功能是使用salt执行函数。salt社区已经投入很多努力创建数百个函数来简单大部分的管理任务。甚至同一个函数能在所有支持的系统上使用。

    显示硬盘使用

    1. salt ‘*’ disk.usage

    运维自动化

    安装一个包

    1. salt ‘*’ pkg.install cowsay

    运维自动化

    列出网络接口

    1. salt ‘*’ network.interfaces

    运维自动化

    SaltStack基础(2) – 安装saltstack

    你可以从包管理器,pip,源码编译或使用bootstrap脚本安装saltstack。saltstack也提供独立的工具来创建机器和在公有和私有云安装saltstack(salt-cloud和salt-virt)。我们这里没有涉及到这些工具,不过只要你有一个系统需要管理,慢慢就会了解这些,saltstack在物理的,云和虚拟资源中使用都相同。

    安装

    如果你使用的是上一篇文章介绍的Vagrant工程,那么saltstack已经安装了并且已经接受每一个minion的连接。你可以根据下面段落中“接受连接”的方法来验证你的minions是否已经连接。
    如果你使用的是不同的环境,安装saltstack最简单的方法是使用bootstrap脚本。执行这个脚本的两个命令就可以在大多数操作系统上安装saltstack。

    接受连接

    salt master和salt minion之间的每一个连接都使用加密密钥进行管理和保护。安装完成后,每一个salt minion发送它的公钥到salt master,等待连接被接受。salt minion密钥必须先被接受才能在系统上执行来自salt master的命令。
    在命令行提示符,cd进入vagrant-demo-master目录,执行如下命令进入salt master:

    1. vagrant ssh master

    连接后,执行如下命令来切换到root用户:

    1. sudo su

    运维自动化

    查看所有密钥

    在salt master,你可以快速查看所有的salt minion连接和查看连接是否被接受,拒绝或待定。

    1. salt-key –list-all

    接受指定密钥

    你必须接受minion的密钥,它才能连接。

    1. salt-key –accept=<key>

    接受所有密钥

    1. salt-key –accept-all

    运维自动化

    发送命令

    你接受每一个密钥后,从salt master发送一个命令来验证salt minions是否在监听。

    1. salt ‘*’ test.ping

    运维自动化

    SaltStack基础(1) – demo环境搭建

    salt基础系统将涉及如下几个方面:

  • 安装saltstack
  • 在受管系统运行命令
  • 定义可重复使用的配置
  • 将命令和配置应用于特定系统
  • 学习SaltStack最好的方法是做各种试验。你可以通过阅读本系列文章对saltstack有一个初步了解,saltstack非常容易配置,这里我们提供几个示例来帮助你学习。另外你可以保留你的demo环境继续做其它试验。

    demo环境

    完成如下步骤来配置一个简单的saltstack环境。

  • 1.安装VirtualBox
  • 2.安装Vagrant
  • 3.下载https://github.com/UtahDave/salt-vagrant-demo。你可以使用git或直接从GitHub下载zip包
  • 4.解压下载的zip文件,然后把目录切换到解压出来的目录
  • windows:

    1. cd %homepath%Downloadssalt-vagrant-demo-master

    Mac:

    1. cd ~Downloadssalt-vagrant-demo-master
  • 5.运行vagrant up来启动demo环境
    1. vagrant up

    大约等待10分钟后,demo环境就搭建好了。

    理解SaltStack(8) – Python

    我知道我们之前有说过使用Salt不需要会写Python和其它代码,这当然是真的。不过会读Python代码在许多情况下会有所帮助,或者至少会读Python函数文档。
    本文介绍Python基础知识,帮助你更好地了解salt的工作原理。

    模块

    Salt中,每个子系统插件是一个Python模块。你可以认为salt模块是一组函数(又称命令)组成,用来管理应用(mysql.docker),系统组件(硬盘,文件)或与外部系统(gitfs)交互。
    你需要了解几点:

  • 所有的模块都在源文件夹的salt目录。每个子系统是一个单独的目录,每个模块是一个单独的python文件
  • 模块以salt.subsystem.module格式命名。此命令空间在文档中可找到,所以你可以快速识别目前在看哪个子系统模块。唯一一个令人困惑的是:执行模块以salt.module开头,是由于这个模块是初始版本中的第一个模块并且只有这个模块可用。
  • 模块包含了我们需要的多个或少量的函数。由于文件管理需要做的事情非常多,所以文件执行模块(salt.modules.file)包含了非常多的函数。而uwsgi统计服务器执行模块(salt.modules.uwsgi)只有一个函数。
  • 函数

    所以你理解了以上的模块,函数应该就更简单了。你可以认为函数是在模块中指定的命令,能调用来管理和配置文件。例如,salt.modules.pkg.install, salt.modules.network.interfaces和salt.modules.user.add都是常见的执行模块函数。函数相当于salt的动词,你通常可以打开模块文档并查看函数名称来决定使用哪个函数。

    参数

    参数有一点复杂,特别是如果是对关键词参数不是很熟悉,参数很可能是你准备入门salt遇到问题的地方。
    远程执行和状态之间的参数不太一样,我们来分别讨论。

    执行函数参数

    当在命令行调用salt时,执行参数作为附加值传递过去,或者作为一个值,或者作为argument = value。必需值通常以空格分隔并以指定顺序传递,带默认值的可选参数以argument=value格式传递。
    例如,我们来看下salt.modules.useradd.add函数:

    1. salt.modules.useradd.add(name, uid=None, gid=None, groups=None, home=None,
    2. shell=None, unique=True, system=False, fullname=”, roomnumber=”,
    3. workphone=”, homephone=”, createhome=True, loginclass=None)

    当调用这个模块,参数name是必需的,你可以看到它没有默认值。其余的参数会使用列出的值,除非你传一个不同的值来覆盖。下面的例子是创建一个用户名为Fred并设置一个不同的默认shell:

    1. salt ‘*’ user.add fred shell=/bin/zsh

    更多的例子
    常规参数和关键字参数(通常缩写为args和kwargs)是你将遇到的最常见的类型。下面的例子传递一个arg和3个kwargs:

    1. salt ‘*’ network.connect google-public-dns-a.google.com port=53 proto=udp timeout=3

    传递两个args和一个kwarg:

    1. salt ‘*’ cp.get_file salt://vimrc /etc/vimrc gzip=5

    一些执行模块接收列表值:

    1. `salt ns1 pkg.install pkgs=[‘bind9′,’bind9-docs’,’bind-utils’]`

    一些甚至可以传字典类型:

    1. `salt ‘*’ pkg.install sources='[{"foo": "salt://foo.deb"},{"bar": "salt://bar.deb"}]’`

    state函数参数

    State函数在state文件中使用YAML语法调用。YAML语法非常适合表示数据类型,所以你会发现调用具有复杂数据类型的函数在state中更容易。为了弄清楚在state中如何添加用户,我们来看下salt.states.user.present函数:

    1. salt.states.user.present(name, uid=None, gid=None, gid_from_name=False,
    2. groups=None, optional_groups=None, remove_groups=True, home=None,
    3. createhome=True, password=None, hash_password=False, enforce_password=True,
    4. empty_password=False, shell=None, unique=True, system=False, fullname=None,
    5. roomnumber=None, workphone=None, homephone=None, loginclass=None, date=None,
    6. mindays=None, maxdays=None, inactdays=None, warndays=None, expire=None,
    7. win_homedrive=None, win_profile=None, win_logonscript=None,
    8. win_description=None)

    即使这个函数有许多参数,在YAML中调用带关键词参数的函数很容易:

    1. a state example that calls user.present:
    2. user.present:
    3.     – name: fred
    4.     – shell: /bin/zsh

    list类型在YAML中也很容易定义:

    1. install bind packages:
    2.   pkg.installed:
    3.     – pkgs:
    4.       – bind9
    5.       – bind9-docs
    6.       – bind-utils

    定义字典也比在命令行中容易:

    1. Install some packages using other sources:
    2.   pkg.installed:
    3.     – name: mypkgs
    4.     – sources:
    5.       – foo: salt://foo.deb
    6.       – bar: http://somesite.org/bar.deb

    理解SaltStack(7) – 系统数据

    本文讨论系统数据的两个主要方面:获取你系统的有关数据和为你的系统设置数据。salt为这两个任务分别提供了两个不同的子系统来完成:salt grains和salt pillar。
    本文还介绍了第三个组件,称为salt mine,用来从minion推送数据到master的共享数据存储上以便所有的minions能访问这些数据。

    GRAINS

    Grains用来获取你系统的数据。Grains是关于底层操作系统静态信息,如内存,硬盘和许多其它系统属性。
    当minion启动时,Grains自动收集信息,然后定期刷新或者使用远程执行命令。
    所以你用grains能做什么?你可以使用grain执行模块收集清单,可以列出所有grains,找到具有特定grain值的系统等。
    Grains也是minion系统的组成部分,也用来定位salt state和salt pillar数据。

    GRAINS如何收集数据?
    在之前的章节中你已经对插件有所了解,已经知道grains如何工作了。grains子系统有几个salt grains模块(又名插件)运行在minion来填充grains目录。grains与远程执行模块类似,每一个grain模块包含在各种OS的收集grain数据的逻辑(不是使用多个模块和__virtualname__)

    SALT PILLAR

    salt pillar用来传送数据到你的系统。想象一个当配置甚至是一个简单的系统时不同的自定义数据:用户名称,服务URL,首选安装路径,端口,非默认应用程序设置和许多其它的设置。通常这些值在每个系统或系统角色(web,数据库等)都不一样。
    salt pillar让你定义这些数据值,然后使用targets将它们分配给一个或多个minions。然后这些值可以作为变量在salt sates中使用。
    salt pilllar使用目标minions的公钥来加密数据和通过安全通道来发送,因此salt pillar也非常适合分发安全数据,如密码和ssh密钥,因为它只能由目标minon来解密。
    默认下salt pillar模块使用YAML文件来定义pillar,超过30个salt pillar模块用来支持各种后端。热门选项包括Mongo和Redis,都是非常适合存储结构数据的。许多用户坚持使用YAML文件,但使用一个私有git repo来管理和分发pillar数据。

    SALT MINE

    salt mine用来在salt minions之间共享数据值。例如如果你设置一个共享的数据库,你可以在数据库服务器上配置salt minion来自动推送它的IP到salt mine。这个方法比手动更新salt state或salt pillar的数据要好。
    当你需要这些值来配置系统时,你可以直接通过salt state文件来访问salt mine的数据。
    salt mine使用简单,最大的问题是许多用户不记得使用它。

    理解SaltStack(6) – salt runners

    runner子系统提供在salt master运行的salt模块(还记得执行和状态模块在目标服务器minion异步执行吗,不是在salt master)。
    Runners可用功能为列出作业状态,实时查看事件,管理salt文件服务器,查看salt mine数据,发送wake-on-lan到minions,调用webhooks和发送其它http请求等。

  • Runners由salt-run命令行接口调用。不需要指定目标因为目标是salt master。
  • salt runners的参数语法与salt执行模块的参数语法一样。
  • ORCHESTRATE RUNNER

    The orchestrate runner提供了salt的核心功能之一:以指定顺序在多个minions之间运行命令和应用配置的能力。例如,使用orchestrate runner你可以使用状态系统的全部功能来配置多个系统(包括必需条件,失败分支,依赖性,有序执行等)。