送书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文件,这样后续迁移到其他机器也相对容易一些。
对于Ansible的hosts文件管理,我们需要对他的格式做一定的规定,以更方便我们后续更容易在数据库层面上读取和存储,为我们后续的Web设计提供基石。
首先,我们制定hosts文件的规则应该遵循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主机添加列表:
在上节内容里面我们介绍了如何定义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文件即可。
上面一节,我们已经设计好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文件,因涉及内容较多及深度缘由,需结合前后文,更多详细请参考
《Ansible权威指南》在京东、亚马逊、当当等各大电商均已上架,敬请关注:
京东:
送书说明:送《Ansible权威指南》5本,规则说明:
1 在本文未留言,留言被点赞前五名送书;
2 截至时间12月4日中午12:00;
相关阅读:
分享在云计算/虚拟化项目实施中的资讯、经验、技术,坚持干货。
以上是关于送书5本|《 Ansible权威指南》Web方式管理Ansible的Inventory(摘)的主要内容,如果未能解决你的问题,请参考以下文章