SaltStack配置管理(2) – PILLAR

salt pillar是salt state实现可重用的重要组件,所以我们来快速创建一个salt state来看pillar如何使用的。

salt pillar top文件

salt pillar使用Top文件来匹配应用到salt minions的salt pillar数据。这个Top文件与用来匹配应用到salt minions的salt state的Top文件类似。
跟salt state函数一样,我们通过示例来学习salt pillar。创建salt-vagrant-demo-master/saltstack/pillar目录,然后在此目录下创建top.sls文件,添加如下内容:

  1. base:
  2.   ‘*’:
  3.     – default

下一步创建default.sls文件,添加如下行:

  1. editor: vim

当salt pillar数据刷新后,每个Salt minion与top.sls文件中列出的目标匹配。当salt minion匹配后,它接收在该目标下面的列表中定义的所有Salt pillar SLS文件。
因为*通配符匹配所有salt minions,每一个salt minion接收到一个键为editor,值为vim的pillar数据。

刷新salt pillar

我们打算用我们刚才配置的salt pillar,所以我们需要在所有minions刷新salt pillar数据:

  1. salt ‘*’ saltutil.refresh_pillar

salt state中使用salt pillar

salt pillar数据可以使用在salt state中,所以我们可以更新上一篇文章中的salt state示例来使用salt pillar字典:

  1. vim installed:
  2.   pkg.installed:
  3.     – name: {{ pillar[‘editor’] }}

salt pillar数据是安全的,你可以用它设置密码。例如,你可以添加如下密码的salt pillar:

  1. ftpusername: me
  2. ftppassword: oxfm4@8t5gglu^h^&

然后在salt state中引用:

  1. sync directory using lftp:
  2.   cmd.run:
  3.     – name: lftp -c "open -u {{ pillar[‘ftpusername’] }},{{ pillar[‘ftppassword’] }}
  4.            -p 22 sftp://example.com;mirror -c -R /local /remote"

命令行下设置salt pillar

为了测试或临时使用,你可以在命令行下设置salt pillar的值。这些值会覆盖salt pillar文件中设置的值。

  1. salt ‘*’ state.apply ftpsync pillar='{"ftpusername": "test", "ftppassword": "0ydyfww3giq8"}’

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

    Docker实践(22) – 通过NFS共享数据

    在部分公司已经在使用NFS共享文件了。如果应用部署在docker容器里,如果能访问这些共享的文件呢?
    docker不支持NFS开箱即用,而在每个容器中安装NFS客户端以便能挂载远程目录不是一个好方法。建议的方法是使用一个docker容器充当其它容器访问NFS共享数据的代理。

    问题

    你想无缝访问NFS的远程文件系统

    解决方法

    使用数据容器代理访问

    讨论

    数据容器的相对介绍请参考http://devops.webres.wang/2016/11/docker-data-container/。下图显示这种方法如何工作。
    虚拟化技术
    NFS服务器暴露内部目录为/export,此目录与/opt/test/db绑定挂载。然后docker主机使用NFS协议挂载到目录/mnt。然后数据容器挂载主机的/mnt来代理其它容器对共享目录的访问。
    虽然NFS的介绍超过了本文的范畴,但NFS与本文的主题密切相关,还是有必要说明下。
    假设你想共享系统为Ubuntu14.04的/opt/test/db目录给其它主机的容器。
    切换为root权限,安装NFS服务器并创建一个export目录:

    1. # apt-get install nfs-kernel-server
    2. # mkdir /export
    3. # chmod 777 /export

    现在绑定挂载db目录到/export目录:

    1. # mount –bind /opt/test/db /export

    你现在应该能在/export目录访问/opt/test/db的内容。

    如果你想让重启后绑定还生效,添加/opt/test/db /export none bind 0 0到/etc/fstab文件。

    现在添加如下行到/etc/exports文件:

    1. /export 127.0.0.1(ro,fsid=0,insecure,no_subtree_check,async)

    因为我们只用了一台机器做试验,即nfs服务器与容器都在一台,所以这里埴写了127.0.0.1,如果是在其它机器,记得把127.0.0.1替换为nfs客户端IP。
    考虑到安全,我们在这里只读挂载,不过你也可以把ro替换为rw设置读写挂载,如果这样做,记得在async选项后添加no_root_squash。
    然后通过NFS挂载/export目录到/mnt目录:

    1. # mount -t nfs 127.0.0.1:/export /mnt
    2. # exportfs -a
    3. # service nfs-kernel-server restart

    现在运行一个数据容器:

    1. # docker run -ti –name nfs_client –privileged -v /mnt:/mnt busybox /bin/true

    然后其它容器关联此数据容器的volumes:

    1. # docker run -ti –volumes-from nfs_client debian /bin/bash
    2. root@079d70f79d84:/# ls /mnt
    3. myb
    4. root@079d70f79d84:/# cd /mnt
    5. root@079d70f79d84:/mnt# touch asd
    6. touch: cannot touch `asd’: Read-only file system

    Docker实践(21) – 使用sshfs挂载远程volume

    我们已经讨论过如何挂载本地文件,不过很快我们就会遇到如何挂载远程文件系统的问题了。例如可能你想共享远程服务器上的数据库并把它当作本地数据库使用。
    虽然理论上可以设置一个NFS服务器并通过在你服务器挂载目录访问远程文件,不过有一种对于大多数用户快速简单的方法,此方法不需要在服务器端安装任何软件(只需要SSH)。

    设置sshfs需要root权限,并且需要安装FUSE(Linux的“用户空间文件系统”内核模块)。你可以通过执行ls /dev/fuse来判断系统是否已经安装有。

    问题

    你想找到一个不需要配置服务器端的方法来挂载远程的文件系统。

    解决方法

    使用sshfs来挂载远程文件系统

    讨论

    sshfs通过使用FUSE内核模块提供的文件系统标准接口和SSH访问远程文件系统,所有的通信使用SSH进行。SSHFS还提供了各种幕后功能(例如远程文件预读),以让我们觉得是在操作本地文件。下图说明它是如何工作的。
    虚拟化技术
    我们现在来做下试验。首先在你主机运行一个带–privileged参数的容器:

    1. $ docker run -t -i –privileged debian /bin/bash

    然后当它启动后,在容器内部运行apt-get update && apt-get install sshfs安装SSHFS。
    当SSHFS安装完成后,按如何登录远程主机:

    1. $ LOCALPATH=/path/to/local/directory
    2. $ mkdir $LOCALPATH
    3. $ sshfs user@host:/path/to/remote/directory $LOCALPATH

    现在你应该能通过本地的$LOCALPATH目录看到远程主机的目录内容了。
    不需要时可以通过fusermount命令来取消挂载:

    1. fusermount -u /path/to/local/directory

    Docker实践(20) – 数据容器

    如果你在主机上使用很多volumes,管理容器的启动可能会变得棘手。你可能希望数据只由容器管理,不管在主机上能直接访问数据。一种简单的方法是使用data-only容器。

    问题

    你想在容器内部访问外部volume,不过你希望这些volume只能由docker访问。

    解决方法

    设置一个数据容器并在其它容器运行时使用–volumes-from参数连接此数据容器。

    讨论

    下图展示了数据容器模式的结构,并解释了它的工作原理。
    虚拟化技术
    最主要是注意第二个主机,容器不需要知道数据在硬盘的哪个位置。它们所要知道的是数据容器的名称。这使得容器的操作更便捷。
    这种方法比直接映射主机目录的另一个好处是,只能由docker访问这些文件,其它进程无法访问。

    数据容器不需要运行! 一个常见的困惑是是否需要运行数据容器。不需要!仅仅需要数据容器在主机运行过并不被删除,之后就不需要运行了,但要保存它一直存在。

    我们看一个示例看看数据容器怎么使用。
    首先运行一个数据容器:

    1. $ docker run -v /shared-data –name dc busybox touch /shared-data/somefile

    -v参数不映射主机上的目录,它只在容器责任范围内创建一个目录。此目录使用touch创建了一个文件,这样数据容器马上生效了 – 数据容器不需要运行使用。我们使用busybox镜像来减小容器大小。
    然后运行另一个容器来连接数据容器:

    1. docker run -t -i –volumes-from dc busybox /bin/sh
    2. / # ls /shared-data
    3. somefile

    –volumes-from参数允许你关联数据容器的volume到当前容器的目录 – 你只需要指定数据容器的ID。

    volumes永久存在!当最后一个容器取消关联数据容器时,数据容器的数据不会被删除。 这是为了防止不必要的数据丢失。

    使用数据容器可能比直接挂载目录管理起来要难,因为数据只能由docker访问,而不能像直接挂载的能在主机上直接访问。不过你如果希望把volumes给一个容器来管理,希望以后变动时不那么麻烦,那么数据容器可能适合你。

    如果你的多个容器的应用程序正在往数据容器里写日志,那么确保它们在数据容器里日志的路径不一样很重要。因为如果日志路径一样的话,那么不同的容器可能会覆盖或截断文件,导致数据丢失。

    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

    运维自动化