之前写过一片博文介绍了saltstack的安装配置,由于最近忙着办理离职,就没有更新了,对不起自己,说好的要坚持下去的。这篇博文准备记录一下saltstack作为文件服务器,从master向minions分发文件的功能。我们知道,类似于hadoop、hbase、zookeeper这些与分布式系统相关的组件在安装配置的时候,往往是一个节点上修改好配置文件后,然后用scp远程拷贝到其他节点上去,如果你有10个节点的话,那么同一条远程拷贝的命令需要执行多次,显然不是一个好办法。那么问题来了,自动化运维之远程分发文件到底哪家强?哈哈,自然是神器saltstack啦!我们需要借助saltstack来实现从master端向minions推送文件的需求。

    Saltstack内置了一个简单的文件服务器用于master分发文件给minions,这个文件服务器是基于zeroMQ消息队列实现的,客户端对文件服务器的操作全部封装在了cp这个模块中。

    首先看环境:

        hadoop0.updb.com    192.168.0.100    OS:CentOS 6.5        Role:master

        uadoop2.updb.com    192.168.0.202    OS:CentOS 6.5        Role:minion

        uadoop3.updb.com    192.168.0.203    OS:CentOS 6.5        Role:minion

    在开始saltstack的配置管理之前,要首先指定saltstack所有状态文件的根目录,在master上做如下操作

## 首先修改master的配置文件,指定根目录,注意缩进全部使用两个空格来代替Tab(python规范)
[root@hadoop0 ~]# vi /etc/salt/master 
file_roots:
  base:
    - /srv/salt
  dev:
    - /srv/salt/dev     
## 确定指定的目录是否存在,如果不存在,需要手动来创建目录
[root@hadoop0 ~]# ls /srv/salt/ -ld
drwxr-xr-x 2 root root 4096 Nov  6 23:54 /srv/salt/
[root@hadoop0 ~]# ls /srv/salt/dev/ -ld
drwxr-xr-x 2 root root 4096 Nov  7 00:36 /srv/salt/dev/
## 重启master服务
[root@hadoop0 ~]# /etc/init.d/salt-master  restart 
Stopping salt-master daemon:                               [  OK  ]
Starting salt-master daemon:                               [  OK  ]

    首先介绍cp.get_file,用来从master端下载文件到minion的指定目录下,如下

## 在master上创建测试用的文件
[root@hadoop0 ~]# echo 'this is test file with module of cp.get_file!' > /opt/getfile.txt
## 拷贝测试文件到master配置的根目录下
[root@hadoop0 ~]# cp /opt/getfile.txt /srv/salt/
## 在master执行文件的分发
[root@hadoop0 ~]# salt 'uadoop2' cp.get_file salt://getfile.txt /opt/getfile.txt 
uadoop2:
    /opt/getfile.txt
## 分发成功,在minion上查看文件是否已经发送到uadoop2上了
[root@uadoop2 ~]# cat  /opt/getfile.txt 
this is test file with module of cp.get_file!

    使用cp.get_file进行文件的分发时时也可以指定是否对分发的文件进行压缩,如下

## 使用gzip的方式进行压缩,数字越大,压缩率就越高,9代表最大的压缩率
[root@hadoop0 ~]# salt 'uadoop2' cp.get_file salt://getfile.txt /opt/getfile.txt gzip=9
uadoop2:
    /opt/getfile.txt
## 分发成功,在minion上查看文件是否已经发送到uadoop2上了    
[root@uadoop2 ~]# cat  /opt/getfile.txt 
this is test file with module of cp.get_file!

    当minion上的目标目录不存在时,可以使用makedirs参数来创建目标目录,如下

[root@hadoop0 ~]# salt 'uadoop2' cp.get_file salt://getfile.txt /opt/test/getfile.txt makedirs=True
uadoop2:
    /opt/test/getfile.txt
## 分发成功,在minion上查看文件是否已经发送到uadoop2上了  
[root@uadoop2 ~]# cat /opt/test/getfile.txt 
this is test file with module of cp.get_file!

    在开始下一个示例之前,先介绍一下grains,这个接口的作用是在minion端的minion服务启动时,调用这个接口,收集minion端的信息,这些信息数据可以在salt的其他模块中直接使用,需要注意的是,这个接口只在minion端的minion服务启动时被调用一次,所以收集的数据是静态的,不会改变的,除非你重启了minion端的服务,关于这点,官方文档是这样说明的:

    Grains Static bits of information that a minion collects about the system when the minion first starts.
The grains interface is made available to Salt modules and components so that the right salt minion commands are
automatically available on the right systems.
    It is important to remember that grains are bits of information loaded when the salt minion starts, so this information
is static. This means that the information in grains is unchanging, therefore the nature of the data is static. So grains
information are things like the running kernel, or the operating system.

    grains的基本用法

## 使用grains.ls列出可以在其他模块中直接使用的grains
[root@hadoop0 ~]# salt 'uadoop2' grains.ls
uadoop2:
    - biosreleasedate
    - biosversion
    - cpu_flags
    - cpu_model
    - cpuarch
    - defaultencoding
    - defaultlanguage
    - domain
    - fqdn
    - fqdn_ip4
    - fqdn_ip6
    - gpus
    - host
    - hwaddr_interfaces
    ..............

## 使用grains.items模块列出所有可用grains的具体数据
[root@hadoop0 ~]# salt 'uadoop2' grains.items
uadoop2:
  biosreleasedate: 07/31/2013
  biosversion: 6.00
  cpu_flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
  cpu_model: Intel(R) Core(TM) i7-2630QM CPU @ 2.00GHz
  cpuarch: x86_64
  defaultencoding: UTF8
  defaultlanguage: en_US
  domain: prolexic.com
  fqdn: unknown.prolexic.com
  fqdn_ip4:
      72.52.4.120
  fqdn_ip6:
  gpus:
      {'model': 'SVGA II Adapter', 'vendor': 'unknown'}
  host: unknown
  hwaddr_interfaces: {'lo': '00:00:00:00:00:00', 'eth0': '00:0c:29:b7:1d:85'}
  id: uadoop2
  ip_interfaces: {'lo': ['127.0.0.1'], 'eth0': ['192.168.0.202']}
  ipv4:
      127.0.0.1
      192.168.0.202
  ipv6:
      ::1
      fe80::20c:29ff:feb7:1d85
  kernel: Linux
  kernelrelease: 2.6.32-431.el6.x86_64
  ..............  

## ping测试grains中os的值为CentOS的主机通信是否正常
[root@hadoop0 ~]# salt -G 'os:CentOS' test.ping
uadoop2:
    True        

## 查看uadoop2主机的ip地址,注意这里不是items噢,而是item
[root@hadoop0 ~]# salt 'uadoop2' grains.item ipv4
uadoop2:
  ipv4:
      127.0.0.1
      192.168.0.202

    好了,在介绍了grains接口之后,接下来看下在cp模块中如何简单的使用grains的数据呢

## 首先在状态配置文件的根目录下创建一个CentOS目录,然后将位于根目录下的getfile.txt测试文件
mv到CentOS目录下
[root@hadoop0 ~]# mkdir  /srv/salt/CentOS/
[root@hadoop0 ~]# mv  /srv/salt/getfile.txt /srv/salt/CentOS/
## 然后执行文件分发的命令,注意这里要使用salt内置模版jinja才能分发成功
[root@hadoop0 ~]# salt 'uadoop2' cp.get_file "salt://`grains`.`os`/getfile.txt" /opt/getfile.txt template=jinja
uadoop2:
    /opt/getfile.txt

   

    接着介绍cp.get_dir,get_dir与get_file的用法十分相似,用来将整个目录分发到minions

## 创建测试目录
[root@hadoop0 ~]# mkdir /srv/salt/test_dir
## 创建测试文件
[root@hadoop0 ~]# echo 'hello a !' > /srv/salt/test_dir/a.txt
[root@hadoop0 ~]# echo 'hello b !' > /srv/salt/test_dir/b.txt 
## 执行目录文件的分发,并使用压缩传输
[root@hadoop0 ~]# salt 'uadoop2' cp.get_dir salt://test_dir /opt/ gzip=9 
uadoop2:
    - /opt//test_dir/a.txt
    - /opt//test_dir/b.txt

## 分发成功,验证
[root@uadoop2 ~]# ls /opt/test_dir/   
a.txt  b.txt
[root@uadoop2 ~]# cat /opt/test_dir/a.txt 
hello a !
[root@uadoop2 ~]# cat /opt/test_dir/b.txt  
hello b !

    在往下介绍之前,首先介绍一下salt的pillar接口,pillar是salt中比较重要的组件,跟grains有些相似,但是pillar相比于grains更加灵活,而且是动态的,数据可以随时更新,只要你愿意的话。而grains只在minion启动时采集一次数据,关于pillar官网描述如下,简单翻译一下,但不保证翻译的到位,意思是说pillar是salt实现部署功能的最重要的组件,能够为minions生成非常灵活的数据,这些数据可以被salt的其他的组件所使用。

    The pillar interface inside of Salt is one of the most important components of a Salt 
deployment. Pillar is the interface used to generate arbitrary data for specific minions. 
The data generated in pillar is made available to almost every component of Salt.

    pillar的基本用法

## 使用pillar之前要在master中配置pillar的工作目录,将下面三行的注释打开
[root@hadoop0 ~]# vi /etc/salt/master
pillar_roots:
  base:
    - /srv/pillar
## 重启master服务 
[root@hadoop0 ~]# /etc/init.d/salt-master restart 
Stopping salt-master daemon:                               [  OK  ]
Starting salt-master daemon:                               [  OK  ]
## 创建所需目录
[root@hadoop0 ~]# mkdir  /srv/pillar/
## 该目录用来测试使用
[root@hadoop0 ~]# mkdir  /srv/pillar/user
## 首先在/srv/pillar目录中要有一个入口文件top.sls
[root@hadoop0 pillar]# vi top.sls 
base:
  'uadoop2':
    - data         ## 为uadoop2定义了一个属性数据,引用了跟top.sls同目录下的data.sls
  
  'uadoop3':
    - webserver    ## 为uadoop3定义了一个属性数据,引用了跟top.sls同目录下的web.sls

  '*':
    - user         ## 为所有节点定义了一个属性数据,引用了/srv/pillar/user/init.sls
                   ## 这里指定的是一个目录,salt会自动在top.sls文件中的引用目录中寻找状态文件
                   ## 因此会找到位于user目录中的init.sls文件
              
## 编写在top.sls文件中引用的状态文件
[root@hadoop0 pillar]# vi data.sls
data: some data
[root@hadoop0 pillar]# vi webserver.sls 
webserver: test_dir
[root@hadoop0 pillar]# vi user/init.sls 
users:
  kora: 1000
  kadefor: 1100
  foway: 1200

## 接着将master上定义的属性同步到对应的minion上去
[root@hadoop0 pillar]# salt '*' pillar.items
uadoop3:
    ----------
    master:
        ----------
        auth_mode:
            1
        auto_accept:
            False
    .............省略N行..............
        worker_threads:
            5
    webserver:
        test_dir
    users:
        ----------
        foway:
            1200
        kadefor:
            1100
        kora:
            1000
uadoop2:
    ----------
    data:
        some data
    master:
        ----------
        auth_mode:
            1
    .............省略N行..............       
        worker_threads:
            5
    users:
        ----------
        foway:
            1200
        kadefor:
            1100
        kora:
            1000

## 在master上远程获取刚刚定义的属性
[root@hadoop0 pillar]# salt 'uadoop2' pillar.item data
uadoop2:
    ----------
    data:
        some data
[root@hadoop0 pillar]# salt 'uadoop3' pillar.item webserver
uadoop3:
    ----------
    webserver:
        test_dir  
[root@hadoop0 pillar]# salt '*' pillar.item users
uadoop2:
    ----------
    users:
        ----------
        foway:
            1200
        kadefor:
            1100
        kora:
            1000
uadoop3:
    ----------
    users:
        ----------
        foway:
            1200
        kadefor:
            1100
        kora:
            1000
## 可以看到刚刚为不同的minion定义的属性已经同步到了各个minion上,从这个测试可以看出,使用pillar
## 我们可以为不同的minion或者不同的minion组定义不同的属性,极其灵活。

    好了,在介绍了pillar接口之后,接下来看下在cp模块中如何简单的使用pillar定义的属性数据呢

## 我们可以利用之前定义的属性来匹配不同的minion
[root@hadoop0 pillar]# salt -I 'users:kora:1000' test.ping
uadoop2:
    True
uadoop3:
    True
[root@hadoop0 pillar]# salt -I 'data:*some*' test.ping      
uadoop2:
    True
[root@hadoop0 pillar]# salt -I 'webserver:test_dir' test.ping     
uadoop3:
    True

## 匹配uadoop3,然后在master上远程分发文件到uadoop3上去
[root@hadoop0 pillar]# salt -I 'webserver:test_dir' cp.get_dir "salt://`pillar`.`webserver`" /opt/ gzip=9 template=jinja    
uadoop3:
    - /opt//test_dir/a.txt
    - /opt//test_dir/b.txt

    从远程执行的结果来看文件已经分发成功,上面的例子就演示了pillar接口定义的属性在cp模块中的简单使用,我们可以通过pillar为不同minion指定的属性及其值来匹配对应的minion,非常的灵活。        

    好了,关于salt文件服务器就介绍到这里。虽然我也只是简单的体验了一下,但是依旧被salt作为文件服务器的强大功能所震精。有了salt的文件分发功能后,真的是鸟枪换炮。当然不需要使用好多条scp命令,只需要写好配置文件,分好组,一条命令过去,完成所有节点的文件分发。