应用环境:

使用salt写了个自动部署mysql的配置配置管理文件,由于mysql的有版本号,端口等不确定属性,需要使用pillar来单独配置每个minion的属性。

一,原始方法

例如,需要在salt id为10.1.1.1-centos.game.web的服务器上部署mysql,版本号为5.5.25,实例有3个,3306,3307,3308, 正常情况下的流程是这样的:

1,在/srv/salt/top.sls中添加配置信息,确保mysql对应的配置被加载

1

2

3

base:

  10.1.1.1-centos.game.web:

    -centos.public_services.mysql

2,在/srv/pillar/top.sls配置minion对应的sls文件位置(ps:salt文件中不能再带".",否则会报错)

1

2

3

base:

  10.1.1.1-centos.game.web:

    -custom.10-1-1-1-centos-game-web

3,新建/srv/pillar/custom/10-1-1-1-centos-game-web.sls,内容如下:

1

2

3

4

5

6

mysql:

 ports:

  -3306

  -3307

  -3308

 version: '5_5_25'

4,执行同步命令

1

salt 10.1.1.1-centos.game.web state.highstate-v-t300

二,改进方法
oh,shit,说好的自动化呢,怎么还要这么多步骤,这可不行!
利用py模式的sls配置文件(其实就是python脚本,只要返回yaml格式的字典文件就好了),我们可以将以上的操作简化成1步,思路如下:
1,/srv/pillar/top.sls中编写配置:

1

2

3

base:

'*':

-custom

2,使用py模式编写/srv/pillar/custom/init.sls,自动读取pillar配置,例如salt  

id是:10.1.1.1-centos.game.web,那么project为game,然后根据获取的pillar_root组合成路径/srv/pillar/custom/game/10.1.1.1-centos.game.web.yaml,利用yaml模块从文件中读取信息,返回字典
3,在/srv/salt/top.sls文件中匹配所有的minion

1

2

*’:

  -centos.public_services

4,/srv/salt/centos/public_services/init.sls文件使用py模式编写,配置会获取对应的minion的pillar信息,如果包含mysql配置信息且配置正确的话,则返回mysql实例的配置。

那现在要怎么使用呢,很简单,例如你的id为10.1.1.1-centos.game.web,首先在/srv/pillar/custom/目录下建个game目录(从salt id获取的项目名),然后在game目录先新建文件10.1.1.1-centos.game.web.yaml,里面写上配置信息:

1

2

3

4

5

6

7

8

mysql:

 ports:

  -3306

  -3307

  -3308

 version: '5_5_25'

 

最后执行命令:

1

salt 10.1.1.1-centos.game.web state.highstate-v-t300

静静的等待执行完成就好了!

三,具体代码

/srv/pillar/custom/init.sls

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

#!py

#coding:utf-8

"""

返回minion对应的pillar信息

"""

import yaml

import os

 

def run():

  """

  首先获取请求的id,从id中获取project,例如id是:1.2.3.4-centos.game.web,那么project为game

  然后根据获取的pillar_root组合成路径/srv/pillar/custom/game/1.2.3.4-centos.game.web.yaml,利用yaml模块从文件中读取信息,返回字典

  """

  config={}

  id=__opts__['id']

  project=id.split('-')[-1].split('.')[1]

  pillar_root=__opts__['pillar_roots']['base'][0]

  path='%s/custom/%s/%s.yaml'%(pillar_root,project,id)

  ifos.path.isfile(path):

    s=open(path).read()

    config=yaml.load(s)

  returnconfig

/srv/salt/centos/public_services/init.sls

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

#!py

#coding: utf-8

import subprocess

 

classMY_ERROR(Exception):

  def __init__(self,value):

    self.value=value

  def __str__(self):

    returnself.value

 

def mysql():

  """

  1,检查是minion中pillar是否有mysql参数,以及参数是否合法

  如果参数没有问题,则返回对应版本的include配置

  pillar e.q.

  mysql:

    ports:

      - 3306

      - 3307

    version: '5_5_25'

  """

  mysql_sls_path='centos.public_services.mysql.'

  #必要的参数

  required_keys=['version','ports']

  if__pillar__.has_key('mysql'):

    mysql_d=__pillar__['mysql']

    #不存在必要的键值对则返回None

    forkey inrequired_keys:

      ifnotmysql_d.has_key(key)orstr(mysql_d[key]).strip()=="":

        raise MY_ERROR('key error! key: %s'%(str(key)))

    #判断port是否合法

    forport inmysql_d['ports']:

      ifnotport ornot1024<int(port)<65535:

        raise MY_ERROR('mysql ports value error: %s'%(str(mysql_d['ports'])))

    #组合配置参数

    cfg=mysql_sls_path+str(mysql_d['version'][0])

    returncfg

  returnNone

 

def run():

  config={}

  config['include']=[]

  #mysql

  mysql_cfg=mysql()

  ifmysql_cfg:

    config['include'].append(mysql_cfg)

  ifconfig['include']==[]:

    return{}

  returnconfig

/srv/salt/centos/public_services/mysql/5/init.sls

1

2

3

4

include:

  -centos.public_services.mysql.5.packet

  -centos.public_services.mysql.5.my_cnf

  -centos.public_services.mysql.5.instance

/srv/salt/centos/public_services/mysql/5/packet.sls
mysql软件包要放到相应的目录中,具体位置参考下面配置

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

{%set version=pillar['mysql']['version']%}

mysql:

  user.present:

    -home:/home/mysql

    -shell:/sbin/nologin

 

/usr/local/nagios/libexec/check_safe-u:

  cmd.wait:

    -watch:

      -user:mysql

 

/usr/local/src/mysql-{{version.replace('_','.')}}.tar.gz:

  file.managed:

    -source:salt://centos/public_services/mysql/5/{{version}}/mysql-{{version.replace('_','.')}}.tar.gz

 

tar-xfmysql-{{version.replace('_','.')}}.tar.gz-C/usr/local/:

  cmd.run:

    -cwd:/usr/local/src

    -unless:ls-l/usr/local/|grep-e".* mysql-{{version.replace('_','.')}}$"

 

/usr/local/mysql-{{version.replace('_','.')}}:

  file.directory:

    -user:mysql

    -group:mysql

    -recurse:

      -user

      -group

 

/data/mysql_log:

  file.directory:

    -makedirs:True

    -user:mysql

    -group:mysql

    -recurse:

      -user

      -group

 

/data/log-bin:

  file.directory:

    -makedirs:True

    -user:mysql

    -group:mysql

    -recurse:

      -user

      -group

 

/usr/bin/mysql:

  file.symlink:

    -target:/usr/local/mysql-{{version.replace('_','.')}}/bin/mysql

    -unless:ls-l/usr/bin|grep-e" mysql$"

/srv/salt/centos/public_services/mysql/5/my_cnf.sls
注意修改最后的初始化密码
my.cnf配置文件需要放到对应的目录中,my.cnf文件中要设置对应的模板变量:

1

2

port={{port}}#还有其它的和端口相关的配置都要改成{{port}}

basedir=/usr/local/mysql-{{version}}#还有其它的和版本相关的配置都要改成{{version}}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#!py

#coding:utf-8

"""

生成my.cnf配置文件,如果文件已存在,不作任何修改

"""

import os

 

def run():

  config={}

  version=__pillar__['mysql']['version']

  forport in__pillar__['mysql']['ports']:

    port=str(port)

    ifnotos.path.isfile('/data/mysql_data_%s/my.cnf'%(port)):

      config['/data/mysql_data_%s/my.cnf'%(port)]={

        'file.managed':[

          {'source':'salt://centos/public_services/mysql/5/%s/my.cnf'%(version)},

          {'template':'jinja'},

          {'context':{'port':port,'version':'%s'%(version.replace('_','.'))}},

          {'require':[{'file':'/data/mysql_data_%s'%(port)}]},

          ],

      }

      config['chown mysql.mysql /data/mysql_data_%s/my.cnf'%(port)]='cmd.run'

 

  returnconfig

/srv/salt/centos/public_services/mysql/5/instance.sls
mysql启动脚本需要放到对应的目录中,启动脚本中要设置对应的模板变量:

1

2

basedir=/usr/local/mysql-{{version}}#还有其它的和版本相关的配置都要改成{{version}}

datadir=/data/mysql_data_{{port}}#还有其它的和端口相关的配置都要改成{{port}}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

{%forport inpillar['mysql']['ports']%}

 

/data/mysql_data_{{port}}:

  file.directory:

    -makedirs:True

    -user:mysql

    -group:mysql

    -recurse:

      -user

      -group

 

/etc/init.d/mysqld_{{port}}:

  file.managed:

    -source:salt://centos/public_services/mysql/5/{{pillar['mysql']['version']}}/mysql.service

    -user:root

    -group:root

    -mode:755

    -template:jinja

    -context:

      port:{{port}}

      version:{{pillar['mysql']['version'].replace('_','.')}}

 

chkconfig--addmysqld_{{port}};chkconfig--level345mysqld_{{port}}on;:

  cmd.run:

    -unless:chkconfig--list|grepmysqld_{{port}}

 

#初始化库

init_mysql_{{port}}:

  cmd.run:

    -name:/usr/local/mysql-{{pillar['mysql']['version'].replace('_','.')}}/scripts/mysql_install_db--user=mysql--basedir=/usr/local/mysql-{{pillar['mysql']['version'].replace('_','.')}}  --datadir=/data/mysql_data_{{port}}/

    -unless:ls-l/data/mysql_data_{{port}}|grep-e".* mysql$"

 

/etc/init.d/mysqld_{{port}}start:

  cmd.wait:

    -watch:

      -cmd:init_mysql_{{port}}

 

/usr/local/mysql-{{pillar['mysql']['version'].replace('_','.')}}/bin/mysqladmin-uroot-S/tmp/mysql_{{port}}.sock password'yourmysqlpasswd!':

  cmd.wait:

    -watch:

      -cmd:init_mysql_{{port}}

 

{%endfor%}

四,总结
这个方法不仅可以用在mysql,同样的nginxredis等都可以举一反三,配置文件编写完成后,仅仅需要简单的在pillar中添加几个变量就可以轻松批量部署了。


本文转自:https://blog.csdn.net/xiefangjin/article/details/51226566