本节内容
一、 主机管理项目需求分析
二 、主机管理项目架构设计
三、主机管理项目初始构建
四、 主机管理项目编主机分发器
一、 主机管理项目需求分析
场景:我现在又一台裸机要实现一下人物
配置管理:
1、装上nginx,mysql
2、nginx用我指定的配置文件
3、mysql用户
4、设置一个默认的数据库访问权限
5、启动mysql and nginx
场景:因为200台机器要连接200次,要花很长时间,写一个脚本。分发到所有的机器,然后再执行脚本,
问题:
1、脚本执行出错
2、客户端环境,不相同(没有判断时什么操作系统)
3、重复脚本内容(很多时候,经常要装各种服,今天装apache,明天装nginx这样不停的重复劳动)
4、无法实现状态管理和检测
安装nginx,他是把服务安装好了,但是它能代表机器上的一种状态吗?比如从应用层面上讲我这个nginx是启动状态还是关闭状态
我确保这台机器有三个固定的用户,mysql状态是正常的,比如说我有500台机器,都安装了mysql,我可以写脚本时可以实现的,也可一起
启动起来,但是过两天有100台down了,我让我的管理建议一个配置文件或者服务你一旦有变化我就reload或者启动服务,过了两天down了
我想自动把它启动起来,所以脚本就不行了
解决:
1、标准化
每个人写的脚本都不一样,别人写的脚本肯定和你不一样,每个人写的环境判断都不一样
如果大量的环境,大量的重复工作
2、客户端最好有个守护进程
二 、主机管理项目架构设计
1、salt架构图
https://docs.saltstack.com/en/getstarted/system/plugins.html
plug-ins(左边):场景可插拔
subsystem-core-subsystem(中间蓝色部分):
- 执行命令
- 分发文件
- 安全存储数据
plug-ins(右边边):
- 通过命令行执行 标准的接口可以进行二次开发
- 可以用什么样的形式去描述机器能认识的
- 任务结果可以存储的
plug-ins(下面)
-
包-变成命令
2、远程执行流程:
流程图(官方图)
流程说明
- 输入一个命令
- 进行用户认证
- 把任务放在控制总线,然后分发给客户端队列
- 客户端判断是配置管理还是远程执行
- 下载配置文件
- 配置文件里的数据提取
- 安全数据(用户名,密码)单独存储
- 状态文件解析编译
- 按照标准的格式返回到时间总线上
- 客户端把执行的结果返回到服务器端把结果展现出来并长期保存
- 把结果展现出来并长期保存
- 当结果返回后触发任务
3、任务解析实例
apache: #yum 安装 pkg.installed: [] service.running: #apache必须运行 - reload: True - watch: - file: /etc/httpd/conf/httpd.conf #如果配置文件有变更就重启 user.present: - uid: 87 #- username: alex - gid: 87 - home: /var/www/html - shell: /bin/nologin - require: - group: apache group.present: #apache组不存在上面的命令不执行 - gid: 87 - require: - pkg: apache /etc/httpd/conf/httpd.conf: #每执行一次配置文件就更新一次 file.managed: - source: salt://apache/httpd.conf - user: root - group: root - mode: 644
三、主机管理项目初始构建
-
创建一个项目stark:存放项目实战里所有的项目
-
创建一个文件夹Arya:存放主机管理项目文件
3、 创建一个主机模板文件models文件编辑
from django.db import models # Create your models here. class Host(models.Model): #主机管理 hostname = models.CharField(max_length=128,unique=True) #saltsack用hostname区别主机 key = models.TextField() #客户端主动找服务器,我想被你管理存放key文件 status_choices = ((0,'Waiting Approval'), #每个主机的三个状态等待、允许、拒绝 (1,'Accepted'), (2,'Rejected'))
四、主机管理项目命令分发器
01、salt.py 只是一个入口,没干什么事情
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:Alex Li import os,sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Stark.settings") BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #print(BASE_DIR) sys.path.append(BASE_DIR) from Arya.action_list import actions from Arya.backends.utils import ArgvManagement obj = ArgvManagement(sys.argv)
02、action_list.py 路由分发器
utils.py 创建了一个类
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:Alex Li from Arya.plugins import cmd,state actions = { 'cmd': cmd.CMD, 'state':state.State }
03、backends 建了一个目录
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:Alex Li import sys from Arya import action_list import django django.setup() from Stark import settings from Arya import models class ArgvManagement(object): ''' 接收用户指令并分配到相应模块 ''' def __init__(self,argvs): self.argvs = argvs self.argv_parse() def help_msg(self): print("Available modules:") for registered_module in action_list.actions: print(" %s" % registered_module) exit()
04、plugins 建立一个目录
cmd.py 创建两个类
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:Alex Li from Arya.backends.base_module import BaseSaltModule class CMD(BaseSaltModule): print('in cmd module ')
state.py
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:Alex Li from Arya.backends.base_module import BaseSaltModule import os class State(BaseSaltModule): def load_state_files(self,state_filename): from yaml import load, dump try: from yaml import CLoader as Loader, CDumper as Dumper except ImportError: from yaml import Loader, Dumper state_file_path = "%s/%s" %(self.settings.SALT_CONFIG_FILES_DIR,state_filename) if os.path.isfile(state_file_path): with open(state_file_path) as f: data = load(f.read(), Loader=Loader) return data else: exit("%s is not a valid yaml config file" % state_filename)