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 S@192.168.50.*’ 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你可以使用状态系统的全部功能来配置多个系统(包括必需条件,失败分支,依赖性,有序执行等)。

    理解SaltStack(5) – 状态系统

    本文介绍salt的状态系统是如何工作的。
    salt状态系统是在远程执行模块之后开发的,如你所想,salt状态系统是建立在远程执行模块之上的。salt状态模块除了一个重要的区别,其它的与远程执行非常类似。区别就是状态模块包含用于查看系统是否已处于正确状态的逻辑。事实上,逻辑确认后,状态模块仅仅是调用远程执行模块来执行任务的。

    状态系统流程

    状态系统与远程执行状态之间最主要的区别是状态系统内的流程控制。Salt提供了特殊的指令,可以定义依赖关系,重用代码,失败分支,控制流以及变量和模板。