当前位置: 首页 > 编程日记 > 正文

我眼中的DevOps(转)

过去一年以来,一批来自欧美的、不墨守陈规的系统管理员和开发人员一直在谈论一个新概念:DevOps。DevOps 就是开发(Development)和运维(Operations)这两个领域的合并。(如果没错的话,DevOps还包括产品管理、QA、*winces* 甚至销售等领域)

脱节(The Broken)

那么……为什么要合并这两个领域?原因很多,但首要原因是:我们目前的工作流程是脱节的。绝对的脱节。很多公司的开发部门和运维部门之间存在的深刻矛盾,其实就是这个“脱节”造成的。(意译,求斧正)

下面是一个大家都基本熟悉的例子:部署软件产品。

开发部门要开发一款新产品。这款产品要使用最新最炫的技术,来保证客户的所有花俏的需求,从而给公司带来百万美元的利润。这款产品被要求使用最新的技术和运行平台,还得马上交付。于是开发部门没日没夜的加班、赶代码(cuts code like crazy),终于如期完成了任务。然后他们把自己的“杰作”一股脑的甩给了运维部门,后者还没能完全接手,前者已经迫不及待的开始了庆功会。

接到产品后,运维部门每个人的心中都充满了恐惧。

下面就是运维部门的恐惧之源:({A.B.C}表示A或B或C之一)

  • 这款优秀的产品在目前的底层平台上无法运行,因为这个平台{太古老了,空间不足,不支持某某版本}
  • 这款产品的体系结构跟我们的{存储,网络,部署,安全}模型不匹配。
  • 这款产品的{ 报告,安全,监视,备份,服务提供} 我们搞不懂 ,所以没法把它做成实际可用的产品。

尽管伴随着不绝于耳的抱怨和咒骂,运维部门最终还是把这款产品安装好了。不幸的是,由于做了很多蹩脚的修改和不合理的强迫式运行,这款产品的性能最后被归结为:终极失败(Epic Fail)。

于是非常沮丧的运维部门开始记录各种问题,源源不断的给开发部门提Issue。而开发部门的回应基本上都是:

  • 这不是我们的错 —— 我们的代码非常完美——而是(运维部门的)部署做的太差劲了。
  • 运维部门比较笨,他们不懂新技术—— 为什么他们没法实现最新的技术呢?为什么他们这么落伍呢?
  • 在我的机器上运行的没问题啊……

两个部门之间的交流很快变成了一场暴风骤雨。客户(以及股东、投资方和管理层)则成了蒙受损失的失败方。最终公司损失了无数的金钱,大家也都失业了。终极的失败。

DevOps 又有啥不同?它有什么好处?

DevOps 就是想方设法的避免这种“终极失败”,同时让大家用更聪明更有效的方式去工作。它是一种框架,包含了很多优秀想法和原则,它鼓励开发部门和运维部门通力合作。在DevOps环境中,开发人员和系统管理员会构建一些关系、流程和工具,从而更好的与客户互动,最终提供更好的服务。

DevOps 也不仅仅是一种软件的部署方法。它通过一种全新的方式,来思考如何让软件的作者(开发部门)和运营者(运营部门)进行合作与协同。使用了DevOps模型之后,会使两个部门更好的交互,使两者的关系得到改善,从而让很多领域从中受益,例如:自动化、监视、能力规划和性能、备份与恢复、安全、网络以及服务提供(provisioning)等等。

“对于DevOps是什么?” 这个问题,DevOps社区中的每个人的回答都不尽相同。因为我们的工作经验不同,关注的问题也不同。就我个人而言,DevOps分成四大部分:

简单

KISS(Keep it Simple and Stupid,简单就是美)原则是最重要的。所以本段文字也很简单。我们要尽量提供简单、可重用的解决方案。“简单”节约了书写文档、培训和提供支持的时间。“简单”增加了沟通的速度、避免混淆、减少了开发和运维出错时的风险。“简单”让人更快的发布产品。

部门之间关系

早参与,多参与。对于开发人员,要让运维人员常驻到开发部门,全程参与开发流程。邀请运维人员参与你的Scrum或者开发会议,与他们分享项目计划、分享新技术的点子和心得。搜集功能性需求(指开发人员用到的需求)的同时也要搜集运维方面的需求。把对于“发布、备份、监控、安全、配置管理和系统功能”的测试作为一项独立的项目流程。软件产品在开发时解决的问题越多,那么在使用时暴露给用户的问题就越少。给运维人员做培训,让他们弄清楚项目的体系结构和核心代码。如果运维人员在反馈bug时提供的信息越多,那么你花在排查问题(trouble-shooting) 的时间就越少,这个bug也就会更快的被解决掉。

对于运维人员,在遇到问题时需要把开发人员加进来,大家一起解决问题。邀请开发人员参与你们的会议,分享项目进度(roadmaps),并且共同修订工作计划。运维人员一定要了解开发部门下一步的工作方向,从而确保产品运行的底层平台能够良好的支持最新技术。开发人员也会带来相关的技术、知识和工作,帮助你们改善产品的运行环境,使其更加易于维护、简洁有效。

有一些开发领域的概念,例如:“要根据API而非封闭的interface来构建工具”,分布式版本控制,驱动测试开发,以及诸如敏捷开发、看板管理(Kanban)和Scrum等方法论。如果把这些概念应用在运维领域,同样会产生革命性的变革。

不要惧怕新点子和新技术。我们可以随时随地的向他人学习,哪怕是一句“我们再也不要那样做了!”也会让我们从中获益。尽管处于不同的部门,但是我们要共同学习、共同成长,这样才能协同工作的更好!

按照从高到低的顺序,有效的沟通方式应该是:面对面交流 、视频会议、电话、即时通讯软件、Email。

工作中的流程

有自己的流程管理(process engineering)—— 从原始的笔录到 ISO9001。但它们都存在一个关键的缺陷:过于理想化,它要求每个步骤都必须成功执行。例如:为了搭建一台新主机,会有下列一套简单的流程:

  • 步骤一:装机(把各个硬件组装到一起)。
  • 步骤二:接线、通电。
  • 步骤三:安装操作系统。
  • 接下来还有步骤四、五、六。

如果一切顺利的话,第N步结束之后就会有一个功能完整、运行正常的新主机。但万一有个流程没跑通怎么办?比如说在某个步骤断了,走不下去了,或者在这一步得到了异常的输出,有没有另外的步骤来处理这个异常?

所以,流程绝对不会从头到尾一帆风顺,所以我们要把每一步流程都认真对待,找出所有潜在的问题和障碍。跟软件产品一样,在流程的管理中也要有异常处理。我们不必做到精确预见每一个问题,但一定要保证:即使流程出错,它还能往下走。

把不同领域的所有流程串到一起。这些领域包括:部署、监控、能力计划(capacity planning) 等等。从逻辑上讲,“部署”是软件开发周期的最后一环,所以它应该属于“开发流程”,而非“运维流程”。另一个例子是度量和监控。在开发领域,如果不理解底线标准和估算,就什么评估都做不了。把开发部门和运维部门的流程衔接在一起,也会让两个部门更好的配合、相互理解、承担共同的责任。最后还有个优点:文档只需要一份而不是两份(开发一份、运维一份),从而节省了资金。

自动化,自动化,还是自动化。构建或使用简单、可扩展的工具(确保提供API, 机器可读的输入、输出 -- 参考 James White的文章:Infrastructure Manifesto)。使用Puppet一类的工具做配置管理。要扩展这些自动化工具,使其能够支持多个领域(开发领域和运维领域),并且在产品的不同环境(开发环境、测试环境、发布环境和生产环境)中使用相同的工具(也叫end-to-end)。这样不但会在产品支持和管理方面带来经济效益,而且也可以在编写新代码的同时,进行产品的发布和管理。

最后,在构建流程和自动化时,要把KISS原则牢记于心。越复杂就越易错。只有简单的流程和工具才易于实现、易于管理和易于维护。

持续改进

不要停止创新和学习。当今技术发展的很快,客户的需求也往往如此。把“持续改进和持续集成” 加入到你的工具和流程中去,这也是运维人员向(优秀的)开发人员学习的好途径,可以学到诸如测试驱动开发等最佳实践。例如:可以向你的部署流程中加入单元测试。做监控时也应该增加些行为测试,提高交付质量。尝试用开发领域中的工具(例如Hudson)在运维领域中做些工作(例如浏览数据(explore)、测量性能(measure)等等)。

要不断的总结教训。要积极主动的、在不同领域寻找错误的根源。 一旦收到错误报告,就果断把开发小组和运维小组找来,一起解决这个问题。有时候开发人员很简单的几次代码重构,就可以很好的避免底层运行环境的改变,减少运维人员的负担。总之,遇到问题时,开发部门和运维部门要密切配合、共同解决,而不是互相推诿、踢皮球。

对我来说...

最后,对我来说,DevOps 的主要内容是:跟谁共同工作、如何共同工作。它最吸引我的地方就是致力于把不同部门不同分工的人召集到一起,共同努力解决问题。这样的工作环境,是我所憧憬的乐园。

关于译者

申思维,2005年本科毕业于华南理工大学计算机学院。一直从事Web领域的开发,3年多Java、2年多Ruby on Rails的工作经验。目前在摩托罗拉公司工作,一名普通的程序员。

声明:本文已获原创作者James Turnbull的许可。

原文链接:http://article.yeeyan.org/view/139924/170387

英文链接:http://www.kartar.net/2010/02/what-devops-means-to-me/

相关文章:

【阿圆实验】Consul HA 高可用方案

一、建立Consul Cluster环境 利用Consul提供的服务实现服务的注册与发现,需要建立Consul Cluster。在Consul方案中,每个提供服务的节点上都要部署和运行Consul的agent,所有运行Consul agent节点的集合构成Consul Cluster。Consul agent有两种…

【C++】拷贝,赋值与构造

拷贝,赋值与构造 文章目录拷贝,赋值与构造1. 拷贝构造函数/合成拷贝构造函数(copy constructor)2. 拷贝赋值运算符3. 析构函数1. 拷贝构造函数/合成拷贝构造函数(copy constructor) 1.1 定义:复…

Java 内存查看与分析

2019独角兽企业重金招聘Python工程师标准>>> 1:gc日志输出 在jvm启动参数中加入 -XX:PrintGC -XX:PrintGCDetails -XX:PrintGCTimestamps -XX:PrintGCApplicationStopedTime,jvm将会按照这些参数顺序输出gc概要信息,详细信息&…

玩转Vuejs--核心原理

一、摘要: Vuejs是一款前端MVVM框架,利用Vuejs、webpack以及周边一系列生态工具我们可以快速的构建起一个前端应用,网上对于Vue的分析大都是基于各个模块,理解起来不够顺畅,本文将从整个执行过程出发,讲一下…

【C++】拷贝控制与资源管理

1. 拷贝控制与资源管理 管理类外资源的类必须定义拷贝控制成员。如P447中所见,这种类需要通过析构函数来释放对象所分配的资源。一旦一个类需要析构函数,那么几乎可确定它也需要一个拷贝构造函数和一个拷贝赋值函数。 明确拷贝语义:可以定义…

leangoo V5.4.2版上线

本次更新增加了“卡片编辑面板内显示成员、截止日期、工作量”的功能。同时我们也进行了大量的功能优化,以下是此次更新详情: 1. 新增“卡片编辑面板内显示成员、截止日期、工作量”功能 本次更新后 ,您在卡片编辑面板内添加成员,…

差分边缘检测实现

#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/opencv.hpp> using namespace cv; // 图像差分操作 void diffOperation(const cv::Mat srcImage, cv::Mat& edgeXImage,cv::Mat& edgeYImage) {cv::Mat…

2.1:CGPROGRAM

文章著作权归作者所有。转载请联系作者&#xff0c;并在文中注明出处&#xff0c;给出原文链接。 本系列原更新于作者的github博客&#xff0c;这里给出链接。 前言 经过前面两个章节的铺垫&#xff0c;我们对渲染以及Unity Shaderlab相关的知识已经有了大概的认识&#xff0c;…

【OpenCV】OpenCV中积分图函数与应用

OpenCV中积分图函数与应用 参考资料 opencv 查找integral&#xff0c;目前网上大部分的资料来自于opencv https://docs.opencv.org/master/d7/d1b/group__imgproc__misc.html#gadeaf38d7701d7ad371278d663c50c77dhttps://blog.csdn.net/jia20003/article/details/52710751ht…

django学习笔记【003】创建第一个带有model的app

【1】python应用程序要连接mysql有多个驱动程序可供选择&#xff1a; 1、MySQLdb 这个只支持python2.x 所以在这里就不说了&#xff1b; 2、mysqlclient 下载地址   https://pypi.python.org/pypi/mysqlclient/1.3.9 3、MySQL Connector/python 这个是mysql官方主推的mysql驱…

图像非极大值抑制 Sobel 边缘实现

bool SobelVerEdge(cv::Mat srcImage, cv::Mat& resultImage) {CV_Assert(srcImage.channels() 1);srcImage.convertTo(srcImage, CV_32FC1);// 水平方向的 Sobel 算子cv::Mat sobelx (cv::Mat_<float>(3,3) << -0.125, 0, 0.125,-0.25, 0, 0.25,-0.125, 0, …

第四次作业 (日期和jieba库的运用)

设计题1&#xff1a; 设计一个本月份日历&#xff0c;输出格式如下&#xff1a; 要求&#xff1a; 1.初始化start_day&#xff0c;end_day两个日期 from datetime import datetime start_daydatetime(2019,4,1) end_daydatetime(2019,4,30) 其它时间数据生成要用datetime或date…

【C++】LINK类型错误分析记录

LINK类型错误 情况1&#xff1a; 根据生成路径&#xff0c;查找是否成功生成静态库/动态库&#xff0c;一般在./bin文件中。 情况2&#xff1a; 是否在CMakeLists中target_link_libraries中添加链接静态库操作 情况3&#xff1a; 是都存在类模板&#xff0c;需要实例化&a…

eBay宣布发布全新的购买和销售APIs

eBay最近宣布发布两款全新的购买和销售APIs。这些APIs旨在促进eBay产品在第三方应用程序中的更好集成。eBay于10月19日在他们的博客上发表了几篇文章&#xff0c;不仅详细介绍了这些全新的购买和销售APIs提供的功能&#xff0c;而且还详细地总结了他们公司从SOAP&#xff08;简…

Sobel 边缘实现

#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace cv; // 非极大值抑制实现sobel竖直细化边缘 bool SobelVerEdge(cv::Mat srcImage, cv::…

vue下实现textarea类似密码框的功能之探索input输入框keyup,keydown,input事件的触发顺序...

项目中引入element的input框组件&#xff0c;触发事件必须要加上.native <el-input placeholder"请输入" type"textarea" v-model"valueText" keyup.native"keyUp(valueText,$event)" keydown.native"keyDown($event)" …

【C++】动态内存管理/move/以及移动构造与移动赋值运算符

文章目录1 .对象移动与右值引用 实际应用过程中遇到的问题及其解决方案c中临时变量不能作为非const的引用参数2. 动态内存管理类3. 对象移动与右值引用4. 移动构造与移动复制运算符1 .对象移动与右值引用 实际应用过程中遇到的问题及其解决方案 问题描述&#xff1a; bool Cr…

图像直接卷积 Sobel 边缘实现

bool sobelEdge(const cv::Mat& srcImage, cv::Mat& resultImage,uchar threshold) {CV_Assert(srcImage.channels() 1);// 初始化水平核因子Mat sobelx (Mat_<double>(3, 3) << 1, 0,-1, 2, 0, -2, 1, 0, -1);// 初始化垂直核因子Mat sobely (Mat_&…

JSON.parse解析特殊字符报错解决方案

2019独角兽企业重金招聘Python工程师标准>>> 具体案例&#xff1a; 页面点击”下一任务” 会去请求后台&#xff0c;这里出现的问题是有虚拟任务的时候。然后会返回一个map&#xff0c;也就是如下图中回调函数中的data。 当该map里存有以下字符的时候&#xff1a; \…

MySQL数据库字符集和整理

MySQL数据库字符集和整理(2009-11-20 22:23:37)mysql数据库 it 其实这个表在MySQL数据库中通过phpMyAdmin就能看到&#xff0c;icech只是把表格整理了一下方便大家使用&#xff0c;如果要更换数据库的字符集&#xff0c;心里有数。其中有三种utf8_general_ci、utf8_unicode_ci…

【SLAM后端】—— ceres优化相机位姿求解

求解结果如下&#xff1a; mat 初始化&#xff0c;eigenvalue初始化 Mat K ( Mat_<double> ( 3,3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );Eigen::Matrix<float,3,1> vd_3d;v_3d << 3, 2, 1;求解目标函数结构体构造与实例 struct CurveFi…

SPOJ 1811 LCS [后缀自动机]

题意&#xff1a; 求两个串的最大连续子串 一个串建SAM&#xff0c;另一个串在上面跑 注意如果走了Suffix Link&#xff0c;sum需要更新为t[u].val1 Suffix Link有点像失配吧&#xff0c;当前状态s走不了了就到Suffix Link指向的状态fa上去&#xff0c;fa是s的后缀所以是可行的…

图像卷积下非极大值抑制 Sobel 的实现

bool sobelOptaEdge(const cv::Mat& srcImage, cv::Mat& resultImage, int flag) {CV_Assert(srcImage.channels() 1);// 初始化sobel水平核因子cv::Mat sobelX (cv::Mat_<double>(3, 3) << 1, 0, -1,2, 0, -2, 1, 0, -1);// 初始化sebel垂直核因子cv::…

was unable to refresh its cache! status = Cannot execute request on any known server

出现这种错误是因为: Eureka服务注册中心也会将自己作为客户端来尝试注册它自己&#xff0c;所以我们需要禁用它的客户端注册行为。 在 yml中设置 eureka.client.register-with-eurekafalse eureka.client.fetch-registryfalse 但在服务端是要这是为false的&#xff0c;在客…

【C++】浅析析构函数(基类中)为什么要写成虚基类?

为什么有了虚析构函数&#xff0c;就能先调用子类的析构函数&#xff1f; class A {virtual ~A(){} };class B : A {virtual ~B(){} };A *p new B(); delete p; 唯一差别是&#xff0c;每个析构函数结束时会自动&#xff08;隐含地&#xff09;调上父类的析构函数&#xff0…

Roberts 边缘检测

#include <opencv2/opencv.hpp> // roberts算子实现 cv::Mat roberts(cv::Mat srcImage) {cv::Mat dstImage srcImage.clone();int nRows dstImage.rows;int nCols dstImage.cols;for (int i 0; i < nRows - 1; i){for (int j 0; j < nCols - 1; j){// 根据公…

vector、map删除当前记录

map<string, string> sMap; map<string, string>::iterator iter; for(iter sMap.begin();iter ! sMap.end();/* iter */) {sMap.erase(iter); }注意下列错误表达&#xff1a;1. for(iter sMap.begin();iter ! sMap.end(); iter ) {sMap.erase(iter); } 错误原因…

1-2 postman工具简介

postman提供了一个多窗口和多选项卡页面用于发送和接受请求&#xff0c;postman努力保持整洁和灵活&#xff0c;提供更多的空间&#xff0c;满足用户的需要。他很简单&#xff0c;能满足大部分接口的测试&#xff0c;性价比特别高。如图所示&#xff1a; 1.侧边栏 postman的侧边…

【C++】重载运算符(一)

1.1 重载运算符特点 重载运算符本质上是一次函数调用 除了operator() 运算符调用外&#xff0c;其他重载运算符不能含有默认参数。 当重载的运算符是成员函数时&#xff0c;this绑定到左侧运算对象。成员运算符函数&#xff08;显式&#xff09;的参数数量比运算对象少一个。…

javaScript的调试(二)

2019独角兽企业重金招聘Python工程师标准>>> 一、Firebug Firebug是Firefox浏览器的调试工具&#xff0c;只要我们在Firefox中安装了Firebug应用&#xff0c;就可以按F12或右击鼠标开启调试 那么我们就先来看一下如何在Firefox中安装了Firebug应用&#xff0c;一图剩…