Ansible权威指南.-阿里云开发者社区

开发者社区> 华章出版社> 正文

Ansible权威指南.

简介:

53ca1c1070443b6815fb86741df0b7d05f399fd5

Linux/Unix技术丛书

Ansible权威指南

李松涛 魏 巍 甘 捷 著





图书在版编目(CIP)数据

Ansible权威指南 / 李松涛,魏巍,甘捷著. —北京:机械工业出版社,2016.11

(Linux/Unix技术丛书)

ISBN 978-7-111-55329-8

I. A… II. ①李… ②魏… ③甘… III. 程序开发工具-指南 IV. TP311.561-62

中国版本图书馆CIP数据核字(2016)第258615号









Ansible权威指南

出版发行:机械工业出版社(北京市西城区百万庄大街22号 邮政编码:100037)

责任编辑:高婧雅 责任校对:殷 虹

印  刷: 版  次:2016年11月第1版第1次印刷

开  本:186mm×240mm 1/16 印  张:21.75

书  号:ISBN 978-7-111-55329-8 定  价:79.00元

凡购本书,如有缺页、倒页、脱页,由本社发行部调换

客服热线:(010)88379426 88361066 投稿热线:(010)88379604

购书热线:(010)68326294 88379649 68995259 读者信箱:hzit@hzbook.com

版权所有 ? 侵权必究

封底无防伪标均为盗版

本书法律顾问:北京大成律师事务所 韩光/邹晓东






Praise?本?书?赞?誉

以下推荐人按姓名音序排序。

随着信息时代发展,全球运维体系不断升级,灵活多变、安全稳定、自动高效的持续保障迫在眉睫。开源运动为IT奠定了坚实的基础环境,使得我们可以不断吮吸着其中的养分而茁壮成长。然而,为适应快速、高效运维,自动化基础设施势必成为运维必备技能。纵观自动化工具,如Puppet、SaltStack、Func、Chef、Ansible,基于Linux原生SSH(不需要agent),并糅合众多老牌运维工具的优秀特性,集成了批量命令执行和文件处理等诸多功能。相信不少朋友已经在使用这些工具,作者也从中直接受益,并结合实战经验汇总成本书,以帮助更多热爱开源的朋友。我们坚信,集众人智慧的结晶,专注开源事业,定能让更多人享受开源运动带来的丰硕成果。而Ansible也将成为专业人员必备技能,这本集合基础原理和实战案例的书籍会成为运维人员必备宝典。


——马永亮,马哥教育创始人

Ansible可以说是配置管理领域的新锐,一经推出便受到了很多运维及客户的青睐。Ansible的架构设计简洁,上手也非常简单,学习成本很低。在我们的客户自动化方案中,考虑到安全性、稳定性、便捷性等多方面要求,我们也把对Ansible的兼容作为首选。非常感谢Stanley和其他笔者不辞辛劳地编写此书,值得大家钦佩。相信本书能给读者带来很大的收益。


——王津银(互联网运维杂谈老王),优维科技创始人

当前,云计算正在快速落地,云使资源的利用更高效,但是云只解决了系统层面资源使用的问题,业务层面的运维自动化还必须借助运维自动化工具、结合具体的业务场景来解决。在众多的自动化工具中,使用Python开发的Ansible无疑是运维人员的最爱,因为它符合Python简单高效的原则。但是Ansible入门容易精通难。很高兴看到李松涛和他的朋友们撰写的这本书的出版,本书使快速精通Ansible成为可能。相信通过阅读本书,没有接触过Ansible的读者可以快速入门,已经在使用Ansible的读者可以从中学到更多知识。


——肖力,《深度实践KVM》作者

有一种距离叫菜鸟到高手的进阶,有一种练级捷径叫活学活用《Ansible权威指南》。本书案例通用、好使、接地气。

菜鸟得之如获至宝,稳扎稳打中轻松晋级;高手用之简洁高效,深度实践中融会贯通。

资深脚本运维有一天会发现,越做越累,正所谓:成也脚本,累也脚本。

场景化运维,可能吗?Playbook帮你实现操作通用或者简化,把纷繁复杂的脚本变为场景中一个个的步骤,让你可以边维护边游戏,提升运维人员的工作效率。

还在为Serverlist的管理发愁吗?Invertory帮你实现服务器分层管理,架构拓扑图一目了然。

还在为生成配置文件时感叹“时间都去哪了”吗?Jinjia的高效配置生成速度,让生成1万个复杂配置文件由30分钟变为1分钟,并且减少了业务停机时间。

本书对Ansible的周边扩展介绍得比较实在,理论联系实践。作者从丰富的工作经验总结出案例,详细列举了celery、模块扩展等具体应用,让Ansbile更加贴合实际的应用场景。

如果你想成为场景化运维人员,如果你想提升工作效率,本书就是为你量身定制的不二选择。


——张志浩,腾讯游戏运营规划专家

随着互联网和云计算的蓬勃发展,数据中心基础设施急速增加,IT运维逐渐成为现代企业生产经营的核心,而且要求越来越高。而要实现海量系统运维和DevOps,兼顾稳定和效率,就离不开运维自动化软件。

回顾运维自动化的发展历程,最早的运维自动化是脚本自动化,依靠SSH通道批量执行脚本。但人们很快就发现,每个运维人员习惯写一堆脚本,脚本的管理维护成为问题,误操作也时有发生。为了解决这个问题,Puppet、SaltStack、Ansible等一批优秀的开源软件应运而生,运维正式进入自动化时代。

当前中国大部分数据中心还是处于“人肉运维”的时代,自动化运维的需求非常强。但对于初学者来说,要驾驭好这些软件也不容易。很多初学者会误认为运维自动化的核心是批量执行,其实不然,运维自动化的核心是配置管理,自动化只是最终效果。

Ansible是运维自动化软件的后起之秀,发展非常快。其特点是简单易用、无代理架构,使用Python这样的运维语言易于二次开发,这使得Ansible非常适合互联网的运维场景和初学者。

本书作者之一李松涛是行业中少有的“能文能武”运维从业者,经过了腾讯海量系统运维的锻炼,又承担了Ansible中国“布道者”的角色,不辞辛苦地在社区和行业中分享经验,最终,花费了大量心血促成了本书的诞生。“授人以鱼,不如授人以渔”,本书不但介绍了Ansible的基础知识,还介绍了Ansible的实践经验和高阶的二次开发,对读者深入理解Ansible、构建自动化运维体系非常有帮助。

我把运维自动化分为:人肉运维、操作自动化、资源统一配置、一体化运维、运营指挥5个成熟度阶段,广大运维同行可以做的事情还很多。衷心祝愿李松涛再接再厉,通过著书立说和传道授业的方式,惠及更多的运维从业者,让天下没有难运维的数据中心。


——智锦,资深运维从业者,杭州云霁科技有限公司CEO






前  言?Preface

为什么要写这本书

首次接触Ansible是缘于一次杭州出差。当时接触互联网3年左右,正是技能的储备阶段,看到Ansible这样的新兴自动化工具不免充满好奇。当时腾讯的蓝鲸还没有出来,但abs脚本和ijobs自动化体系已经应用多年,并在整个IEG中心广泛应用。大型企业讲究分工精细化,各司其职,强大的自我研发能力。但伴随业绩和KPI的压力,很多人其实是没有多余精力关注外界技术领域的发展,尤其是游戏行业,行业自身属性对开发人员的技术能力要求非常高,前沿开源技术与业务特殊性需求并不能很好地融合,致使多数工具依赖于开发人员,整体运维体系以应用、发现、维护、服务方向为主,底层运维没有技术能力和资源协调能力为业务创造直接价值。高级运维和领导层更需着眼于高层面的业务拓展和整体运维体系规划,所以多数互联网前沿技术以技能储备的方式被引入,待机蓄力而发。

后来蓝鲸和ijobs融合后,在强大技术力的驱动下,运维的技术能力进一步淡化,对应的业务能力、需求发现、服务意识被强化,并提出更高的要求,DevOps的岗位定义更加明确。蓝鲸平台类似于苹果公司的App Store,是一个载体,只要有开发能力就可以编写自己的应用。只要应用的通用性足够高,所有业务都可以下载使用,而通用性则是开源技术最讲究的点。同时开源工具也是非常好的学习对象,往往经过简单的修改即可变成自己的产品,因此运维对开源技术的关注度越来越高,而笔者也正是在这样的背景下接触到Ansible。

对比主流的自动化工具SaltStack、Puppet等,Ansible给人最直观的感觉就是比较简单,而这也是笔者选择使用Ansible最重要的理由之一。因为笔者一直认为每个人精力有限,如腾讯早期的Ops技能培训希望个人同时兼备Ops和Dev的战略,但直到现在身边真正同时具备Dev和Ops能力于一身的人凤毛麟角。类似于Puppet和SaltStack这样的工具,高级使用均需涉及诸如Class类开发这样的技能才可运用,而初级运维和没有开发经验的运维掌握面向对象技术去开发高级应用确实没有那么妥当。Ansible早期的官网也是以Stupid Simple来形容其简单程度的,其前沿的去中心化思想和近期被RedHat(红帽)官方收购的消息,也更坚定了笔者使用Ansible的想法。

但当时Ansible在国内公司应用的并不多,且其官网屡屡被破解,使得虽然自动化的理念早已家喻户晓,但国内Ansible的文档和社区却始终不温不火。无独有偶,笔者发现腾讯也开始在自家蓝鲸平台使用Ansible,并结合业务进行了深入应用,所以就产生了编写一本Ansible书籍的想法。因此,也有了后来的Ansible官网中文翻译团队和本书写作团队,再后来也就有了Ansible中文权威网站、运维部落微信公众号、Ansible部落微信群、Ansible中文权威QQ群。更为幸运和开心的是,在坚持的过程中也遇到了一批自动化工具爱好者。http://www.ansible.com.cn/将Ansible官网中大家日常常用的部分功能翻译成中文,所以起名为Ansible中文权威指南。而后Google、Baidu的关键字搜索结果仅次于官网,这使得我们的信心大增。这里要特别感谢马哥Linux团队成员的薛定谔的章鱼、guli、以马内利、黄博文、coocla、云中鹤、stanley,这些朋友们历经数月,辛勤翻译多达5万字文档。

在一次和朋友聊天中,朋友问到你们Ansible已经应用这么久,同时也有自己独立开发的界面,现在国内Ansible的势头虽高,但文档和书籍欠缺,何不把你们的经验总结出来分享给更多朋友呢。我当时一怔,但也有担心:一方面精力不支,另一方面老婆怀孕,我担心生活工作不能兼顾。后来在老婆的鼓励下,经肖力和黄博文兄的引荐认识了华章公司的高编辑,正式开始书籍的编写之旅。在这个过程中,很高兴又有新的伙伴骑行牛人魏巍和Python能力出众的甘捷陆续加入,也使得个人的压力和精力有更多的释放,书籍的内容也有更完整、丰富的互补。在整个写书过程中我们也在成立的运维部落、Ansible公众号和QQ群,定期分享书籍内容,收集用户反馈和体验。到目前为止,QQ群近1300人,公众号也有2000多人在关注。群中也专门请行业应用经验丰富的专员来解答Ansible的技术类问题,同时成立专门的QA站点,收集用户QQ群问题处理方案,并对积极回答问题勇于分享的朋友定期寄送礼品以示鼓励。团队很高兴也很幸运能通过这样的方式为国内Ansible的发展贡献自己的力量。

本书特色

从技术层面讲,运维自动化理论及思想在国内日趋成熟,自动化工具更是遍地开花。现在运维不再纠结于没有工具可用,而是惆怅于选择何种工具。而Ansible正是在这样的大环境下产生,并且迅速脱颖而出。Ansible去中心化思想和“简单就是一切”的原则也使其在运维圈快速流行。但正如所有事物一样,入门简单并不代表深入简单,这也正是本书的意义所在。

从适合读者阅读和掌握知识的结构安排上讲,本书分为“基础入门篇”“高级进阶篇”“Web自动化开发篇”。本书在介绍新技术应用的同时更注重读者对技术的消化和接受程度,整个过程都秉承原理→练习→实战的思路,让读者轻松逐步深入,不会有生硬和突兀感。在介绍Ansible的核心技术应用Playbook章节更是不惜用50页左右的篇幅,通过企业实际案例讲解分析Playbook的使用技巧和经验心得。在Ansible企业应用实战相关章节,详细介绍Ansible与现今流行技术的结合使用,以及如何自我发展、自我完善技能。

在由浅入深介绍Ansible的同时,本书所有的应用案例按章节顺序全部上传至GitHub,附带自研的Web自动化页面,也全部开源至GitHub(同时本书写作团队收入的20%将捐赠给开源组织,捐赠金额和去向也会通过公众号和网站的方式对外公开)。

读者对象

IT网络运维工程师

业务运维工程师

DevOps技术人员

中小型企业无运维岗但需运维服务器的开发人员

虚拟化技术人员

对自动化理念感兴趣的技术人员

如何阅读本书

本书分为三篇,共14章,其中第1~3、6、8~10由李松涛编写,第4、5、7、11由魏巍编写,第8、12~14章由甘捷编写。

第一篇为基础入门篇(第1~5章),该篇着重介绍Ansible发展史,工作原理,基础元素组成,Playbook入门。该部分内容虽简单,却是掌握Ansible高级技巧的基石,如没有接触过相关自动化工具和Ansible,还需认真阅读。

第二篇为高级进阶篇(第6~11章),该篇也是本书内容的最大构成部分,着重结合企业实际需求场景,以大量的实际案例拓展介绍Ansible的高级语法进阶和实际应用技巧,涉及的技术点有Roles、Inventory、Jinja2、Galaxy等。结合的行业主流技术包括(但不限)Zabbix、Except、MemCache、Inotify、Logio、GitLab、Docker、LNMP、Redis、MySQL、Node.js等,并提供丰富的实战案例供大家参考学习。

第三篇为Web自动化开发篇(第12~14章),该篇内容主要针对不想购买Tower产品,但又有Web全自动化发布界面需求的人而专门撰写。该部分内容使用当前最流行成熟的Python,并结合Django前后端技术,通过Ansible celery管理后台任务队列。虽该部分内容从零基础部分开始介绍,逐步引导上手,但考虑时间和精力成本,建议具备一定的Python、Django、前端基础后进行学习。

本书前11章,各章没有强关联,如觉得内容已掌握可跳跃式阅读,遇到不理解的地方回头再看也问题不大。从第12章开始为Web化自动开发章节,需要循序渐进地学习,建议按顺序阅读。

勘误和支持

Ansible的发展非常快,当我们开始着手写这本书的时候Ansible的版本还是1.9.4,但没过多久2.0稳定版本就更新出来,但1.9版本分支还一直在维护,随后又陆续更新了1.9.5和1.9.6的稳定版,这对我们的写作也造成一定的困扰。当时多数公司使用的还是1.9版本的分支,2.0分支也陆续收到朋友们反馈各类问题。所以本书的写作过程总体还是基于1.9分支的基础,1.9和2.0的差别主要在于API接口和页面开发上,后者功能模块更加完善丰富,但对于普通使用者整体差别不大,有差别的地方书中均会提到。

由于笔者的水平有限,编写时间仓促,所有的写作过程都在深夜和周末,书中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果您有更多的宝贵意见,欢迎您关注我们的公众号linux178,或加入我们的QQ群:Ansible中文权威-2号群(486022616),或访问我们的问答平台http://www.178linux.com/qa,我们会尽量提供最满意的解答。期待能够得到你们的真挚反馈,在技术之路上互勉共进。

我想和作者聊聊

微信公众号:

linux178

或扫以下二维码


QA公共平台:

http://www.178linux.com/qa

普通用户请加群:

Ansible中文权威-2号群 486022616

书籍读者请加群:

中文权威读者群577479881

致谢

感谢翻译团队在Ansible官网文档翻译过程中的无私付出。

感谢魏巍、甘捷两位“笔友”在我狂轰滥炸的“淫威”下坚持写作,并持续输出高质量的内容。感谢机械工业出版社华章公司的策划编辑高婧雅,在近一年的时间中始终支持我的写作。你们的鼓励和帮助引导我们顺利完成全部书稿。

特别致谢

最后,我要特别感谢我的太太yolanda,为写作这本书,我牺牲了很多陪伴她的时间,但也正因为有了她的付出与支持,我才能坚持写下去。

同时,也要郑重感谢马哥教育在我写作的过程中提供不遗余力的资源支持,让我们得以放开手脚无所束缚地完成写作工作。

谨以此书献给我最亲爱的家人,以及众多热爱开源技术的朋友们!


李松涛(stanley)

2016年8月






Contents?目  录

本书赞誉

前言

第一篇 基础入门篇

第1章 Ansible基础入门  2

1.1 Ansible是什么  2

1.2 Ansible发展史  4

1.3 为什么选择Ansible  5

1.4 Ansible是如何工作的  6

1.5 Ansible通信发展史  8

1.6 Ansible应用场景  11

1.7 Ansible的安装部署  12

1.7.1 PIP方式  13

1.7.2 YUM方式  13

1.7.3 Apt-get方式  14

1.7.4 源码安装方式  14

1.7.5 验证安装结果  15

1.8 Python多环境扩展管理  16

1.8.1 Pyenv的部署与使用  16

1.8.2 Virtualenv的部署与使用  18

1.9 本章小结  20

第2章 Ansible基础元素介绍  21

2.1 Ansible目录结构介绍  21

2.2 Ansible配置文件解析  23

2.3 Ansible命令用法详解  25

2.4 Ansible系列命令用法详解与使用场景介绍  28

2.4.1 ansible  28

2.4.2 ansible-galaxy  29

2.4.3 ansible-pull  31

2.4.4 ansible-doc  31

2.4.5 ansible-playbook  31

2.4.6 ansible-vault  32

2.4.7 ansible-console  32

2.5 Ansible Inventory配置及详解  34

2.5.1 定义主机和组  34

2.5.2 定义主机变量  35

2.5.3 定义组变量  35

2.5.4 定义组嵌套及组变量  36

2.5.5 多重变量定义  36

2.5.6 其他Inventory参数列表  37

2.6 Ansible与正则  37

2.7 本章小结  39

第3章 Ansible Ad-Hoc命令集  40

3.1 Ad-Hoc使用场景  40

3.2 Ad-Hoc命令集介绍  41

3.2.1 Ad-Hoc命令集用法简介  41

3.2.2 通过Ad-Hoc查看系统设置  46

3.2.3 通过Ad-Hoc研究Ansible的并发特性  47

3.2.4 通过Ad-Hoc研究Ansible的模块使用  49

3.3 Ad-Hoc组管理和特定主机变更  52

3.3.1 Ad-Hoc组定义  52

3.3.2 Ad-Hoc配置管理:配置Proxy与Web Servers实践  54

3.3.3 Ad-Hoc配置后端:配置NoSQL与Database Servers实践  56

3.3.4 Ad-Hoc特定主机变更  57

3.4 Ad-Hoc用户与组管理  58

3.4.1 Linux用户管理  58

3.4.2 Windows用户管理  63

3.4.3 应用层用户管理  64

3.5 本章小结  65

第4章 Playbook快速入门  66

4.1 Playbook语法简介  66

4.1.1 多行缩进  67

4.1.2 单行缩写  67

4.2 Playbook案例分析  68

4.3 Playbook与Shell脚本差异对比  71

4.4 Ansible-playbook实战小技巧  71

4.4.1 限定执行范围  71

4.4.2 用户与权限设置  72

4.4.3 Ansible-playbook:其他选项技巧  73

4.5 实战一:Ansible部署Node.js企业实践  73

4.5.1 添加第三方源  73

4.5.2 运行Node.js进程  77

4.5.3 Node.js app服务部署总结  78

4.6 实战二:Drupal基于LAMP的自动化部署  78

4.6.1 定义变量并设置Handlers  79

4.6.2 部署LAMP基础服务  80

4.6.3 配置Apache  81

4.6.4 配置PHP  82

4.6.5 配置MySQL  83

4.6.6 安装Drush和Composer  84

4.6.7 通过Git和Drush安装Drupal  85

4.6.8 Drupal部署过程总结  86

4.7 实战三:Ansible部署Tomcat企业实战  86

4.7.1 定义变量并设置Handlers  86

4.7.2 安装Java  87

4.7.3 安装Tomcat 8  88

4.7.4 安装Apache Solr  89

4.8 本章小结  91

第5章 Ansible Playbook拓展  92

5.1 Handlers  92

5.2 环境变量  93

5.3 变量  95

5.3.1 Playbook 变量  96

5.3.2 在Inventory文件中定义变量  97

5.3.3 注册变量  98

5.3.4 使用高阶变量  98

5.3.5 主机变量和组变量  100

5.3.6 Facts(收集系统信息)  101

5.3.7 Ansible加密模块Vault  104

5.3.8 变量优先级  106

5.4 if/then/when——流程控制  107

5.4.1 Jinja2 正则表达、Python 内置函数和逻辑判断  107

5.4.2 变量注册器register  108

5.4.3 when条件判断  109

5.4.4 changed_when、failed_when条件判断  110

5.4.5 ignore_errors条件判断  111

5.5 任务间流程控制  111

5.5.1 任务委托  111

5.5.2 任务暂停  112

5.6 交互式提示  112

5.7 Tags标签  113

5.8 Block块  115

5.9 本章小结  116

第二篇 高级进阶篇

第6章 Playbook高级技巧进阶  118

6.1 巧用 Includes  118

6.1.1 Includes使用场景  118

6.1.2 Includes用法  119

6.1.3 动态 Includes  123

6.1.4 Handler Includes使用技巧  123

6.1.5 Playbooks Includes使用技巧  124

6.2 巧用Roles  124

6.2.1 构建Roles  125

6.2.2 使用Roles重构Playbooks  125

6.2.3 Roles技巧之Handlers:动态变更  129

6.2.4 Roles技巧之Files:文件传输  131

6.2.5 Roles技巧之Templates:模板替换  133

6.2.6 更多复杂的跨平台Roles  135

6.3 Jinja2实现模板高度自定义  136

6.3.1 Jinja2 For循环  136

6.3.2 Jinja2 If条件  137

6.3.3 Jinja多值合并  138

6.3.4 Jinja default()设定  140

6.3.5 Ansible结合Jinja2生成Nginx配置  141

6.3.6 Ansible结合Jinja2生成Apache多主机配置  146

6.3.7 Jinja2动态变量配置及架构优化  148

6.4 Ansible Galaxy  151

6.4.1 Ansible-galaxy命令用法  151

6.4.2 使用Galaxy  152

6.5 本章小结  154

第7章 Inventory文件扩展  155

7.1 Inventory文件实战  155

7.2 独立的Inventory文件  159

7.3 Inventory变量  159

7.3.1 host_vars目录  160

7.3.2 group_vars目录  161

7.4 动态Inventory  161

7.5 本章小结  168

第8章 Ansible插件扩展  169

8.1 Ansible 插件使用场景  169

8.2 Ansible插件类型  170

8.3 如何编写自己的插件  171

8.4 插件案例实践  172

8.5 本章小结  174

第9章 Ansible企业应用实战  175

9.1 为新系统添加安全认证SSHKey  175

9.1.1 Ansible密码认证  175

9.1.2 ssh-copy-id  176

9.1.3 Kickstart  177

9.1.4 Python Paramiko  178

9.1.5 Expect  179

9.2 企业高可用架构的Ansible应用  180

9.2.1 Playbook目录编排  181

9.2.2 高可用架构基于Ansible的自动化实现  181

9.2.3 使用Includes衔接各服务配置  188

9.3 ELK日志系统基于Ansible的自动化实现  189

9.3.1 ELK Server的自动化实现  190

9.3.2 ELK Client的自动化实现  192

9.4 实时日志系统基于Ansible的自动化实现  192

9.4.1 配置概览  192

9.4.2 架构部署  193

9.5 Zabbix基于Ansible的自动化实现  195

9.5.1 Zabbix Server基于Ansible的自动化实现  196

9.5.2 Zabbix Agent基于Ansible的自动化实现  199

9.5.3 Zabbix Proxy基于Ansible的自动化实现  201

9.6 Ansible+Git+GitLab实现自动化发布  202

9.6.1 架构概览  203

9.6.2 架构部署  203

9.7 Docker的Ansible自动化应用  206

9.7.1 Docker容器入门  206

9.7.2 使用Ansible创建和管理容器  207

9.7.3 基于Ansible创建Flask的Docker容器  208

9.7.4 数据存储容器配置  210

9.7.5 Flask容器配置  211

9.7.6 MySQL容器配置  213

9.7.7 启动容器  215

9.8 本章小结  215

第10章 Ansible基于Windows的管理架构  217

10.1 Ansible管理机部署安装  218

10.2 Windows系统预配置  219

10.3 Windows下可用模块  224

10.4 Windows Ansible模块使用实战  224

10.5 本章小结  226

第11章 Ansible安全优化篇  227

11.1 SSH与远程连接简介  227

11.1.1 Telnet  228

11.1.2 RLOGIN、RSH和RCP  228

11.1.3 SSH  228

11.1.4 SSH的发展和远程访问的未来  229

11.2 通信加密  230

11.3 禁止root远程登录  231

11.4 操作系统简介  232

11.5 遵守权限最小化原则  233

11.5.1 用户管理  233

11.5.2 文件权限管理  233

11.6 定期维护更新  234

11.6.1 手动更新  234

11.6.2 自动定时更新  234

11.7 善用Iptables防火墙  236

11.8 定期磁盘巡检  238

11.9 系统登录日志审记  238

11.10 正确使用SELinux和AppArmor  239

11.11 本章小结  240

第三篇 Web自动化开发篇

第12章 Ansible模块编写  242

12.1 初步认识Ansible模块  242

12.2 Ansible简单模块编写  243

12.3 模块变量添加  245

12.4 模块状态返回的标识及应用  246

12.5 模块退出状态处理  249

12.6 模块其他功能补充  250

12.7 Ansible模块API的调用  251

12.8 本章小结  265

第13章 开发自己的Ansible WebUI  267

13.1 搭建Django开发环境  267

13.1.1 为什么要使用Web页面做管理  267

13.1.2 系统及软件环境  268

13.2 Django配置文件详解  269

13.2.1 Django的基础配置及运行  269

13.2.2 Django的主配置目录介绍  270

13.2.3 Django的app目录介绍  271

13.3 编写Ansible的Web接口  272

13.4 前端基础知识介绍  278

13.4.1 HTML和CSS简介  278

13.4.2 JavaScript简介  279

13.5 Ansible WebUI界面开发  280

13.5.1 对接前端页面与Ansible的Web接口  280

13.5.2 配置Web页面传参  282

13.6 本章小结  285

第14章 Web与Ansible结合的常用实例  286

14.1 Web方式管理Ansible的Inventory  286

14.1.1 重新定制Ansible的Hosts文件规则  286

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

14.1.3 使用数据库的存储数据生成的Ansible Hosts文件  290

14.1.4 通过页面来生成Hosts文件  293

14.2 使用celery后台执行任务  301

14.2.1 为什么要使用celery  301

14.2.2 使用celery的前期准备  301

14.2.3 使用celery开始任务  303

14.2.4 使用celery取消正在进行的任务  305

14.3 运行YML文件并实时读取日志  306

14.4 通过页面上传文件并基于Ansible分发  313

14.5 在页面上构建YML文件注册中心  316

14.6 操作者注册中心界面  324

14.7 本章小结  331

第一篇 Part 1

基础入门篇

第1章 Ansible基础入门

第2章 Ansible基础元素介绍

第3章 Ansible Ad-Hoc命令集

第4章 Playbook快速入门

第5章 Ansible Playbook拓展


第1章

Ansible基础入门

“未来主体是传统行业利用互联网技术,以云端用人工智能的方式处理大数据”,在腾讯“云+未来”技术峰会上,马化腾这样形容未来。15年前,电脑还只是少数人的专属,那时的网吧还很火,还没人知道“网咖”是什么。而现在人手一部智能手机,物联网更是让日常生活中的普通家电也能在互联网占据一席之地。这一切都推动着互联网如火如荼发展,IT技术的发展更是日新月异,IT工种的分类日益精细专业化。

从早期All In One(所有应用部署在一台服务器上)的简单应用,到后期集群、高可用、缓存、消息队列、配置中心、主从分离、负载均衡、大数据存储等尖端技术的复杂应用,对运维的技术专业度和综合技能要求越来越高,运维的交付标准不再以周或天为单位,而是以分钟为单位。在现在是如此,在未来更是如此。运维不再如早期一样,手动一台台地登录服务器、部署应用配置环境、手动交付(诸如亚马逊、Google等巨型企业早已实现自动扩缩容,配置应用自动化,流程自动交付等功能)。该方式耗时耗力,很难避免人为因素的错误,最主要的是这些重复手工劳动无法让运维有更大的价值释放,这一切都是不合理的,需要有更好的解决方式。

相信看到这里,大家都明白,我们需要一套自动化管理工具来帮助运维更高质量、更有效地完成手头工作,以证明运维能创造的价值不止于此,况且生活不止眼前的苟且,还有诗和远方,不是吗?但当下SaltStack、Puppet、Fabric、Chef等自动化工具遍地开花,为什么还要推荐Ansible呢?读完本章你会有些许想法,未来已来,只是尚未流行。

1.1 Ansible是什么

随着移动互联、物联网、互联网+、大数据、云计算等大规模应用的催生推动,以及人们日常生活的互联网化,互联网的蓬勃发展不仅冲击影响着整个经济体,更对人们的生活理念影响深远。在体验到互联网带来的便利和舒适的同时,人们也不再满足于“可以用”,而是要“用得爽”,在政策、需求、利益、趋势等原因的刺激下,互联网的发展速度可想而知。众所周知,智能的背后意味着复杂,这一现象在互联网的发展中体现得淋漓尽致。在互联网迅猛发展的同时,运维这个工种也从默默无闻的后台逐步走向公众视野,被更多的人所知晓。早期公司业务有数十台、上百台服务器已经是非常庞大的规模,每个运维同时操作10~20台机器,忙碌地奔波于各电脑之间配置重启服务,数十人摩肩接踵的场面是何等壮观。只是每个人都在数十台机器上做同样的修改、配置、操作,如何保证每台机器的操作都完全一样呢?又如何保证其他所有人的操作都能准确无误、没有遗漏过失呢?更何况,随着互联网的迅猛发展,一个公司拥有几十台上百台机器早已不是稀奇事,巨型公司数以万计的机器都不在话下,再沿用老一套办法一台台地人工修改配置已然不现实,这该怎么办呢?相信此时你已然明白运维自动化具体是什么了。简单来讲,运维自动化就是将日常重复性的工作通过规则设定使其遵循预先既定规则,在指定的范围时间内自动化运行,但整个过程无需人工参与。而Ansible正是帮助运维人员实现自动化的工具之一。

Ansible是近年越来越火的一款运维自动化工具,其主要功能是帮忙运维实现IT工作的自动化、降低人为操作失误、提高业务自动化率、提升运维工作效率,常用于软件部署自动化、配置自动化、管理自动化、系统化系统任务、持续集成、零宕机平滑升级等。它丰富的内置模块(如acl、command、shell、cron、yum、copy、file、user等,多达569个)和开放的API接口,同时任何遵循GPL协议的企业或个人都可以随意修改和发布自己的版本。

Ansible在其官网上定义如下:Ansible is a radically simple IT automation engine。即Ansible是一款极其简单的IT自动化工具。这里特别使用了radically simple来形容Ansible的简单程度,在0.X版本的Ansible官网中,更“过分”地使用Stupid Simple来形容Ansible是“令人发指的简单”。在Ansible官网的通篇文档中也不时使用Incredibly Simples、Keep It Simple、Power+Simplicity等字眼,可见Ansible这款自动化工具的设计非常注重Simple的理念。但Ansible的功能却非常不简单,完全没有因为使用方式上的简单而缩水,其自身内置模块的数量达500多个,而且还在快速地增加新模块,以下是这些模块的覆盖面的大致分类。

系统层:支持的系统有Linux、Windows、AIX等,对应的模块有acl、cron、pip、easy_install、yum、authorized_key等大量的内置模块;

知名第三方平台支持:支持的云平台有AWS、Azure、Cloudf?lare、Openstack、Google、Linode、Digital Ocean等,对应的模块有ec2、azure_rm_deployment、cloudflare_dns、clc_aa_policy、glance_image、gc_storage、digital_ocean等;

虚拟化:VMware、Docker、Cloudstack、LXC、Openstack等,对应的模块有vmware_vmkernel、docker、cs_account、lxc_container、glance_image等;

商业化硬件:F5、ASA、Citrix、Eos等,对应的模块有bigip_facts、asa_acl、netscaler、eos_command等;

系统应用层:Apache、Zabbix、Rabbitmq、SVN、GIT等,对应的模块有apache2_module、zabbix_group、rabbitmq_binding、subversion、git等。

GitHub上有众多开源爱好者为Ansible贡献功能模块,这些模块完全可以满足日常工作所需。官方对模块也从使用者角度进行详细分类,如Cloud Modules(云主机模块)、Clustering Modules(集群模块)、Commands Modules(命令模块)、Database Modules(数据库模块)等。详细的模块分类可参考官方模块列表:http://docs.ansible.com/ansible/modules_by_category.html,该网址内容的更新速度非常快,如果公司在使用Ansible,建议最少两周关注一次。

Ansible名字其实是来源于其作者喜欢的一本书——奥森·斯科特·卡特的《安德的游戏》,该书中Ansible是一种能跨越时空的即时通信工具,使用Ansible可以在相距数光年的距离远程实时控制前线的舰队战斗。Michael DeHaan希望借这个名词比喻控制远端大量的服务器,因此便将自己的这款产品命名为Ansible。

Web界面是一款功能完善的管理工具的必备功能,Tower是Ansible的Web化管理界面,但免费版的容量只有10台主机,付费版则无容量限制。基于此原因,本书的第12~14章会介绍搭建属于自己的Web化管理界面的方法,并代码全开源,具体地址大家可从GitHub上下载,同时读者遇到的问题都可以通过QQ群“Ansible中文权威”咨询,或在微信公众号“运维部落”留言。

更多信息请参考:

Ansible官方地址:https://docs.ansible.com/;

GitHub地址:https://github.com/ansible/ansible/blob/devel/docsite/rst/index.rst;

Ansible中文权威地址:http://www.ansible.com.cn/。

1.2 Ansible发展史

Ansible的第一个版本是0.0.1,发布于2012年3月9日,其作者兼创始人是Michael DeHaan。Michael DeHaan曾经供职于Puppet Labs、RedHat、Michael,在配置管理和架构设计方面有丰富的经验。其在RedHat任职期间主要开发了Cobble,经历了各种系统简化、自动化基础架构操作的失败和痛苦,在尝试了Puppet、Chef、Cfengine、Capistrano、Fabric、Function、Plain SSH等各式工具后,决定自己打造一款能结合众多工具优点的自动化工具,Ansible由此诞生。

其第一个版本号被非常谨慎地定义为0.01。到目前为止共发布107个版本,最新稳定版是Stable 2.1.1.0-1,最新Beat版Beat 2.1.1.0-0.1.rc1。值得一提的是,作为自动化工具新秀,Ansibe已被RedHat官方收购,在GitHub上被关注的势头也极为迅猛,Star和Fork数是当下红极一时的SaltStack的2倍多。同类自动化工具GitHub关注程度如表1-1所示。从表可以看出Ansible的受欢迎度。被RedHat收购后,其未来发展潜力更是不可估量。

表1-1 同类自动化工具GitHub关注程度(2016-07-10)

同类自动化工具 Watch(关注) Star(点赞) Fork(复制) Contributors(贡献者)

Ansible 1387 1?7716 5356 1428

SaltStack 530 6678 3002 1520

Puppet 463 4044 1678 425

Chef 383 4333 1806 464

Fabric 379 7334 1235 116


Ansible版本更新速度非常快,有时会一天推出多个Dev版本,7天推出一个稳定版本。所以使用Ansible的过程中也需多留意官网的更新。

1.3 为什么选择Ansible

Ansible自2012年发布以来,没多久便在美国开始流行。快速被IT人员接受的原因较大方面得益于Michael DeHaan在美国IT圈的名气和影响力。随后它逐步在各国流行。而笔者选择Ansible的原因主要有如下几个方面:

Ansible完全基于Python开发,而DevOps在国内已然是一种趋势,Python被逐步普及,运维人员自己开发工具的门槛逐步降低,得益于此,方便对Ansible二次开发;

Ansible丰富的内置模块,甚至还有专门为商业平台开发的功能模块,近600个模块完全可以满足日常功能所需;

在Ansible去中心化概念下,一个简单的复制操作即可完成管理配置中心的迁移;

Agentless(无客户端),客户端无需任何配置,由管理端配置好后即可使用,这点非常诱人。在第10章会介绍如何部署配置Windows系统的主机端,用后会有深切的感受。

自Ansible发布后,也陆续被AWS、Google CloudPlatform、Microsoft Azure、Cisco、HP、VMware、Twitter等大公司接纳并投入使用。关于笔者个人与Ansible的一些故事,有兴趣的朋友可以参考本书前言。

1.4 Ansible是如何工作的

Ansible没有客户端,因此底层通信依赖于系统软件,Linux系统下基于OpenSSH通信,Windows系统下基于PowerShell,管理端必须是Linux系统,使用者认证通过后在管理节点通过Ansible工具调用各应用模块将指令推送至被管理端执行,并在执行完毕后自动删除产生的临时文件。Ansible具体的工作机制官方有专栏介绍https://www.ansible.com/how-ansible-works,但整体稍过简略。我们参考从官网视频中的截图来详细了解下其工作方式,如图1-1所示。根据Ansible使用过程中的不同角色,我们将其分为:

使用者

Ansible工具集

作用对象

(1)使用者

如图1-1中Ansible工作机制所示,Ansible使用者来源于多种维度,图中为我们展示了4种方式:

第一种方式:CMDB(Conf?iguration Management Database,配置管理数据库),CMDB存储和管理着企业IT架构中的各项配置信息,是构建ITIL项目的核心工具,运维人员可以组合CMDB和Ansible,通过CMDB直接下发指令调用Ansible工具集完成操作者所希望达成的目标;

第二种方式:PUBLIC/PRIVATE方式,Ansible除了丰富的内置模块外,同时提供丰富的API语言接口,如PHP、Python、PERL等多种当下流行语言,基于PUBLIC(公有云)/PRIVATE(私有云),Ansible以API调用的方式运行;

第三种方式:USERS直接使用Ad-Hoc临时命令集调用Ansible工具集来完成任务执行,Ad-Hoc将在第3章有详细介绍;

第四种方式:USERS预先编写好的ANSIBLE PLAYBOOKS,通过执行Playbooks中预先编排好的任务集按序完成任务执行。

(2)Ansible工具集

ansible命令是Ansible的核心工具,ansible命令并非自身完成所有的功能集,其只是Ansible执行任务的调用入口,大家可心理解为“总指挥”,所有命令的执行通过其“调兵遣将”最终完成。ansible命令共有哪些兵将可供使唤呢?大家看中间绿色框中有INVENTORY(命令执行的目标对象配置文件)、API(供第三方程序调用的应用程序编程接口)、MODULES(丰富的内置模块)、PLUGINS(内置和可自定义的插件)这些可供调遣。

(3)作用对象

Ansible的作用对象,不仅仅是Linux和非Linux操作系统的主机(HOSTS),同样也可以作用于各类公有云/私有云,商业和非商业设备的网络设施。


图1-1 Ansible工作机制

同样,如果我们按Ansible工具集的组成来讲,由图1-1可以看出Ansible主要由6部分组成。

ANSIBLE PLAYBOOKS:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,通常是JSON格式的YML文件;

INVENTORY:Ansible管理主机的清单;

MODULES:Ansible执行命令的功能模块,多数为内置的核心模块,也可自定义;

PLUGINS:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用。

API:供第三方程序调用的应用程序编程接口;

ANSIBLE:该部分图中表示的不明显,组合INVENTORY、API、MODULES、PLUGINS的绿框大家可以理解为是Ansible命令工具,其为核心执行工具;

Ansible执行任务,这些组件相互调用关系如图1-2所示:


图1-2 Ansible组件调用关系

使用者使用Ansible或Ansible-playbook(会额外读取Playbook文件)时,在服务器终端输入Ansible的Ad-Hoc命令集或Playbook后,Ansible会遵循预先编排的规则将Playbooks逐条拆解为Play,再将Play组织成Ansible可识别的任务(Task),随后调用任务涉及的所有模块(Module)和插件(Plugin),根据Inventory中定义的主机列表通过SSH(Linux默认)将任务集以临时文件或命令的形式传输到远程客户端执行并返回执行结果,如果是临时文件则执行完毕后自动删除。

1.5 Ansible通信发展史

Ansible主推的卖点是其无需任何Daemon维护进程即可实现相互间的通信,且通信方式是基于业内统一标准的安全可靠的SSH安全连接。同时因为SSH是每台Linux主机系统必装的软件,所以Ansible无需在远程主机端安装任何额外进程,即可实现Agentless(无客户端),进而助力其实现去中心化的思想。尽管稳定、快速、安全的SSH连接是Ansible通信能力的核心,但SSH的连接效率一直被诟病,所以Ansible的通信方式和效率在过去的数年中也在不停地改变和提高。基于以上认识,我们先来了解Ansible SSH的工作机制,再来回顾其发展史。

1.?Ansible SSH工作机制

Ansible执行命令时,通过其底层传输连接模块,将一个或数个文件,或者定义一个Play或Command命令传输到远程服务器/tmp目录的临时文件,并在远程执行这些Play/Comand命令,然后删除这些临时文件,同时回传整体命令执行结果。这一系列操作在未来的Ansible版本中会越来越简单、直接,同时快速、稳定、安全。通过了解其工作机制及其一直以来秉承的去中心化思想,我们可以总结,Ansible是非C/S架构,自身没有Client端,其主要特点如下。

无客户端,只需安装SSH、Python即可,其中Python建议版本为2.6.6以上。

基于OpenSSH通信,底层基于SSH协议(Windows基于PowerShell)。

支持密码和SSH认证,因可通过系统账户密码认证或公私钥认证,所以整个过程简单、方便、安全。建议使用公私钥方式认证,因为密码认证方式的密码需明文写配置文件,虽然配置文件可加密,但会增加Ansible使用的复杂度。

支持Windows,但仅支持客户端,服务端必须是Linux系统。

如Ansible官方介绍,如上特性是希望实现以下最终目标:

Clear(简易):YAML语法,Python语言编写,易于管理,API简单明了;

Fast(敏捷):快速学习,设置简单,无需任何第三方软件;

Complete(全面):配置管理、应用部署、任务编排等功能集于一身,丰富的内置模块满足日常功能所需;

Eff?icient(高效):没有额外软件包消耗系统性能;

Secure(安全):没有客户端,底层基于OpenSSH,保证通信的安全可靠性。

2.?Ansible通信方式发展历程

Ansible底层基于安全可靠的SSH协议通信,但一直被人们诟病于其效率,通信功能作为Ansible最核心的功能之一,官方也一直在做改进。本节我们来了解Ansible通信发展史。

(1)Paramiko通信模块

最初,Ansible只使用Paramiko实现底层通信功能,但是Paramiko只是Python语法的一个第三方库,发展速度远不及OpenSSH。同时,Paramiko的性能和安全性较OpenSSH稍逊一筹(在笔者眼里)。

在后续发布的新版本中,Ansible仍继续兼容Paramiko,甚至在诸如RHEL 5/6等不支持ControlPersist(只在OpenSSH 5.6+版本中支持)的系统中封装其为默认通信模块。

(2)OpenSSH

从Ansible 1.3版本开始,Ansible默认使用OpenSSH连接实现各服务器间通信,以支持ControlPersist(持续管理)。Ansible从0.5版本起即支持OpenSSH功能,但直到1.3版本开始才将其设置为默认。

多数本地SSH配置参数,诸如Hosts、公私钥文件等是默认支持的,但如果希望通过非默认的22端口运行命令等操作,则需要在Inventory文件中配置ansible_ssh_port的值。OpenSSH相比Paramiko更快、更可靠。

(3)加速模式

据官网介绍:开启加速模式后Ansible通信速度有质的提升,是开启ControlPersist后的SSH的2~6倍,是Paramiko通信速度的10倍。

尽管加速模式对Ad-Hoc命令不友好,但是Playbook通过加速模式会收到更高的性能。加速模式抛弃SSH多次连接的方式,通过SSH初始化后,带着AES key的初始化连接信息通过特定的端口(默认5099,但可配置)执行命令传输文件。使用加速模式唯一需要的额外包是python-keyczar,如此一来,几乎所有的常规模块OpenSSH/Paramiko均工作在加速模式,但如下使用sudo的情况例外:

1)sudoers文件需要关闭其中的requiretty功能,注释掉或者设置每个用户的默认值为username !requiretty。sudoers的man文档说明如下。

requiretty

If set, sudo will only run when the user is logged in to a real tty.  When this flag is set, sudo can only be run from a login session and not via other means such as cron(8) or cgi-bin scripts.  This flag is off by default.

2)开启加速模块必须事先设置sudo文件NOPASSWD配置,禁用sudo后的PASSWORD交互认证过程。加速模式相对OpenSSH可以提供2~4倍的性能提升(尤其对于文件传输功能),在Playbook的应用中可以通过增加配置开关来实现。

---

- hosts: all

accelerate: true

accelerate_port: 5099

[...]

其中的端口也可以在ansible.cfg中单独配置。

[accelerate]

accelerate_port = 5099

加速模式是现在已经被废弃的Fireball模式的进化版,类似于Ansible加速通信方式,但需控制机事先安装ZeroMQ服务(这与Ansible简单、无依赖、无Daemon的理念是相违背的),并且一点也不支持sudo操作。

(4)Faster OpenSSH in Ansible 1.5+

Ansible 1.5+版本中的OpenSSH有了非常大的改进,旧版本中实现方式是复制文件至远程服务器后运行,然后删除这些临时文件,而新版本的替代方案是通过OpenSSH发送执行命令,将所有操作附带在SSH连接过程中同步实现。该方式只在Ansible 1.5+版本有效,且需在/etc/ansible/ansible.cfg的[ssh_connection]区域开启pipelining=True功能。

关于加速模式我们还需要关注如下内容:

pipelining=True需结合sudo的requiretty配置方可生效,请确保/etc/sudoers的Defaults requiretty为注释状态。绝大多数现有流行系统默认开启该选项。

在Mac OSX、Ubuntu、Windows的Cygwin或其他流行OS最好选择5.6以上的OpenSSH版本,这些版本对ControlPersist有更友好的支持。

如Ansible运行的主机系统是RHEL或CentOS,然而希望升级当前OpenSSH到最新版本以支持Faster/Persistent连接模式,可以通过yum update openssh升级最新版本。

本节内容可以通过如图1-1所示的Ansible通信方式发展史鱼骨图来概括,从最开始的Paramiko,后来初步演变为OpenSSH,加速模式官方推荐Pipelining方式。


图1-3 Ansible通信方式发展史

在了解Ansible通信原理及发展史后,我们进一步学习Ansible自身的发展史。要知道,在Chef、Puppet、SaltStack、Fabric等自动化工具群雄争霸的市场背景下,Ansible依然能够杀出重围,在GitHub取得如此惊人成就,并且被红帽官方收购,其发展史不得不让人刮目相看。

1.6 Ansible应用场景

Ansible底层基于Python,以简单著称,配置文件格式也以INI和YAML为主,与其他管理工具相比,学习成本较低,学习曲线也很平滑,无论是基础运维人员还是资深运维工程师都可以较快上手,稍加练习便可以熟练掌握。如果具备Dev基础,熟悉Python、PHP等主流语言,基于Ansible开放API接口做二次开发,可以灵活有效地发挥其价值。Ansible自身也包括非常丰富的内置模块,从Windows系统到开源Linux系统,从文件同步到命令执行,从软件的安全升级到配置的维护变更,从商业硬件A10、F5到公(私)有云AWS、Digital、VMware、Docker等,几乎囊括了运维日常所有的技术应用。系统下所有的操作可从运维操作角度划分为两类。

文件传输:文件的本地传输和异地传输,所有文件的空间形态、时间形态变化均构成文件传输类操作。

命令执行:终端所有操作对系统来讲都是指令的组成,最终转换为基础硬件可接受的电信号完成任务集。对运维操作的用户行为来讲,除文件传输以外的其他操作均可称为命令执行。

从自动化工作类型角度归类如下。

(1)应用部署

现今的应用功能越来越强大,同步应用部署过程的依赖和规则也日趋复杂,但对应用运维的要求没有随之降低,有效快速正确平滑的应用部署需求日趋强烈。Ansible内置网络、应用、系统、第三方云平台扩展等完善的功能模块,协助运维快速完成应用的安装、卸载、升级、启停、配置等部署类工作,即使对跨平台或知名的商业硬件也同样支持。

(2)配置管理

配置管理(Conf?iguration Management,CM)是通过技术或行政手段对软件产品及其开发过程和生命周期进行控制、规范的一系列措施。配置管理的目标是记录软件产品的演化过程,确保软件开发者在软件生命周期中各个阶段都能得到精确的产品配置。在日益复杂的IT环境和用户需求下,Ansible内置File、Template,结合Jinja、Lineinf?ile等内置模块,同时无缝结合GitHub、GitLab、Git、SVN、Jenkins等主流版本控制和CI持续集成工具,助力配置管理自动化。

(3)任务流编排

有效保证Tasks任务流按既定规则和顺序完成事先制订的目标和计划,同时Roles编排方式又能在一定程度上从书写习惯和代码层编排上保证整体项目的可架构性和规范性,协助控制项目维护成本不致过高。

如上场景适用于网络管理员、系统运维、应用运维、桌面运维、DevOps、基础架构运维等多领域运维行业,以及无运维岗但服务规模又需有一定精力投入维护的小型公司,开发人员经过简单的了解即可初步上手。同样也适用于中大型公司,可以投入人力、精力、财力对Ansible进行二次开发,使其更加适用。

1.7 Ansible的安装部署

了解完Ansible是什么、通信原理及发展史、Ansible发展历程及其应用场景后,接下来为大家介绍Ansible的安装部署。

Ansible的安装部署非常简单,其仅依赖于Python和SSH,而系统默认均已安装。除Windows外,RedHat、Debian、CentOS、OSX均可作为管理节点部署Ansible。Ansible被RedHat红帽官方收购后,其安装源被收录在EPEL中,如已安装EPEL可直接YUM或APT安装,通过pip和easy_install的Python第三方包管理器也可以便捷安装Ansible,下面我们详细介绍部署方式。

1.7.1 PIP方式

Ansible底层也是基于Python编写,所以可以通过PIP方式安装Ansible。

步骤1:安装python-pip及python-devel程序包。

// 安装python-pip程序包及python-devel,

yum install python-pip python-devel –y

返回类似如下结果则表示安装成功:

    Installing : python-devel-2.7.5-34.el7.x86_641/2

    Installing : python-pip-7.1.0-1.el7.noarch2/2

    Verifying  : python-pip-7.1.0-1.el7.noarch1/2

    Verifying  : python-devel-2.7.5-34.el7.x86_642/2


Installed:

    python-devel.x86_64 0:2.7.5-34.el7        python-pip.noarch 0:7.1.0-1.el7


Complete!

步骤2:安装Ansible服务。

// 安装请前确保服务器的gcc、glibc开发环境均已安装,系统几乎所有的软件包编译环境均基于gcc,如不确认可先执行如下命令:

yum install gcc glibc-devel zlib-devel  rpm-build openssl-devel –y

// 升级本地PIP至最新版本

pip install --upgrade pip

// 安装Ansible服务

pip install ansible –upgrade

执行命令ansible --version,有类似如下返回结果则表示Ansible安装成功并可正常使用。

ansible 2.1.1.0

    config file = /etc/ansible/ansible.cfg

    configured module search path = Default w/o overrides

如下其他验证安装是否成功的方式也一样,均可执行ansible––version验证,后面不一一列出。

1.7.2 YUM方式

YUM(Yellow dog Updater,Modif?ied)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器。基于RPM包管理,能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无需烦琐地一次次下载、安装。YUM安装Ansible过程如下:

// 需事先安装EPEl源后方可找到并安装Ansible

rpm -Uvh https:// dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm

// 安装Ansible

yum install ansible –y

安装速度视网络情况而定,因为安装过程会安装非常多的依赖包,又因各系统环境的差异性,如返回类似如下结果则表示安装成功:

Installed:

    ansible.noarch 0:2.1.1.0-1.el7


Dependency Installed:

    PyYAML.x86_64 0:3.10-11.el7          libtomcrypt.x86_64 0:1.17-23.el7

    libtommath.x86_64 0:0.42.0-4.el7     python-babel.noarch 0:0.9.6-8.el7

    python-httplib2.noarch 0:0.7.7-3.el7 python-jinja2.noarch 0:2.7.2-2.el7

    python-keyczar.noarch 0:0.71c-2.el7  python-markupsafe.x86_64 0:0.11-10.el7

    python-pyasn1.noarch 0:0.1.6-2.el7   python2-crypto.x86_64 0:2.6.1-9.el7

    python2-ecdsa.noarch 0:0.13-4.el7    python2-paramiko.noarch 0:1.16.1-1.el7

    sshpass.x86_64 0:1.05-5.el7


Complete!

1.7.3 Apt-get方式

Apt-get全称是Advanced Package Tool,是一款适用于UNIX和Linux系统的应用程序管理器,适用于Ubuntu、Debian等deb包管理式的操作系统,主要用于自动地从互联网的软件仓库中搜索、安装、升级、卸载软件或操作系统。

// 添加Ansible源

apt-add-repository -y ppa:ansible/ansible

// 升级库文件

apt-get update

// 安装Ansible

apt-get install -y ansible

1.7.4 源码安装方式

源码安装本身就是一道很高的门槛,作为刚接触Linux的新手不建议使用该方式。

在什么情况下我们需要从源代码安装软件呢?其实源码安装是相对于二进制安装而言的,所谓的二进制安装即前言讲到的,PIP、YUM、Apt-get都是二进制的安装方式,一般当新软件推出了新的版本,而所用的发行版并没有及时跟进,这时候,想要“尝鲜”的话,就非得靠自己而不可使用源码编译安装;另一种情形是,不管是软件的开发者还是现用的系统都没有提供可直接使用的二进制包,而自己又非要使用该软件,那么也需源码安装才行。当然,还有其他的情形。总而言之,学会源码安装软件方式是一项非常重要的技能,但又因其编译环境准备起来复杂不堪,同时安装过程又需人工逐一解决安装过程中可能遇到的各项应用层依赖和系统库依赖,所以门槛较高,故不建议初学者使用该方式。

// 不建议安装Beta版

// 安装Git客户端

yum install git –y

整个安装过程无报错,有类似如下返回结果则表示安装成功。

Installed:

    git.x86_64 0:1.8.3.1-5.el7


Dependency Installed:

    libgnome-keyring.x86_64 0:3.8.0-3.el7 perl-Error.noarch 1:0.17020-2.el7

    perl-Git.noarch 0:1.8.3.1-5.el7       perl-TermReadKey.x86_64 0:2.30-20.el7


Complete!

安装Ansible软件包。

// 使用Git将拉取指定的Ansible版本至本地当前目录

git clone git:// github.com/ansible/ansible.git –recursive

// 切换至程序包目录

cd ./ansible

// 执行env-setup脚本,安装Ansible软件包

source ./hacking/env-setup

1.7.5 验证安装结果

如上列举了互联网主流系统的Ansible安装方式,如整个过程均无报错,则执行如下命令应有类似结果返回:

ansible --version

ansible 1.9.6

如上述命令能正常执行,表示Ansible安装成功,并可正常使用。通常情况下,Ansible的安装简单顺利,但确实会有安装报错的情况发生,多数情况是由本地复杂的系统环境导致的。下面我们为大家介绍Python多环境管理,来解决该类问题。

1.8 Python多环境扩展管理

众所周知,Python发展至今,版本众多,部分版本功能差异较大,在使用过程中经常遇到第三方库依赖的Python版本和系统Python版本不一致的情况。同时又因系统底层需调用当前版本Python,所以不能随意变更当前系统Python版本。如此情景下就会有Python多版本共存的情况。于是,Python多环境管理工具应运而生。这里为大家介绍两款工具,分别是Pyenv和Virtualenv。Pyenv和Virtualenv均为Python管理工具,不同的是,前者是对Python的版本进行管理,实现不同版本间的切换和使用;而后者则通过创建虚拟环境,实现与系统环境以及其他Python环境的隔离,避免相互干扰。

1.8.1 Pyenv的部署与使用

Pyenv是一个简单的Python版本管理工具,以前叫作Pythonbrew。它让你能够方便地切换全局Python版本,安装多个不同的Python版本,设置独立的某个文件夹或者工程目录特异的Python版本,同时创建Python虚拟环境(virualenv's)。所有这些操作均可以在类UNIX系统的机器上(Linux和OS X)不需要依赖Python本身执行,而且它工作在用户层,不需要任何sudo操作。

(1)部署

Pyenv作为Python的版本管理工具,通过改变Shell的环境变量来切换不同的Python版本,以达到多版本共存的目的。该工具不支持Windows系统。具体工作原理如下。

1)Pyenv安装后会在系统PATH中插入shims路径,每次执行Python相关的可执行文件时,会优先在shims里寻找Python路径~/.pyenv/shims:/usr/local/bin:/usr/bin:/bin;

2)系统选择Python版本,依如下顺序选择Python的版本:

Shell变量设置(执行pyenv shell查看)

当前可执行文件目录下的.python_version文件里的版本号(执行pyenv shell查看)

上层目录查询找到的第一个.pyenv-version文件

全局的版本号在~/.pyenv/version文件内(执行pyenv global查看)

3)确定版本文件的位置和Python版本后,Pyenv会根据版本号在~/.pyenv/versions/文件夹中查找对应的Python版本。执行命令pyenv versions可查看系统目前安装的Python版本。

接下来开始部署Pyenv,具体部署方式如下:

// clone pyenv至家目录

git clone git:// github.com/yyuu/pyenv.git ~/.pyenv

// 修改环境变量

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc

echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc

echo 'eval "$(pyenv init -)"' >> ~/.bashrc

// 重启当前 Shell

exec $Shell –l

执行pyenv versions命令,有类似如下返回结果表示安装正常:

* system (set by /home/o2o/.pyenv/version)

    2.7.8

接下来我们来了解Pyenv的使用方式。

(2)通过Pyenv管理多Python版本

Pyenv命令使用规则如下:

Usage: pyenv <command> [<args>]

我们通过Pyenv安装Python 3.4.1版本来熟悉其用法。

// 查看可安装的版本列表

pyenv install –list

// 安装指定的Python版本

pyenv install 3.4.1

// 切换当前目录Python版本为3.4.1

pyenv local  3.4.1

// 切换全局目录Python版本为3.4.1

pyenv global  3.4.1

// 刷新shims

pyenv rehash

Pyenv更多用法如下:

commands 列出pyenv的所有可用命令

local 设置或列出当前环境下Python版本号

global 设置或列出全局环境下Python版本号

shell 设置或列出Shell环境下Python版本

install 安装指定的Python版本

uninstall 卸载指定的Python版本

rehash 重新加载Pyenv的shims路径(安装完Python版本后需执行该命令)

version 展示当前Python版本号及其生效的路径

versions 列出Pyenv管控的所有可用Python版本

which 列出要使用命令的绝对路径

whence 列出后缀命令的所有可用版本

至此,Pyenv介绍完毕,接下来再介绍一款Python多管理工具Virtualenv,它不是通过多版本管理的方式来实现系统同时兼容多Python环境。Virtualenv是底层基于Python开发的Python环境隔离工具,其通过虚拟目录的方式来实现多环境的并存。其工作原理很简单:在你所需的地方创建工作目录,该目录类似系统安装的Python目录,保留完整的Python环境、解释器、标准库和第三方库等,当我们需要时,切换环境变量激活即可使用。接下来我们进一步学习Virtualenv的安装部署及版本管理。

1.8.2 Virtualenv的部署与使用

Python的第三方包成千上万,在一个Python环境下开发时间越久、安装依赖越多,就越容易出现依赖包冲突的问题。为了解决这个问题,开发者们开发出了Virtualenv,它可以搭建虚拟且独立的Python环境。这样就可以使每个项目环境与其他项目独立开来,保持环境的干净,避免包冲突问题。另外,在开发Python应用程序的时候,所有第三方的包都会被PIP安装到系统Python版本的site-packages目录下。但如果我们要同时开发多个应用程序,那这些应用程序会共用一个Python,这意味着所有的包都安装在系统的Python目录下,这不仅影响我们的正常开发工作,还有可能因为随意变更系统Python版本信息而造成系统的不稳定。这种情况下,每个应用可能需要各自拥有一套“独立”的Python运行环境。Virtualenv就是用来为一个应用创建一套“隔离”的Python运行环境的。下面我们来看看Virtualevn的部署,以及它如何管理Python环境。

(1)部署

假设你已经学习过我们上节内容并安装好PIP了,那么Virtualenv的安装非常简单,操作如下:

// 安装virtualenv

pip install virtualenv

返回如下结果表示安装成功:

Installing collected packages: virtualenv

Successfully installed virtualenv-15.0.3

(2)通过Virtualenv管理多Python版本

需强调说明的是:Virtualenv不是通过多版本管理的方式来实现系统同时兼容多Python环境的,而是其通过在工作目录中虚拟完整的Python环境来实现Python多环境并存。接下来我们看Virtualenv的使用方式。

Virtualenv命令的使用格式如下:

virtualenv [OPTIONS] DEST_DIR

中括号OPTIONS表示参数选项,是可选项,即可有可无;DEST_DIR表示命令要执行的目录,如:

// 创建/data/magedu/的虚拟目录

virtualenv /data/magedu/

可用的OPTIONS选项如下:

--version  显示当前版本号。

-h, --help  显示帮助信息。

-v, --verbose  显示详细信息。

-q, --quiet  不显示详细信息。

-p PYTHON_EXE, --python=PYTHON_EXE  指定所用的python解析器的版本,比如--python=python2.5 就使用2.5版本的解析器创建新的隔离环境。默认使用的是当前系统安装(/usr/bin/python)的python解析器。

--clear  清空非root用户的安装,并从头开始创建隔离环境。

--no-site-packages  令隔离环境不能访问系统全局的site-packages目录。

--system-site-packages  令隔离环境可以访问系统全局的site-packages目录。

--unzip-setuptools  安装时解压Setuptools或Distribute。

--relocatable  重定位某个已存在的隔离环境。使用该选项将修正脚本,并令所有.pth文件使用相应路径。

--distribute  使用Distribute代替Setuptools,也可设置环境变量VIRTUALENV_DISTRIBUTE达到同样效果。

--extra-search-dir=SEARCH_DIRS  用于查找setuptools/distribute/pip发布包的目录。可以添加任意数量的–extra-search-dir路径。

--never-download  禁止从网上下载任何数据。此时,如果在本地搜索发布包失败,virtualenv就会报错。

--prompt==PROMPT  定义隔离环境的命令行前缀。

下面详细看看virtualenv在工作中的应用方式。我们先创建一个/data/dataf?ile/software/virtualpy/的虚拟工作目录,而后再切换至虚拟环境。

// 创建虚拟工作目录

virtualenv /data/datafile/software/virtualpy/

// 通过source加载环境变量,使本地环境切换至虚拟工作目录

source /data/datafile/software/virtualpy/bin/activate

看到如图1-4所示的Virtualenv虚拟工作目录标识,表示已切换至虚拟工作目录。


图1-4 Virtualenv虚拟工作目录

退出虚拟环境命令如下:

// 退出虚拟环境

Deactivate

看到如图1-5所示的退出虚拟工作目录显示正常的BASH Shell提示符,表示即已退出虚拟工作目录。


图1-5 退出虚拟工作目录

至此,多版本Python环境管理工具Pyenv和Virtualenv介绍完毕。如果基于系统默认Python版本安装有问题,可尝试基于Pyenv或Virtualenv切换Python版本后,再次重试1.7节Ansible的安装步骤。

1.9 本章小结

Ansible是运维自动化工具的后起之秀。本章前半部分我们学习了Ansible是什么,底层通信发展史,Ansible发展历程等概念性知识。后半部分我们详细介绍了Ansible安装部署方式,同时考虑本地复杂环境可能导致的部署问题,本章后半部分我们也引申介绍了Python多环境扩展管理,以方便大家应对部署过程中可能出现的各类问题。当然,Ansible的部署总体非常简单,一般出问题多数是因为系统的glibc、gcc等开发环境没有安装或不完整导致。在学习过程中还请严格参考本章安装操作步骤循序渐进,相信大家学完本章也有所体会。







第2章

Ansible基础元素介绍

第1章介绍了Ansible的功能作用、通信发展史、基础的安装部署及处理Ansible安装问题所需的Python多环境管理工具Pyenv和Virutalenv。在前期基本工作准备妥当的基础上,本章进一步深入学习Ansible的基础元素,会相继接触Ansible目录结构简介、Ansible系列命令、Ansible Inventory配置规范、Ansible模式匹配规则等,其中部分内容,诸如Inventory、Ansible-playbook等在后续涉及章节会更深入介绍。本章主要是为大家呈现Ansible及系列命令的基础入门介绍,所介绍的内容相互之间没有紧密关系,可选择性地阅读感兴趣章节。

2.1 Ansible目录结构介绍

Ansible是开源工具,整个开发过程或二次开发均遵循GPL协议,所以所有源码均可见。作为一款日常工作所需的核心软件,我们有必要知道其目录分布及各目录功能。通过如下命令我们可以获取Ansible所有文件存放目录:

# rpm -ql ansible

该命令输出内容较多,大致分为如下几类:

配置文件目录/etc/ansible/

执行文件目录/usr/bin/

Lib库依赖目录/usr/lib/pythonX.X/site-packages/ansible/

Help文档目录/usr/share/doc/ansible-X.X.X/

Man文档目录/usr/share/man/man1/

整体的目录概要可参考如图2-1所示的Ansible目录树结构。


图2-1 Ansible目录树结构

其中,如下目录运维常要配置,需熟练掌握。

1)配置文件目录/etc/ansible/,主要功能为:Inventory主机信息配置、Ansible工具功能配置等。所有Ansible的配置均存放在该目录下,运维日常的所有配置类操作也均基于此目录进行。

2)执行文件目录/usr/bin/,主要功能为:Ansible系列命令默认存放目录。Ansible所有的可执行文件均存放在该目录下。

在/usr/lib/pythonXXX/site-packages/下,该目录是系统当前默认的Python路径,因为Ansible是基于Python编写的,所以Ansible的所有lib库文件和模块文件也均存放于该目录下。希望了解Ansible源码的话可至该目录下查看其工作原理,当然也可至GitHub上下载历史或最新Ansible版本。

2.2 Ansible配置文件解析

Inventory用于定义Ansible的主机列表配置,Ansible的自身配置文件只有一个,即ansible.cfg,Ansible安装好后它默认存放于/etc/ansible/目录下。ansible.cfg配置文件可以存在于多个地方,Ansible读取配置文件的顺序依次是当前命令执行目录→用户家目录下的.ansible.cfg→/etc/ansible.cfg,先找到哪个就使用哪个的配置。其ansible.cfg配置的所有内容均可在命令行通过参数的形式传递或定义在Playbooks中。

配置文件ansible.cfg约有350行语句,大多数为注释行默认配置项。该文件遵循INI格式,分为如下几类配置。

(1)[defaults]

该类配置下定义常规的连接类配置,如inventory、library、remote_tmp、local_tmp、forks、poll_interval、sudo_user、ask_sudo_pass、ask_pass、transport、remote_port等。

[defaults]

# inventory = /etc/ansible/hosts # 定义Inventory

# library = /usr/share/my_modules/ # 自定义lib库存放目录

# remote_tmp = $HOME/.ansible/tmp # 临时文件远程主机存放目录

# local_tmp = $HOME/.ansible/tmp # 临时文件本地存放目录

# forks = 5 # 默认开启的并发数

# poll_interval = 15 # 默认轮询时间间隔

# sudo_user  = root # 默认sudo用户

# ask_sudo_pass = True # 是否需要sudo密码

# ask_pass  = True # 是否需要密码

# roles_path = /etc/ansible/roles # 默认下载的Roles存放的目录

# host_key_checking = False # 首次连接是否需要检查key认证,建议设为False

# timeout = 10 # 默认超时时间

# timeout = 10 # 如没有指定用户,默认使用的远程连接用户

# log_path = /var/log/ansible.log # 执行日志存放目录

# module_name = command # 默认执行的模块

# action_plugins = /usr/share/ansible/plugins/action # action插件的存放目录

# callback_plugins = /usr/share/ansible/plugins/callback # callback插件的存放目录

# connection_plugins = /usr/share/ansible/plugins/connection # connection插件的

# 存放目录

# lookup_plugins = /usr/share/ansible/plugins/lookup # lookup插件的存放目录

# vars_plugins = /usr/share/ansible/plugins/vars # vars插件的存放目录

# filter_plugins = /usr/share/ansible/plugins/filter # filter插件的存放目录

# test_plugins = /usr/share/ansible/plugins/test # test插件的存放目录

# strategy_plugins = /usr/share/ansible/plugins/strategy # strategy插件的存放目录

# fact_caching = memory # getfact缓存的主机信息存放方式

# retry_files_enabled = False

# retry_files_save_path = ~/.ansible-retry # 错误重启文件存放目录

上述是日常可能用到的配置,这些多数保持默认即可。

(2)[privilege_escalation]

出于安全角度考虑,部分公司不希望直接以root的高级管理员权限直接部署应用,往往会开放普通用户权限并给予sudo的权限,该部分配置主要针对sudo用户提权的配置。

[privilege_escalation]

# become=True # 是否sudo

# become_method=sudo # sudo方式

# become_user=root # sudo后变为root用户

# become_ask_pass=False # sudo后是否验证密码

(3)[paramiko_connection]

定义paramiko_connection配置,该部分功能不常用,了解即可。

[paramiko_connection] # 该配置不常用到

# record_host_keys=False # 不记录新主机的key以提升效率

# pty=False # 禁用sudo功能

(4)[ssh_connection]

Ansible默认使用SSH协议连接对端主机,该部署是主要是SSH连接的一些配置,但配置项较少,多数默认即可。

[ssh_connection]

# pipelining = False # 管道加速功能,需配合requiretty使用方可生效

(5)[accelerate]

Ansible连接加速相关配置。因为有部分使用者不满意Ansible的执行速度,所以Ansible在连接和执行速度方面也在不断地进行优化,该配置项在提升Ansibile连接速度时会涉及,多数保持默认即可。

[accelerate]

# accelerate_port = 5099 # 加速连接端口

# accelerate_timeout = 30 # 命令执行超时时间,单位秒

# accelerate_connect_timeout = 5.0 # 连接超时时间,单位秒

# accelerate_daemon_timeout = 30 # 上一个活动连接的时间,单位分钟

# accelerate_multi_key = yes

(6)[selinux]

关于selinux的相关配置几乎不会涉及,保持默认配置即可。

[selinux]

# libvirt_lxc_noseclabel = yes

# libvirt_lxc_noseclabel = yes

(7)[colors]

Ansible对于输出结果的颜色也进行了详尽的定义且可配置,该选项对日常功能应用影响不大,几乎不用修改,保持默认即可。

[colors]

# highlight = white

# verbose = blue

# warn = bright purple

# error = red

# debug = dark gray

# deprecate = purple

# skip = cyan

# unreachable = red

# ok = green

# changed = yellow

# diff_add = green

# diff_remove = red

# diff_lines = cyan

上面尽可能全地介绍了运维工作中可能需要修改的配置选项,除了在关闭首次连接提示(host_key_checking = False)或提速调整([accelerate]区域块配置调整)时可能会稍做调整,其中绝大多数选项默认即可,Ansible安装好后无需任何改动即可使用。

2.3 Ansible命令用法详解

Ansible命令行执行方式有Ad-Hoc、Ansible-playbook两种方式,Web化执行方式其官方提供了付费产品Tower(10台以内免费),个人的话可以基于其提供的API开发类似的Web化产品。关于命令行执行的两种方式Ad-Hoc和Ansible-playbooks、什么是Ad-Hoc及Ad-Hoc与Ansible-playbook的区别我们在第3章有详细介绍,这里不再赘述。需简要说明的是两者没有本质上的区别,Ad-Hoc主要用于临时命令的执行,Ansibel-playbook可以理解为Ad-Hoc的集合,通过一定的规则编排在一起。两者的操作也极其简便,且提供了如with_items、failed_when、changed_when、until、ignore_errors等丰富的逻辑条件和Dry-run的Check Mode。但在Chceck Mode下并不真正执行命令,即将执行的操作不会对端服务器产生任何影响,只模拟命令的执行过程是否能正常执行。

通过第1章的学习我们知道,Ansible的通信默认基于SSH,因此我们需要对主机先进行认证。Ansible认证方式有密码认证和公私钥认证两种方式,其实完全等同于SSH的认证,所以这里关于这两种认证方式不做过多介绍。Ansible默认使用(笔者也建议各位使用)公私钥认证方式,究其原因无非是出于安全的考虑,密码不用明文存放。以本机为例,执行如下命令即可添加本机认证信息。

// 随机生成公私钥对,ssh-keygen是Linux下认证密钥生成、管理和转换工具,详细用法可参考其man文档

ssh-keygen  -N "" -b 4096 -t rsa -C "stanley@magedu.com" -f /root/.ssh/stanley.rsa

// 为本机添加密钥认证

ssh-copy-id –i /root/.ssh/stanley.rsa root@localhost

输入的时候会有如下提示:

Are you sure you want to continue connecting (yes/no)?

输入全小写的英文字母yes即可。

而后会有类似如下提示输入对应root用户的密码信息:

root@localhost's password:

输入正确的密码信息后结果认证,随后在当前命令行输入如下命令尝试免密码登录:

ssh -i /root/.ssh/stanley.rsa root@localhost

如不提示输入密码即可直接登录则表示密钥验证成功。当然,这里只是为大家简要演示密钥认证的过程,实际应用中为方便起见,一般会使用非root用户生成默认文件名为id_rsa、id_rsa.pub的密钥对,在使用时通过sudo的方式获取权限。

Ansible的命令使用格式如下:

ansible <host-pattern> [options]

<host-pattern>是Inventory中定义的主机或主机组,可以为ip、hostname、Inventory中的group组名、具有“.”或“*”或“:”等特殊字符的匹配型字符串,<>表示该选项是必须项,不可忽略。

[options]是Ansible的参数选项,[]表示该选项中的参数任选其一。

Ansible命令可用选项非常多,这里列举如下会用到的选项,详细选项可参考man或第3章。

-m NAME, --module-name=NAME:指定执行使用的模块。

-u USERNAME, --user=USERNAME:指定远程主机以USERNAME运行命令。

-s, --sudo:相当于Linux系统下的sudo命令。

-U SUDO_USERNAME, --sudo-user=SUDO_USERNAME:使用sudo,相当于Linux下的sudo命令。

具体示例如下:

// 以bruce用户执行ping存活检测

ansible all -m ping -u bruce

// 以bruce sudo至root执行ping存活检测

ansible all -m ping -u bruce --sudo

// 以bruce sudo至batman用户执行ping存活检测

ansible all -m ping -u bruce --sudo --sudo-user batman

但在新版本中Ansible的sudo命令废弃,改为--become或-b,如上命令需改为如下:

// 以bruce sudo至root执行ping存活检测

ansible all -m ping -u bruce -b

// 以bruce sudo至batman用户执行ping存活检测

ansible all -m ping -u bruce -b --become-user batman

Ansible-playbook的命令用法和Ansible略有不同,虽然参数选项与Ansible有很多相同的地方,但也新增了针对Ansible-playbook特有的参数。

Ansible-playbook的命令使用格式如下:

ansible-playbook playbook.yml

ansible-playbook命令后跟事先编辑好的playbook.yml文件即可。本节只简单介绍其用法,在第4、5、6章有大量内容介绍其写法、高级用法及优化方向。Ansible-playbook新增的功能参数如下:

--ask-vault-pass:加密playbook文件时提示输入密码。

-D, --diff:当更新的文件数及内容较少时,该选项可显示这些文件不同的地方,该选项结合-C用会有较好的效果。

-e EXTRA_VARS, --extra-vars=EXTRA_VARS:在Playbook中引入外部变量。

--f?lush-cache:将fact清除到的远程主机缓存。

--force-handlers:强制运行handlers的任务,即使在任务失败的情况下。

-i INVENTORY:指定要读取的Inventory文件。

--list-tags:列出所有可用的tags。

--list-tasks:列出所有即将被执行的任务。

--skip-tags=SKIP_TAGS:跳过指定的tags任务。

--start-at-task=START_AT_TASK:从第几条任务开始执行。

--step:逐步执行Playbook定义的任务,并经人工确认后继续执行下一步任务。

--syntax-check:检查Playbook中的语法书写。

-t TAGS, --tags=TAGS:指定执行该tags的任务。

在日常工作中,大家经常会遇到批量添加认证的问题,而逐条添加认证方式,如机械地对每台主机都一条条添加认证,那是一件非常麻烦的事,也违反了我们期望的自动化方式。具体的批量添加认证方式请参考第9章。如前面所介绍,Ansible不仅有ansible、ansible-playbook命令,还有ansible-galaxy、ansible-pull、ansible-doc、ansible-vault、ansible-console(2.0版本新增)命令,掌握Ansible的基础用法后,我们将更深一步学习Ansible系列命令。

2.4 Ansible系列命令用法详解与使用场景介绍

如何获取Ansible的系列命令呢?在终端键入ansible后连续按两次Tab键,会补全所有以ansible字母开头的命令,这些命令均是Ansible系列命令。本节我们来逐一介绍Ansible的系列命令使用。

ansible

ansible-galaxy

ansible-pull

ansible-doc

ansible-playbook

ansible-vault

ansible-console

2.4.1 ansible

命令ansible是日常工作中使用率非常高的命令之一,man中是如此定义其功能的:run a command somewhere else,可见其灵活性。ansible命令主要在如下场景使用:

非固化需求

临时一次性操作

二次开发接口调用

那么什么是非固化需求和临时一次性操作呢?简单来讲,比如工作中我临时想查看web1服务器组是否存活,或我想临时复制本地的/etc/fstab到web服务器组的/tmp目录下做测试,类如这些没有规律的、临时需要做的任务,我们称之为非固化需求、临时一次性操作。具体的命令使用如下:

// 检查服务器存活

ansible web1 –m ping

// 复制本地文件到远程

ansible web1 –m copy –a "src=/etc/fstab dest=/tmp/fstab owner=root group=root mode=644 backup=yes"

Ansible的返回结果都非常友好,一般会用3种颜色来表示执行结果:红色、绿色、橘黄色。其中红色表示执行过程有异常,一般会中止剩余所有的任务,如图2-2所示的Ansible执行结果错误的结果返回;绿色和橘黄色表示执行过程没有异常,所有任务均正常执行,但橘黄色表示命令执行结束后目标有状态的变化。如图2-3所示,Ansible执行结果正确的结果返回中的圆圈1为橘黄色显示;而绿色表示命令执行结束后目标没有状态变化,如图2-3中的圆圈2显示。


图2-2 Ansible执行结果错误的结果返回


图2-3 Ansible执行结果正确的结果返回

不仅ansible命令的执行结果如此设置,Ansible系列命令均如此设置,所以判断Ansible系列命令的执行结果是否正常是一件非常容易的事情,只要看颜色即可。

2.4.2 ansible-galaxy

这里的galaxy和三星手机没有任何关系。ansible-galaxy的功能可以简单地理解为GitHub或PIP的功能,通过ansible-galaxy命令,我们可以根据下载量和关注量等信息,查找和安装优秀的Roles。Roles是Ansible非常重要的一项功能,关于Roles的详细功能会在第6章介绍。在ansible-galaxy上,我们可以上传和下载Roles,这里也是优秀Roles的聚集地,下载地址为https://galaxy.ansible.com。

ansible-galaxy命令使用格式如下:

ansible-galaxy [init|info|install|list|remove] [--help] [options] ...

ansible-galaxy命令分三大部分:

(1)[init|info|install|list|remove]

init:初始化本地的Roles配置,以备上传Roles至galaxy。

info:列表指定Role的详细信息。

install:下载并安装galaxy指定的Roles到本地。

list:列出本地已下载的Roles。

remove:删除本地已下载的Roles。

Ansible 2.0版本中,针对ansible-galaxy增加了login、import、delete、setup等功能,但这些功能需基于login在galaxy认证成功后方可执行,主要为了方便对galaxy上已有的Roles的配置工作。

(2)help用法显示[--help]

针对第一部分的init、info等功能,其后跟--help可单独显示该项用法。例如:

ansible-galaxy init ––help

执行后会返回ansible-galaxy init选项的用法说明。

Usage: ansible-galaxy init [options] role_name


Options:

    -f, --force           Force overwriting an existing role

    -h, --help            show this help message and exit

    -c, --ignore-certs    Ignore SSL certificate validation errors.

    -p INIT_PATH, --init-path=INIT_PATH

                          The path in which the skeleton role will be created.

                          The default is the current working directory.

    --offline             Don't query the galaxy API when creating roles

    -s API_SERVER, --server=API_SERVER

                          The API server destination

    -v, --verbose         verbose mode (-vvv for more, -vvvv to enable

                          connection debugging)

    --version             show program's version number and exit

其他选项与help用法一样。

(3)参数项[options]

该部分结合第一部分的参数完成ansible-galaxy完整的功能用法,如:

ansible-galaxy init [options] role_name即ansible-galaxy init后跟[-f|-h|-c|-p|--off?line|-s SERVER|-v|--version]参数,后跟role-name成为一条完整的命令。

具体可参考如下:

// 下载用户hectcastro的Nginx这个Role到本地并忽略错误(默认存放在/etc/ansible/roles/)

ansible-galaxy --ignore-errors install azavea.git

因为ansible-galaxy是对https://galaxy.ansible.com网站的上传、下载、配置类工作,如有类似如下报错,请确保该网站可正常访问。

the API server (galaxy.ansible.com) is not responding, please try again later.

2.4.3 ansible-pull

该指令的使用涉及Ansible的另一种工作模式:pull模式(Ansible默认使用push模式)。这和通常使用的push模式工作机理刚好相反,其适用于以下场景:①你有数量巨大的机器需要配置,即使使用高并发线程依旧要花费很多时间;②你要在刚启动的、没有网络连接的主机上运行Anisble。

ansible-pull命令使用格式如下:

ansible-pull [options] [playbook.yml]

通过ansible-pull结合Git和crontab一并实现,其原理如下:通过crontab定期拉取指定的Git版本到本地,并以指定模式自动运行预先制订好的指令。

具体示例参考如下:

*/20 * * * * root /usr/local/bin/ansible-pull -o -C 2.1.0 -d /srv/www/king-gw/ -i /etc/ansible/hosts -U git:// git.kingifa.com/king-gw-ansiblepull >> /var/log/ansible-pull.log 2>&1

ansible-pull通常在配置大批量机器的场景下会使用,灵活性稍有欠缺,但效率几乎可以无限提升,对运维人员的技术水平和前瞻性规划有较高要求。

2.4.4 ansible-doc

ansible-doc是Ansible模块文档说明,针对每个模块都有详细的用法说明及应用案例介绍,功能和Linux系统man命令类似。该命令使用方式如下:

ansible-doc [options] [module...]

ansible-doc命令后跟[options]参数或[模块名],显示模块用法说明,具体示例如下:

// 列出支持的模块

ansible-doc –l

// 模块功能说明

ansible-doc ping

2.4.5 ansible-playbook

ansible-playbook是日常应用中使用频率最高的命令,其工作机制是:通过读取预先编写好的playbook文件实现批量管理。要实现的功能与命令ansible一样,可以理解为按一定条件组成的ansible任务集。

ansible-playbook命令后跟YML格式的playbook文件,执行事先编排好的任务集,命令使用方式如下:

ansible-playbook playbook.yml

具体示例如下:

// 执行gw.yml这个playbook中定义的所有任务集

ansible-playbook gw.yml

Playbook具有编写简单、可定制性高、灵活方便,以及可固化日常所有操作的特点,运维人员应熟练掌握。

2.4.6 ansible-vault

ansible-vault主要用于配置文件加密,如编写的Playbook配置文件中包含敏感信息,不希望其他人随意查看,ansible-vault可加密/解密这个配置文件,具体使用方式如下:

Usage: ansible-vault [create|decrypt|edit|encrypt|rekey|view] [--help] [options] file_name

具体示例如下。

设定如下密码,加密a.yml文件。

ansible-vault   encrypt a.yml

会有以下输入加密密码提示:

Vault password:

Confirm Vault password:

Encryption successful

这时,再打开a.yml文件后会发现该文件乱码,只有通过如下命令解密后方可正常查看。

ansible-vault decrypt a.yml

输入预设的密码后方可解密。

Vault password:

Decryption successful

此时a.yml文件可正常查看。

到此,我们对Ansible的用法及系列命令已经有了概念性的了解和掌握,接下来我们进一步了解Ansible Inventory文件的配置管理。

2.4.7 ansible-console

ansible-console是Ansible为用户提供的一款交互式工具,用户可以在ansible-console虚拟出来的终端上像Shell一样使用Ansible内置的各种命令,这为习惯于使用Shell交互方式的用户提供了良好的使用体验。ansible-console主要是针对1.X版本中ansible-shell工具而研发的,目前官网还没有对ansible-console进行详细的用法说明,最新版本的Ansible软件包也没有对应的man文档说明。经笔者实测,ansible-console命令的使用格式如下。

在终端键入ansible-console命令后,会进入如图2-4所示的类似Shell一样的交互式终端环境。


图2-4 ansible-console命令用法1

图2-4中的“root@all (4)[f:5]$”是提示符,该提示符表示“当前的使用用户@当前所在的Inventory中定义的组,默认是all分组(Inventory中all组所有主机的数量)[forks:线程数]$”。

使用cd命令可切换至指定Hosts或分组,同时提示符的相应信息也会随之变动,如图2-5所示。


图2-5 ansible-console命令用法2

如图2-5中的Ansible-console命令用法2所示,cd至webs分组后,原来的root@all (4)[f:5]$也相应地变更为root@webs (3)[f:5],表示当前分组为webs分组,该分组所拥有的主机总数为3台。执行forks 2后,提示符再次变更为root@webs (3)[f:2]$,表示设置并发的线程数为2。

所有的操作与Shell类似,而且支持Tab键补全,如启动httpd服务时,键入service后连续按两次Tab键后会自动补全剩余的命令选项。ansible-console命令用法3如图2-6所示。


图2-6 ansible-console命令用法3

如需启动httpd服务,使用命令service name=httpd state=started,命令用法与Ad-Hoc一致,只是格式上的使用习惯不同而已。如想获取service模块更详细的用法,输入help service命令即可。ansible-console命令用法4如图2-7所示。


图2-7 ansible-console命令用法4

使用完毕如希望退出,按快捷键Ctrl+D或Ctrl+C即可退出当前的虚拟终端。

ansible-console命令在实际工作中用于Ad-Hoc和Ansible-playbooks之间的场景,常用于集中一批临时操作或命令,使用Ad-Hoc要键入很多次但整体操作的复杂度又不至于使用Playbooks时,这时ansible-console是最佳选择。

2.5 Ansible Inventory配置及详解

Inventory是Ansible管理主机信息的配置文件,相当于系统HOSTS文件的功能,默认存放在/etc/ansible/hosts。为方便批量管理主机,便捷使用其中的主机分组,Ansible通过Inventory来定义其主机和组,在使用时通过–i或--inventory-file指定读取,与Ansible命令结合使用时组合如下:

ansible –i /etc/ansible/hosts webs –m ping

如果只有一个Inventory时可不用指定路径,默认读取/etc/ansible/hosts。Inventory可以同时存在多个,而且支持动态生成,如AWS EC2、Cobbler等均支持,本节我们来学习Inventory的使用规则。

2.5.1 定义主机和组

Inventory配置文件遵循INI文件风格,中括号中的字符为组名。其支持将同一个主机同时归并到多个不同的组中,分组的功能为IT人员维护主机列表提供了非常大的便利。此外,若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明,以行为单位分隔配置,详细信息可参考以下代码中的注释。

# “# ”开头的行表示该行为注释行,即当时行的配置不生效

# Inventory可以直接为IP地址

192.168.37.149

# Inventory同样支持Hostname的方式,后跟冒号加数字表示端口号,默认22号端口

ntp.magedu.com:2222

nfs.magedu.com

# 中括号内的内容表示一个分组的开始,紧随其后的主机均属于该组成员,空行后的主机亦属于该组,即web2.magedu.com这台主机也属于[websevers]组

[websevers]

web1.magedu.com

web[10:20].magedu.com # [10:20]表示10~20之间的所有数字(包括10和20),即表示web10.magedu.com、web11.magedu.com……web20.magedu.com的所有主机


web2.magedu.com[dbservers]

db-a.magedu.com

db-[b:f].magedu.com # [b:f]表示b到f之间的所有数字(包括b和f),即表示db-b.magedu.com、db-e.magedu.com……db-f.magedu.com的所有主机

2.5.2 定义主机变量

在日常工作中,通常会遇到非标准化的需求配置,如考虑到安全性问题,业务人员通常将企业内部的Web服务80端口修改为其他端口号,而该功能可以直接通过修改Inventory配置来实现,在定义主机时为其添加主机变量,以便在Playbook中使用针对某一主机的个性化要求。

[webservers]

web1.magedu.com http_port=808 maxRequestsPerChild=801 # 自定义http_port的端口号为808,配置maxRequestsPerChild为801

Ansible其实支持多种方式修改或自定义变量,Inventory是其中的一种修改方式,在第6章中我们会详细介绍。不管哪种修改方式,大家一定要有自己的修改规范,以便于区别管理已有配置。

2.5.3 定义组变量

Ansible支持定义组变量,主要针对大量机器的变量定义需求,赋予指定组内所有主机在Playbook中可用的变量,等同于逐一给该组下的所有主机赋予同一变量。定义组变量的参考案例如下:

[groupservers]

web1.magedu.com

web2.magedu.com


[groupservers:vars]

ntp_server=ntp.magedu.com  # 定义groupservers组中所有主机ntp_server值为ntp.magedu.com

nfs_server=nfs.magedu.com # 定义groupservers组中所有主机nfs_server值为nfs.magedu.com

2.5.4 定义组嵌套及组变量

Inventory中,组还可以包含其他的组(嵌套),并且也可以向组中的主机指定变量。不过,这些变量只能在Ansible-playbook中使用,而Ansible不支持。组与组之间可以相互调用,并且可以向组中的主机指定变量。

参考示例如下:

[apache]

httpd1.magedu.com

httpd2.magedu.com


[nginx]

ngx1.magedu.com

ngx2.magedu.com


[webservers:children]

apache

nginx


[webservers:vars]

ntp_server=ntp.magedu.com

Ansible以简单为其核心理念,上述实现在业务日常使用中并不常见,大家了解其用法即可。

2.5.5 多重变量定义

变量除了可以在Inventory中一并定义,也可以独立于Inventory文件之外单独存储到YAML格式的配置文件中,这些文件通常以.yml、.yaml、.json为后缀或者无后缀。变量通常从如下4个位置检索:

Inventory配置文件(默认/etc/ansible/hosts)

Playbook中vars定义的区域

Roles中vars目录下的文件

Roles同级目录group_vars和hosts_vars目录下的文件

假如foosball主机同属于raleigh和webservers组,那么其变量在如下文件中设置均有效:

/etc/ansible/group_vars/raleigh # can optionally end in '.yml', '.yaml', or '.json'

/etc/ansible/group_vars/webservers

/etc/ansible/host_vars/foosball

对于变量的读取,Ansible遵循如上优先级顺序,因此大家设置变量时尽量沿用同一种方式,以方便维护人员管理。

2.5.6 其他Inventory参数列表

除了支持如上的功能外,Ansible基于SSH连接Inventory中指定的远程主机时,还内置了很多其他参数,用于指定其交互方式,如下列举了部分重要参数:

ansible_ssh_host:指定连接主机ansible_ssh_port,指定SSH连接端口,默认22

ansible_ssh_user:指定SSH连接用户ansible_ssh_pass,指定SSH连接密码ansible_sudo_pass:指定SSH连接时sudo密码

ansible_ssh_private_key_file:指定特有私钥文件

其他内置参数还有数十个,这些参数均可以直接写在命令行或Playbook文件中,以覆盖配置文件中的定义。更多参数请参考官网。

2.6 Ansible与正则

正则表达式(Patterns)是各类高级语言的必定支持的方法之一,Ansible也不例外。其Patterns功能等同于正则表达式,语法使用也和正则类同,这大大便利了运维的使用。其对于Ansible的灵活性有着极大贡献,该功能同样支持Ansible-playbook。其用法也非常简单。

ansible <pattern_goes_here> -m <module_name> -a <arguments>

该功能主要针对Inventory的主机列表使用,我们通过一些案例可以更好地了解其功能及用法。在如下示例中主要针对webservers进行正则匹配:

// 重启webservers组所有主机的httpd服务

ansible webservers -m service -a "name=httpd state=restarted"

(1)All(全量)匹配

匹配所有主机,all或*号功能相同。如检测所有主机存活情况。

// all和*功能相同,但*号需引起来

ansible all –m ping

ansible "*" -m ping

检查192.168.1.0/24网段所有主机存活状况。

ansible 192.168.1.* -m ping

(2)逻辑或(or)匹配

如我们希望同时对多台主机或多个组同时执行,相互之间用“:”(冒号)分隔即可。

web1:web2

使用方式如下:

ansible "web1:web2" -m ping

(3)逻辑非(!)匹配

逻辑非用感叹号(!)表示,主要针对多重条件的匹配规则,使用方式如下:

// 所有在webservers组但不在phoenix组的主机

webservers:!phoenix

(4)逻辑与(&)匹配

和逻辑非一样,逻辑与也主要针对多重条件的匹配规则,只是逻辑上的判断不同。逻辑与使用&表示,请看如下示例:

// webservers组和staging组中同时存在的主机

webservers:&staging

(5)多条件组合

Ansible同样支持多条件的复杂组合,该情况企业应用不多,这里做简单举例说明。

// webservers和dbservers两个组中的所有主机在staging组中存在且在 phoenix组中不存在的主机

webservers:dbservers:&staging:!phoenix

(6)模糊匹配

*通配符在Ansible表示0个或多个任意字符,主要应用于一些模糊规则匹配,在平时的使用中应用频率非常高,请参考如下示例:

// 所有以.magedu.com结尾的主机均符合

*.magedu.com

// one开头.com结尾的所有主机和dbservers组中的所有主机

one*.com:dbservers

(7)域切割

Ansible底层基于Python,因此也支持域切割。Python字符串域切割的示例如下:

str = '12345678'

print str[0:1]

通过[0:1]即可获取数值1。该功能在Ansible中也支持,以如下Inventory内容为例:

[webservers]

cobweb

webbing

weber

通过截取数组下标可以获得对应变量值。

webservers[0] # == cobweb

webservers[-1] # == weber

webservers[0:1] # == webservers[0],webservers[1]

# == cobweb,webbing

webservers[1:] # == webbing,weber

(8)正则匹配

Ansible同样完整支持正则匹配功能,“~”开始表示正则匹配。

~(web|db).*\.example\.com

检测beta.example.com、web.example.com、green.example.com、beta.example.org、web.example.org、green.example.org的存活,使用如下匹配模式:

ansible "~(beta|web|green)\.example\.(com|org)" -m ping

检测Inventory中所有以192.168开头的服务器存活信息:

ansible ~192\.168\.[0-9]\{\2}.[0-9]\{2,} -m ping

关于Ansible的正则功能到此结束,相信大家在浏览的过程中对其灵活程度也会有所感触,在对Ansible的实际应用过程中也会不断地加深对其理解。

2.7 本章小结

本章着重为大家介绍了Ansible目录结构功能及Ansible命令使用方式。在对Ansible的使用有概念性的了解后,又介绍Ansible系列命令的功能作用,通过简单的案例加深对各命令功能的理解。Inventory是Ansible的核心功能点之一,本章用了约一半内容讲解了Inventory的入门、书写规范、使用技巧及其与正则的结合使用。正则作为运维必备技能与Ansible的结合也使得Ansible愈显灵活,功能也愈显强大,请务必熟练掌握。下章我们将为大家介绍Ansible Ad-Hoc命令集的进阶使用。






第3章

Ansible Ad-Hoc命令集

第2章介绍了Ansible的各项元素、系列命令、Inventory基础,以及Ansible与正则的结合使用,这些内容是掌握Ansible的基础,请务必熟练掌握。在前两章的基础上,本章为大家介绍Ansible Ad-Hoc命令集,通过模拟真实的企业案例和应用场景更深入地了解Ansible。作为Ansible最常用的命令,本节内容显得尤为重要。

3.1 Ad-Hoc使用场景

所谓Ad-Hoc,简而言之是“临时命令”,英文中作为形容词有“特别的,临时”的含义。Ad-Hoc只是官方对Ansible命令的一种称谓,大家按各自习惯称呼即可。笔者平时一般称之为“临时操作”或Ansible命令。

从功能上讲,Ad-Hoc是相对Ansible-playbook而言的,Ansible提供两种完成任务方式:一种是Ad-Hoc命令集,即命令ansible,另外一种就是Ansible-playbook了,即命令ansible-playbook。前者更注重于解决一些简单或者平时工作中临时遇到的任务,相当于Linux系统命令行下的Shell命令,后者更适合于解决复杂或需固化下来的任务,相当于Linux系统的Shell Scripts。通常,深入Ansible是从接触Ansible-playbook开始的,灵活运用Ansible-playbook才能更好地体会到Ansible的强大所在。

具体来讲,什么样的场景下我们需要用到Ad-Hoc,什么样的情况下需要使用Ansible-playbook呢?

(1)需要使用Ad-Hoc的场景

情景1:

节假日将至,我们需要关闭所有不必要的服务器,并对所有服务器进行节前健康检查。

情景2:

临时更新Apache &Nginx的配置文件,且需同时将其分发至所有需更新该配置的Web服务器。

(2)需要使用Ansible-playbook的场景

情景1:

新购置的服务器安装完系统后需做一系列固化的初始化工作,诸如:定制防火墙策略、添加NTP时间同步配置、添加EPEL源等。

情景2:

业务侧每周定期对生产环境发布更新程序代码。

其实两者之间关系用急行军(Ad-Hoc)和远征军(Ansible-playbook)来形容可能更容易理解。急行军需轻装上阵,注重灵活机动;远征军需稳扎稳打,注重长远规划。正如我们上面所讲,Ad-Hoc更注重于解决一些简单或者平时工作中临时遇到的任务,Ansible-playbook更适合于解决复杂的或需固化下来的任务。后面的章节中我们会介绍大量企业实战场景,相信大家会有更深刻的体会。

3.2 Ad-Hoc命令集介绍

本节介绍通过Ad-Hoc命令集查看系统设置,通过Ad-Hoc研究Ansible的并发特性,通过Ad-Hoc研究Ansible的模块使用。俗话说,磨刀不误砍柴工。开始之前做一些简单的初始化检查,如系统时间正确与否、磁盘容量是否充足等,是很有必要的。

在实际工作中,很多“诡异”问题迫使我们花费大量时间排查,最终却发现是非常简单的基础环境问题导致的。这其实还是挺常见的,不论对新手还是老鸟均如此,谨记!

我们前面做的系统时间正确与否、磁盘容量是否充足等工作,其实Linux下是有开源工具可以帮助我们自动监控的。这里也为大家推荐几款Linux下耳熟能详的监控工具,如Zabbix、Nagios、Cacti、falcon、Cat等。

3.2.1 Ad-Hoc命令集用法简介

本节我们介绍Ad-Hoc命令集用法。Ad-Hoc命令集由/usr/bin/ansible实现,其命令用法如下:

ansible <host-pattern> [options]

可用选项如下。

-v, --verbose:输出更详细的执行过程信息,-vvv可得到执行过程所有信息。

-i PATH, --inventory=PATH:指定inventory信息,默认/etc/ansible/hosts。

-f NUM, --forks=NUM:并发线程数,默认5个线程。

--private-key=PRIVATE_KEY_FILE:指定密钥文件。

-m NAME, --module-name=NAME:指定执行使用的模块。

-M DIRECTORY, --module-path=DIRECTORY:指定模块存放路径,默认/usr/share/ansible,也可以通过ANSIBLE_LIBRARY设定默认路径。

-a 'ARGUMENTS', --args='ARGUMENTS':模块参数。

-k, --ask-pass SSH:认证密码。

-K, --ask-sudo-pass sudo:用户的密码(--sudo时使用)。

-o, --one-line:标准输出至一行。

-s, --sudo:相当于Linux系统下的sudo命令。

-t DIRECTORY, --tree=DIRECTORY:输出信息至DIRECTORY目录下,结果文件以远程主机名命名。

-T SECONDS, --timeout=SECONDS:指定连接远程主机的最大超时,单位是秒。

-B NUM, --background=NUM:后台执行命令,超NUM秒后中止正在执行的任务。

-P NUM, --poll=NUM:定期返回后台任务进度。

-u USERNAME, --user=USERNAME:指定远程主机以USERNAME运行命令。

-U SUDO_USERNAME, --sudo-user=SUDO_USERNAME:使用sudo,相当于Linux下的sudo命令。

-c CONNECTION, --connection=CONNECTION:指定连接方式,可用选项paramiko (SSH)、ssh、local,local方式常用于crontab和kickstarts。

-l SUBSET, --limit=SUBSET:指定运行主机。

-l ~REGEX, --limit=~REGEX:指定运行主机(正则)。

--list-hosts:列出符合条件的主机列表,不执行任何命令。

下面的示例有助于加深对上述内容的理解。

情景1:检查proxy组所有主机是否存活。

执行命令:

ansible proxy  –f 5 –m ping

返回结果如图3-1所示。


图3-1 ansibleping命令返回结果

执行结果诠释:

192.168.37.159 | success >> {

    "changed": false,

    "ping": "pong"

}

其中192.168.37.159是指命令执行的主机,Success表示命令执行成功,“>> {}”表示详细返回结果如下。“"changed": false”表示没有对主机做变更,“"ping": "pong"”表示执行了ping命令返回结果为pong。

情景2:返回proxy组所有主机的hostname,并打印最详细的执行过程到标准输出。

执行命令:

ansible proxy -s -m command -a 'hostname' -vvv

返回结果如图3-2所示。


图3-2 ansiblehostname命令返回结果

执行结果诠释:

<192.168.37.159> ESTABLISH CONNECTION FOR USER: root on PORT 22 TO 192.168.37.159  # 远程主机192.168.37.159监听ROOT用户的22号端口

<192.168.37.159> REMOTE_MODULE command hostname # 远程执行命令hostname

<192.168.37.159> EXEC /bin/sh -c 'mkdir -p $HOME/.ansible/tmp/ansible-tmp-1455684626.83-94958346638443 && echo $HOME/.ansible/tmp/ansible-tmp-1455684626.83-94958346638443' # 生成临时目录用于存放Ansible远程执行脚本

<192.168.37.159> PUT /tmp/tmp5sawsq TO /root/.ansible/tmp/ansible-tmp-1455684626.83-94958346638443/command # 改名临时脚本并存放至临时目录

<192.168.37.159> EXEC /bin/sh -c 'sudo -k && sudo -H -S -p "[sudo via ansible, key=urvzacjxvaagwvlrywymxpxfhjkirkqb] password: " -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-urvzacjxvaagwvlrywymxpxfhjkirkqb; LANG=C LC_CTYPE=C /usr/bin/python /root/.ansible/tmp/ansible-tmp-1455684626.83-94958346638443/command; rm -rf /root/.ansible/tmp/ansible-tmp-1455684626.83-94958346638443/ >/dev/null 2>&1'"'"'' # 使用sudo方式并以Python脚本方式执行命令

192.168.37.159 | success | rc=0 >> # 返回结果为success,CodeResult为0

Linuxlst # 返回的命令返回结果如下

使用-vvv参数可以清楚地了解Ansible命令执行流程,如图3-3所示。


图3-3 Ansible命令执行流程图

情景3:列出Web组所有主机列表。

执行命令:

ansible web --list

返回结果如下:

10.3.33.21

10.3.33.23

执行结果诠释:

--list选项列出web组所有主机列表信息,Web组中包括 10.3.33.21 和 10.3.33.23两台主机

接下来我们模拟较为复杂的场景。

情景4:对10.21.40.61服务器以root执行sleep 20,设置最大连接超时时长为2s,且设置为后台运行模式,执行过程每2s输出一次进度,如5s还未执行完则终止该任务。

执行命令:

// time命令可省,为方便观察结果,这里使用time命令查看执行时长

time ansible 10.21.40.61 -B 5 -P 2 -T 2 -m command -a 'sleep 20'  -u root

返回结果如图3-4所示。


图3-4 返回结果

执行结果诠释:

第1行:[WARNING]不用理会,需升级gmp,该提醒不影响命令返回结果

第2行:background launch...表示使用-B使该命令后台运行

下面每隔2s输出一次执行进度

<job 182625384959.32339> polling on 10.21.40.61, 3s remaining表示执行时长剩余3s

下面每隔2s输出一次执行进度

<job 182625384959.32339> polling on 10.21.40.61, 1s remaining表示执行时长剩余1s

real    0m10.268s程序执行总时长

user    0m1.898s系统用户层执行时长

sys     0m0.163s系统内核层执行时长

 细心的朋友会发现,我们sleep 20表示暂停 20s,即该命令最少执行时长为20s,但为什么real程序实际运行时长只有10s呢?这就是-B选项的意义了,如果超过其指定时间则终止正在执行的任务(但real为什么是10.268s而不是5.268s,经笔者实测,-B功能生效但时间不精确,正式使用前请多测试)。

以上为Ad-Hoc命令集的用法说明,后面的章节我们会通过更复杂的实例深入了解其功能。

3.2.2 通过Ad-Hoc查看系统设置

3.2.1节为大家介绍了Ad-Hoc的命令集用法,本节我们通过df、free命令查看系统设置,但是是通过Ad-Hoc实现的,在此过程中帮助大家了解Ansible。我们模拟如下两个场景。

情景1:批量查看apps组所有主机的磁盘容量(使用command模块)。

执行命令:

ansible apps -a "df -lh"

返回结果如下:

192.168.37.130 | success | rc=0 >>

Filesystem            Size  Used Avail Use% Mounted on

/dev/mapper/vg_linuxlst-lv_root

                       19G  3.6G   14G  21% /

tmpfs                 123M     0  123M   0% /dev/shm

/dev/sda1             485M   29M  431M   7% /boot


192.168.37.155 | success | rc=0 >>

Filesystem                       Size  Used Avail Use% Mounted on

/dev/mapper/vg_linuxlst-lv_root   18G  4.9G   12G  30% /

tmpfs                            144M     0  144M   0% /dev/shm

/dev/sda1                        485M   33M  427M   8% /boot


192.168.37.142 | success | rc=0 >>

Filesystem                       Size  Used Avail Use% Mounted on

/dev/mapper/vg_linuxlst-lv_root   18G  5.4G   12G  33% /

tmpfs                            144M     0  144M   0% /dev/shm

/dev/sda1                        485M   33M  427M   8% /boot


192.168.37.156 | success | rc=0 >>

Filesystem                       Size  Used Avail Use% Mounted on

/dev/mapper/vg_linuxlst-lv_root  8.4G  6.4G  1.6G  81% /

tmpfs                            140M     0  140M   0% /dev/shm

/dev/sda1                        485M   35M  426M   8% /boot

/dev/sdb5                         20G  3.0G   16G  16% /data2

执行结果诠释:

以192.168.37.130的返回为例,success表示命令执行成功,rc=0表示ResultCode=0,即命令返回结果,返回码为0,表示命令执行成功,>>后面跟的内容相当于在主机本地执行df –lh后的结果返回。

情景2:批量查看远程主机内存使用情况(shell模块)。

执行命令:

ansible apps -m shell -a  "free -m"

返回结果如下:

192.168.37.142 | success | rc=0 >>

             total       used       free     shared    buffers     cached

Mem:           286        282          4          0         34        119

-/+ buffers/cache:        128        158

Swap:         2015        668       1347


192.168.37.130 | success | rc=0 >>

             total       used       free     shared    buffers     cached

Mem:           244        188         56          0         30        101

-/+ buffers/cache:         56        187

Swap:         1023          0       1023


192.168.37.155 | success | rc=0 >>

             total       used       free     shared    buffers     cached

Mem:           286        217         69          0         84         63

-/+ buffers/cache:         68        218

Swap:         2015          0       2015


192.168.37.156 | success | rc=0 >>

             total       used       free     shared    buffers     cached

Mem:           279        251         28          0         29         33

-/+ buffers/cache:        188         91

Swap:         1023         22       1001

执行结果诠释:

以192.168.37.142的返回为例,success表示命令执行成功,rc=0表示ResultCode=0,即命令返回结果,返回码为0,表示命令执行成功,>>后面跟的内容相当于在主机本地执行free-m后的结果返回。

通过上面两个场景的示例相信大家对Ad-Hoc的用法有一定的了解,接下来的章节我们进一步学习Ansible的并发特性。

3.2.3 通过Ad-Hoc研究Ansible的并发特性

如3.2.1节所讲,Ansible和Ansible-playbook默认会fork 5个线程并发执行命令,但在实际工作中,如果主机数量众多,Ansible并发5个线程是远不能满足企业所需的,所以本节介绍Ansible的并发特性。我们通过如下测试来更深入地了解Ansible的并发工作模式。

场景如下:我们定义[apps]组,多次执行同样的Ad-Hoc命令来查看其返回的结果。

以下是执行步骤。

步骤1:定义[apps]组,编辑/etc/ansible/hosts的配置。

执行命令vi /etc/ansible/hosts,键入i进入vi编辑模式,跳转到文件最末尾,添加如下配置:

[apps]

192.168.37.130

192.168.37.155

192.168.37.142

192.168.37.156

步骤2:多次执行Ansible命令,执行命令如下:

ansible apps -m ping -f 3

步骤3:对比返回结果,如表3-1所示。

表3-1 返回结果对比

第1次返回结果 第2次返回结果

192.168.37.130 | success >> {

    "changed": false,

    "ping": "pong"

}


192.168.37.142 | success >> {

    "changed": false,

    "ping": "pong"

}


192.168.37.155 | success >> {

    "changed": false,

    "ping": "pong"

}


192.168.37.156 | success >> {

    "changed": false,

    "ping": "pong"

} 192.168.37.130 | success >> {

    "changed": false,

    "ping": "pong"

}


192.168.37.155 | success >> {

    "changed": false,

    "ping": "pong"

}


192.168.37.142 | success >> {

    "changed": false,

    "ping": "pong"

}


192.168.37.156 | success >> {

    "changed": false,

    "ping": "pong"

}



返回结果分析如下:

1)同样的命令多次执行,但每次的输出结果都不一定一样。

2)输出结果不是按照/etc/ansible/hosts中[apps]定义的主机顺序输出。

3)结果输出基本上遵循每次输出3条记录(线程池始终保持3个线程,所以这里如果每次输出小于等于3都是正常的)。

通过上面的实验我们对Ansible的并发性有了概念性的了解。回到前面的问题,企业实际应用中,如主机数量很多,我们需调大线程数,该如何操作呢?这里Ansible为我们提供了便捷的选项,-f指定线程数,如-f 1表示并发启动一个线程,-f 10则表示同时启动10个线程并发执行命令。其实查看源码可知,Ansible使用multiprocessing管理多线程。

 单台主机的性能始终有限,大家根据自己机器实际的硬件配置做调整,建议并发数配置的CPU核数偶数倍就好。如4Cores 8GB的服务器,建议最多并发20个线程。关于Ansible的性能,后面章节会为大家介绍Ansible的加速模式。

3.2.4 通过Ad-Hoc研究Ansible的模块使用

前面的章节为大家详细介绍了Ad-Hoc的命令集使用方法及其并发特性等,那么,Ansible究竟有多少现成功能可供大家使用呢?本节来为大家介绍Ad-Hoc的模块使用。

截至本篇编写时(2016-2-11),官方呈现的所有可用模块为468个(2016-8-19所有可用模块为622个,短短6个月增加了154个,可见Ansible的发展速度),所有模块官方也做了详尽的功能分类。明细可参考官方链接。另外,Ansible也提供了类似于man功能的help说明工具ansible-doc,直接按回车键或输入-h显示功能用法。它和Linux系统下的man命令一样重要,正式学习Ansible模块使用前,有必要先了解ansible-doc用法。

命令用法:

ansible-doc [options] [module...]

可用选项如下。

--version:显示工具版本号。

-h, --help:显示该help说明。

-M MODULE_PATH, --module-path=MODULE_PATH:指定Ansible模块的默认加载目录。

-l, --list:列出所有可用模块。

-s, --snippet:只显示playbook说明的代码段。

-v:等同于—version,显示工具版本号。

下面我们看些简单的示例。

情景1:显示所有可用模块。

执行命令:

ansible-doc –l

返回结果如下:

a10_server                    Manage A10 Networks AX/SoftAX/Thunder/vThunder devices

a10_service_group             Manage A10 Networks AX/SoftAX/Thunder/vThunder devices

a10_virtual_server            Manage A10 Networks AX/SoftAX/Thunder/vThunder devices

acl                           Sets and retrieves file ACL information.

add_host                      add a host (and alternatively a group) to the ansible-playboo...

airbrake_deployment           Notify airbrake about app deployments

alternatives                  Manages alternative programs for common commands

apache2_module                enables/disables a module of the Apache2 webserver

apt                           Manages apt-packages

apt_key                       Add or remove an apt key

apt_repository                Add and remove APT repositories

apt_rpmapt_rpm package manager

arista_interface              Manage physical Ethernet interfaces

arista_l2interface            Manage layer 2 interfaces

arista_lag                    Manage port channel (lag) interfaces

arista_vlan                   Manage VLAN resources

assemble                      Assembles a configuration file from fragments

情景2:以yum模块为例,我们希望获取yum模块的HELP说明。

执行命令:

ansible-doc yum

返回结果如下:

> YUM

    Installs, upgrade, removes, and lists packages and groups with the

    `yum' package manager.


Options (= is mandatory):


- conf_file

        The remote yum configuration file to use for the transaction.

        [Default: None]

其他模块HELP说明以此类推即可。下面通过Ansible内置模块来完成一些具体工作。

【示例1】安装redhat-lsb并查看服务器系统版本号。

步骤1:安装redhat-lsb。

执行命令:

ansible apps -m yum -a 'name=redhat-lsb state=present'

返回结果如下:

192.168.37.142 | success >> {

    "changed": false,

    "msg": "",

    "rc": 0,

    "results": [

        "redhat-lsb-4.0-7.el6.centos.i686 providing redhat-lsb is already installed"

    ]

}

其中:

"changed":主机是否有变更,true为有;false为没有(第1次运行或事先没有安装,返回值一般是true,否则为false)。

"msg":安装过程信息。

"rc": 0, resultcode:结果返回码,非0返回码往往是红色并且错误的返回,非常明显。

步骤2:查看系统版本号。

执行命令:

ansible apps -m command -a 'lsb_release -a'

返回结果如下:

192.168.37.155 | success | rc=0 >>

Version:    :base-4.0-ia32:base-4.0-noarch:core-4.0-ia32:core-4.0-noarch:graph

LSB

ics-4.0-ia32:graphics-4.0-noarch:printing-4.0-ia32:printing-4.0-noarch

Distributor ID: CentOS

Description:    CentOS release 6.5 (Final)

Release:        6.5

Codename:       Final

部分执行结果诠释:

192.168.37.155:表示命令执行的对象。

success:表示命令执行的返回状态为成功状态。

rc=0:表示命令执行的状态码为0。

>>:该符号后返回的所有内容为执行lsb_release –a命令返回的信息。

LSB Version:表示该系统的内核版本信息。

Distributor ID:表示发行厂商。

Description:表示版本简要信息。

Release:表示该系统的发行版本号。

Codename:表示发行版本代号。

【示例2】为所有服务器安装ntp服务,并设置为开机启动。

步骤1:安装ntp服务。

执行命令:

ansible apps -s -m yum -a "name=ntp state=present"

步骤2:启动ntp服务,并设置为开机启动。

执行命令:

ansible apps -m service -a "name=ntpd state=started enabled=yes"

返回的结果不再一一为大家列举出来,相信上面那么多的示例,大家对如何判断结果是否正确能够理解了。

如Linux所有命令的用法一样,我们只能记住日常工作中最常用到的那些,另外那些不常用的命令用法我们只需要知道如何快速获取它们的用法即可。Linux系统为我们提供了man工具来快速获取所需。ansible-doc则等同于 man 的功能和作用,这样解释相信大家会更容易理解其重要性。

3.3 Ad-Hoc组管理和特定主机变更

3.2节为大家介绍了Ansible模块列表及HELP说明获取方式。日常运维工作中,我们往往会将负责相同场景应用的主机划分为一个组,以方便统一管理。Ansible也提供了简洁但强大的组管理功能。同时,我们也可能遇到只针对这组主机中一台或某些主机做变更的场景,针对这些复杂多变的企业场景,本节我们将深入了解Ad-Hoc组管理和特定主机变更,进一步了解Ansible如何应对复杂多变的企业环境。

3.3.1 Ad-Hoc组定义

Ad-Hoc的组功能定义在Inventory文件中,默认路径是/etc/ansible/hosts,书写格式遵循INI风格,中括号中的字符为组名。可以将同一个主机同时归并到多个不同的组中;此外,若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明。下面通过实际案例来了解Inventory文件的书写规则。

如下为Inventory文件示例,包括了组定义及冒号加端口号功能的使用。

ntp.magedu.com


[webservers]

www1.magedu.com:2222

www2.magedu.com


[dbservers]

db1.magedu.com

db2.magedu.com

db3.magedu.com

如果远程主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机,如下案例为大家展示该写法。

[webservers]

www[01:50].magedu.com


[databases]

db-[a:f].magedu.com

本次架构规划了前端Proxy、Web Servers和后面DB一套完整应用,以方便大家实际参考,拓扑规划请参考图3-5。图中共定义了Proxy、App、NoSQL和DB这4个组。组配置请编辑/etc/ansible/hosts添加如下配置:


图3-5 架构拓扑规划

[proxy]

192.168.37.159

[app]

192.168.37.130

192.168.37.160

[nosql]

192.168.37.142

[db]

192.168.37.142

应用分布如下。

[proxy]组:Nginx;

[app]组:Nginx+PHP+Django;

[nosql]组:Redis;

[db]组:Mariadb。

如图3-5所示的架构拓扑是简化后的互联网Web服务架构,用户请求通过Proxy转发至后端WebServers响应,通过NoSQL服务缓冲后,最终将请求传送到DB。我们本章的实战内容就是通过Ansible来搭建这样一套Web服务架构。

3.3.2 Ad-Hoc配置管理:配置Proxy与Web Servers实践

本节通过配置Proxy &Web Servers学习Ad-Hoc的组管理方式,前端Proxy只用到Nginx七层代理功能,将请求转发至后端Web Servers,Web Servers同时部署Nginx、PHP和Django应用,我们按Proxy、WebServers依次顺序部署应用。

(1)Ad-Hoc配置管理Proxy(即Nginx)

安装Nginx,执行命令:

ansible proxy -m yum -a "name=nginx state=present"

利用Ansible安装Nginx,如图3-6所示。


图3-6 Ansible安装Nginx

部分执行结果诠释:

"changed": true, // 表示本次命令对执行的目标有变更,如再执行一次则为false,表示执行的目标没

// 有变更,这里的false和true不代表该命令执行成功或失败,只是表示执行目

// 标是否被变更

"rc": 0, // resultcode的简写,表示命令的执行结果状态返回,非0均为异常,命令执行失败

"results": [ // 执行结果信息返回

如果我们要检查Nginx正常安装,可以执行命令:ansible proxy -m command -a "nginx -v",如果正常则返回如下内容:

192.168.37.159 | success | rc=0 >>

nginx version: nginx/1.0.15

Ansible的YUM模块同样支持指定某版本安装,其name参数指定具体版本地址(网络或本地均可)。YUM模块也支持从网络安装或从本地安装。

如果从网络安装,执行命令:

ansible proxy -m yum -a "name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present"

如果从本地安装,执行命令:

ansible proxy -m yum -a "name=/usr/local/src/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present"

如指定网络安装,安装期间请保障网络畅通,并可以访问Internet,具体安装时长视网络宽带质量而定,如100M带宽,该项安装进行了约2min。如图3-6为Nginx安装的部分结果反馈,Ansible在对执行结果返回提示做得确实不尽人意,虽为JSON格式输出,但换行和颜色标识功能仍有待改善。

(2)Ad-Hoc配置管理Web Servers

Web Servers需同时部署Nginx、PHP和Django,其中Nginx、PHP依然通过YUM模块实现,Django推荐使用PIP或easy_install方式。

1)Nginx、PHP安装命令如下:

ansible app -m yum -a "name=nginx state=present"

ansible app -m yum -a "name=php state=present"

2)Django安装命令如下:

步骤1:安装MySQL-python和python-setuptools依赖包。

ansible app -m yum -a "name=MySQL-python state=present"

ansible app -m yum -a "name=python-setuptools state=present"

步骤2:安装Django。

ansible app -m pip -a "name=django state=present"

步骤3:检查Django安装是否正常,执行命令如下:

ansible app -m command -a "python -c 'import django; print django.get_version()'"

其中Django依赖Python 2.7+版本,如执行报错如下,请检查Python版本。

Traceback (most recent call last):

    File "<string>", line 1, in <module>

    File "/usr/lib/python2.6/site-packages/django/__init__.py", line 1, in <module>

fromdjango.utils.version import get_version

    File "/usr/lib/python2.6/site-packages/django/utils/version.py", line 7, in <module>

fromdjango.utils.lru_cache import lru_cache

    File "/usr/lib/python2.6/site-packages/django/utils/lru_cache.py", line 28

fasttypes = {int, str, frozenset, type(None)},

                ^

SyntaxError: invalid syntax

PIP和easy_install模块支持virtualenv虚拟多环境配置,该功能极为强大,是Python应用者的必备利器。如上我们使用PIP模块安装Django,众所周知easy_install也是Python安装软件包常用的工具之一,Ansible同样支持easy_install,命令类同# ansible app -m easy_install -a "name=django"即可。两者相比较而言,PIP的功能较easy_install更为强大,且支持卸载、指定版本号等。经过笔者亲测,建议使用PIP模块安装Python系列软件包,除功能强大外,我们发现PIP模块的稳定性和速度也远胜easy_install模块(CentOS 6.5 Final)。

截至目前,Proxy & Web Servers部署完毕,通过数条语句即可完成。本示例中的服务器只有4台,如果是40、400、4000台,其带来的便利和节省的时间成本是不可估量的,更为重要的是,这在很大程度上,可以保障操作的正确性。

其实上面的这些变更通过Ansible-playbook进行是更好的选择,在后面playbook章节的讲解与应用过程中大家会逐步有所体会。当然通过shell单独登录到对应的服务器也能实现我们想要完成的工作,但Ansible为我们节省了海量的时间成本,这也是我们学习Ansible的意义所在。

3.3.3 Ad-Hoc配置后端:配置NoSQL与Database Servers实践

3.3.2节我们使用Ansible配置了Proxy和Web Servers,接下来我们使用类似的方法配置NoSQL和DB服务。我们使用Redis配置NoSQL,我们使用MariaDB配置DB,之所以没有使用MySQL是因为自从MySQL被甲骨文公司收购后,虽埃里森宣称MySQL依然免费,但随着时间的推移,MySQL原班核心人马相继离开甲骨文,并创立MariaDB及MySQL社区,开发者对现有Oracle举动感到不满,行业内不少企业已在考虑使用MariaDB,或计划替换现有MySQL。

具体操作步骤如下。

Redis安装命令:ansibledb -m yum -a "name=redis state=present"。

Redis安装检查:ansibledb -m command -a "redis-cli --version"。

MariaDB安装步骤如下。

步骤1:添加yum源,vim编辑/etc/yum.repos.d/mariadb.repo添加内容如下。

# MariaDB 10.1 CentOS repository list - created 2016-02-13 04:31 UTC

# http://mariadb.org/mariadb/repositories/

[mariadb]

name = MariaDB

baseurl = http://yum.mariadb.org/10.1/centos6-x86

gpgkey=https:// yum.mariadb.org/RPM-GPG-KEY-MariaDB

gpgcheck=1

步骤2:安装MariaDB-server,

ansibledb -m yum -a "name=MariaDB-server state=present"

步骤3:安装MariaDB-client,

ansibledb -m yum -a "name=MariaDB-client state=present"

步骤4:开启防火墙3306访问权限。

ansible db -m command -a "iptables -A INPUT -s 192.168.37.0/24 -p tcp -m tcp --dport 3306 -j ACCEPT"

截至目前,如图3-5所示的应用成功部署完毕。其实我们搭建一套主流Web应用框架,期间无需登录远程主机,通过Ansible的结果返回即可判断所有操作是否正确。

3.3.4 Ad-Hoc特定主机变更

前两节我们通过搭建了一套主流Web应用框架熟悉了Ansible的组管理,接下来为大家介绍如何针对特定服务器做变更,该情景在日常运维工作中很常见。

Ansible有多种方式实现针对特定主机做变更。

1)--limit:通过--limit参数限定主机做变更。

情景:在App组中启动192.168.37.15的NTP服务。

命令用法:

ansible app -m command -a "service ntpd status" --limit "192.168.37.158"

2)指定IP:通过指定具体IP限定主机做变更。

情景:启动192.168.37.158的NTP服务。

执行命令:

ansible 192.168.37.158 -m command -a "service ntpd status"

3)用“:”作分隔符,指定多台机器做变更。

情景:启动192.168.37.158和192.168.37.161的NTP服务。

执行命令:

ansible "192.168.37.158:192.168.37.161" -m command -a "service ntpd status"

4)通过“*”泛匹配,更灵活地针对多台主机做变更。

情景:启动192.168.37.*所有主机的NTP服务。

执行命令:

ansible 192.168.37.* -m command -a "service ntpd status"

--limit在日常工作中经常用到,Ansible-playbook也支持该参数。“:”分隔指定多主机也是不错的办法,但记得要用引号将所有地址引起来。

到目前为止Ad-Hoc组管理及特定主机变更我们已经掌握,这对灵活管理海量服务器有很大帮助,关于组及指定主机管理介绍到此结束。接下来为大家介绍的是Ad-Hoc基于用户的管理。

3.4 Ad-Hoc用户与组管理

用户权限管理是运维日常最重要的管理工作之一,如生产环境禁用开发和测试人员登录变更,但测试环境的用户权限仍需耗费精力维护,这项工作大公司也存在(将测试环境交给测试或开发管理并不是每个公司都能做到的,但未来是趋势)。所以掌握Ad-Hoc用户与组管理很有用,如笔者现在的公司每次大版本更新后都会大量修改所有服务器密码。每次需要修改数十台服务器环境密码,若手动单台登录修改可是一项不小的工作,并且手动方式难免会出错误。本节为大家介绍Ad-Hoc用户与组管理。

Ansible系统用户模块有如下两个:

Linux系统用户管理:user。

Windows系统用户管理:win_user。

3.4.1 Linux用户管理

User模块功能诸多,各功能作用几乎完全覆盖平时工作常规及非常规场景。模块所有属性如表3-2所示。

表3-2 user模块属性

参 数 必填项 默认值 选 项 注 释

append no no yes

no Yes:增量添加group

no:全量变更group,只设置groups指定的group组

comment no 可选设置用户账户的描述(又名GECOS)

createhome no yes yes

no 默认yes,当创建用户期时或家目录不存在时为用户创建HOME目录

expires(1.9版本增加) no 1.9版本的新增功能,用户过期时间,不支持的平台该参数将被忽略,现在支持Linux和FreeBSD

force no no yes

no 强制,当和state=absent结合使用时,效果等同于userdel --force

generate_ssh_key no no yes

no 是否生成SSH key,不会覆盖已有的SSH key

group no (可选)设置用户属组

groups no 设置用户附加群组,使用逗号分隔多个群组,如果参数为空(即'groups='),则删除用户所有附加组(属组不受影响)

home no (可选)设置用户家目录

login_class no (可选)设置FreeBSD、OpenBSD、NetBSD系统的用户登录class

move_home no no yes

no 如设置为yes,结合使用home=,临时迁移用户家目录到特定目录

name yes 用户名

non_unique no no yes

no (可选)和-u结合使用,允许改变用户ID为非唯一值

password no (可选)设置用户密码为该项指定的密码(加密后的密码),详细请参考http://docs.ansible.com/ansible/faq.html# how-do-i-generate-crypted-passwords-for-the-user-module

需要注意的是,在Darwin系统,该选项必须是明文,请注意安全问题

remove no no yes

no 结合state=absent使用相当于userdel --remove

seuser no (可选)设置seuser类型启用SELinux

(2.1版本增加)

shell no (可选)设置用户shell

skeleton no (可选)设置用户的skel目录,需和createhome参数结合使用

ssh_key_bits no 2048 (可选)指定生成的SSH key加密位数

ssh_key_comment no ansible-generated on $HOSTNAME (可选)定义SSH key注释

ssh_key_f?ile no .ssh/id_rsa (可选)指定SSH key文件名,如果该文件名是相对路径,则默认路径为用户家目录

ssh_key_passphrase no 设置SSH key密码,如果没有提供密码,则默认没有加密

ssh_key_type no rsa (可选)指定SSH key类型,具体可用的SSH key类型取决于目标主机

state no present present

absent Present:新建(使存在)用户

absent:删除用户

system no no yes

no 当创建新账户时,该选项为yes,为用户设置系统账户,该设置对已经存在的用户无效

uid no (可选)设置用户UID

update_password(1.3版本增加) no always always

on_create always:只有当密码不相同时才会更新密码

on_create:只为新用户设置密码


日常工作所需功能几乎均囊括在内,接下来为大家介绍用户相关的五大场景应用,以供参考。

场景1:新增用户。

需求描述:新增用户dba,使用BASH Shell,附加组为admins, dbagroup,家目录为/home/dba/。

该场景中我们可以掌握如下技能点。

1)groups设定:groups=用户组1,用户组2……

2)增量添加属组:append=yes

3)表明属组状态为新建:state=present

执行命令:

ansibledb -m user -a "name=dba shell=/bin/bash groups=admins,dbagroup append=yes home=/home/dba/ state=present"

返回结果如下:

192.168.37.142 | success >> {

    "changed": true,

    "comment": "",

    "createhome": true,

    "group": 503,

    "groups": "admins,dbagroup",

    "home": "/home/dba/",

    "name": "dba",

    "shell": "/bin/bash",

    "state": "present",

    "system": false,

    "uid": 501

}

返回结果信息非常简洁明了,这里不再一一做解释

场景2:修改用户属组。

需求描述:修改DBA附件组为dbagroups(即删除admins组权限)。

该场景中我们可以掌握如下技能点。

全量变更属组信息:append=no

执行命令:

ansibledb -m user -a "name=dba groups=dbagroup append=no"

返回结果如下:

192.168.37.142 | success >> {

    "append": false,

    "changed": true,

    "comment": "",

    "group": 503,

    "groups": "dbagroup",

    "home": "/home/dba/",

    "move_home": false,

    "name": "dba",

    "shell": "/bin/bash",

    "state": "present",

    "uid": 501

}

删除admins组权限的命令中 append值为no。 另外,细心的朋友会发现,新增用户时,Ansible默认为用户添加用户组(primary group)。

场景3:修改用户属性。

需求描述:设置dba用户的过期时间为2016/6/1 18:00:00 (UNIXTIME: 1464775200)。

该场景中我们可以掌握如下技能点。

1)设置用户登录过期时间:expire=1464775200

2)UNIX时间转换:2016/6/1 18:00:00需转换为UNIXTIME格式(不做介绍,请自行百度)

执行命令:

ansibledb -m user -a "name=dba  expires=1464775200"

这样,我们已经完成了DBA用户的过期时间设置。

场景4:删除用户。

需求描述:删除用户DBA,并删除其家目录和邮件列表。

该场景中我们可以掌握如下技能点:

1)表明属组状态为删除:state=absent

2)设定remove=yes:remove=yes

执行命令:

ansibledb -m user -a "name=dba state=absent remove=yes"

结果检查:到对应主机使用ROOT用户查看/etc/passwd是否存在dba用户,或执行命令id dba确认是否有结果返回。

场景5:变更用户密码。

需求描述:设置系统用户tom的密码为redhat123。

执行命令:

ansibledb -m user -a "name=tom shell=/bin/bash password=to46pW3GOukvA update_password=always"

请注意,password后的字符串to46pW3GOukvA并非真正的密码,而是经过加密后的密码。Ansible变更用户密码方式与直接通过系统命令passwd修改密码有较大差别。Ansible变更密码时所使用的密码是将明文密码加密后的密码(有些拗口)。官网上介绍了两种密码加密方式,笔者建议使用方式2 passlib,因为mkpasswd方式因系统而异,功能差异较大。

方式1:使用命令mkpasswd生成密码。

步骤1:查找安装包名称。

执行命令:yum whatprovides */mkpasswd,结果如下。

epel/filelists_db                                         | 8.0 MB

expect-5.44.1.15-5.el6_4.x86_64 : A program-script interaction and testing utility

Repo        : base

Matched from:

Filename    : /usr/bin/mkpasswd

步骤2:安装软件包。

centos 6.5执行命令:yum install expect

Debian6 Ubuntu 12.04执行命令:sudo apt-get install whois

步骤3:使用mkpasswd生成密码。

执行命令:mkpasswd --method=SHA-512

笔者也对安装的软件包(centos安装expect, debian&ubuntu安装whois)感觉诧异,一番Google查询也没有结果。因为这与本书内容关系不大所以没有深究,感兴趣的朋友自行研究后可告知笔者,以便后续补充给用户。

方式2:使用Python的passlib、getpass库生成密码。

步骤1:安装passlib(Python版本建议2.7以上)。

执行命令:

pip install passlib

步骤2:生成密码。

Python 3.X系列版本请使用如下命令(sha512加密算法)。

python -c "from passlib.hash import sha512_crypt; import getpass; print (sha512_crypt.encrypt(getpass.getpass()))"

Python 3.X系列版本请使用如下命令(普通加密算法)。

python -c 'import crypt; print (crypt.crypt("redhat123", "dba"))'

Python 2.X系列版本请使用如下命令(sha512加密算法)。

python -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt(getpass.getpass())"

Python 2.X系列版本请使用如下命令(普通加密算法)。

python -c 'import crypt; print (crypt.crypt("redhat123", "dba"))'

生成的密码如图3-7所示。


图3-7 生成的密码

1)同样密码多次加密结果不一样属正常情况,想深入了解的朋友可自行研究加密算法及原理。

2)Ad-Hoc方式建议使用普通算法加密,sha512加密后的密码包括诸多特殊元字符,传输至远程服务器会有密码被转义截断的问题。sha512加密算法建议在playbook中使用。

Linux系统下的用户与组管理涉及的各类场景本节均有介绍,作为运维日常最重要的工作之一,希望本节内容对相关人员会有帮助。

3.4.2 Windows用户管理

如第1章所介绍,作为关注度最高的集中化管理工具,Ansible同样支持Windows系统。但考虑Windows不开源的特殊性及服务器市场的占有率,使得Ansible与Windows的结合使用时总是会出问题,但其实类似问题其他工具也同样存在,这是Windows特性使然。本章我们只做简单演示,第10章我们还介绍Windows相关内容。

场景:新增用户stanley,密码为magedu@123,属组为Administrators。

执行命令:

ansible windows -m win_user -a "name=stanley passwd=magedu@123 group=Administrators"

返回结果:

192.168.37.146 | success >> {

    "account_disabled": false,

    "account_locked": false,

    "changed": true,

    "description": "",

    "fullname": "stanley",

    "groups": [

        {

            "name": "Administrators",

            "path": "WinNT:// WORKGROUP/LINUXLST/Administrators"

        }

    ],

    "name": "stanley",

    "password_expired": true,

    "password_never_expires": false,

    "path": "WinNT:// WORKGROUP/LINUXLST/stanley",

    "sid": "S-1-5-21-3965499365-1200628009-3594530176-1004",

    "state": "present",

    "user_cannot_change_password": false

}

部分返回结果诠释:

account_disabled——禁用用户登录;

account_locked——解锁用户;

groups——用户所属组;

name——用户名;

password_expired——下次登录修改密码;

user_cannot_change_password——用户是否可修改密码。

仅从操作上即可看出,Ansible对Windows的用户管理也是基于Linux管理方式的沿用,旨在简单易用。

3.4.3 应用层用户管理

前面两小节为大家介绍了Ansible基于Linux和Windows的系统管理。事实上,除开源系统类UNIX系统和大家耳熟能详的Windows系统以外,Ansible也支持商业系统或产品类应用,系统如AWS的IAM,MAC的OSX;软件如Apache CloudStack、Jabberd、OpenStack、MongoDB、MySQL、PostgreSQL、RabbitMQ、Vertica。本节我们以MySQL用户管理为例介绍。

情景:新增MySQL用户stanley,设置登录密码为magedu@bj,对zabbix.*表有ALL权限。

执行命令:

ansible db -m mysql_user -a 'login_host=localhost login_password=magedu login_user=root name=stanley password=magedu@bj priv=zabbix.*:ALL state=present'

返回结果:

192.168.37.142 | success >> {

    "changed": true,

    "user": "stanley"

}

登录验证步骤如下。

1)在db服务器上测试登录。

mysql -ustanley -pmagedu@bj

2)执行命令:show grants for 'stanley'@'localhost';验证权限是否正确。

其实如上命令存在很大的安全隐患,因为MySQL的登录信息完全暴露在命令台。Ansible建议的使用方式如下。

1)在远程主机的~/.my.cnf文件中配置root的登录信息,配置信息如下:

    [client]

user=root

password=magedu

2)命令行执行命令如下:

ansible db -m mysql_user -a 'name=stanley password=magedu@bj priv=zabbix.*:ALL state=present'

此方式密码将不再暴露在控制台,在一定程度上提高了服务安全性。

3.5 本章小结

Ansible Ad-Hoc在运维日常工作中的作用举足轻重,日常工作中的临时并发性操作均通过Ad-Hoc协助完成,因此我们花了很多篇幅为大家介绍其使用及企业实践。同样重要的还有Ansible的Playbook功能,Ansible-playbook可帮助我们完成更多、更复杂、更重要的功能。我们将在第4章、第5章、第6章深入学习Ansible-playbook的强大功能。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接