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环境就搭建好了。

    Docker实践(19) – 保留容器的bash历史记录

    我们知道在容器内做试验完成时,容器可以设置自动清除,这就省了好多事。不过仍然有一些不方便的地方。其中一个是我们可能需要在容器中多次执行一个相同的命令,而bash历史又没有了,只能手打。

    问题

    你想与容器共享你的主机bash历史记录。

    解决方法

    为docker run命令设置一个别名来与主机共享bash历史记录。

    讨论

    要理解这个问题,我们来展示一个场景。
    假设你在Docker容器做试验,比如做一些有趣的和可重复使用的东西。这里我们使用echo命令,但这可能是一个长且复杂的一连串程序:

    1. $ docker run -ti –rm ubuntu /bin/bash
    2. $ echo my amazing command
    3. $ exit

    过了一些时间,你想重新执行之间执行过的复杂的echo命令。不过,你不记得命令了,而且终端会话也找不到这个命令,你尝试找bash历史记录,但没有任何输出:

    1. $ history | grep amazing

    为了解决这个问题,我们可以在你运行docker镜像时挂载一个volume,如下:

    1. $ docker run -e HIST_FILE=/root/.bash_history
    2.  -v=$HOME/.bash_history:/root/.bash_history
    3.  -ti ubuntu /bin/bash

    命令太长太难记了,我们把它设置为一个别名吧,在~/.bashrc文件中添加:

    1. $ alias dockbash=’docker run -e HIST_FILE=/root/.bash_history
    2.  -v=$HOME/.bash_history:/root/.bash_history

    这个体验仍然不好,因为当你要执行docker run命令时都要记住执行dockerbash命令。要获得更加无缝的体验,你您可以将这些添加到〜/ .bashrc文件:

    1. function basher() {
    2.   if [[ $1 = ‘run’ ]]
    3.   then
    4. shift
    5. /usr/bin/docker run
    6.   -e HIST_FILE=/root/.bash_history
    7.   -v $HOME/.bash_history:/root/.bash_history "$@"
    8.    else
    9.     /usr/bin/docker "$@"
    10. fi
    11. }alias docker=basher

    现在当你打开bash shel并执行任意的docker run命令时都会自动把bash历史记录的设置添加到命令中去。

    Docker实践(18) – 使用BitTorrent Sync分发volumes

    在团队中试用Docker时,你可能希望能够在团队成员之间共享大量数据,不过你可能没有足够的空间来搭建一台共享服务器。最简单的方法是当你需要时再从其它团队成员复制最新的文件 – 不过在一个更大的团队中这个方法就不太可行了。
    解决方案是使用BitTorrent Sync工具来共享文件 – 不需要专门的资源。

    问题

    你想通过internet在主机之间共享volumes。

    解决方法

    使用BitTorrent Sync镜像来共享volume。

    讨论

    下图说明了这个方法是如何运作的。
    虚拟化技术
    最终结果是通过因特网方便地同步的卷(/data),不需要任何复杂的设置。
    执行如下命令在第一台主机上设置容器:

    1. [host1]$ docker run -d -p 8888:8888 -p 55555:55555 –name btsync ctlc/btsync
    2. $ docker logs btsync
    3. Starting btsync with secret: ALSVEUABQQ5ILRS2OQJKAOKCU5SIIP6A3
    4. By using this application, you agree to our Privacy Policy and Terms.
    5. http://www.bittorrent.com/legal/privacy
    6. http://www.bittorrent.com/legal/terms-of-use
    7. total physical memory 536870912 max disk cache 2097152
    8. Using IP address 172.17.4.121
    1. [host1]$ docker run -i -t –volumes-from btsync ubuntu /bin/bash
    2. $ touch /data/shared_from_server_one
    3. $ ls /data
    4. shared_from_server_one

    在第二个服务器,打开一个终端运行这些命令来同步volume:

    1. [host2]$ docker run -d –name btsync-client -p 8888:8888 -p 55555:55555 ctlc/btsync ALSVEUABQQ5ILRS2OQJKAOKCU5SIIP6A3
    1. [host2]$ docker run -i -t –volumes-from btsync-client ubuntu bash
    2. $ ls /data
    3. shared_from_server_one
    4. $ touch /data/shared_from_server_two
    5. $ ls /data
    6. shared_from_server_one  shared_from_server_two

    回到第一台主机运行的容器,你应该能看到第二台主机的创建的文件了:

    1. [host1]$ ls /data
    2. shared_from_server_one  shared_from_server_two

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

    Docker实践(17) – 容器挂载主机目录

    容器最强大的功能是它在迁移时能保持系统环境一致性。
    不过有时候你不想把所有的文件放进容器中。你可能想在容器之间共享一些大的文件,或者单独管理这些文件。典型的例子是你希望容器访问大型集中式数据库,但是还希望其它客户端也能与容器一起访问。
    解决方法是volumes,在容器生命周期外管理文件的Docker机制。虽然这违背了容器“部署在任何地方”的理念(例如,你将无法在没有挂载数据库的系统中部署容器),不过有时候在实际环境中不得不用。

    问题

    你想在容器内部访问主机的文件。

    解决方法

    使用Docker的volume参数来设置容器访问主机文件。

    讨论

    下面的命令显示主机的/var/db/tables目录被挂载到容器的/var/data1上。

    1. $ docker run -v /var/db/tables:/var/data1 -it debian bash

    -v参数(–volume)表明需要为容器设置一个外部的volume。随后的参数值是由两个以冒号分隔的目录组成,冒号之前的目录是主机目录,之后是容器目录,如果这两个目录不存在则会自动创建。
    下图说明容器访问主机目录是如何交互的:
    虚拟化技术

    Docker实践(16) – 引用特定镜像构建镜像

    在你构建镜像大多数时候会引用镜像名称,如“node”或”ubuntu”,这个没有任何问题。
    如果你引用镜像名称,它有可能tag名称保持一样而镜像被更改了。看起来这自相矛盾,不过它真实发生了!repository名称仅仅是个引用,它有可能被更改指向一个不同的镜像。指定一个带冒号的tag名称也不会消除这种风险,因为安全更新会使用相同的tag来自动重新构建有漏洞的镜像。
    大多数时候你会想让它这样做 – 镜像维护者对镜像有所改进,并修补了安全漏洞是一件好事。不过有时候可能会给你带来痛苦。这不仅仅是一个理论上的风险:这已经出现过很多次了,中断了持续交付且很难调试。在Docker早期,镜像会添加和删除软件包(包括,记忆中消失了的passwd命令),使构建镜像突然地中断。

    问题

    你想确保镜像的构建始终从一个指定的不会被更改的镜像。

    解决方法

    从一个指定的镜像ID构建。

    讨论

    对于你想决定确认从一个指定的镜像构建镜像时,可以在Dockerfile中指定镜像ID.
    下面是示例:

    1. FROM 8eaa4ff06b53
    2. RUN echo "Built from image id:" > /etc/buildinfo
    3. RUN echo "8eaa4ff06b53" >> /etc/buildinfo
    4. RUN echo "an ubuntu 14.4.01 image" >> /etc/buildinfo
    5. CMD ["echo","/etc/buildinfo"]

    像这样从一个指定的镜像ID构建镜像,这个镜像必须已经保存在了本地。Docker registry不会在Docker Hub搜索这个镜像ID的。
    注意你引用的镜像不需要tag。你可以从任意层来构建镜像。

    理解SaltStack(5) – 状态系统

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

    状态系统流程

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

    理解SaltStack(4) – 远程执行

    本文介绍salt远程执行系统是如何工作的。
    salt一开始就是设计成为一个远程执行工具的,salt中其它子系统对远程执行使用非常频繁。

  • salt命令设计能跨系统和跨平台工作。根据目标平台情况salt ‘*’ pkg.install git命令使用yum,apt,pacman或salt的windows包仓库安装git软件。一个命令支持多个系统。
  • salt命令以一致的数据结构返回结果。这样使得测试结果和存储结果到数据库变得容易。
  • 由于接收命令是异步的,所有的目标系统能同时执行一个任务。
  • salt使用数百个python模块库完成远程管理,并且你可以添加自己的模块(或最好贡献你的模块到项目!)。任何能通过Python,shell命令或者任何其它接口访问的程序或服务都可以封装一个salt执行模块来执行任务。
  • 远程执行系统通过salt命令行来访问。让我们来尝试执行一个简单的命令,然后通过salt系统来跟踪它:

    1. salt ‘*’ test.rand_sleep 120

    基于我们对salt通信系统的了解,下面是这个命令的一些底层行为:

  • 1.此命令通过publisher端口发送到所有已连接的minions。
  • 2.所有minon检查此命令,评估自身与命令带的target字段是否匹配以此来决定是否应该执行这个命令。
  • 3.目标系统执行命令并返回结果给request server。
  • 我们来深入了解,当在minon执行命令时发生了什么。首先每个命令分到一个单独的工作线程,所以salt minion能同时执行多个任务。
    那么在minion谁来执行test.rand_sleep 120命令?当然是salt执行模块!
    所有用来管理系统的命令都由salt执行模块来提供。这些模块就是在salt中做实际的工作的,并且你只要用一次后就大概知道它们如何工作了。
    当salt minion收到一个命令,找到正确的模块(在这个示例中是test模块),然后调用相关的函数(rand_sleep)及其参数(120)。
    运维自动化