送书5本|《 Ansible权威指南》Web方式管理Ansible的Inventory(摘)

Posted 云技术实践

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了送书5本|《 Ansible权威指南》Web方式管理Ansible的Inventory(摘)相关的知识,希望对你有一定的参考价值。


送书说明:送《Ansible权威指南》5本,规则说明:

1 在本文未留言,留言被点赞前五名送书;

2 截至时间12月4日中午12:00;


Web方式管理Ansible的Inventory(摘)

1.重新定制Ansible的Hosts文件规则

2.使用ConfigParser解析并生成Ansible Hosts文件

3.使用数据库的存储数据生成Ansible的hosts文件

Web方式管理Ansible的Inventory(摘)


在上一章第13章内容中,我们学习了Web与Ansible的结合使用的简单例子,本章内容我们将把重点放在读者日常可能使用到的例子,为大家尽可能多的打开设计的思路。

Ansible的hosts文件大家在起初的几章节已经被介绍过了,可能觉得没什么值得多说的,和linux机器的hosts文件属于同一类性质的文件,只是作为定义主机来提供Ansible命令指定目标主机来使用的。但是笔者想告诉大家的是请大家一定要尽可能运用Ansible对主机定义的特性,来制定尽可能完整又相对简洁的hosts文件,因为它将影响你后续程序设计的全局文件,请大家考虑好在对它进行规划,我们会将它的信息存入数据库,再反向生成该hosts文件,这样后续迁移到其他机器也相对容易一些。

1
重新定制Ansible的Hosts文件规则

对于Ansible的hosts文件管理,我们需要对他的格式做一定的规定,以更方便我们后续更容易在数据库层面上读取和存储,为我们后续的Web设计提供基石。 
首先,我们制定hosts文件的规则应该遵循2点:

  1. 制定是请遵循简单明了的原则,避免产生歧义。

  2. 最好不要有其他复杂的inventory的定义,满足精确到一台机器即可。

对于上述1,大家可能觉得hosts文件写出一下方式就可以了:

[group-test1]
192.168.1.2
192.168.1.3

但随着设计的深入和复杂,这种简单的方式将不再适合设计的需要,根据我们上面的第一点规则,我们建议的Ansible的hosts文件的写法最好是如下方式,因为它把所有最基础和必要的信息都写入文件中,避免了所有的歧义:

[group-test1]
test_test1 ansible_ssh_port=22 ansible_ssh_host=192.168.1.2
ansible_ssh_user=deploy
test_test2 ansible_ssh_port=22 ansible_ssh_host=192.168.1.3
ansible_ssh_user=deploy

以下设计也是可以的(用冒号来定义主机名),但是只适用Ansible1.7.x以上的版本, Ansible2.0以上版本将不再支持对此类文件的解析:

test_test1: ansible_ssh_port=22 ansible_ssh_host=192.168.1.2
ansible_ssh_user=deploy

再举一个错误的例子,请大家也不要写成以下形式:

[group-test1]
192.168.1.2  ansible_ssh_port=22 ansible_ssh_user=deploy
192.168.1.3  ansible_ssh_port=22 ansible_ssh_user=deploy

这是因为上面hosts文件的两个IP并没有冲突,如果是下面的形式,第二台机器(尽管他的端口不一样)将永远不会被读取(如ansible 192.168.1.2 –a xxx),如读者把hosts文件写出下面形式的格式,那么端口为222的这台机器将无法被读取:

[group-test2]
192.168.1.2  ansible_ssh_port=22 ansible_ssh_user=deploy
192.168.1.2  ansible_ssh_port=222 ansible_ssh_user=deploy

所以请使用我们推荐的方式来规范你的配置文件,从而有效地规避Ansible识别主机的歧义。 

对于规则的第二条的解释,保持一个文件的简洁性和主机定义的原子性,可以有效地为我们后续设计的多样和复杂性铺平道路,因为我们以后的选择机器和机器组,将会使用:进行选择和拼接(例如test_test3:test_test1),虽然我们觉得这样每次调用Playbook写如此长的host定义会比较麻烦,但是如果交给我们后续设计的程序来拼接,就一点也不麻烦了。 

这样,大家可能没什么概念,大家之后可以设计成如下,这样我们就可以精确到主机节点,后续就可以设计更复杂的组合了,如图14-1主机添加列表:

2
使用ConfigParser解析并生成Ansible Hosts文件

在上节内容里面我们介绍了如何定义hosts文件,并解释了这样定义的原因,接下来我们要通过数据库取到的json数据来为Ansible文件产生下面的hosts列表,使用json格式的数据是因为我们后面会使用javascript,而其交换数据是通过json格式来完成的,例如生成后为以下文件:

[test-group1]
test1  ansible_ssh_port=22 ansible_ssh_host=127.0.0.1 ansible_ssh_user=deploy
test2  ansible_ssh_port=22 ansible_ssh_host=127.0.0.1 ansible_ssh_user=deploy

[test-group2]
test3  ansible_ssh_port=22 ansible_ssh_host=127.0.0.1 ansible_ssh_user=deploy

为了产生上面的Ansible的hosts主机信息,我们将使用Python的ConfigParser模块来生成。但有一点需要注意:为了便于区分Ansible的key和value,我们将统一使用两个空格为键值(如test1 ansible_ssh_port=22)。但是由于原生的ConfigParser模块在保存文件后将自动把冒号和空格等解析成等号(如test1= ansible_ssh_port=22),从而造成Ansible无法解析生成的hosts文件,所以为了避免键值标记的冲突(主要是等号),我们将对ConfigParser模块进行扩展,那么来编写Part1,把ConfigParser模块修改我们的所能使用的模块KconfigParser。

#!/usr/bin/env  python
# -*- coding: utf-8 -*-

import json
import ConfigParser
class KconfigParser(ConfigParser.RawConfigParser):
   def write(self, fp):
       """解决ConfigParser的冒号空格等被自动保存为等号而引起的后续解析问题"""
       if self._defaults:
           fp.write("[%s]\n" % DEFAULTSECT)
           for (key, value) in self._defaults.items():
               fp.write("%s  %s\n" % (key, str(value).replace('\n', '\n\t')))
           fp.write("\n")
       for section in self._sections:
           fp.write("[%s]\n" % section)
           for (key, value) in self._sections[section].items():
               if key != "__name__":
                   fp.write("%s  %s\n" %
                 (key, str(value).replace('\n', '\n\t'))) #使用两个空格取代key
           fp.write("\n")

接下来我们将会使用KconfigParser来替代原生的ConfigParser,这里我们将用二个空格来替代等号或者冒号来作为key,而且经过测试,空格将通过Ansible所有版本的主机名识别,为了区别其他空格的(如ansible_ssh_port=22 ansible_ssh_host=127.0.0.1),我们改为用二个空格区分key和value(如test1 ansible_ssh_port=22),冒号将在Ansible2+版本不被识别,我们来写下如何生成自己的hosts文件的方法,那么来编写Part2:

class Generate_ansible_hosts(object):
   def __init__(self, host_file):
       self.config = KconfigParser(allow_no_value=True)
       self.host_file = host_file

   def create_all_servers(self, items):
       for i in items:
           group = i['group']
           self.config.add_section(group)
           for j in i['items']:
               name = j['name']
               ssh_port = j['ssh_port']
               ssh_host = j['ssh_host']
               ssh_user = j['ssh_user']
               build = "ansible_ssh_port={0} ansible_ssh_host={1} ansible_ssh_user={2}".format(
                       ssh_port, ssh_host, ssh_user)
               self.config.set(group, name, build)
       with open(self.host_file, 'wb') as configfile:
           self.config.write(configfile)
       return True

在使用我们的数据库前(程序取出后我们将其转化问json格式),那么,我们首先使用一些假定的json数据来代替我们之后从数据库取出的数据,来完成我们的编写测试工作,以下就是我们定义的json数据,并用来存入hosts文件:

[
   {
       "group": "group-name",                #  定义组名
       "items": [
           {
               "name": "host-name",              # 定义主机名
               "ssh_host": "host-ip",               # 定义主机ip
               "ssh_port": host-port,               # 定义主机端口
               "ssh_user": "host-user"              # 定义信任用户
           }
       ]
   }
]

最后,那么我们来编写Part3的制造一些json数据,同时编写语句来测试我们上面的方法吧!

generate_hosts = Generate_ansible_hosts('/tmp/hosts')     #定义Ansible的hosts文件
   data = [              
           {
               "group": "test-group1",
               "items": [
                   {
                       "name": "test1",
                       "ssh_host": "127.0.0.1",
                       "ssh_port": 22,
                       "ssh_user": "deploy"
                   },
                   {
                       "name": "test2",
                       "ssh_host": "127.0.0.1",
                       "ssh_port": 22,
                       "ssh_user": "deploy"
                   }
               ]
           },
           {
               "group": "test-group2",
               "items": [
                   {
                       "name": "test3",
                       "ssh_host": "127.0.0.1",
                       "ssh_port": 22,
                       "ssh_user": "deploy"
                   }
               ]
           }
       ]
   generate_hosts.create_all_servers(data)         #  生成数据

这样,我们便完成了编造好了存储的json格式数据了,之后,通过该上述的generate_hosts.create_all_servers方法来生成Ansible的hosts文件即可。

3
使用数据库的存储数据生成Ansible的hosts文件

上面一节,我们已经设计好json的数据格式,那么我们就参照这个数据格式来编写我们的数据库的字段了。 

我们简单地设计了我们的字段:文件在ansible_demo/demo_2/ api/models.py:

class Ansible_Host(models.Model):
   group = models.CharField(max_length=50, blank=True, default='')         # 组名
   name = models.CharField(max_length=50, blank=True, default='')          # 主机别名
   ssh_host = models.CharField(max_length=50, blank=True, default='')      # 主机ip
   ssh_user = models.CharField(max_length=50, blank=True, default='')      # 信任的用户名
   ssh_port = models.CharField(max_length=50, blank=True, default='')      # 主机端口
   server_type = models.CharField(max_length=100, blank=True, default='')  # 主机类型
   commit = models.TextField(blank=True, null=True)                        # 备注

再设计好models.py的文件后,我们就可以生成demo_2数据库的Ansible_Host表结构,我们可以使用一下命令来完成:

cd ansible_demo
./manage.py makemigrations demo_2
./manage.py migrate demo_2

我们要编写接口来生成我们Hosts文件了,这时我们上面编写的生成Hosts文件的方法也可以被我们的接口调用了。 
之后,我们就在  里输入一些数据。

那么,我们先任意添加一些测试数据:

有了这些测试数据后,我们就可以着手编写我们的生成Ansible的hosts接口的接口了,我们通过使用到上面编写的Generate_ansible_hosts方法来完成生成工作就可以了。 
ansible_demo/demo_2/api/api_demo_2.py文件:

def generate_hosts(self):
       data = Ansible_Host.objects.all().values()
       s_data = [{'group': group, 'items': list(items)} for group, items in itertools.groupby(data, lambda x: x['group'])]
       generate_hosts = Generate_ansible_hosts('/tmp/hosts')
       try:
           generate_hosts.create_all_servers(s_data)
           msg = 'hosts has been create'
           flag = True
       except:
           msg = 'hosts has not been create'
           flag = False
       return msg, flag

   @list_route(methods=['get', 'post'])                      
   def create_ansible_hosts(self, request):
       msg, flag = self.generate_hosts()
       return Response({'msg': msg, 'flag': flag})

注意:请真正使用时把generate_hosts = Generate_ansible_hosts(‘/tmp/hosts’)更改为generate_hosts = Generate_ansible_hosts(‘/etc/ansible/hosts’),并给这个文件对应的写入权限即可。

所有工作完成后,我们来访问下接口,并检查生成了的hosts文件: 
其次还有通过页面来生成Hosts文件,因涉及内容较多及深度缘由,需结合前后文,更多详细请参考

送书5本|《 Ansible权威指南》Web方式管理Ansible的Inventory(摘)

《Ansible权威指南》在京东、亚马逊、当当等各大电商均已上架,敬请关注:

京东:

送书5本|《 Ansible权威指南》Web方式管理Ansible的Inventory(摘)


送书说明:送《Ansible权威指南》5本,规则说明:

1 在本文未留言,留言被点赞前五名送书;

2 截至时间12月4日中午12:00;

送书5本|《 Ansible权威指南》Web方式管理Ansible的Inventory(摘)

相关阅读:

云技术社区微信群加入,联系北极熊
格式:姓名-城市-公司


送书5本|《 Ansible权威指南》Web方式管理Ansible的Inventory(摘)

分享在云计算/虚拟化项目实施中的资讯、经验、技术,坚持干货。

以上是关于送书5本|《 Ansible权威指南》Web方式管理Ansible的Inventory(摘)的主要内容,如果未能解决你的问题,请参考以下文章

《Ansible权威指南》笔记——安装,ssh密钥登陆,命令

送书之《Angular权威教程》

马哥团队《Ansible权威指南》卖爆了!!!看图

马哥团队《Ansible权威指南》也来到GITC大会

我们出新书了《Ansible权威指南》,小伙伴快来围观!

《Ansible权威指南》笔记——Inventory配置