当前位置: 首页 > 新闻 > 信息荟萃
编号:2433
运维前线 : 一线运维专家的运维方法、技巧与实践.pdf
http://www.100md.com 2020年2月1日
第1页
第6页
第13页
第25页
第33页
第210页

    参见附件(22893KB,855页)。

     运维前线 : 一线运维专家的运维方法、技巧与实践,这是一本关于互联网运维的,全书为读者介绍了IT运维领域的知识点,包含了不同行业的运维工作,值得一看。

    运维前线介绍

    当前IT领域的概念层出不穷,云计算、物联网、移动互联网、大数据、人工智能、VR,所有的这一切都基于IT系统,IT系统正在向规模更大、更复杂、更高级的方向演进,一切IT资源都掌握在运维手里,通过运维来操作。这个时代对运维的要求越来越高,运维如果稍有不慎,就会造成重大的损失,所以随着IT系统的发展,运维的重要性也越来越高。根据量子力学理论,世界由基本粒子组成,因此世界是不连续的,这个理论在运维知识体系的建立上同样适用。仔细回想一下自己运维体系的建立,就是逐个攻克和掌握知识点,再进一步通过实践不断加深的过程。《运维前线》也是这样,其中的每一篇文章都能够协助读者更快地掌握一个或多个知识点,相信通过运维前线系列的逐步出版,终能够覆盖更多的运维知识点,为读者带来更多的实践经验和理念。

    运维前线特色

    当前IT领域的概念层出不穷,云计算、物联网、移动互联网、大数据、人工智能、VR,所有的这一切都基于IT系统,IT系统正在向规模更大、更复杂、更高级的方向演进,一切IT资源都掌握在运维手里,通过运维来操作。这个时代对运维的要求越来越高,运维如果稍有不慎,就会造成重大的损失,所以随着IT系统的发展,运维的重要性也越来越高。

    根据量子力学理论,世界由基本粒子组成,因此世界是不连续的,这个理论在运维知识体系的建立上同样适用。仔细回想一下自己运维体系的建立,就是逐个攻克和掌握知识点,再进一步通过实践不断加深的过程。《运维前线》也是这样,其中的每一篇文章都能够协助读者更快地掌握一个或多个知识点,相信通过运维前线系列的逐步出版,最终能够覆盖更多的运维知识点,为读者带来更多的实践经验和理念。作为运维前线系列的第一本书,本书覆盖了运维自动化、系统运维、云及虚拟化、Web运维、游戏运维、DBA运维等6个方面14个知识点,都是各位作者总结自己多年实践经验的干货,每一篇文章都很精彩,都值得读者仔细品味。

    运维前线主目录

    第1章 自动化运维之深度解码

    第2章 利用Facter和Django快速构建CMDB

    第3章 数据中心搬迁中的×86自动化运维

    第4章 集中配置管理工具Puppet

    第5章 深度实践iptables

    第6章 使用systemd管理Linux系统服务

    第7章 PHP运维实践

    第8章 应用系统运行分析

    第9章 虚拟化中存储配置典型场景:启动风暴

    第10章 私有云桌面网络组建

    第11章 浅谈服务器交付的那些事儿

    第12章 企业级Nginx Web服务优化实战

    第13章 游戏运维的思考

    第14章 数据库平台建设实战

    运维前线 : 一线运维专家的运维方法、技巧与实践截图

    前线系列

    运维前线:一线运维专家的运维方法、技巧与实践

    云技术社区 著

    ISBN:978-7-111-55697-8

    本书纸版由机械工业出版社于2017年出版,电子版由华章分社(北京华

    章图文信息有限公司,北京奥维博世图书发行有限公司)全球范围内制

    作与发行。

    版权所有,侵权必究

    客服热线:+ 86-10-68995265

    客服信箱:service@bbbvip.com

    官方网址:www.hzmedia.com.cn

    新浪微博 @华章数媒

    微信公众号 华章电子书(微信号:hzebook)目录

    推荐序

    前言

    第1章 自动化运维之深度解码

    1.1 概述

    1.2 运维自动化的三重境界

    1.3 运维自动化的困境和价值

    1.3.1 运维自动化的困境

    1.3.2 运维自动化的价值

    1.4 运维自动化的多维解读

    1.4.1 基于应用变更场景的维度划分

    1.4.2 基于系统层次的维度划分

    1.4.3 基于与业务程序耦合紧密程度的维度划分

    1.4.4 面向服务的自动化能力划分

    1.5 运维自动化的方法论

    1.6 运维自动化系统的实现

    1.6.1 DNS管理系统

    1.6.2 CMDB管理系统

    1.6.3 名字服务中心系统

    1.6.4 持续部署管理系统1.6.5 运维调度管理系统

    1.7 运维自动化系统的API参考实现

    1.8 运维自动化依赖的团队模型

    1.8.1 团队的能力模型

    1.8.2 团队的驱动模型

    1.8.3 团队的技能模型

    1.8.4 参考的运维团队组织结构

    1.9 小结

    第2章 利用Facter和Django快速构建CMDB

    2.1 CMDB简介

    2.2 开源CMDB介绍

    2.2.1 OneCMDB介绍

    2.2.2 CMDBuild介绍

    2.2.3 其他的开源CMDB

    2.3 Puppet及Facter介绍

    2.3.1 什么是Puppet

    2.3.2 为什么是Puppet

    2.3.3 什么是Facter

    2.3.4 Facter的特点

    2.3.5 Facter变量

    2.4 如何利用Python获取Facts2.4.1 工作原理

    2.4.2 利用Python脚本获取Facts

    2.5 使用Django快速构建CMDB系统

    2.5.1 Django介绍

    2.5.2 Django安装

    2.5.3 Django常用命令

    2.5.4 Django的配置

    2.6 高级进阶

    2.6.1 历史查询功能

    2.6.2 API功能

    2.6.3 数据表结构

    2.6.4 用户管理功能

    2.6.5 用户组管理功能

    2.7 小结

    第3章 数据中心搬迁中的x86自动化运维

    3.1 数据中心搬迁准备

    3.1.1 数据中心搬迁介绍

    3.1.2 搬迁环境介绍

    3.1.3 搬迁前的准备工作

    3.1.4 搬迁信息收集

    3.2 利用VMware脚本简化虚拟化层的搬迁3.2.1 通过脚本完成ESXI安装后的基础设置

    3.2.2 批量挂载数据盘

    3.2.3 批量注册虚拟机

    3.2.4 vCenter目录结构的调整

    3.2.5 批量更改虚拟机名称及port group

    3.2.6 批量设置虚拟机版本和CPU、内存保留值

    3.3 利用批处理与Shell脚本简化逻辑节点的搬迁

    3.3.1 逻辑节点切换脚本的思路

    3.3.2 利用批处理脚本简化Windows逻辑节点的搬迁

    3.3.3 利用Shell脚本简化Linux逻辑节点的搬迁

    3.3.4 通过SFTP和WMIC指令将脚本文件上传至所有虚拟机

    3.3.5 搬迁期间的注意事项

    3.4 小结

    第4章 集中配置管理工具Puppet

    4.1 如何同步puppet-agent端上的常用服务

    4.2 如何在puppet-agent端上自动安装常用的软件包

    4.3 如何自动同步puppet-agent端的yum源

    4.4 如何根据不同名字的节点机器推送不同的文件

    4.5 如何根据节点机器名来选择性地执行Shell程序

    4.6 如何快速同步puppet-server端的www目录文件

    4.7 如何利用ERB模板自动配置Apache虚拟主机4.8 如何利用ERB模板自动配置Nginx虚拟主机

    4.9 小结

    第5章 深度实践iptables

    5.1 禁用连接追踪

    5.1.1 排查连接追踪导致的故障

    5.1.2 分析连接追踪的原理

    5.1.3 禁用连接追踪的方法

    5.1.4 确认禁用连接追踪的效果

    5.2 慎重禁用ICMP协议

    5.2.1 禁用ICMP协议导致的一则故障案例

    5.2.2 MTU发现的原理

    5.2.3 解决问题的方法

    5.3 网络地址转换在实践中的案例

    5.3.1 源地址NAT

    5.3.2 目的地址NAT

    5.4 深入理解iptables的各种表和各种链

    5.5 小结

    第6章 使用systemd管理Linux系统服务

    6.1 systemd和sysVinit之间的关系

    6.1.1 sysVinit方式下系统的启动特点

    6.1.2 systemd方式下系统的启动特点6.2 systemd的原理和启动顺序

    6.2.1 sysVinit的启动顺序

    6.2.2 systemd的启动顺序

    6.3 systemd的进程控制命令

    6.3.1 systemctl命令

    6.3.2 hostnamectl命令

    6.3.3 localectl命令

    6.3.4 loginctl命令

    6.3.5 timedatectl命令

    6.4 systemd服务管理

    6.4.1 编写Nginx的sysVinit启动脚本

    6.4.2 编写Nginx的systemd启动脚本

    6.4.3 systemd的其他功能

    6.5 优化

    6.5.1 使用systemd-analyze优化启动时间

    6.5.2 使用systemd journal功能

    6.6 小结

    第7章 PHP运维实践

    7.1 PHP再认识

    7.1.1 PHP进程的工作方式

    7.1.2 PHP代码的编译和部署7.1.3 PHP内部实现和生命周期

    7.1.4 PHP在互联网技术栈的位置

    7.2 PHP开发、架构、运维问题及解决思路

    7.2.1 运维对PHP研发提要求

    7.2.2 运维参与PHP项目架构设计

    7.2.3 PHP运维常见问题及解决之道

    7.3 PHP进程部署和配置、代码发布

    7.3.1 PHP进程的部署

    7.3.2 PHP配置文件变更

    7.3.3 PHP配置项

    7.3.4 PHP进程部署及配置文件管理实践

    7.3.5 PHP代码发布

    7.3.6 PHP代码发布实践:代码发布系统

    7.4 PHP性能分析

    7.4.1 性能问题概述

    7.4.2 PHP性能问题

    7.4.3 性能分析方法

    7.4.4 PHP性能分析实践:性能分析系统

    7.5 PHP故障处理与监控

    7.5.1 PHP故障分类及处理思路

    7.5.2 业务监控和故障发现7.5.3 PHP故障消除的方法

    7.5.4 故障分析案例

    7.6 小结

    第8章 应用系统运行分析

    8.1 分析模型

    8.1.1 数据采集

    8.1.2 数据模型

    8.2 运行分析平台建设

    8.2.1 数据采集接口

    8.2.2 数据分析模块

    8.2.3 推广

    8.3 呼叫中心系统运行分析示例

    8.3.1 确定分析方案

    8.3.2 问题分析案例介绍

    8.4 小结

    第9章 虚拟化中存储配置典型场景:启动风暴

    9.1 oVirt虚拟化平台配置介绍

    9.1.1 存储配置背景知识

    9.1.2 模板与实例同一存储

    9.1.3 模板与实例分离存储

    9.1.4 无状态实例的硬盘与快照分离存储9.2 启动风暴相关系列实验

    9.2.1 模板配置

    9.2.2 实验脚本

    9.2.3 WD 1TB机械硬盘启动Windows XP实验

    9.2.4 Intel 480GB SSD启动Windows XP实验

    9.2.5 实验结论

    9.3 私有云中处理启动风暴的常用方法

    9.3.1 启动排队

    9.3.2 存储分层选择

    9.3.3 其他提升桌面云存储性能的方式

    9.4 小结

    第10章 私有云桌面网络组建

    10.1 桌面云常用网络

    10.1.1 NAT网络

    10.1.2 桥接网络

    10.1.3 VLAN网络

    10.1.4 Access模式

    10.1.5 Trunk模式

    10.1.6 Open vSwitch

    10.2 oVirtOpenStack的桌面网络应用

    10.2.1 oVirtOpenStack组网方式10.2.2 应用场景举例

    10.3 小结

    第11章 浅谈服务器交付的那些事儿

    11.1 设备签收的学问

    11.2 服务器设置

    11.3 Cobbler的流程与规划

    11.4 服务器安装时遇到的各种坑

    11.4.1 DHCP客户端获取IP地址失败

    11.4.2 TFTP加载失败

    11.4.3 TFTP Client交互后无响应

    11.4.4 yum安装失败

    11.4.5 Linux内核无法识别新硬件

    11.4.6 恶意PXE启动导致原有系统被误装

    11.5 交接后的故事

    11.6 小结

    第12章 企业级Nginx Web服务优化实战

    12.1 Nginx基本安全优化

    12.1.1 调整参数隐藏Nginx软件版本号信息

    12.1.2 更改源码隐藏Nginx软件名及版本号

    12.1.3 更改Nginx服务的默认用户

    12.2 根据参数优化Nginx服务性能12.2.1 优化Nginx服务的worker进程个数

    12.2.2 优化绑定不同的Nginx进程到不同的CPU上

    12.2.3 Nginx事件处理模型优化

    12.2.4 调整Nginx单个进程允许的客户端最大连接数

    12.2.5 配置Nginx worker进程的最大打开文件数

    12.2.6 优化服务器域名的散列表大小

    12.2.7 开启高效文件传输模式

    12.2.8 优化Nginx连接参数,调整连接超时时间

    12.2.9 上传文件大小的限制(动态应用)

    12.2.10 FastCGI相关参数调优(配合PHP引擎动态服务)

    12.2.11 配置Nginx gzip压缩实现性能优化

    12.2.12 配置Nginx expires缓存实现性能优化

    12.3 Nginx日志相关的优化与安全

    12.3.1 编写脚本实现Nginx access日志轮询

    12.3.2 不记录不需要的访问日志

    12.3.3 访问日志的权限设置

    12.4 Nginx站点目录及文件URL访问控制

    12.4.1 根据扩展名限制程序和文件访问

    12.4.2 禁止访问指定目录下的所有文件和目录

    12.4.3 限制网站来源IP访问

    12.4.4 配置Nginx,禁止非法域名解析访问企业网站12.5 Nginx图片及目录防盗链解决方案

    12.6 Nginx错误页面的优雅显示

    12.6.1 生产环境中常见的HTTP状态码列表

    12.6.2 为什么要配置错误页面优雅显示

    12.7 Nginx站点目录文件及目录权限优化

    12.8 Nginx防爬虫优化

    12.9 利用Nginx限制HTTP的请求方法

    12.10 使用CDN做网站内容加速

    12.10.1 什么是CDN

    12.10.2 CDN的特点

    12.10.3 企业使用CDN的基本要求

    12.11 Nginx程序架构优化

    12.12 使用普通用户启动Nginx(监牢模式)

    12.12.1 为什么要让Nginx服务使用普通用户

    12.12.2 给Nginx服务降权的解决方案

    12.12.3 给Nginx服务降权实战

    12.13 控制Nginx并发连接数量

    12.14 控制客户端请求Nginx的速率

    12.15 小结

    第13章 游戏运维的思考

    13.1 游戏运维最关键的几件事13.1.1 安全

    13.1.2 稳定

    13.1.3 高效

    13.1.4 成本节约

    13.2 游戏运维人的发展

    13.3 小结

    第14章 数据库平台建设实战

    14.1 规范建立

    14.1.1 安装规范

    14.1.2 配置规范

    14.1.3 账号、权限规范

    14.1.4 目录规范

    14.1.5 其他规范

    14.2 架构设计

    14.2.1 架构图

    14.2.2 各个模块介绍

    14.3 功能介绍与实践

    14.3.1 操作部分

    14.3.2 日志部分

    14.3.3 资产部分

    14.3.4 信息展示14.3.5 入口(LVSRedir)

    14.4 后期功能展望

    14.5 小结

    附录A 求职者与面试官推荐序

    许式伟,七牛云CEO。曾就职于金山、百度、盛大,拥有超过15年

    的技术积累,连续8年组织ECUG实效云计算开发组年会。曾获国家科

    学技术进步奖二等奖。

    2011年,与吕桂华一起创立七牛云,现已服务50多万家企业。

    非常荣幸能受邀为本书作序。

    2011年我从盛大离职,创办了七牛云。

    在移动互联网时代,初创企业和巨头们之间的力量相差悬殊,这滋

    生了创业扶持产业的出现与兴起。所谓创业扶持产业,从技术革新上看

    就是“云”,云服务让所有的初创企业有了和巨头们一样的基础设施。

    很快,云服务的时代就在预期中到来了。很多人开始担心,自己的

    业务知识能否胜任“新运维”的需求。其实我想告诉大家,互联网中各类

    技术的革新总是很快的,无论你做哪一类工作,当跟不上技术发展的时

    候,就会面临被淘汰的危险。传统运维的革新是一个必然的过程,如果

    你对运维知识的了解一直停留在原地,那你离悬崖就不远了。

    云服务下的运维相较于传统服务器的模式,优势已相当明显。企业

    无需花费巨额的资金来购买新的服务器和托管机房的机位,就能够低成本、低风险地实现新增业务。同时,运维人员不再只能利用传统的网管

    手段来定位系统故障,他们可以通过云计算管理平台以及虚拟设备管理

    平台进行分析。

    此外,云服务的蓬勃发展也令互联网产业发生了巨变,互联网产业

    整体的蛋糕做大了,这使得其对运维的总体需求呈现上升的趋势。这对

    运维人员是一个非常好的机会,只要知识与能力满足了岗位需求,你的

    待遇和发展就能上一个台阶。

    作为云服务行业以及创业公司的代表,七牛云深谙创业的艰辛。我

    们反复说,七牛云的目标是打造一个场景化的PaaS(Platform-as-a-

    Service,平台即服务)平台,帮助开发者缩短从想法到产品的距离。我

    们打造了很多子产品,包括大数据、通用计算、云计算等。从我们发布

    产品的服务类型来看,第一类是对象存储服务,第二类是融合CDN服

    务,第三类是数据处理服务,第四类是直播云以及实时流网络LiveNet

    服务。

    《运维前线》这本书集合14位资深运维专家的实践经验,覆盖了互

    联网和传统行业运维的各个领域。其中所述的运维方法、技巧与实践,都和七牛云息息相关,这也正是我为本书作序的原因。

    这里我举两个例子:

    在本书第3章中讲到,动静分离的架构是基于Web开发的互联网服务中常见的架构的,它是指将数据库中的动态内容存储和文件存储分

    开,常见的做法是将动态内容存储在原有的数据库系统中,而将静态文

    件,如图片和音视频等,托管存储在七牛云提供的对象存储服务中,这

    样可以更方便地维护不同类型的数据。

    在本书第12章中讲到,CDN节点由于数量众多,承受的流量巨大,再加上国内网络的复杂度极高,因此真正商用CDN的建设有一定难度,并且硬件和运维成本都不低,因此一般而言,企业不会去自建CDN,而

    是选择七牛云这样的企业来解决问题。

    云服务的兴起改变了运维,而这种改变不会停止。

    云服务厂商可以将所有事情标准化,然后以服务的形式打包提供给

    客户。而运维人员将告别烦琐的工作内容,但是他们可能要承担更多的

    职责——解决监控、评估、采购、报修等问题。

    当然,你如果在云服务厂商做运维工作,便需要对传统运维有更深

    刻的理解了。前言

    为什么要写这本书

    《运维前线:一线运维专家的运维方法、技巧与实践》(以下简称

    《运维前线》)是前线系列的一个子集,前线系列图书的出版理念是邀

    请多位业界专家,总结所在行业的最新理念或深度实践经验。前线系列

    图书不同于市面上的很多图书,这类书并不系统,有的只是一线专家的

    实战经验,人们常称之为“干货”。一篇文章、一家公司、一个案例、一

    个场景,独立成篇,在满足碎片化阅读的同时,也能让读者进行横向比

    较和深入思考。本系列图书不强调大而全,追求的是每篇文章都是精

    品,希望能给读者带来深度的启发和收获。

    按照这个理念,之前著名产品经理兰军(笔名Blues)策划的《产

    品前线》,出版之后大获成功,随之而来的《运维前线》令我感觉到压

    力巨大。《运维前线》的出版犹如十月怀胎,中间充满波折,好几次我

    都以为要半途而废了,最后终于得以出版,在此要特别感谢机械工业出

    版社华章公司著名出版人杨福川,是他的坚持和鼓励让我总能在迷茫中

    看到希望。我和福川有共同的理念,希望把《运维前线》做成精品,如

    果有哪点不符合要求,那么我们宁愿耗时长一些,多打磨打磨,很庆幸

    能与福川一起合作。本书共有14位作者,包含了在腾讯、YY语音、UC、京东、盛大游

    戏、金山西山居、猎豹移动、广发银行、优维科技等多家公司工作的实

    践经验,基本覆盖了互联网和传统行业运维的各个领域,估计这是迄今

    为止第一本由这么多资深运维专家联合写成的图书,也是第一本分享了

    众多一线运维专家亲身实践的图书。本书的出版也充分体现了互联网开

    放合作的精神。

    看到本书的目录时,我激动不已,即使书中的内容我已经看了好多

    遍,但是在回顾目录的时候,我依然感到这是一本非常有吸引力的书,是一本每名运维工程师都应该案头常备的书!

    本书特色

    当前IT领域的概念层出不穷,云计算、物联网、移动互联网、大数

    据、人工智能、VR,所有的这一切都基于IT系统,IT系统正在向规模

    更大、更复杂、更高级的方向演进,一切IT资源都掌握在运维手里,通

    过运维来操作。这个时代对运维的要求越来越高,运维如果稍有不慎,就会造成重大的损失,所以随着IT系统的发展,运维的重要性也越来越

    高。

    根据量子力学理论,世界由基本粒子组成,因此世界是不连续的,这个理论在运维知识体系的建立上同样适用。仔细回想一下自己运维体

    系的建立,就是逐个攻克和掌握知识点,再进一步通过实践不断加深的过程。《运维前线》也是这样,其中的每一篇文章都能够协助读者更快

    地掌握一个或多个知识点,相信通过运维前线系列的逐步出版,最终能

    够覆盖更多的运维知识点,为读者带来更多的实践经验和理念。

    作为运维前线系列的第一本书,本书覆盖了运维自动化、系统运

    维、云及虚拟化、Web运维、游戏运维、DBA运维等6个方面14个知识

    点,都是各位作者总结自己多年实践经验的干货,每一篇文章都很精

    彩,都值得读者仔细品味。

    本书作者

    本书第1章“自动化运维之深度解码”,来自订阅号“互联网运维杂

    谈”的作者、优维科技创始人王津银,人称“老王”。我在多个场合听

    过“老王”的分享,有40分钟的,也有长达3个小时的,令我惊讶的

    是,“老王”每次总能带来新的东西。这篇“自动化运维之深度解码”也是

    如此,凝结了老王许多最新的见解,值得深读。

    胥峰是我在盛大游戏的前同事,从胥峰身上我学到了不少知识,比

    如解决问题的思路和方法,有时候碰到运维难题,也许换一个角度就能

    迎刃而解。

    刘宇、尹会生、陈立军是我多年的同事。刘宇、会生已经出版了多

    本运维图书,他们都是非常资深的运维专家。刘宇无论演讲还是文章都

    逻辑清晰,丝丝入扣。会生和立军分享的都是我亲眼所见的、在工作中碰到的难题及解决方法。

    张观石是欢聚时代(YY)互娱事业部业务运维负责人,有多年的

    将PHP运用到日常运维中的经验。观石将PHP用到了极致,即使不懂

    PHP,也可以通过本书一窥观石在运维方面的丰富经验。

    马亮有多年的游戏运维经验,目前在腾讯云专注做游戏云的架构设

    计,对游戏运维有深刻的理解。

    本书的作者还有冉宏元(老男孩)、余洪春(抚琴煮酒)、吴传

    玉、彭华盛、蒋迪、赵旻、赵海军。虽然我与他们未曾谋面,但是彼此

    都是熟悉的网友,他们的文章我都曾仔细拜读并多次请教过,其中的运

    维思想让我深深折服,非常期待能有机会向他们当面请教。

    读者对象

    本书面向所有的运维工程师,无论是资深运维,还是刚入行的运

    维,相信都能从本书中获益。本书的读者对象包括如下几类:

    ·系统运维工程师

    ·安全工程师

    ·数据库运维工程师

    ·业务运维工程师·网络运维工程师

    ·运维系统开发工程师及架构师

    ·云计算虚拟化运维工程师

    ·其他对运维感兴趣的读者

    勘误和支持

    由于作者的水平有限,编写时间比较仓促,书中难免会出现一些错

    误或不准确的地方,恳请读者批评指正。如果您有更多宝贵的意见,欢

    迎关注我的订阅号“云技术实践”,然后在后台将您的宝贵意见发送给

    我。本书的勘误也会通过订阅号进行发布,关注订阅号请扫描下面的二

    维码:

    “运维前线”是一个系列,欢迎在平时工作中积累了实战经验的广大运维工程师继续参与“运维前线”的写作,带来更多的干货分享!

    期待能够得到你们的真挚反馈,在运维之路上互勉共进。

    致谢

    从开始构思到《运维前线》的出版,本书的创作过程犹如十月怀

    胎,期间也获得了无数的支持与肯定。借此机会,向所有为此奉献力量

    的人表示深深的感谢。

    感谢参与本书写作的14位行业专家,他们在百忙之中伏案写作,将

    自己的经验共享给广大读者。能够和你们合作,我深感荣幸,经过将近

    一年时间的沟通和交流,你们的专业和执着深深地打动了我,同时也让

    我学到了不少东西。

    感谢机械工业出版社华章公司的首席策划杨福川,编辑高婧雅、孙

    海亮。在近一年的时间中,你们的敬业精神不断地鼓舞着我前进,你们

    的鼓励、帮助和坚持引导了本书的完成。

    这里,我还要特别感谢七牛云。七牛云是我见过的最具技术气质的

    云服务企业,肩负“帮助开发者缩短从想法到产品的距离”的使命,立志

    打造以数据为核心的场景化PaaS服务。七牛云主张技术共享并热衷于技

    术的传播,发起架构师实践日,推出各类创业扶持计划,这些都是七牛

    云正在做的事。特别致谢

    本书在成书过程中,得到了一批热心志愿者的协助,他们是陈家

    豪、曹学朋、邓荣兴、刘海文、李斯朗、韩海林,尤其刘海文做了大量

    的义务工作,在此特别感谢!

    肖力

    志愿者的话

    能在力哥组织的这本书中担任助理,我感到非常荣幸。本书出自一

    群经验老到并乐于分享的运维前辈之手,是一本案头必备的好书。

    刘海文第1章 自动化运维之深度解码

    作者简介

    王津银,2005年硕士毕业,参与电信BOSS系统研发两年。而后于

    2007年进入腾讯公司接触运维,经历服务器从百到万的运维历程,先后

    在YY和UC参与不同业务形态的运维,期间带过前端运维、数据存储运

    维、YY语音、游戏运维、运维研发等多种运维团队,对运维有着全面

    的理解。极力倡导互联网价值的运维理念,即面向用户的价值是由自动

    化平台来交付和传递,同时由数据化来提炼和衡量的。“精益运维”理论

    的创始人。个人微信公众号“互联网运维杂谈”(waynewang_ops),粉

    丝2.5万人,现创办优维科技公司,旨在缩短企业到达互联网运维的路

    径。

    自动化运维是一个人让人兴奋且容易失控的话题!兴奋是因为我想

    做一次尝试,把它的全貌和细节说清楚;容易失控是因为涉及点太多,一则怕遗漏,二则怕顾此失彼。带着这份复杂的心情,我们来一次自动

    化运维的解析之旅吧。说实话,一个运维团队的运维能力究竟如何,其

    实看一个自动化管理系统便可得知!1.1 概述

    作为开篇,首先让我们来熟悉一下运维全平台的规划体系吧,如图

    1-1所示。

    很多人看到这样一个架构图,可能会纳闷,难道对于一个小型企业

    来说,也要实施如此复杂的运维自动化体系吗?其实,对于不同规模的

    企业来说,对运维自动化的诉求的确是不同的。对于大规模企业,如

    BAT,这些能力基本上都是必不可少的;而对于小型互联网企业,比如

    说App开发公司,则核心的自动化诉求可能更多的是配置管理工具,比

    如说Puppet、SaltStack或Jenkins+Rsync等。

    图1-1 运维全平台规划体系我们不禁要问,有什么样的准则可以让我们作为依据来判断何时该

    如何导入自动化?应该导入自动化的哪些部分?当你需要持续、频繁地

    进行一些事情时,此时就需要引入自动化,比如说版本发布,如果这个

    时候你感觉到很痛苦,那么此时就需要引入自动化了。关于应该导入自

    动化的哪些部分,我个人的经验是根据角色去梳理他的工作现状(持

    续、频繁的工作),然后引入自动化的能力,再根据角色人数的多与少

    来确定事情的优先级,比如说系统管理和业务发布,很明显业务发布的

    优先级更高,因为它的自动化所带来的人力解放的收益更大。当然还有

    一种更理想的情况,那就是根据整体业务交付流来构建,以它的全流程

    自动化为目标,此时引入的是该交付链上所有的自动化能力,当然对于

    很多企业来说,这种自动化实现的代价很高,而得到的收益却很小。1.2 运维自动化的三重境界

    宋代禅宗大师青原行思(六祖门下首座)提出参禅的三重境界:

    参禅之初,看山是山,看水是水;

    禅有悟时,看山不是山,看水不是水;

    禅中彻悟,看山仍然山,看水仍然是水。

    这三重境界其实和我们眼中运维自动化的三重境界是类似的。

    运维自动化第一重境界:看山是山,看水是水。 开始接触运维自

    动化的时候,我们看到了很多工具认为它们就代表着自动化,比如说早

    期将Expect+SSH封装在一起之后,就认为可以实现批量运维了。看到有

    人说Puppet可以做配置管理,这个时候就会认为Puppet可以做配置管

    理,甚至是发布管理。这个时期的典型问题就是以偏概全,对于某个开

    源自动化工具来说,还没法去界定它的使用场景和范围,这样将直接影

    响系统的建设效益。这个时候才开始知道我们看到的山不是真正的山,而是迷雾环绕的深山。

    运维自动化第二重境界:看山不是山,看水不是水。 此时我们已

    经知道只有Expect+SSH还不够,随着业务规模的变化,我们还需要一个

    更完整的概念来做发布系统,真正的发布系统要做版本管理、环境管理、配置管理,还有生命周期管理等;配置管理工具想让自动化变得更

    加完美,其实还要依赖于OS和应用层的标准化规范,比如说应用交付

    规范、应用打包规范、OS的统一等等。对于其他资源对象的管理来

    说,生命周期的概念均穿行其中,比如说DNS、LVS、接口、配置、应

    用包等。为了有效地标识资源的生命周期状态,需要用大量的数据来实

    时反馈。这是运维自动化更具体的层面,将一个个的山貌都看清楚了。

    运维自动化第三重境界:看山还是山,看水还是水。这是一种自动

    化本质上的追究,站在高山之巅,俯览众山,会发出原来如此的感叹:

    所有自动化的本质都是为了可视化,让所有的人看到一致的服务,从而

    确保结果一致;从底层来说,你可以认为所有自动化的本质都是指令

    +文件分发的组合;你会进一步抽象系统的运维自动化能力,提供即插

    即用的机制;结合服务化的需求,进一步云化所有的运维系统,确保内

    外使用的一致性,最终自动化的平台就是一个整合的持续交付平台。这

    是化境!1.3 运维自动化的困境和价值

    1.3.1 运维自动化的困境

    谈到运维自动化的困境,我觉得要带着两大行业特点去看待这个问

    题,一个是互联网行业、另外一个就是传统行业。这两个行业面临的运

    维自动化的困境完全不同,普遍的共性是运维研发资源能力的不足。

    对于互联网行业,业务的发展速度很快,底层运维自动化能力可通

    过IaaS公有云来解决。在OS之上的运维自动化,则是通过一些开源工具

    来解决的,比如说Puppet、SaltStack、Ansible等。大部分都是以开源工

    具为主,开源产品的引入,也在不断加大维护的难度和复杂度,带来的

    另外一个问题就是平台可扩展的能力非常弱。所以一般成规模的互联网

    企业,最后都走向了自研的道路。不过有利于互联网行业运维平台建设

    的条件是互联网的基础比较标准,在硬件和软件的差异上不像传统企业

    那么大。

    对于传统行业,业务的互联网是瞬间展开的,另外传统的封闭式系

    统架构也走向了开放式x86架构,导致运维维护的基础设施对象和上层

    的业务对象提升了一个数量级。而传统企业的运维手段之前都依赖于商

    业产品和人肉运维等方式。无论是成规模的互联网企业还是传统企业,在业务的倒逼之下,运

    维的突破力都是不断向前的,但是这个整体的规划蓝图是什么样的、实

    施路径如何、需要什么样的方法论,则需要有一个全面的解答。1.3.2 运维自动化的价值

    谈到运维自动化的价值,运维人员应该很容易就能达成我所说的如

    下共识。

    首先是效率的提升、人力的解放,通过工具或平台来提升人均的运

    维效率和产出,比如说之前通过人肉发布一天只能发布10张单,现在通

    过工具,一天可以发布100张单。

    其次提升了产品的交付效率,提高了业务的竞争能力。快是制胜的

    法宝之一,如果你的产品推出得比对方更快,那么你就能更快地接触到

    用户或客户。

    还能提升产品的质量,通过工具不断去提高持续交付链上各角色的

    能力,比如说测试组的自动化测试、配置管理组的持续集成服务,等

    等,通过能力的整合,不断提高软件交付的质量;还有在发生故障的时

    候,能有更快的恢复手段来确保故障的恢复,也是质量保障的一部分。

    最后运维自动化的收益是成本的节省,一种是最直接的人力成本的

    节省,可以让更少的人做更多的事情;间接的成本受益是把很多运维经

    验固化成平台的经验,从而减少了整个交付链上的文档化内容的输出。1.4 运维自动化的多维解读

    1.4.1 基于应用变更场景的维度划分

    我们曾经探讨过,所有运维的价值导向最终都是面向业务、面向用

    户,所以自然而然就需要从业务的维度进行划分。而运维是有很多种场

    景的,但从业务的角度来说,核心的业务场景一般就包括如下5种:业

    务上线、业务下线、业务扩容、业务缩容和应用升级。下面将以其中一

    种场景为例,将整个流程穿起来看看,以此识别流程的节点到底对接了

    哪些系统?针对其他的业务场景,我们也可以用同类的方法进行分析。

    首先预设业务的架构如图1-2所示。图1-2 业务架构示例图

    (1)业务上线。 表示上线一个完整的应用。从无到有部署整个业

    务上线,具体的流程如图1-3所示。

    仔细看图1-3中所示的流程,我们会发现该流程涉及多个系统,每

    个系统所完成的职能又都有不同,这里只是大概地描述了一下。但一旦

    将这个流程清晰地梳理出来,我们就能知道真正地将一个应用全部上线

    到底有多复杂了。但看完图1-3又会觉得其实比较简单了,因为从业务

    上线的流程来看,我们只需要一个上层的流程调度引擎再加上对应的执行器,执行器通过API和底层的各个系统对接即可。这也是为什么之前

    在框架图(图1-2)中,要求各个专业系统一定要向上提供API,并且要

    求这个API的风格必须是一致的。图1-3 业务上线流程

    最复杂的业务上线流程梳理完成之后,业务下线 其实很简单,它

    是上线过程的逆过程,上线负责装,下线负责拆。

    业务上线之后,随着用户活跃度的上升,业务的容量逐渐会出现不

    足的情况,此时就需要进行业务扩容 。业务扩容其实很简单,当某类

    节点出现不足的时候,就对它进行扩容。业务扩容所要做的变更,其实

    都是业务上线的子流程。比如说如果Web层容量不够,那就申请机器,安装组件、下发应用包,进行自动化测试。这个时候需要注意的是:在

    业务上线的过程中,我们把很多的配置信息都下放到CMDB中了,因此

    我们在选择扩容的时候,就要从CMDB中把信息读取出来,以指导变

    更。

    应用升级 ,目前持续集成所讲的自动化都集中在这块。简单来

    讲,就是升级程序包、升级配置、执行额外的指令等,一般来说逃脱不

    了这几种模式。读者可能会问,如果正如你所说的这么简单,那么是不

    是将SSH封装成一个UI就可以了。当然不是,这个时候还需要你以对运

    维的理解,在底层进行一些标准化的工作,否则你提供的就只是一个工

    具,而完全没有运维的思路,比如说程序运行属主、运行路径、监控的

    策略等。另外建设应用发布平台的目的就是要让测试和生产环境的运维

    变得更可控。以上几个运维场景的自动化是否要一次性全部做完呢?当然不是,它们也是有先后和主次之分的。对于以上的运维场景,我在当前所负责

    的游戏运维中做过统计,数据如图1-4所示。

    图1-4 持续部署的数量

    (2)持续部署的数量 ,一个月2000次左右。

    (3)其他场景的分布情况 。一个月上线一次、下线两次、扩容一

    次左右。

    有了这个数据,我们在建设一个自动化系统的时候,就能意识到应

    该先做什么后做什么。当然,不同的企业有不同的实际情况,还是应该

    找到核心痛点,而不是一上来就建设完整的业务变更系统,那样不仅见效不快,且容易让项目收益不大,从而遇到很大的阻力。1.4.2 基于系统层次的维度划分

    首先来看下系统层次的维度划分,如图1-5所示。

    图1-5 基于系统层次的维度划分

    给出如图1-5所示的分层体系图,其实就是为了让大家更好地识别

    系统的职责和范围,下层干上层的活,或者上层干下层的活都是越界,越界将带来耦合的问题。举个例子,系统服务层由Puppet(或者Chef)

    配置管理,但网上的很多资料都说Puppet可以用来做发布,也就是说可

    以做应用服务层的事情。后来我看过几家用Puppet来做应用服务层发布

    的公司,最后都走不下去,因为应用包的需求变化太大,只靠Puppet编

    写factor的模式来适应所有的场景,基本上是不可能的,所以说Puppet适合的是系统服务层配置管理。以上所举的例子就是一种越界!1.4.3 基于与业务程序耦合紧密程度的维度划分

    基于与业务程序耦合紧密程度的维度划分,这点非常重要,这个划

    分其实是确定系统建设的Owner,从而避免让运维团队承担过多的系统

    建设职能,否则将会导致运维能力提升缓慢。那么应该如何判断与业务

    程序耦合的紧密程度呢?我的准则非常简单,线上程序直接调用的就是

    紧耦合,或者由研发主导的公共服务,类似于APISDK类的后端服务,应该由测试来主导系统建设;有些服务与程序不是直接关联的,或者是

    由运维牵头建设的,则由运维来主导,例如LVS、DNS服务等。

    有这样一种情况,在很多应用程序中,DNS和LVS服务也存在于程

    序调用链中,怎么办?在我的方案中,绝对不允许内部服务走DNS和

    LVS。我们都知道DNS和LVS的服务对于服务异常的处理(DNS无状

    态、LVS是七层能力弱),远远达不到线上服务的要求,所以要坚决拒

    绝。如果真的有人要使用DNS和LVS,那么第一告诉他们业务的风险;

    第二,发生故障的时候,需要让研发参与处理。另外这也是系统的边界

    没划分清楚的问题,是让运维组件去承担业务上应该具备的容灾容错功

    能,这会令后面的运维系统建设增加很多不必要的功能。1.4.4 面向服务的自动化能力划分

    运维最终是需要对外提供服务的,这些服务能力应该由很多底层的

    自动化平台来承载,个人对其能力划分如下,其实细分到每一层都将发

    现自动化无处不在,而服务化的能力其实是自动化平台的核心能力,能

    力划分具体如图1-6所示。

    图1-6 自动化平台

    1.运营能力层

    运营能力可体现IT运营价值,把IT的运营价值和业务场景紧密联系

    在一起,这些场景和之前所谈的运营价值体系(质量、成本、效率和安全)是一致的。在运维发展的不同阶段,IT系统的运营价值体现会有所

    不同,IT运营的核心方法是要有迭代式的思维 。

    对于很多企业来说,自动化提升效率是运维的第一个价值突破点;

    再往后,业务的高可用保证和成本控制,则是下一个价值方向;再之

    后,精细化运营的业务支撑则是更高的诉求,类似于质量要求(质量的

    概念非常宽泛)。越往后,越能凸显数据的价值,而非自动化工具的价

    值。因此我个人觉得在某一个阶段,自动化平台突破之后,主要的瓶颈

    将不是效率,而是数据化IT运营的能力。该能力在依赖平台的同时,更

    依赖于运维团队的业务理解能力和经验总结 。数据化运营能力是精细

    化的运营能力,是面向产品的,从底层的基础设施质量、到应用的访问

    体验、再到产品发布后的用户满意度,等等。

    这一层的能力表现为一个具体的产品形式+运营方法 ,从而可以

    确保能够很好地闭环起来。举个例子来说:基于资源容量管理的成本优

    化能力,首先需要一个贴合面向应用的容量分析模型,现实中一般是通

    过应用所消耗的资源(CPU、内存、IO、网络等)进行分析运算;其

    次是需要通过IT运营分析产品来呈现应用的容量水平(当前、历史

    等);基于可视化的数据呈现,建立相应的容量管理机制。这里又分为

    如下三点:

    (1)建立标准。低负载需要提升资源使用容量、高负载则需要扩

    容资源(降低资源使用容量)。(2)明确责任人和职责。确定容量管理的负责人,可以按照应用

    的粒度进行划分,同时还要明确这部分的管理要求,对于大规模服务来

    说,可以借用考核的工具来进行驱动。

    (3)结果驱动。通过定时的结果可视化来驱动容量管理的持续优

    化。

    2.平台能力层

    一个完整的运维平台应具有以下特点:

    ·其能力是集成的 ,而非离散的 ——平台需要提供很好的集成能

    力,让系统得到收敛,避免将系统分割成单个的执行单元,用户也会为

    此痛苦不堪。

    ·其能力是场景化的 ,而非基于功能需求的 ——场景能够串联工

    具。

    ·其能力是基于角色的 ,而非基于单一用户的 ——运维的角色能够

    清晰地定义场景需求,用户的需求往往是片面而不真实的需求。

    ·其能力是基于事务的 ,而非基于职能的 ——事务能够跨越职能

    组,让运维组织的自动化和数据能力流动起来。

    平台能力是指基于底层平台构建起来的具有的运维自动化数据化(监控+分析)安全的能力,这层能力实现了底层能力的组合与封

    装,屏蔽了底层各个专业子平台的实现细节,是面向业务运维场景的,比如说应用交付、资源交付、业务交付、持续反馈等。

    3.通用能力层

    通用能力层是基于基础设施之上封装的公共服务能力,这层架构的

    能力可分成两个部分:一部分是面向业务技术架构的,另一部分是面向

    运维服务架构的 。图1-6中所列的服务只是其中的一部分,这个也是我

    经常和交流者强调的能力建设的核心,不能把这个问题留给下面的资源

    能力层,也不能交给上层的平台能力层。

    对于线上技术架构来说,通用能力层将会涉及名字服务、负载均衡

    服务、分布式缓存、消息队列、分布式关系存储等,运维需要对其技术

    实现的工作人员要求API直接调用的服务能力。

    对于运维服务来说,通用能力层提供了资源服务、作业服务、部署

    服务、F5管理、GSLB等。这层的平台能力我一直将其理解成是PaaS平

    台的核心,有了它们其实就可以实现端到端的能力调度。

    该层服务能力平台可以很好地对上层平台进行积木式的支撑,同时

    还可以对底层设施层能力做服务化能力交付,脱离了资源交付的范畴。

    4.基础设施层基础设施层是资源交付层,对于一个运维系统来说,应该屏蔽底层

    基础设施的交付能力,无论是IaaS,还是物理层基础设施。尤其是对于

    一些IaaS云平台来说,更应该屏蔽IaaS底层实现的细节差异,通过API服

    务向上提供能力。国外早年就有了同类的产品,如RightScale,它很好

    地实现了多云管理的能力。1.5 运维自动化的方法论

    1.全局驱动

    无论是全部自动化管理平台的规划,还是某个平台的规划,都希望

    大家能够找到一个全局的立足点。比如说我们当时成立持续部署服务平

    台的时候,大家把全局的目标对齐于提高产品交付的速度和质量,开

    发、测试、运维很快就达成共识了。目前这个平台建设完成之后,运维

    已经从发布变更流程中彻底退出了,真正实现了让运维变成审核者。

    2.分而治之

    从上面的几个维度中可以看到有很多系统,如果每个系统都要建设

    的话,那么周期和难度都将很大。所以需要分而治之,特别是线上架构

    组件的管理系统,更需要随着组件的交付一并交付运维管理能力,比如

    面向组件的自动化管理能力、运维的监控能力、运维的数据分析能力

    等。之前我也表达过类似的观点,所有只交付组件,不交付管理能力的

    研发都是耍流氓。因为从运维的角度来说,这样低价值的交付产品越

    多,越会导致运维不堪重负。而如果让运维从头去构建这个管理,则他

    们需要花费很多的时间去了解,从而导致系统建设周期拉长。举个例

    子,比如说某个分布式cache服务,做得不好的,是通过读取日志然后

    对其进行监控;做得好的,是给你开启一个管理端口,让你从端口中读取状态信息。这就大大降低了系统的复杂度(不用进行日志采集和处理

    组件了)。

    分而治之,其实就是让不同的团队做不同的事情,不要将所有事情

    全部压给运维;其次不同的时期建设不同的系统,不要在同一时刻做很

    多系统,从而避免战线过长。当然如果有很多运维研发人员的话,就另

    当别论了。

    3.自底向上

    自底向上,其实是让大家找到一个更清晰更具体的系统建设目标来

    展开工作。从系统分解上,来让大家规避被一个庞大而模糊的目标带入

    歧途。如果一上来,我们就说要做一个全自动的运维管理系统,那样很

    容易就会让运维研发团队迷失方向。所以这里可以先设定全局和最终目

    标(全自动化),然后从底层逐步构建地基,做框架,最后再盖一个完

    整的房子,详见图1-1。

    4.边界清晰

    边界有两个维度,一个是管理边界;一个是职能边界。

    首先是管理边界,其是从Owner的角度出发的,谁产生服务,谁就

    是Owner,管理统一都是运维。比如研发提供了一个统一的分布式消息

    队列服务,那么Owner就是研发,他应该对可运维性负第一责任,不要让运维去承担这个服务的WebAdmin管理系统建设任务。

    其次是职能边界,深层次的理解是组件的功能范围。对运维架构师

    的考验也就在这儿,比如说让LVS去承担业务异常的容灾和容错切换是

    不合适的;让DNS跨过LVS层,负责后端服务异常的自动容错处理也是

    不合适的。如果不把职能界定清楚,将会导致系统做很多无用功,这会

    增加系统建设的复杂度。

    5.插件化

    插件化的思维无处不在,在面对纷繁复杂的管理对象时,我们进行

    抽象,提供管理模式,然后将具体的实现交给用户,这点在我们日常所

    见的运维系统中经常可以看到,比如说Nagios就是一种插件化的采集思

    路。对于配置管理来说,Puppet采用的也是这个思路。对于最上层的调

    度管理系统,可以让运维自己去编写执行器,特别是和业务紧密相关

    的,但最终运维整个控制权还是要交给平台。我的经验是,在应用服务

    层 和架构服务层 ,不要引入插件化的管理方案,过多的插件化部署,会让生产环境的管理最终混乱不堪,甚至失控。所以提供类SSH界面的

    运维发布和部署平台,是没有任何运维价值的。1.6 运维自动化系统的实现

    挑战自动化的极致场景(可视化),是运维人员对极致的追求。极

    致的自动化是运维事务全流程的自动化,运维事务全流程自动化是包含

    了一次应用完整交付所涉及的所有资源的自动化能力,比如说DNS资

    源、负载均衡资源、数据库资源、服务器资源、配置资源等。下面将列

    举几个典型的运维自动化系统以供大家参考。1.6.1 DNS管理系统

    DNS是Web形态下的一个重要入口,用户服务的访问严格依赖于这

    个服务入口。现在一般被称为GSLB(全局服务负载均衡调度),目前

    是CDN服务中的重要服务节点。实现的目标都是要解决运维从哪里来,到哪里去最快,当目标机房发生故障的时候,如何把服务调度走。

    在移动APP大量应用的今天,DNS协议的缺点已经逐渐暴露出来

    了,DNS解析时间长,另外还经常会被劫持。因为有端的控制,现在逐

    渐开始走HTTPDNS的服务,通过HTTP服务的方式获取域名对应的IP地

    址,此时由DNS平台直接对外提供HTTP服务。在有端App的情况下,还可以借助端的数据挖掘技术,识别非权威DNS域名是否存在被劫持的

    情况。系统需要保持和业务的与时俱进。

    这里还需要注意一个问题,内部DNS能否统一管理?理论上是可以

    的,把单个机房当作单个的view,不过我不建议将两个场景耦合在一

    起,尽管这样能够实现统一管理。

    系统Demo如图1-7所示。图1-7 DNS管理系统1.6.2 CMDB管理系统

    CMDB管理系统的建设这里就不展开介绍了,感兴趣的读者可以关

    注微信公众号“互联网运维杂谈”,并参阅《运维平台之CMDB系统建

    设》一文。

    系统Demo如图1-8所示。1.6.3 名字服务中心系统

    “名字服务中心系统”的概念最初来自于Zookeeper,该系统结合实际

    情况,实现了名字服务中心。把程序接口之间的调用抽象成单个服务之

    间的调用,在服务中心实现调度的统一注册、鉴权、ACL、容灾容错控

    制。将其看作线上服务最核心的系统,一点也不为过,并且它还是收益

    最大的系统,可直接替换掉DNS、LVS,降低线上系统对运维系统的依

    赖性。

    系统Demo如图1-9所示。图1-8 CMDB管理系统

    图1-9 名字服务中心系统1.6.4 持续部署管理系统

    持续部署是应用升级的核心系统,该系统每个月都承担着大量的变

    更。在系统规划之初,我们就给它设定了清晰的业务管理目标:持续交

    付的一部分,实现图1-10中的4个维度管理目标;也设定了具体业务的

    运维目标:升级所有的包和配置,且让业务运维彻底退出业务的变更流

    程。具体如图1-10所示。

    系统Demo如图1-11所示。

    持续部署系统是持续交付系统的核心(持续集成、持续测试、持续

    部署、持续反馈),它是产品发布到达生产环境的关键步骤。在这个平

    台的建设上,运维人员应该将它作为突破的第一个点。在该平台搭建完

    成之后,运维就可以从日常的部署事务中解放出来了。图1-10 持续部署管理系统示意图

    图1-11 发布系统1.6.5 运维调度管理系统

    运维调度平台又称为调度编排系统,编排是一种场景化的运维能力

    封装,是对复杂运维事务的封装。我们在平时的运维过程中能够看到很

    多复杂的运维场景,比如说容灾切换、故障处理、服务迁移等。这些场

    景,很多时候都不是单一的动作就能够完成的,往往需要借助多种运维

    能力组合,如图1-12所示。

    图1-12 运维调度管理系统示意图在图1-12中,我们把Ops自动化调度下面的服务支撑层分解为三部

    分:工具平台OpsStore,用来编写日常的运维工具;外部服务,用于公

    共API对外提供封装;Ops发布,用于提供代码持续部署服务。

    一个完整的自动化调度平台应具备能够对接一切服务的能力,例如

    通过配置管理来初始化内核、通过OpenStack来初始化资源、通过DNS

    来获取全局调度服务、通过存储来获取存储的服务,甚至还可以通过公

    有云API来获取外部公有云的资源服务能力,如图1-13所示。

    图1-13 自动化调度平台示意图

    还有数据库运维管理平台、分布式Cache管理系统等也都有相应的

    实现,由于篇幅所限,这里就不贴图介绍了。1.7 运维自动化系统的API参考实现

    所有的底层系统都是通过API对外提供服务的,API可供各个系统

    使用。接口的使用需要通过授权来获得,建议这个授权可以是基于系统

    级别的,也可以是接口级别的,而不是采用统一开放的模式。另外接口

    内需要有相应的一些权限控制,以避免底层服务被任意操作。

    可以仿照AWS的接口实现方式,统一实现API的接口开放访问地

    址,同时统一协议(HTTP、HTTPS),协议可以使用Get的方式进行访

    问。图1-14所示是一个开放API的结构。

    图1-14 开放API的结构1.8 运维自动化依赖的团队模型

    下面将从能力模型、驱动模型和技能模型三个角度来阐述运维团队

    和个人的能力要求,最后给出一个参考的组织结构。1.8.1 团队的能力模型

    具体的团队能力模型示意图如图1-15所示。

    图1-15 团队能力模型

    对于我带过的应用运维团队,我都会从如上三个方面对组员提出运

    维能力要求。

    1)业务运维。 因为对这块能力的要求越来越低,因此其在我们的

    考核体系中所占的比重也越来越低。日常的变更、扩容、故障定位、运

    维规划对人的能力要求都非常低,这些工作都能模式化且平台化,从而

    减少了对人的倚重。2)运维研发。 我希望每一个应用运维人员都有运维研发的能力,但这在现实中是不可能的。对于应用运维团队和运维部门来说,运维研

    发的配备必不可少。在应用运维团队的内部,可以让有研发能力的人迅

    速承担面向业务运维平台的建设,或者参与到部门的运维系统建设中,可以抽出50%的时间参与研发。运维研发能力是能够让团队价值迅速达

    成的有效保证,没有研发能力的运维不能成为一个好运维。

    3)技术研究。 运维是一个技术团队,需要通过技术来体现价值,当找到好的技术时就要想着如何将技术应用到业务上,为用户带来价

    值,比如说提升用户体验,减少成本等。

    这个时候就会产生一个问题,应用运维团队内的人也会运维研发,同时又有专职的运维研发团队,那么他们的职责分工如何解决,在工作

    上是否会存在重复建设?我的回答是这样的:

    首先,可以把运维研发初期定位在公共服务平台的研发上,比如说

    DNS、LVS、配置管理、监控系统、CMDB、数据分析平台等。

    其次,运维研发还需要制定相应的运维研发规范,代码规范、UI规

    范、测试规范等,让所有参与运维研发的人统一遵守,包括应用运维研

    发的组员。

    最后来说一下应用运维小组内的研发能力该如何发挥的问题。其实

    在很多运维团队中,运维都是跟随业务的,一则可以让应用运维研发人员开发面向业务的运维系统,因为他们最了解该业务的需求,能够实现

    自己想要的;另外一种更好的操作方式,是让应用运维小组内的研发人

    员抽出50%的时间参与到以运维研发牵头成立的虚拟研发小组中。一则

    可以进一步提高应用运维的研发水平;另外还可以提高运维研发对业务

    运维的理解,同时还能提高带队作战的能力。

    那么,运维研发和应用运维的比例应该设置成多少比较合适?我个

    人认为3:1比较合适,大家也可以自检一下,自己的运维团队到底设置

    了多少运维研发人员?另外想要检测运维研发配备是否足够,可以周期

    性地看看运维团队取得的进步,特别是效率和质量等维度。

    一个高性能的运维团队一定是以应用运维和运维研发为核心构建

    的!1.8.2 团队的驱动模型

    具体的团队驱动模型如图1-16所示。

    图1-16 团队驱动模型

    团队的驱动力不同,带来结果的就会完全不同。为什么很多运维人

    员都说自己很辛苦?这时你可以思考一下到底是什么在引导着你进行运

    维工作?传统的维护,往往都集中在第一阶段和第二阶段,而进入到高

    阶运维体系之后,我们需要迅速切换到价值驱动和用户驱动的维度上

    来。有了用户驱动和价值驱动,对运维的效率和质量就都会有更高的要

    求,对于外部驱动我们必须走自动化和平台这条道路。建议大家在平时

    的工作中加入质量、效率、成本等一些KPI要求,不要只局限于自己所

    做的事情,而是要关注自己所做的事情对产品和用户的影响。1.8.3 团队的技能模型

    BAT(百度、阿里、腾讯)很早就实施了职业通道体系,在运维侧

    细分了多个能力通道,比如说网络运维、业务运维、运维研发、DBA

    等。对于运维人员的成长也有明确的要求和衡量体系,在此我就不详细

    介绍了。1.8.4 参考的运维团队组织结构

    我们不一定要按照这个结构明确设置运维小组,但是运维的职能差

    不多就是这样。我还有另外一个建议,最好将公共服务研发团队和运维

    团队放在一个组织结构下,这样将会有利于公共化服务的推广,而公共

    化服务对运维效率的影响是最大的,如图1-17所示。

    图1-17 运维团队组织结构

    至此,自动化平台的深度解码已经完成。本章从多个层面带领大家

    了解运维自动化,其实还是希望能给大家带来一点借鉴意义。大胆地往

    前走吧,一切都有可能,唯独那些实现不了的,都是我们人的问题,无它。1.9 小结

    无论是传统企业还是中小型互联网公司,运维自动化都是当前运维

    阶段的核心能力。实现了运维自动化,传统的人肉运维状况才会被改

    变,才会有更多的精力去思考更大的运维价值。在建设运维自动化平台

    的过程中,对运维自动化的需求进行清晰的识别、界定、规划和落地是

    很考验运维研发者能力的事情,本章从整体规划入手,给出了一些具体

    的方法论,同时还给出了几个实现的例子,目的是帮助大家看到一条清

    晰的建设路径。第2章 利用Facter和Django快速构建CMDB

    作者简介

    陈立军,金山西山居DevOps,原新浪研发系统开发。

    刘宇,网名守住每一天,金山西山居架构师,《Puppet实战》一书

    作者,《Puppet实战手册》译者之一,《Python高级进阶》译者之一,InfoQ社区编辑,自动化运维专家。

    CMDB(Configuration Management Database),又称配置管理数据

    库,更多的时候我们习惯将其称为资产管理系统。它既是ITIL标准体系

    的核心,又是运维的基础核心系统。它通常位于整个运维自动架构的底

    层,但在运维自动化体系中,它又起到了极其关键性的作用。据我个人

    了解目前很多中小型企业,乃至一些中大型互联网公司,都还在采用传

    统的Excel来管理资产。

    采用Excel维护资产时,需要耗费大量的人力和精力,这些工作包

    括:数据的采集、整合、记录、维护、检验和更新,每一项都比较繁

    琐。而采用开源CMDB系统却又不够灵活,无法和公司的其他系统相结

    合。面对这些问题,自行研发一套适用于公司的CMDB系统,是当务之

    急。本章将会详细讲解,如何利用开源软件Facter和Django快速构建一

    个小型的CMDB系统。界面与功能不算复杂,这也是它轻量的体现,本

    章更多的是提供一种思路,以达到抛砖引玉的作用,仅供大家参考。

    说明

    本章的所有代码都托管在Github网站

    上https:github.comoysterclubopen-cmdb 。其中脚本集中在CMDB目录

    中。2.1 CMDB简介

    CMDB用于存储和管理企业IT架构中各种设备的配置信息,其中包

    括主机、项目、用户、机房、网络等。其被认为是ITIL服务管理的核

    心,所有流程所需要使用的配置信息都将通过CMDB来进行获取,例如

    监控、Dashboard、自动化、流程等。CMDB在企业IT架构中的核心地

    位如图2-1所示。

    图2-1 CMDB的核心地位

    CMDB特性如下:

    ·设备信息统一化、标准化。·设备信息可维护性更强。

    ·设备信息关系清晰化、可视化。

    ·设备信息的查询、更新更快。

    当然,在实际生产中,会对上述特性和涵盖范围有轻重大小的区

    分,为了能够更加合理、更加准确地设计出适合自有业务模式的

    CMDB,下面我们来看下几大主流开源CMDB是如何设计的。2.2 开源CMDB介绍

    目前主流的开源CMDB软件包括:OneCMDB、CMDBuild、Itop

    CMDB、Rapid OSS、ECDB、i-doit等,其中比较出名的是前二者,因

    此本节将重点对比这两款开源软件。2.2.1 OneCMDB介绍

    OneCMDB主要面向的是中小型企业。可以作为一个独立的CMDB

    来保持软件和硬件资产及其相互关系的轨道。由于其具有开放的API,因此其也可以是拥有灵活的强大的配置管理引擎的其他服务管理软件。

    OneCMDB易于安装和填充数据,它有一个无需用户具有编程能力

    就能改变和增强的数据模型,它能让用户轻松做到如下几点:

    ·创建CMDB数据模型,而无需写代码。

    ·填充数据,可以通过网络自动发现。

    ·通过各种灵活的导入和转换机制来从外部源获取信息。

    ·导入导出网络配置信息从到Nagios网络监控系统。

    OneCMDB也有如下一些缺点:

    ·纯英文操作界面,增加了误操作率。

    ·只支持从Nagios系统自动发现导入。

    ·现在该产品基本无人维护。·UI可定制化低。

    官网地址http:www.onecmdb.org ,纯英文操作界面,官网wiki上

    的截图如图2-2所示。

    图2-2 OneCMDB操作界面2.2.2 CMDBuild介绍

    CMDBuild是一个通过Web界面配置的CMDB系统。可以通过Web

    界面来进行建模、创建资产数据库,并处理相关的工作流程。

    CMDBuild可用于集中管理数据库模块和外部应用:自动库存、文

    档管理、文本处理、目录服务、电子邮件、监控系统、用户网站、其他

    信息系统等。

    官网地址http:www.cmdbuild.org ,也是纯英文操作界面,截图如

    图2-3所示。图2-3 CMDBuild操作界面

    CMDBuild应该是使用者比较多的一款产品,它具有如下优点:

    ·Ajax操作十分便捷(采用了ExtJS作为支持)。

    ·数据格式自由定制(在GLPI中,资产的数据格式都已经定义好

    了,用户很难再做修改)。

    ·支持多种开源标准(XPDL)。

    ·可以自定义Workflow,便于ITIL。

    ·有专门的团队在不断进行维护,截至本章写作时,最新版本为于

    2016年6月16日更新的2.4.1版本。·SOAP和REST的WebService接口。

    要说其缺点也就只有一条让人望而却步:文档少、资料极少。2.2.3 其他的开源CMDB

    随着开源潮流的发展壮大,开源的CMDB也越来越多,比如Itop

    CMDB、Rapid OSS、ECDB、i-doit等。然而这些开源的样式长得都差

    不多。最大的弊端在于不能有效地与其他系统友好结合。如果只是单纯

    地进行统计使用,也未尝不是一种选择。有时,现有的开源工具和系统

    不能满足业务发展的需求,我们就需要修改或完全自行编写一个符合业

    务需求的工具或系统,即“造轮子”。

    自己造轮子有如下几个优点。

    ·需求:满足公司内部的各种需求。

    ·可控:自行控制。

    ·体验:增加联动性,打通各个流程。

    ·提升:提升个人开发水平。2.3 Puppet及Facter介绍

    本节所要讲的不是重复造轮子,而是如何有效地利用开源工具构建

    自己的平台。首先我们来看看CMDBuild操作界面,如图2-4所示。

    图2-4 CMDBuild操作界面

    从图2-4中可以看出,CMDB的信息收集可以是多种多样、共融共

    存的:

    (1)通过一些Agent客户端收集信息,然后注册到中心服务器数据库。

    (2)通过监控系统收集,比如Zabbix、Nagios、IPMI等。

    (3)通过配置管理工具收集,比Puppet、SaltStack、Ansible等。

    我在本文中使用配置管理工具Puppet的Facts来进行信息收集,最主

    要的原因是,目前我使用的是Puppet来管理所有的机器,因此使用Facts

    最方便、简单、快捷,成本低而且效率高,如果读者使用的是Ansible或

    其他配置管理工具来做管理,本文中所介绍的方法也可以通用。2.3.1 什么是Puppet

    通常定义:Puppet是一个跨平台的集中化配置管理系统,它使用自

    身的描述语言,可管理配置文件、用户、Cron、软件包、系统服务等,Puppet把这些统称为“资源”。Puppet设计的目标就是简化对这些资源的

    安装、配置、管理,以及妥善处理资源之间的依赖关系。2.3.2 为什么是Puppet

    Puppet能够帮助系统管理员方便、快速地管理所有机器,目前

    Puppet已经能够支持所有的客户端,主流的有RedHat、CentOS、Gentoo、Debian、Ubuntu、Solaris、SuSe、Mac OS X、FreeBSD、OpenBSD、Windows,等等。

    支持的资源众多:目前Puppet支持的资源有很多,其中常用的包括

    File、Package、Exec、Service、Group、Host、Router、Yumrepo、User、Cron、SSHKey等,更多的相关信息和使用方法可以参

    考https:docs.puppetlabs.comreferenceslatesttype.html 。

    第三方模块众多:目前Puppet的第三方模块众多,基本包含了我们

    所能使用的全部软件模块,例如Mysql、Django、Java、PHP、Nginx、Apche、Openstack、SSH、Tomcat、Jboss、Yum等。2.3.3 什么是Facter

    Facter是Puppet跨平台的系统性能分析库。它能发现并报告每个节

    点的信息,在Puppet代码中是以变量的形式出现的。它返回的是每个

    Agent的fact信息,这些信息包括主机名、IP地址、操作系统、内存大小

    及其他的系统配置选项,这些fact信息在Puppet Agent运行的时候进行收

    集并传递给Master,同时被自动创建为可以被Puppet使用的变量。2.3.4 Facter的特点

    Facter最大的作用就是收集服务器系统信息,包括主机名、IP地

    址、操作系统、内存大小及其他的系统配置选项。这些系统配置选项正

    是CMDB所需要的基础核心数据。

    我们先来看看Facter收集的系统数据,下面将列举一些常用的系统

    数据,具体信息如下。

    (1)Facter获取fqdn信息,在Facter中fqdn=hostname+domain:

    facter fqdn

    puppet.domain.com

    (2)Facter获取IP地址:

    facter ipaddress

    10.20.122.100

    (3)Facter获取MAC地址:

    facter macaddress

    00:1A:4A:25:E2:10

    (4)Facter获取空闲内存大小:

    facter memoryfree1.61G

    (5)Facter获取内存大小:

    facter memorysize

    1.83G

    (6)Facter获取操作系统:

    facter operatingsystem

    CentOS

    (7)Facter获取CPU信息:

    facter processors

    {models=>[Intel Core 2 Duo P9xxx (Penryn Class Core 2), Intel Core 2 Duo P9xxx (Penryn Class Core 2)], physicalcount=>2, count=>2}

    (8)Facter获取机器运行时间:

    facter uptime

    1 day2.3.5 Facter变量

    Facter目前的最新版本为3.4.1(截至本章写作时),支持的变量有

    131个,所支持的变量可以在官方网站

    http:docs.puppetlabs.comfacterlatestcore_facts.html 中查看。Facter所支

    持的变量可以按使用频率简单划分为常用类型和不常用类型,具体如图

    2-5所示。

    图2-5 Facter变量分类图2.4 如何利用Python获取Facts

    2.4.1 工作原理

    通过2.3节的学习可以知道Facts可以获取主机的系统信息,并以K-V

    形式进行存储,我们只需要处理Puppet Server收集的Agent Facts信息、入库,然后通过Django来读取数据库信息即可,如图2-6所示。

    图2-6 Facts信息获取流程图2.4.2 利用Python脚本获取Facts

    首先要确定系统中已经安装了Puppet,如果没有,可以从

    http:yum.puppetlabs.com 下载,并参

    考https:docs.puppetlabs.compuppetlatestreferenceinstall_pre.html 进行

    安装,接下来看看如何通过Python程序来获取Facts信息(注意:下面的

    程序是查看当前机器的fact信息,下面的这个程序对结果不会做过多的

    处理,在后面进行CMDB项目的时候将详细讲解fact的数据处理),实

    例程序facter_message.py的内容如下:

    !usrbinpython

    encoding: utf-8

    __authors__ = ['LiuYu']

    __version__ = 1.0

    __date__ = '2015-08-19 14:34:44'

    __licence__ = 'GPL licence'

    导入模块

    import commands

    import re

    定义一个变量

    command = 'facter'

    定义要打印的列表

    show_list = [('fqdn', u'主机名

    '),('domain', u'域名

    '),('uptime', u'运行时间

    '),('operatingsystem', u'系统

    '),('kernelrelease', u'内核版本'),('ipaddress', u'IP'),('macaddress', u'MAC'),('memorysize_mb', u'内存

    MB'),('processors', u'CPU'),('blockdevices', u'磁盘

    '),]

    定义一个处理命令的函数

    def handle_command_message(command):

    status, content = commands.getstatusoutput(command)

    if status == 0:

    return content

    else:

    return

    通过函数处理名称,然后打印结果

    if __name__ == '__main__':

    result_dict = {}

    result = handle_command_message(command)

    if result:

    for line in result.strip.split('\n'):

    if re.findall('=>', line):

    key, value = line.split('=>', 1)

    result_dict[key.strip] = value.strip

    for f_k, f_s in show_list:

    if f_k in result_dict:

    print f_s, ':', result_dict[f_k]

    下面我们来运行facter_message.py程序,打印结果:

    python facter_message.py主机名

    : puppetclient.domain.com域名

    : domain.com运行时间

    : 1 day系统

    : CentOS内核版本

    : 2.6.32-431.1.2.0.1.el6.x86_64

    IP: 10.20.122.111

    MAC : 00:22:E2:5E:4D:10内存

    MB : 996.48

    CPU : {count=>1, models=>[QEMU Virtual CPU version 1.1.2], 磁盘

    : sr0,vda,vdb,vdc通过如上的简单代码就可以将Facts的信息进行集中处理。2.5 使用Django快速构建CMDB系统

    2.5.1 Django介绍

    Django是一个免费的、开源的Web框架,由Python语言编写,由于

    其是在一个快节奏的新闻编译室环境中开发出来的,因此它的设计目的

    是让普通开发者的工作变得简单。Django遵循模型-视图-控制器

    (MVC)框架模式,目前由一个非盈利的独立组织的软件基金会

    (DSF)维持。

    Django鼓励快速开发和干净实用的设计。Django可以更容易更快速

    地构建更好的Web应用程序。它是由经验丰富的开发人员来创建的,省

    去了Web开发的很多麻烦,因此你可以专注地开发应用程序而不需要去

    白费力气地重复工作。

    Django目前已经被运维圈广泛使用,本文在此不会详细介绍Django

    的基础知识,有兴趣的朋友可以去Django官网查看更为详细的介绍,同

    时也有Django中文文档可供学习。2.5.2 Django安装

    Django的安装分为4个步骤,下面以Django 1.7.1、CentOS 6.5

    x86_64为例进行讲解,详细步骤如下。

    1.安装Python 2.7.x

    用CentOS 7以下版本的朋友需要将Python升级到2.7.x以上,Django

    对Python版本存在依赖,具体如图2-7所示。

    图2-7 Django与Python版本的依赖关系

    编译步骤如下:

    yum install -y zlib-dev openssl-devel sqlite-devel bzip2-devel

    wget http:www.python.orgftppython2.7.6Python-2.7.6.tgz

    tar zxf Python-2.7.6.tgz

    cd Python-2.7.6

    .configure --prefix=usrlocal

    make make altinstall(1)安装easy_install工具,操作命令如下:

    wget https:bootstrap.pypa.ioez_setup.py -O -| python

    (2)安装Django,使用easy_install来安装,安装的版本为1.7.1,具

    体命令如下:

    easy_install django==1.7.1

    (3)测试Django的安装,操作命令如下:

    easy_install django==1.7.1

    django-admin –

    version

    1.7.1

    2.MySQL安装

    本文推荐使用yum命令进行安装,并设置MySQL root密码,创建

    cmdbtest数据库,具体安装步骤如下:

    yum -y install mysql mysql-server

    mysql_install_db --user=mysql

    etcinit.dmysqld start

    mysqladmin -u root password 'cmdbtest'

    mysql -u root -pcmdbtest -e 'create database if not exists cmdbtest'2.5.3 Django常用命令

    完成Django的安装后,可以通过如下命令快速熟悉Django的操作,以便快速创建一个CMDB App,如果你对如下这些Django命令很熟悉,可以直接跳过。

    (1)新建一个django-project:

    django-admin startproject project-name

    (2)新建App:

    django-admin startapp app-name

    (3)同步数据库:

    python manage.py syncdb

    (4)启动Django服务器:

    python manage.py runserver

    (5)Django Shell调试:

    python manage.py shell(6)帮助:

    django-admin --help

    python manage.py --help2.5.4 Django的配置

    1.环境准备

    笔者准备了两台测试机器用来进行代码测试,测试机器的环境信息

    分别如下。

    (1)服务端机器信息:

    IP: 10.20.122.100

    Role: puppet server + cmdb

    System OS: CentOS release 6.5 x86_64

    Python version: 2.7.8 Django version: 1.7.1

    Mysql version: 5.1.73

    (2)客户端机器信息:

    IP: 10.20.122.111

    Role: puppet agent

    System OS: CentOS release 6.5 x86_64

    2.软件安装

    前几节已经对所需要的环境进行了安装,在这里我们再回顾一下:

    (1)master安装Puppet Server。

    (2)master安装Python。(3)master安装MySQL。

    (4)master安装Django。

    (5)master安装项目依赖的Python模块。

    (6)Agent安装Puppet Agent。

    3.创建CMDB项目

    创建CMDB项目的同时,在这个项目中创建一个CMDB App,登录

    10.20.122.100,运行如下命令。

    (1)创建一个Project:

    django-admin startproject myproject

    (2)进入myproject目录:

    cd myproject

    (3)创建一个CMDB App:

    django-admin startapp cmdb

    (4)创建一个存放静态文件和模板的目录: mkdir static templates

    运行成功后使用11命令就可以看到如图2-8所示的目录结构。

    4.配置CMDB项目信息

    在图2-8中我们可以在myproject目录下看到settings.py的全局配置文

    件,Django在运行时会默认先加载此配置文件,因此我们需要先对它进

    行定义,需要配置如下6个地方,操作步骤具体如下。

    图2-8 Django安装后的目录组织结构

    (1)修改数据库设置:

    DATABASES = {

    'default': { 'ENGINE': 'django.db.backends.mysql','NAME': 'cmdbtest','HOST': 'localhost','USER': 'root','PASSWORD': 'cmdbtest','PORT': '3306','OPTIONS': {'init_command': 'SET storage_engine=INNODB', 'charset': 'utf8', }

    } }

    (2)设置App,把我们新建的CMDB App加到末尾,代码如下:

    NSTALLED_APPS = ('django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles', 'cmdb',)

    (3)设置静态文件存放目录:

    STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), )

    (4)设置模板文件存放目录:

    TEMPLATE_DIRS = [ os.path.join(BASE_DIR, 'templates'), ]

    (5)设置登录URL:

    LOGIN_URL = 'cmdblogin'

    (6)设置其他参数,可以根据自己的需求进行设置:

    TEMPLATE_CONTEXT_PROCESSORS = ( 'django.core.context_processors.static', 'cmdb.context_processors.menu', django.contrib.auth.context_processors.auth, django.core.context_processors.request,) CMDB_VERSION = '1.0' CMDB_NAME = u'测试

    CMDB' LOGIN_REDIRECT_URL = 'home'

    到此为止基础环境已经准备完毕,接下来需要设计数据库,并定义好视图。

    5.数据表设计

    Django遵循MVC设计,其中M(模型)就是数据库模型,也就是

    App中的models.py文件的设置,Django自带数据库的ORM(Object

    Relational Mapping)架构,这使得我们不用再需要学习复杂的数据库操

    作,只需要通过定义models即可。下面是我设置的最简单的CMDB数据

    结构:

    指定解析器为

    Python

    !usrbinenv python

    指定字符编码为

    utf8

    encoding:utf8

    从

    django.db中导入

    models模块

    from django.db import models

    导入

    User模块

    from django.contrib.auth.models import User

    Create your models here.

    定义一个

    Server_Group类,从

    models.Model中继承,这里就是所谓的数据表结构

    class Server_Group(models.Model):

    定义主机组名称字段

    name = models.CharField(u'主机组', max_length=255, unique=True)

    关联的项目字段,这里是关联一个外键

    project = models.ForeignKey(Project, verbose_name='项目名称

    ')

    备注字段

    memo = models.CharField(u'备注

    ', max_length=255, blank=True)

    unicode返回值

    def __unicode__(self):

    返回的格式

    return '%s-%s' % (self.project.name, self.name)

    定义

    Meta属性

    class Meta:

    数据库中的表名

    db_table = 'server_group'

    存储的时候需要确认组合键是唯一的

    unique_together = ((name, project),)

    定义一个

    IDC类,主要存储

    IDC信息,数据表结构有

    2个字段

    class IDC(models.Model):

    定义

    IDC的名称字段

    name = models.CharField(u'IDC名称

    ', max_length=255, unique=True)

    memo = models.CharField(u'备注

    ', max_length=255, blank=True)

    def __unicode__(self):

    return self.name

    class Meta:

    db_table = 'idc'

    定义一个Project类,主要存储项目信息,数据表结构有

    2个字段

    class Project(models.Model):

    name = models.CharField(u'项目名称

    ', max_length=255, unique=True)

    memo = models.CharField(u'备注

    ', max_length=255, blank=True)

    def __unicode__(self):

    return self.name

    class Meta:

    db_table = 'project'

    定义一个

    Server_Role类,主要存储服务器角色信息,数据表结构有

    3个字段

    class Server_Role(models.Model):

    name = models.CharField(u'角色

    ', max_length=255)

    关联

    Server_Group,也就是服务器组

    group = models.ForeignKey(Server_Group, verbose_name='项目组

    ')

    memo = models.CharField(u'备注

    ', max_length=255, blank=True)

    def __unicode__(self):

    return '%s-%s-%s' % (self.group.project.name, self.group.name, self.name)

    class Meta:

    设置数据库表名

    db_table = 'server_role'

    存储的时候需要确认组合键是唯一的

    unique_together = ((name, group),)

    CMDB核心数据表结构,用来存储服务器系统信息

    class Server_Device(models.Model):

    服务器状态选择,具体的字段存储数据为

    0~

    3的

    int数字 SERVER_STATUS = (

    (0, u'下线

    '),(1, u'在线

    '),(2, u'待上线

    '),(3, u'测试

    '),)

    定义一个名称字段

    ,若

    blank没有设置则默认为

    False,不能为空,且

    unique=True必须唯一

    name = models.CharField(u'主机名称

    ', max_length=100, unique=True)

    定义

    SN编号字段,blank=True,可以为空

    sn = models.CharField(u'SN号

    ', max_length=200, blank=True)

    公网

    IP字段,可以为空

    public_ip = models.CharField(u'外网

    IP', max_length=200, blank=True)

    私网

    IP字段,可以为空

    private_ip = models.CharField(u'内网

    IP', max_length=200, blank=True)

    定义

    MAC地址字段 mac = models.CharField(u'MAC地址

    ', max_length=200, blank=True)

    定义操作系统字段

    os = models.CharField(u'操作系统

    ', max_length=200, blank=True)

    定义磁盘信息字段

    disk = models.CharField(u'磁盘

    ', max_length=200, blank=True)

    定义内存信息字段

    mem = models.CharField(u'内存

    ', max_length=200, blank=True)

    定义

    CPU信息字段

    cpu = models.CharField(u'CPU', max_length=200, blank=True)

    关联

    IDC信息

    idc = models.ForeignKey(IDC, max_length=255, blank=True, null=True, verbose_

    name='机房名称

    ')

    定义一个多对多字段,一台服务器可以对应多个角色

    role = models.ManyToManyField(Server_Role, verbose_name='角色

    ', blank=True)

    机器状态,默认都为在线状态

    status = models.SmallIntegerField(verbose_name='机器状态

    ', choices=SERVER_STATUS,default=1)

    管理用户信息

    admin = models.ForeignKey('auth.User', verbose_name='管理员

    ', null=True, blank=True)

    定义备注字段

    memo = models.CharField(u'备注

    ', max_length=200, blank=True) def __unicode__(self):

    return self.name

    class Meta:

    db_table = 'server_device'

    初始化数据库,同时设置登录所需要的username和password,命令

    如下:

    python manage.py syncdb

    Operations to perform:

    Apply all migrations: admin, contenttypes, auth, sessions

    Running migrations:

    Applying contenttypes.0001_initial... OK

    Applying auth.0001_initial... OK

    Applying admin.0001_initial... OK

    Applying sessions.0001_initial... OK

    You have installed Django's auth system, and don't have any superusers defined.

    Would you like to create one now? (yesno): yes

    这里输入用户名

    Username (leave blank to use 'root'): admin

    Email address:

    这里输入密码

    Password:

    重复输入密码

    Password (again):

    Superuser created successfully.

    在命令行登录数据库,并查看数据库信息,就能看到如图2-9所示

    的内容,说明数据库已创建成功。图2-9 查看数据库是否已创建

    6.视图设置

    上文中我们已经成功设置了Django的M(Models,模型),下面我

    们来设置V(View,视图),如下代码是一个登出页面和一个home页面

    的View:

    encoding:utf8

    Create your views here.

    导入需要使用的模块

    from django.template import RequestContext

    from django.shortcuts import render_to_response

    from django.contrib.auth.decorators import login_required

    from django.contrib.auth.views import logout_then_login

    判断用户是否登录

    @login_required

    登出时的调用

    def logout_view(request):

    return logout_then_login(request)

    判断用户是否登录

    @login_required

    登录后调用

    home页所展示的页面,template为

    home.html

    def home(request):

    return render_to_response('home.html', locals, context_instance=RequestCo

    ntext(request))

    URL设置

    (这里直接使用了

    Django自带的

    login函数,所以不需要自己写

    login view): 设置字符编码

    encoding:utf8

    从

    urls中导入

    patterns、include、url模块

    from django.conf.urls import patterns, include, url

    从

    contrib中导入

    admin模块

    from django.contrib import admin

    从

    http中导入

    HttpResponseRedirect模块

    from django.http import HttpResponseRedirect

    设置前端访问的

    URL对应的后端视图

    urlpatterns = patterns('', url什么参数都不带时,直接重定向到

    login

    url(r'^', lambda x: HttpResponseRedirect('login')), 登出对应的视图为

    cmdb.views.logout_view

    url(r'^logout','cmdb.views.logout_view', name='cmdb_logout'), 登录对应的

    view为

    django.contrib.auth.views.login,对应的

    template为

    login.html

    url(r'^login','django.contrib.auth.views.login', {'template_

    name': 'login.html'},name='cmdb_login'), home页面,对应的

    view为

    cmdb.views.home

    url(r'^home', 'cmdb.views.home', name='home'),)

    通过如上定义,现在就启动Django服务,登录后即可看到如图2-10

    所示的界面。代码已托管至Github网站https:github.comoysterclubopen-

    cmdb ,有兴趣的朋友可以去复制下来查看、修改或使用。下面就来展

    示一下登录界面的效果图(注,前端框架为bootstrap)。

    图2-10 系统登录界面

    利用python manage.py syncdb命令输入的用户名和密码登录。登录

    后的页面为home空白页(见图2-11),具体如下(home空白页主要是为了以后做导向流页面或数据图表展示页面,这里先留空):

    图2-11 系统登录后的界面

    7.使用Python程序获取Facts数据

    通过如上定义,我们已经完成了视图、数据表结构的定义。而数据

    的来源既可以通过添加,也可以通过Facter工具来获取。下面我们就来

    讲讲如何自动获取Agent机器的系统数据(如果想要充分了解Facter工

    具,可以参考阅读《Puppet实战》的第9章“Facter介绍”)。Facter工具会

    在Puppet Agent与Puppet Master通信的时候把获取到的Agent主机系统信

    息和自己定义的Facts信息汇报给Puppet Master,生成一个hostname.yaml

    格式的文件,文件存放在varlibpuppetyamlfacts目录下,文件的格式

    如图2-12所示,其中的values数据:domain、ipaddress、macaddress等正

    是构建CMDB所需要的系统数据,因此我们可以通过一个Python程序来

    处理这些数据,并录入MySQL中,最终通过Django来实现前端展示。

    因此一个最简单的CMDB系统就构建完成了。图2-12 Facter上报至Puppet Master后的yaml部分信息

    我们先来具体看一下facter_message.py程序(Python程序处理Facter

    数据),完整代码如下:

    !usrbinenv python

    encoding: utf8

    __authors__ = ['liuyu', 'chenlijun']

    __version__ = 1.0

    __date__ = '2015-09-06 14:58:23'

    __licence__ = 'GPL licence'

    导入模块

    import yaml

    import os

    IPy主要用来判断

    IP类型,IPy.IP('ip').iptype

    import IPy

    yaml文件目录yaml_dir = 'varlibpuppetyamlfacts'

    结果集,结果集的格式

    {'cmdb_agent':}

    all_host_facter_message = {}

    结果列表

    result_list = ['name','SN','public_ip','private_ip','mac','os','disk','mem','cpu','idc','role','status','admin','memo']

    db对应的

    Facter字段

    ,需要获取其他的字段时可以一一对应

    list_field = {'name': 'fqdn','public_ip': 'ipaddress__interfaces','private_ip': 'ipaddress__interfaces','mac': 'macaddress__interfaces','os': ['operatingsystem', 'operatingsystemrelease', 'hardwaremodel'],'disk': 'blockdevice__blockdevices','mem': 'memorysize','cpu': ['processorcount', 'processor0']}

    ruby objectobjectconstruct

    def construct_ruby_object(loader, suffix, node):

    return loader.construct_yaml_map(node)

    def construct_ruby_sym(loader, node):

    return loader.construct_yaml_str(node)

    读取数据

    def yaml_file_handle(filename):

    stream = open(filename)

    mydata = yaml.load(stream)

    return mydata

    获取

    IP的类型

    def get_ip_type(ip):

    try:

    return IPy.IP(ip).iptype.lower

    except Exception, e:

    print e

    处理单个Agent的数据

    def handle_facter_message(data):

    定义一个结果字典,字段和

    db一样,处理完的结果和

    db中的一样

    result_dict = {}

    对结果进行处理

    for db_field in result_list:

    定义一个字段结果字符

    value = ''

    result_list中的字段是否存在于我们需要的

    Facter取值列表中,如果存在

    if db_field in list_field:

    facter_field = list_field[db_field]

    先判断

    facter_field的类型,然后进行处理

    if type(facter_field) == type([]):

    for tag in facter_field:

    if data.get(tag):

    value += data[tag] + ' '

    else:

    由于

    disk、IP等需要进一步处理,所以用了一个

    __来分隔,然后再进行处理

    field_tmp = facter_field.split(__)

    if len(field_tmp) == 2:

    if db_field == 'disk':

    for tag in data[field_tmp[1]].split(,):

    对磁盘进行处理

    , 由于磁盘的字段为

    blockdevice_type_size,所以需要单独进行处理

    f = field_tmp[0] + '_' + tag + '_' + 'size' if data.get(f):

    去除

    sr0 tag的字段

    if tag != 'sr0':

    结果字符串

    value += tag + ':' + str(int(data[f]) 1024

    1024 1024) + 'G' + ' '

    对外网

    IP进行处理

    elif db_field == 'public_ip':

    for tag in data[field_tmp[1]].split(,):

    f = field_tmp[0] + '_' + tag

    if data.get(f):

    去除

    lo tag的字段

    if tag != 'lo':

    if get_ip_type(data[f]) == 'public':

    结果字符串

    value += data[f] + ' '

    对内外

    IP进行处理

    elif db_field == 'private_ip':

    for tag in data[field_tmp[1]].split(,):

    f = field_tmp[0] + '_' + tag

    if data.get(f):

    去除

    lo tag的字段

    if tag != 'lo':

    if get_ip_type(data[f]) == 'private':

    结果字符串

    value += data[f] + ' '

    else:

    其他的字段直接就处理了

    for tag in data[field_tmp[1]].split(,):

    f = field_tmp[0] + '_' + tag

    if data.get(f):

    去除lo tag的字段

    if tag != 'lo':

    结果字符串

    value += tag + ':' + data[f] + ' '

    else:

    if data.get(facter_field):

    结果字符串

    value = data[facter_field]

    将结果添加到

    result列表中

    result_dict[db_field] = value.strip

    如果不存在

    else:

    result_dict[db_field] = ''

    返回结果字典

    return result_dict

    定义获取

    facter的函数

    def get_all_host_facter_message:

    由于

    Puppet的

    yaml文件是

    Ruby格式的,因此需要进行转换

    yaml.add_multi_constructor(u!rubyobject:, construct_ruby_object)

    yaml.add_constructor(u!rubysym, construct_ruby_sym)

    获取所有有

    Facter信息的主机文件名称

    for dirpath, dirnames, filenames in os.walk(yaml_dir):

    只需要处理

    yaml目录下以

    yaml结尾的文件

    if dirpath == yaml_dir:

    for file in filenames: file_name, file_ext = os.path.splitext(file)

    if file_ext == '.yaml':

    host_yaml_path = yaml_dir + '' + file

    得到

    yaml文件的内容

    , 字典形式

    host_yaml_result_dict = yaml_file_handle(host_yaml_path)

    对单个

    Agent的数据进行处理

    if host_yaml_result_dict:

    由于有

    key为

    facts,所以可以直接查找

    facts key的值

    if host_yaml_result_dict.has_key('facts'):

    data_dict = host_yaml_result_dict['facts']['values']

    没有的就直接取

    else:

    data_dict = host_yaml_result_dict['values']

    现在就可以对

    data进行处理,获取我们所需要的数据了

    result_dict = handle_facter_message(data_dict)

    all_host_facter_message[file_name] = result_dict

    返回我们最终的数据结果集

    return all_host_facter_message

    以上程序可以过滤Facter中我们想要得到的Agent数据,运行

    facter_message.py程序,结果输出如下:

    python facter_message.py

    {'puppetclient.domain.com':

    {'status': '','name': 'puppetclient.domain.com','mem': '1.83 GB','memo': '','idc': '','public_ip': '','admin': '','mac': 'eth0:00:1A:4A:25:E2:12 eth1:00:1A:4A:25:E2:13','role': '','private_ip': '10.20.122.111','disk': 'vda:20G vdb:30G','os': 'CentOS 6.5 x86_64','cpu': '2 Intel Core 2 Duo P9xxx (Penryn Class Core 2)','SN': ''}

    }

    到这里,我们能够看到facter_message.py得到的数据字段和

    models.py中数据结构的字段正好一样,下一步我们就可以直接将

    facter_message.py的数据导入到数据库中了,具体程序如下:

    检测用户是否登录

    @login_required

    定义一个

    views,用来处理导入信息

    def import_data(request, model):

    导入计数器

    import_num = 0

    查看

    model是否存在于定义的模板中

    if model in BASE_ADMIN:

    获取

    tag名称

    tag_name = BASE_ADMIN[model]['name']

    获取

    model名称

    model_name = BASE_ADMIN[model]['model']

    这里只处理

    server_device的导入信息 if model == 'server_device':

    server_device_data = get_all_host_facter_message

    进行数据入库处理

    for hostname, facter_message in server_device_data.items:

    主机名处理,判断

    facter_message中

    name key是否有值,if facter_message['name']:

    如果有值,name就使用该值

    name = facter_message['name']

    如果没有这个值

    else:

    就使用

    hostname

    name = hostname

    对于

    IDC信息、User信息、项目角色信息的处理都需要自己去写

    Facter插件,不

    写的都为空,然后进行处理

    IDC关联处理,如果

    facter_message中的

    idc key有值

    if facter_message['idc']:

    idc_name就为该值

    idc_name = facter_message['idc']

    同时处理该

    IDC信息是否存在于

    IDC表中,如果有则取出

    ID

    if IDC.objects.filter(name=idc_name):

    idc_id = IDC.objects.get(name=idc_name).id 如果没有

    ,则进行保存,然后取出

    ID

    else:

    idc_sql = IDC(name=idc_name)

    try:

    idc_sql.save

    取出

    ID

    idc_id = IDC.objects.get(name=idc_name).id

    except Exception, e:

    return e

    如果

    idc key没有值,则为

    None

    else:

    idc_id = None

    管理员信息关联处理,如果用户存在则关联,不存在则跳过

    if facter_message['admin']:

    admin_name = facter_message['admin']

    如果用户存在

    User表中则取

    ID,若没有则为空

    if User.objects.filter(username=admin_name):

    user_id = User.objects.get(username=admin_name).id

    else:

    user_id = None

    没有就为空

    else:

    user_id = None

    这里还有一个角色多对多关系的处理,由于这里没有定义机器角色,因此此处不处理

    角色信息

    判断主机是否存在于

    server_device表中,如果不存在则添加

    if not model_name.objects.filter(name=name):

    import_sql = model_name(name=name,sn=facter_message['sn'],public_ip=facter_message['public_ip'],private_ip=facter_message['private_ip'],mac=facter_message['mac'],idc=idc_id, os=facter_message['os'],disk=facter_message['disk'],mem=facter_message['mem'],cpu=facter_message['cpu'],admin=user_id,memo=facter_message['memo'],)

    try:

    保存

    import_sql.save

    except Exception, e:

    return e

    如果有了,则查询数据,若信息不对则更新

    elif not model_name.objects.filter(name=name,sn=facter_message['sn'],public_ip=facter_message['public_ip'],private_ip=facter_message['private_ip'],mac=facter_message['mac'],os=facter_message['os'],disk=facter_message['disk'],mem=facter_message['mem'],cpu=facter_message['cpu'],memo=facter_message['memo']):

    try:

    更新数据库

    model_name.objects.filter(name=name).update(sn=

    facter_message['sn'],public_ip=facter_message['public_ip'],private_ip=facter_message['private_ip'],mac=facter_message['mac'],os=facter_message['os'],disk=facter_message['disk'],mem=facter_message['mem'],cpu=facter_message['cpu'],memo=facter_message['memo'],)

    except Exception, e:

    return e

    如果有了,且信息

    ok,则跳过

    else:

    continue

    return HttpResponseRedirect('cmdb%sshow' % model)

    return render_to_response('all_data_show.html', locals, context_instance=RequestContext(request))

    重新登录CMDB之后的页面,有一个导入主机的按钮,点击导入主

    机按钮,就可以自动导入通过Facter获取的Agent主机信息了,如图2-13所示。

    我们还可以通过添加的方式来维护CMDB的内容,到目前为止我们

    已经完成了使用Python和Puppet来构建一个小型的、简单的CMDB系

    统。

    CMDB是需要我们定期进行维护和更新的,因此它还需要提供历史

    查看、API等更实用的功能,为此在2.6节中我们将介绍一下Django提供

    的几个好用的功能模块。

    图2-13 信息导入界面2.6 高级进阶

    2.6.1 历史查询功能

    操作历史,应该是管理系统必备的功能之一。Django-echelon就是

    一个很好的功能模块,该功能模块可以单独使用于任何的Django项目

    中,非常方便,接下来我们讲解如何将该功能添加到CMDB系统中,设

    置步骤具体如下。

    (1)修改settings.py设置。

    ①添加echelon APP:

    INSTALLED_APPS = (

    '......','echelon',)

    ②添加echelon中间件:

    MIDDLEWARE_CLASSES = (

    '......','echelon.middleware.EchelonMiddleware',)

    (2)修改urls.py设置:

    encoding:utf8from django.conf.urls import patterns, include, url

    urlpatterns = patterns('','......', 操作历史

    url(r'^cmdbchangelog', include('echelon.urls')),)

    (3)将echelon代码复制到Django项目的主目录中,将html代码复

    制到templates目录中。

    (4)刷新DB,创建数据表:

    python manage.py syncdb

    (5)把操作历史的URL信息添加到前端页面的导航栏中就可以了

    (配置cmdbcmdb_menu.py程序),具体操作如下:

    CMDB_TOP_MENU = [

    '......',导航名称、URL、图标、子导航信息

    [u'操作历史

    ', 'cmdbchangelog', 'time', []],]

    (6)启动Django服务,打开前端页面,然后点击操作历史,就可

    以看到用户的操作信息了(见图2-14),具体如下。图2-14 用户的操作信息

    以上代码都可以在open-cmdb库上找到源代码。2.6.2 API功能

    CMDB作为一个数据源中心,很多运维工具都会调用CMDB数据进

    行使用,因此API接口就非常有必要了,由于各个系统的需求不一样,从头到尾开发一套适用于各个系统的CMDB API也比较困难,那么有没

    有什么简单的方法呢?答案肯定是有,这里我推荐Django API利器

    Django REST framework。

    Django REST framework是一个非常强大、灵活的API构建工具,它

    能很容易、很快速地帮我们构建Web API。下面来讲解构建的过程,具

    体步骤如下。

    (1)安装Django REST framework。

    主要安装3个模块:djangorestframework、markdown、django-

    filter。具体代码如下:

    pip install djangorestframework

    pip install markdown

    pip install django-filter

    (2)配置settings.py:

    INSTALLED_APPS = (

    '......','rest_framework',)REST_FRAMEWORK = {

    Use Django's standard `django.contrib.auth` permissions, or allow read-only access for unauthenticated users.

    'DEFAULT_PERMISSION_CLASSES': [

    'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'

    ]

    }

    (3)设置urls.py:

    urlpatterns += patterns(

    '',url(r'^api', include(myproject.api.router.urls)),url(r'^api-auth', include('rest_framework.urls', namespace='rest_framework')),)

    (4)创建我们的CMDB API(根据models信息来创建,这里只附上

    一个简单的讲解,具体的内容请看源码):

    -- coding: utf-8 --

    导入

    cmdb.models模块

    import cmdb.models

    从

    rest_framework中导入模块

    from rest_framework import routers, serializers, viewsets

    给需要生成

    API的

    model定义一个数据序列

    Serializers define the API representation.

    class IDCSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:

    使用的

    model名称

    model = cmdb.models.IDC

    字段序列 fields = ('url', 'name', 'memo')

    定义视图

    class IDCViewSet(viewsets.ModelViewSet):

    查询所有数据,这个可以根据自己的需要来展示几个

    queryset = cmdb.models.IDC.objects.all

    序列化信息

    serializer_class = IDCSerializer

    配置路由注册,自动生成

    API URL

    Routers provide an easy way of automatically determining the URL conf.

    router = routers.DefaultRouter

    router.register(r'idcs', IDCViewSet)

    (5)配置导航栏信息:

    cmdb_menu.py CMDB_TOP_MENU = [ [u'API文档

    ', 'api', 'book', []], ]

    (6)启动Django服务,展示如下(图2-15)。

    图2-15 启动Django服务

    通过API文档,可以看到全部的API信息,如图2-16所示。图2-16 全部的API信息

    点击IDC的具体URL,就能看到展示的信息和用法,如图2-17所

    示。

    到这里CMDB API就完成了最基本的功能,后续还需要读者自己去

    调整页面和授权等。图2-17 展示的信息和用法2.6.3 数据表结构

    对于数据表结构,前面的定义是比较简单的,有兴趣的读者可以根

    据自己的实际需求去增加,这里仅列举一个简单的优化例子——IDC表

    优化。

    IDC表前面就一个IDC名称字段,这里将根据作者所在公司的需求

    来做优化,优化后的字段具体如下:

    class IDC(models.Model):

    机房名称字段

    name = models.CharField(u'机房名称

    ', max_length=200, unique=True)

    名称缩写

    short_name = models.CharField(u'名称缩写

    ', max_length=200, unique=True)

    机房地域

    zone = models.CharField(u'机房地域

    ', max_length=200, blank=True)

    机房地域缩写

    zone_short_name = models.CharField(u'地域缩写

    ', max_length=200, blank=True)

    机房地址

    address = models.CharField(u'机房地址

    ', max_length=200, blank=True)

    机柜

    U数unit_size = models.PositiveIntegerField(u'机柜

    U数

    ', default=42, help_text=机房每个机柜拥有

    Unit数目

    )

    机柜电数

    power_size = models.PositiveIntegerField(u'机柜电数

    ', default=12, help_text=机房每个机柜拥有电力

    (An)数目

    )

    INTERFACE_TYPE_CHOICES = (

    (0, '光纤

    '),(1, '普通

    '),(2, '其他

    '),)

    网络接入方式是光纤、普通还是其他

    interface_type = models.SmallIntegerField(

    '网络接入

    ', choices=INTERFACE_TYPE_CHOICES, default=0)

    机房所有设备的总带宽

    bandwidth_equipment = models.BigIntegerField(u'设备带宽

    ', default=0, help_text=设备带宽

    (Mbps))

    机房可用带宽

    bandwidth_usable = models.BigIntegerField(u'可用带宽

    ', default=0, help_text=可使用最大带宽

    (Mbps))

    物理接入带宽

    bandwidth_line = models.BigIntegerField(u'接入带宽

    ', default=0, help_text=物理接入带宽(Mbps))

    保底带宽

    bandwidth_min = models.BigIntegerField(u'保底带宽

    ', default=0, help_text=保底带宽

    (Mbps))

    报警阀值

    bandwidth_threshold = models.BigIntegerField(u'报警阈值

    ', default=0, help_text=报警阈值

    (Mbps))

    LINE_MODEL_CHOICES = (

    (0, '单线

    '),(1, '双线

    '),(2, 'BGP'),)

    机房线路类型是单线、双线还是

    BGP

    line_model = models.SmallIntegerField(

    '线路类型

    ', choices=LINE_MODEL_CHOICES, default=0)

    接入线路条数

    line_count = models.IntegerField(u'线路条数

    ', default=1, help_text=接入线路条数

    )

    是否冗余

    line_redundancy = models.BooleanField(是否冗余

    , default=False, help_text=接入线路是否冗余

    )

    是否限速,限速大小

    speed_limit = models.IntegerField(u'限速大小

    ', default=0, help_text=限速大小

    (Mbps, 0:不限速))

    CHARGE_TYPE_CHOICES = (

    (0, '峰值'),(1, '95值

    '),(2, '保底

    '),(3, '计时

    '),(4, '包月

    '),(5, '包年

    '),)

    计费模式

    charge_type = models.SmallIntegerField(

    '计费模式

    ', choices=CHARGE_TYPE_CHOICES, default=0)

    是否直连

    ISP

    isp_direct_link = models.BooleanField(是否直连

    ISP, default=False)

    所属运营商,这里需要再建立一个

    ISP的类

    isp = models.ForeignKey(ISP, verbose_name=运营商

    )

    联系人

    contact = models.ForeignKey(UserProfile, related_name=idc_contact, verbose_name=联系人

    , help_text=IDC机房联系人

    )

    IDC经理

    manager = models.ForeignKey(UserProfile, related_name=idc_manager, verbose_name=经理

    , help_text=IDC经理

    )

    值班人

    duty_officer = models.ForeignKey(UserProfile, related_name=duty_officer, verbose_name=

    , help_text=IDC机房值班联系人)

    IDC报障邮箱

    support_email = models.EmailField(u'报障邮箱

    ', help_text=IDC报障邮箱

    )

    公司联系人

    company_contact = models.ForeignKey(UserProfile, related_name=xsj_contact, verbose_name=

    , help_text=公司联系人

    )

    开通时间

    start_time = models.DateTimeField(u'开通时间

    ',auto_now_add=True)

    到期时间

    end_time = models.DateTimeField(u'到期时间

    ',default=datetime.datetime(2140, 1, 1, 0, 0, 1))

    memo = models.CharField(u'备注

    ', max_length=200, blank=True)

    def __unicode__(self):

    return self.name

    class Meta:

    db_table = 'idc'

    现在这个表结构就是一个复杂的数据表结构,通过修改

    base_admin.py就可以直接展示了。2.6.4 用户管理功能

    Django有一套自己的用户管理、用户组管理和权限管理,我们在初

    始化Django项目的时候,Django会默认创建User、Permission、Group这

    3个表及对应的关联关系表。

    本章所介绍的这套简单的CMDB系统,已经将展示、添加、编辑和

    删除都模块化了。通过模板构建用户管理也是一件很轻松的事情,只需

    要把Django自带的用户信息提取出来套用模板即可,具体步骤如下。

    (1)在cmdbbase_admin.py中设置。

    导入User模块:

    from django.contrib.auth.models import User

    'user': {

    model名称

    'model': User, form表单

    'form': User_CheckFrom,名称

    'name': u'用户管理

    ',是否可以导入信息

    'import': '', table展示字段

    'list_display': ['username','password', 'email', 'is_superuser', 'is_active', 'is_staff','groups','user_permissions'],编辑只读字段

    'readonly': ['username'],动作

    'action_list': [(u'编辑

    ', 'pencil', 'cmdbusermodify'),]

    },(2)把用户管理的URL信息添加到前端页面的导航栏中。(配置

    cmdbcmdb_menu.py程序),具体操作如下:

    CMDB_TOP_MENU = [

    '......',导航名称、URL、图标、子导航信息

    [u'用户管理

    ', 'cmdbusershow', 'user', []],]

    (3)启动Django服务,打开前端页面,点击用户管理,信息如图

    2-18所示。

    图2-18 用户组管理信息(4)到这里一个简单的用户管理功能就实现了,如果读者需要更

    详细的用户信息,可以去创建一个UserProfile表,然后关联到Django自

    带的User信息中,限于篇幅,本章就不逐一详细介绍了。2.6.5 用户组管理功能

    用户组管理和用户管理的原理是相通的,添加方式也是一样的,这

    里只是简述讲解一下添加的步骤。

    (1)在cmdbbase_admin.py中设置:

    'group': {

    model名称

    'model': Group, form表单

    'form': Group_CheckFrom, 名称

    'name': u'用户组管理

    ', 是否可以导入信息

    'import': '', table展示字段

    'list_display': ['name','permissions'], 编辑只读字段

    'readonly': ['name', ], 动作

    'action_list': [(u'编辑

    ', 'pencil', 'cmdbgroupmodify'),]

    },(2)把用户组管理的URL信息添加到前端页面的导航栏中就可以了(配置cmdbcmdb_menu.py程序),具体操作如下:

    CMDB_TOP_MENU = [

    '......',导航名称、URL、图标、子导航信息

    [u'用户组管理

    ', 'cmdbgroupshow', 'list', []],]

    (3)启动Django服务,打开前端页面,点击用户组管理(默认为

    空),信息如图2-19所示。

    图2-19 添加用户组管理

    (4)到这里组管理功能也实现成功了,现在我们就可以创建自己

    想要的组信息,把相应的用户添加到组中了。

    到此为止,我们已经基于CMDB完善了用户、用户组、操作历史、开放API几大实用功能。通过这些构建,可以将CMDB和自动化运维平

    台的其他系统逐一打通,构建属于自己的平台。2.7 小结

    无论IT系统多么庞大或微小,也无论提供的服务是多是少,是繁杂

    还是单一;作为实际管理和掌控这套系统和服务的读者来说,必须要明

    确的一点是:人是整个系统中最薄弱和不可预测的一环。如果由人工来

    进行维护,那么数据不准确的情况100%是会出现的。而通过程序自动

    采集数据,进行规则入库这种自动化操作,则使数据达到100%的准确

    率成为了现实。

    本文所展现的快速构建方法,仅仅是整套优化、完善动作的持续进

    行步骤中的一个环节,但此方法不但可以实现CMDB的快速构建,还对

    整个运维体系的建立、自动化平台架构的完善,也有非常重要的参考价

    值和借鉴意义。

    最后希望读者能通过对本文的阅读,不仅能够构建出属于自己的、定制化的CMDB平台,还能通过更深入的思考,为完善运维工作、完美

    自动化平台增加更多更深刻的理解认知。第3章 数据中心搬迁中的x86自动化运维

    作者简介

    吴传玉,具有10年以上x86服务器平台系统管理经验,熟悉

    Windows及Redhat Linux系列运维,自2008年接触VMware虚拟化产品,获得RHCT、VMware VCP和HCNA认证。善于使用各类脚本工具编制

    日常运维的脚本。目前就职于某大型金融企业基础设施运维部门,负责

    容灾及研发测试环境x86整体运维工作。

    本章主要介绍在大型数据中心搬迁的过程中,如何利用自行编制的

    各类脚本,低成本、高效率又准确地完成大量节点的逻辑搬迁工作。3.1 数据中心搬迁准备

    3.1.1 数据中心搬迁介绍

    世间万物都存在着自身的生命周期,大到宇宙恒星的诞生与消亡,小到细胞从一次分裂完成开始到下一次分裂结束所经历的全过程,都离

    不开生命周期。

    作为承载着公司核心竞争、运维能力的数据中心,也无法回避生命

    周期的问题。当数据中心的空间、电力等基础硬件无法支持公司业务需

    求的高速扩展时,公司的决策层势必会考虑采用更合理的方案,以满足

    日益增长的业务需求。第一种是在保持现有数据资源不变的情况下,建

    立第二个数据中心(非容灾中心);另一种是新建一个条件更优越的数

    据中心以替代旧的数据中心。

    采用第一种方式,可以平滑地进行扩容,但从长远来看双倍的运维

    成本会加重公司的负担。如果采用第二种方式,虽然在搬迁过程中对基

    础层、应用层运维人员的要求相对较高,但从长远来看可为公司节省可

    观的运维开支,主要的成本仅在于一次性搬迁的方案所承担的开支。

    大型金融企业中,基础运维人员相对于应用运维、开发人员、测试

    人员来说是属于更底层、更核心的角色。从整体运维的宏观结构来看,基础运维位于一个漏斗的底部出口位置,支撑着众多应用业务系统的基

    础需求。总结起来就是底层硬件架构多元化、需求种类多、运维量大,如果涉及搬迁则工作量更大更繁琐。

    因我主要负责的是x86平台的非生产环境日常运维工作,且正参与

    数据中心的搬迁项目。故本章将从系统层基础运维人员的角度出发,介

    绍在大型数据中心搬迁的过程中,如何自行编制脚本,从而降低成本、高效准确地完成大量节点的逻辑搬迁工作。

    首先介绍一下物理搬迁与逻辑搬迁的对比。

    数据中心的搬迁一般分为两类:物理搬迁和逻辑搬迁。

    如果物理设备及其上的逻辑节点数量少且搬迁距离较短,对可用性

    的要求不高,能够进行短期的停机,那么这种小型数据中心,一般较适

    用于同城数据中心的物理搬迁。

    如果涉及的节点数量多且搬迁距离较长,对可用性要求较高,无法

    满足短期停机的要求,则需要考虑逻辑搬迁。3.1.2 搬迁环境介绍

    此次我所参与的搬迁存在诸多制约因素,如硬件种类繁多、应用关

    联性大、搬迁周期短、搬迁成本缩减等。基于以上现状分析,最终确定

    按应用环境,逐批次实施逻辑搬迁。

    搬迁批次的定义如表3-1所示。

    表3-1 搬迁批次定义3.1.3 搬迁前的准备工作

    搬迁过程不仅仅是物理设备位置的改变,还需要对虚拟化层及各个

    节点内的参数进行调整。由于金融企业的环境特殊,公司安全部门禁止

    自行配置自动化运维管理工具,因此只能利用现有的技术做文章了。

    在此次迁移过程中,我利用了平时运维常用的一些系统自带的脚本

    工具。

    这些工具分为三类,其中有用于虚拟化层的工具vCLI、PowerCLI,有用于Linux环境的Bash,还有用于Windows环境的批处

    理、WMIC和注册表。

    ·vCLI:vSphere CLI,命令行管理接口。

    ·PowerCLI:VMware vSphere PowerCLI,是一款功能强大的命令行

    工具,可自动执行vSphere的各方面管理,包括主机、网络、存储、虚

    拟机、客户操作系统等。

    ·Bash:Bourne-Again Shell,是一个为GNU计划编写的Unix Shell,是许多Linux发行版的默认Shell,Bash的命令语法是Bourne Shell命令语

    法的超集。数量庞大的Bourne Shell脚本大多不经修改即可在Bash中正

    常执行。·批处理:Batch,也称为批处理脚本。顾名思义,批处理就是对某

    些对象进行批量处理,通常被认为是一种简化的脚本语言,它一般应用

    于DOS和Windows系统中。批处理文件的扩展名为bat。

    ·WMIC:WMIC扩展WMI(Windows Management Instrumentation,Windows管理工具),提供了对从命令行接口和批命令脚本执行系统管

    理的支持。

    ·注册表:Registry,是Microsoft Windows中的一个重要的数据库,用于存储系统和应用程序的设置信息。3.1.4 搬迁信息收集

    俗话说“九层之台,起于垒土”,因此对于搬迁来讲,基础信息至关

    重要。我们需要准确掌握现有搬迁环境所涉及的所有物理与逻辑信息,才能更好地完成搬迁任务。因此搬迁的首要任务就是收集所有的资源信

    息。

    1.计算资源信息收集

    作为目标端新设备的配置依据,应收集(包含但不限于)如下信

    息:型号、序列号、CPU、MEM、硬件管理IP、HBA WWN号 [1]。

    编辑文件tmpgetESXIinfo.sh,保存内容如下:

    获取物理设备型号

    xh=`esxcli hardware platform get | grep Product Name | awk -F: '{print 2}'`

    获取物理设备序列号

    SN=`esxcli hardware platform get | grep Serial Number | awk -F: '{print 2}'`

    获取物理

    CPU个数

    cpunum=`esxcli hardware cpu list | grep CPU: | wc -l`

    获取物理内存容量(以

    GB计算)

    mem=`esxcli hardware memory get | grep Physical Memory | awk -F '{print

    3}'`

    TotalMem=` expr mem 1024 1024 1024 `

    获取硬件管理IP

    vmkip=` esxcli network ip interface ipv4 get | grep vmk0 | awk '{print 2}'`

    获取

    HBA WWN信息

    wwn=`esxcli storage core adapter list | grep link-up | awk -F: '{print 2}'

    | awk '{print 1}'`

    wwn1=`echo wwn | awk -F '{print 1}'`

    wwn2=`echo wwn | awk -F '{print 2}'`

    echo xh,SN,cpunum,TotalMem,vmkip,wwn1,wwn2 >tmpv ......

您现在查看是摘要介绍页, 详见PDF附件(22893KB,855页)