触摸DevOps,从现在开始DevOps之旅

来源:互联网 发布:淘宝店面美工 编辑:程序博客网 时间:2024/05/01 16:07

伴随着互联网时代的真正到来和云计算市场的兴起,DevOps这个词越来越多的进入了我们的视野。我们可以认为DevOps是一组方法论的统称,它 扩大了开发和运维的外延,促进开发、运维、质量保障、运营等各部门的协调与整合,它定义了简明、自动化的流程,使我们可以承担更快的变更、更小的风险,可 以使开发人员更多的控制生产环境,让我们更多的以基础设施为中心来理解应用,同时也让我们更多的以应用为主心来理解基础设施。

可以说,DevOps就是不断优化的生产过程。

可是在微观层面,大家对DevOps的理解又不尽相同,也有人可能会对这个名词望而生畏,觉得它有些不可接近。其实DevOps既不高深也不复杂, 它只是由一些简单的概念和工具链构成的工作流程,我们可以暂时忘掉那些教科书式的理论,开始一次务实又轻松的DevOps之旅。 从现在开始,su root,你就是掌控一切的上帝,让我们看看你是如何从一点一滴做起,为你的小伙伴们准备一套DevOps体系的。

-- 开始吧!

创世之初,你得建造一个跳板机

一个好的跳板机可以作为DevOps体系的总入口,它为每个人提供运维的个人帐号,并负责精细化的运维权限管理。它提供DevOps工具链的运行环境,还可以记录、审计所有人的操作历史。

跳板机对权限管理的思路是:跳板机的root帐号拥有最高的运维权限,它获得了所有服务器的各种授权,包括ssh authorized_keys授权,管理端口访问授权,拷贝、部署授权,命令操作授权等,每一台服务器都无条件信任跳板机的root帐号。而你的每个小 伙伴都在跳板机上拥有一个属于他自己的普通帐号,该帐号可以运行所有的DevOps工具,每个DevOps工具都是运行在root权限下,它根据自己具体 的权限配置来决定是否允许某人运行某个命令。

举一个具体的例子,跳板机最基本的功能就是登陆其它服务器,假如这个登陆的命令叫qssh,它需要提供qssh some_server这样的功能,我们如何实现呢?

qssh是一个C语言编写的可执行文件,这个可执行文件用于提权,它的核心伪代码是

uid = getuid(); // 得到当前用户setuid(0); // 提升为root用户exec(“_ssh”, [uid, args...]); //执行_ssh外部程序,并将原始用户名传递给_ssh程序。

当然,这个qssh的执行文件需要赋予suid权限:chmod a+s

经过了qssh的提权动作,_ssh就是运行在root下的了,_ssh比较灵活,可以用任何语言编写,比如bash,值得注意的是_ssh程序需要做用户的授权控制,通常它会有一个如下形式的配置文件:

Tom  web_server1 web_server2   # Tom有两台web服务器的登陆权限Bob  db_server1                # Bob有一台数据库服务器的登陆权限Jo   web_server*               # Jo有所有web服务器的登陆权限

上面可以看到,_ssh被fork的时候,第一个参数便是用户名,_ssh内部使用传入的用户名查询权限配置表,以决定是否继续执行。

_ssh中还需要做一件重要的工作,就是以root身份记下所有人的操作历史,这份记录要保证是普通用户无法修改的。记录的形式大概为:

Thu Oct 10 02:51:38 CST 2013 -- 188.60.175.3 -- Tom -- login  -- web_service1 Thu Oct 10 02:59:01 CST 2013 -- 188.60.175.3 -- Tom -- logout -- web_service1

我们后面会看到,DevOps体系会提供很多命令,它们都运行在跳板机上。我们以qssh为例说明跳板机上程序的工作原理,这个原理对其它的命令基本是一样的。

有了跳板机为基础,我们有了工具运行的环境,有了精细化权限管理的能力,下面就可以放开手脚大干一场,补充各种DevOps的工具,让大家的工作更方便了。

部署,让所有人头疼?

部署,是DevOps中最重要的一个环节,弄好了跳板机,我们开始去构建一个安全、方便的部署系统吧。好消息是你同样不需要做太多的开发工作,我们的部署系统是基于puppet的。

首先,我们需要把部署的信息用版本控制工具管理起来,这里推荐git。来看看我们的deploy.git是什么样子的
 

  1.deploy.git/nodes/  2.    web_server1/  3.        puppet/memcached.p  4.        root/home/app/memcached/memcached.conf  5.    db_server1/

上面的例子展示了deploy.git大致的目录结构,nodes下是代表每台服务器的子目录,每台服务器的目录下有两个最核心的目录,分别是puppetrootpuppet下放置puppet的配置文件,root目录下的所有子目录与服务器上的/一样,root目录下放置需要部署到服务器上的所有文件。对于上面的例子,我们在web_server1上部署了一套memcached服务,现在看看memcached.p是什么样子的:
 

  1.qbin {"/home/app/memcached":  2.    packagepath => "op/baseline/memcached-1.4.15-linux-x86_64.tar.gz",  3.}  4.  5.qfile {"/home/app/memcached/memcached.conf":  6.    owner => "app",  7.}

在这个文件中,qbinqfile是我们写的puppet扩展类,他们的实现方式很简单,这里就不赘述了。我们用qbin部署memcached的二进制文件,部署系统将memcached-1.4.15-linux-x86_64.tar.gz解压缩到服务器上的/home/app/memcached目录。我们用qfile放 置memcached的配置文件,部署系统将deploy.git/nodes/web_server1/root/home/app /memcached/memcached.conf这个文件部署到服务器上的对应位置:/home/app/memcached /memcached.conf。

准备好的部署的配置,我们可以开始部署了,方式很简单,在跳板机上运行下面的命令便可: deploy web_server1

这个命令会做以下几件事件:

  1. 将deploy.git切到上一次成功部署web_server1的版本。
  2. 检查服务器上的状态是否与该版本的deploy.git一致,如果不一致,则报告冲突,并中止执行。这一步主要是防止服务器上的文件被绕过部署系统直接修改。
  3. 冲突检查通过后,该命令将deploy.git切换到master,将最新的内容部署到服务器上。

deploy命令支持如下的参数:

-t 不实际部署,只打印将要部署的内容-f 跳过冲突检查的步骤-i 交互模式,进行每一步前询问用户

了解了工具,我们看看流程,基于上述部署工具链的流程大致是:

  1. fork deploy.git
  2. 做自己希望的变更
  3. 提交pull request,请求合并到master
  4. pull requset经过管理者review后,被合并
  5. 由pull request发起者登陆到跳板机上进行实际部署动作

由于有了pull request和code review流程,所以deploy的权限可以很开放,基本每个运维和开发人员都可以有。设想一下,一个第一天入职的运维或开发就可以放心地在线上升级服 务,或部署新服务,是多么美妙的事情!通过使用一些简单的工具链,并建立适当的流程,部署再也不是一件让人头疼的事情了。

指令编排,解放大家的手指

部署系统本质上是对服务器状态的维持,除此之外,我们还需要对服务器进行一些操作,比如重启某个服务、重新加载某个配置、查看服务器的状态等,这就 需要指令编排系统。指令编排系统提供了一系列预设好的指令,和与之配套的权限控制,这些指令可以由操作员来调用,并作用于服务器。我们基于salt来构建指令系统,先看看指令系统是如何使用的吧:

  1.do web_server1 nginx.op.reload # 重新加载web_server1的nginx配置  2.do web_server* nginx.op.reload # 重新加载所有web_server的nginx配置  3.do db_server1 system.view.ps # 查看db_server1的进程列表  4.do db_server* mysql.view.logs 1h # 查看最近1小时的所有db_server上的mysql日志

它的权限控制大致是如下形式:

Tom *:system.view web_server*:nginx.op # Tom有所有机器的系统查看权限,有所有web_server的nginx操作权限Bob *:* # Bob有所有权限(超级管理员)Jo web_server1:nginx.view.logs # Jo只有web_server1这台服务器的nginx日志查看权限

do命令只需要很少的编码工作,它基本上是直接转调salt命令,salt维护了所有服务器到跳板机之间的长连接,所以指令的执行是非常快的。

如果你需要的命令系统没有提供怎么办?其实所有预设的指令都是在一个代码库里,你随时可以提交自己的命令,salt会自动把脚本部署到每台服务器,非常方便。
 

善待你的日志

日志的处理是DevOps中另一个比较大的话题,好的日志处理方式可以让大家方便的查看、分析日志,可以支持各种分析系统以准实时的方式分析日志,并输出我们想要的任何结果。让我们来看看如何使用开源的工具链构建一套强大的日志处理系统。

一个系统的日志通常有多个部分组成,比如程序的日志,用于审计的事务日志,第三方程序(比如nginx、mongodb、memcached等)的 日志,甚至还可能包括第三方合作伙伴(比如支付宝、CDN等)的日志,这些日志分散在很多的地理位置、很多的服务器、很多的磁盘目录或其它介质中,我们第 一个需求是把这些日志收集、汇总,并按照合理的形式存放,方便大家随时查看,也方便后续的程序进行分析。我们使用logstash来实现这个需求。

logstash是一个日志管理工具,它可以用来收集,分析,存储日志。logstash采用插件机制,它的所有功能都以插件的形式提供,它的插件 分为三种:输入、过滤、输出。输入插件常用的有file、tcp、log4j、redis等,过虑插件常用的有grep、json、ruby等,输出插件 常用的有file、tcp、redis、stdout等,更多的插件可以到它的官网上 http://logstash.net/ 查询,我们也可以使用ruby语言方便的扩展它的插件。

假设我们有两台服务器产生日志,我们使用logstash的input:file插件在服务器本地收集日志,并通过output:tcp发往日志汇集服务器,在日志汇集服务器上,使用input:tcp来收集网络上发过来的日志,并用output:file将日志存放在本地。这样,我们就实现了多处日志的传输、汇总。

通过上面的例子看到,用logstash实现最简单的日志汇集的需求是非常容易的。除了日志汇集,还有日志全文搜索有需求,这里我们使用redis 、elasticsearch、kibana三个工具配合来实现。上面提到在日志汇集服务器上我们使用input:tcp来收集日志,使用output:file将日志组织在本地磁盘上,现在我们再配置logstash把日志存储在本地之外,再使用output:redis插件将日志发送到redis中一份,然后启动一个新的logstash实例,使用input:redis插件从上面的redis中读取,使用output:elasticsearch输出到elasticsearch中建立索引,最后,我们使用kibana运行一个图形化的搜索界面,供大家使用。整个架构不需要写一行代码。

 p1

提到日志的处理,就必须要提opentsdb。opentsdb是一个时间序列的分布式数据库,是日志分析的神器。我们用它存放分析日志后得到的数 据点。从上面描述的架构中,我们看到最终收集到的日志输出了两份,一份是本地磁盘,一份是redis,进而输入到索引系统。现在我们再引入一个 redis,作为日志分析系统的待处理队列,将日志导入这个队列中,再由opentsdb的处理程序从这个队列中读取。日志灌入redis的过程与上面一 样,不再赘述。在将日志输入到redis后,我们启动一个新的logstash实例,这个实例的input是从redis读取,并用output:exec插 件来执行自己的分析脚本,分析脚本的输入是标准输入中的一行一行的原始日志,脚本对日志分析后,将结果存入opentsdb。logstash支持多个 output并联,所以我们可以配置很多分析脚本,用于分析各种我们关心的数值,比如性能、可用率、命中率、流量等。数据导入opentsdb后,我们可 以用它来绘图、告警等。

 p2

保证质量!

质量永远是我们的终极诉求。

没有对质量的保证,一切都是空谈,DveOps也只是浮华的空中楼阁。幸运的是,DevOps实践并不是质量的敌人,相反,我们可以把一些简单有效的保证质量的手段融入DevOps实践中。

首先,我们需要持续集成和单元测试,这是质量保障最基本的手段。jenkins是非常好用的持续集成工具,也很容易配置,我们用jenkins配置 一个定时的编译任务,每10分钟pull最新的master代码,编译、运行单元测试、分析单元测试覆盖率,如果有某项没有通过或不满足要求,则立刻发邮 件通知到大家,并要求相关的责任人及时处理。

OK,现在对质量有了最基本的保障,可这还远远不够。下面我们来构建集成测试系统。主要使用的工具有travis-cidocker.iotravis-ci是一个云端的持续集成服务,通常与github.com配合使用,docker.io是一套lxc工具链,可以方便得实现系统级资源的隔离,比如内存、文件系统、网络、CPU等,它类似于虚拟机技术,但比虚拟机更轻量级,对资源的消耗也更少。

集成测试的流程大概是:当github.com上有新的pull request提交,可以触发travis-ci启动构建,travis-ci构建成功后,使用脚本将构建出的程序发往集成测试服务器,集成测试服务器使 用docker.io启动一个独立的沙箱,按预设的配置将所有服务运行起来。服务运行正常后,集成测试服务器取得testing.git中的所有集成测试脚本并逐个运行,最后将成功或失败的消息返回给travis-citravis-ci会根据集成测试的结果,在pull request上标记'travis-ci passed'或'travis-ci failied'。

有了集成测试流程,当我们看到一个pull request时,就可以很方便的知道这个功能或bugfix的集成测试有没有通过,大大降低了code review的压力,既加快研发速度,又提升产品质量。

 p3

你真的了解你的系统吗?

走完了上面的流程,我们的服务已经顺利上线运行啦!现在还有最后一个问题,你真的了解你系统的运行状态吗?---- 系统有没有出故障?网站的速度如何?可用性怎么样?哪些地区的访问还需要优化?某个业务的转化率是高是低?用户流失最多的是哪个功能或页面?是什么原因?

在一个公司中,需要有人回答上面的问题,我们认为这是DevOps的职责所在。那么,去了解一个线上的系统,有哪些手段呢?



在线监控

在线监控是监控系统中最重要的一环,它提供最实时的系统运行状态的信息,通常信息反馈的速度是按秒来计算。在线监控最重要的功能是告警,当系统的某 些指标不符合预期,或基础设施出现故障,在线监控系统都应该立刻告警,告警的方式通常是邮件和短信。构建在线监控系统,我推荐使用zabbix,原是是:

  1. 软件成熟度较高,社区活跃,使用也比较广泛
  2. 内置多IDC方案,非常适合多IDC场景使用,扩展方便
  3. 界面友好,上手容易
  4. 内置的监控项目和模板很多,基础设施的监控基本不需要自己处理
  5. 扩展自己监控脚本很方便
  6. 告警条件非常丰富
  7. 除告警外,数据报表,数值曲线等功能也很强大

使用zabbix来构建基本的在线监控系统十分方便和简单,这里不再展开讨论,官方文档 zabbix.com 可以解答几乎所有疑问。



第三方在线监控

从事故的预警来看,在线监控可以覆盖大部分的故障,但有一些IDC一级的网络问题内部监控是无法察觉的,这时我们需要使用一些外部监控来更全面的覆 盖可能发生的故障。第三方的监控我推荐使用监控宝一类的监控服务,这类监控服务可以在全国多个地区发起监控请求,我们只需要将自己的业务逻辑,比如打开页 面,登陆,上传,下载等的http请求方式配置好,这类服务就可以模拟真实的用户发起请求,如果出现机房网络故障或区域性的网络故障,或者请求的返回不符 合预期,这类监控服务就会立刻通过邮件和短信告警。适当使用第三方的监控服务,成本不高,但可以有效得弥补内部监控的缺陷,值得一试。



第三方测量

除了告警外,监控系统还应该关注最终的用户体验,这也是监控系统中最难测量的一块。幸运的是现在出现了一些第三方的测量服务,比如基调、博锐等,这 类测量服务在全国拥有大量的真实客户端,可以支持从这些客户端发起预设的请求,使用最真实的方式还原终端用户的访问,收集性能、可能性等指标。我推荐大家 使用这类服务,把自己最核心的业务流程监控起来,通常这类服务都有自己的数据展示和报表页面,也支持发送日报、周报和月报。当时,如果你对它的报表不满 意,或者有自己特殊的报表需求,也可以通过api将最原始的监测数据导出,自己进行分析和展示。

嗯,差不多了,还有什么?

我们花了一点时间,聊了几个DevOps的话题,这几个话题串起来,基本构成了DevOps的流程。我们也看到了DevOps并不复杂,使用一些常 见的工具就可以方便地构建自己的DevOps架构,我鼓励大家从现在开始就动手尝试,边完善边推动,边推边使用,边使用边完善,在生产中摸索适用于自己公 司的DevOps实践。

运维二字承载了太多的内容,DevOps极大的丰富了运维的外延,但我认为运维的内涵始终没有变过,流程固然重要,但也不能忘记本质。所以说 DevOps并不是运维的全部内容,我也想请各位从事运维工作的朋友时刻谨记这点,抓住运维工作的内核,辅以不断优化的生产过程,定是如虎添翼,成为业务 和产品的强有力的守护神。

0 0
原创粉丝点击