【转载】LevelDb日知录之三 log文件
郑重声明:本文转载自郎格科技系列博客,原文地址:http://www.samecity.com/blog/Article.asp?ItemID=84
上节内容讲到log文件在LevelDb中的主要作用是系统故障恢复时,能够保证不会丢失数据。因为在将记录写入内存的Memtable之前,会先 写入Log文件,这样即使系统发生故障,Memtable中的数据没有来得及Dump到磁盘的SSTable文件,LevelDB也可以根据log文件恢 复内存的Memtable数据结构内容,不会造成系统丢失数据,在这点上LevelDb和Bigtable是一致的。 下面朗格科技带大家看看log文件的具体物理和逻辑布局是怎样的,LevelDb对于一个log文件,会把它切割成以32K为单位的物理Block,每次 读取的单位以一个Block作为基本读取单位,下图展示的log文件由3个Block构成,所以从物理布局来讲,一个log文件就是由连续的32K大小 Block构成的。
在应用的视野里是看不到这些Block的,应用看到的是一系列的Key:Value对,在LevelDb内部,会将一个Key:Value对看做一条记录 的数据,另外在这个数据前增加一个记录头,用来记载一些管理信息,以方便内部处理,图3.2显示了一个记录在LevelDb内部是如何表示的。
记录头包含三个字段,ChechSum是对“类型”和“数据”字段的校验码,为了避免处理不完整或者是被破坏的数据,当 LevelDb读取记录数据时候会对数据进行校验,如果发现和存储的CheckSum相同,说明数据完整无破坏,可以继续后续流程。“记录长度”记载了数 据的大小,“数据”则是上面讲的Key:Value数值对,“类型”字段则指出了每条记录的逻辑结构和log文件物理分块结构之间的关系,具体而言,主要 有以下四种类型:FULL/FIRST/MIDDLE/LAST。 如果记录类型是FULL,代表了当前记录内容完整地存储在一个物理Block里,没有被不同的物理Block切割开;如果记录被相邻的物理Block切割开,则类型会是其他三种类型中的一种。我们以图3.1所示的例子来具体说明。
假设目前存在三条记录,Record A,Record B和Record C,其中Record A大小为10K,Record B 大小为80K,Record C大小为12K,那么其在log文件中的逻辑布局会如图3.1所示。Record A是图中蓝色区域所示,因为大小为10K<32K,能够放在一个物理Block中,所以其类型为FULL;Record B 大小为80K,而Block 1因为放入了Record A,所以还剩下22K,不足以放下Record B,所以在Block 1的剩余部分放入Record B的开头一部分,类型标识为FIRST,代表了是一个记录的起始部分;Record B还有58K没有存储,这些只能依次放在后续的物理Block里面,因为Block 2大小只有32K,仍然放不下Record B的剩余部分,所以Block 2全部用来放Record B,且标识类型为MIDDLE,意思是这是Record B中间一段数据;Record B剩下的部分可以完全放在Block 3中,类型标识为LAST,代表了这是Record B的末尾数据;图中黄色的Record C因为大小为12K,Block 3剩下的空间足以全部放下它,所以其类型标识为FULL。
从这个小例子可以看出逻辑记录和物理Block之间的关系,LevelDb一次物理读取为一个Block,然后根据类型情况拼接出逻辑记录,供后续流程处理。
收起阅读 »
上节内容讲到log文件在LevelDb中的主要作用是系统故障恢复时,能够保证不会丢失数据。因为在将记录写入内存的Memtable之前,会先 写入Log文件,这样即使系统发生故障,Memtable中的数据没有来得及Dump到磁盘的SSTable文件,LevelDB也可以根据log文件恢 复内存的Memtable数据结构内容,不会造成系统丢失数据,在这点上LevelDb和Bigtable是一致的。 下面朗格科技带大家看看log文件的具体物理和逻辑布局是怎样的,LevelDb对于一个log文件,会把它切割成以32K为单位的物理Block,每次 读取的单位以一个Block作为基本读取单位,下图展示的log文件由3个Block构成,所以从物理布局来讲,一个log文件就是由连续的32K大小 Block构成的。
在应用的视野里是看不到这些Block的,应用看到的是一系列的Key:Value对,在LevelDb内部,会将一个Key:Value对看做一条记录 的数据,另外在这个数据前增加一个记录头,用来记载一些管理信息,以方便内部处理,图3.2显示了一个记录在LevelDb内部是如何表示的。
记录头包含三个字段,ChechSum是对“类型”和“数据”字段的校验码,为了避免处理不完整或者是被破坏的数据,当 LevelDb读取记录数据时候会对数据进行校验,如果发现和存储的CheckSum相同,说明数据完整无破坏,可以继续后续流程。“记录长度”记载了数 据的大小,“数据”则是上面讲的Key:Value数值对,“类型”字段则指出了每条记录的逻辑结构和log文件物理分块结构之间的关系,具体而言,主要 有以下四种类型:FULL/FIRST/MIDDLE/LAST。 如果记录类型是FULL,代表了当前记录内容完整地存储在一个物理Block里,没有被不同的物理Block切割开;如果记录被相邻的物理Block切割开,则类型会是其他三种类型中的一种。我们以图3.1所示的例子来具体说明。
假设目前存在三条记录,Record A,Record B和Record C,其中Record A大小为10K,Record B 大小为80K,Record C大小为12K,那么其在log文件中的逻辑布局会如图3.1所示。Record A是图中蓝色区域所示,因为大小为10K<32K,能够放在一个物理Block中,所以其类型为FULL;Record B 大小为80K,而Block 1因为放入了Record A,所以还剩下22K,不足以放下Record B,所以在Block 1的剩余部分放入Record B的开头一部分,类型标识为FIRST,代表了是一个记录的起始部分;Record B还有58K没有存储,这些只能依次放在后续的物理Block里面,因为Block 2大小只有32K,仍然放不下Record B的剩余部分,所以Block 2全部用来放Record B,且标识类型为MIDDLE,意思是这是Record B中间一段数据;Record B剩下的部分可以完全放在Block 3中,类型标识为LAST,代表了这是Record B的末尾数据;图中黄色的Record C因为大小为12K,Block 3剩下的空间足以全部放下它,所以其类型标识为FULL。
从这个小例子可以看出逻辑记录和物理Block之间的关系,LevelDb一次物理读取为一个Block,然后根据类型情况拼接出逻辑记录,供后续流程处理。
收起阅读 »
【转载】LevelDb日知录之二整体架构
郑重声明:本文转载自郎格科技系列博客,原文地址:http://www.samecity.com/blog/Article.asp?ItemID=84
LevelDb本质上是一套存储系统以及在这套存储系统上提供的一些操作接口。为了便于理解整个系统及其处理流程,我们可以从两个不同的角度来看待 LevleDb:静态角度和动态角度。从静态角度,可以假想整个系统正在运行过程中(不断插入删除读取数据),此时我们给LevelDb照相,从照片可以 看到之前系统的数据在内存和磁盘中是如何分布的,处于什么状态等;从动态的角度,主要是了解系统是如何写入一条记录,读出一条记录,删除一条记录的,同时 也包括除了这些接口操作外的内部操作比如compaction,系统运行时崩溃后如何恢复系统等等方面。
本节所讲的整体架构主要从静态角度来描述,之后接下来的几节内容会详述静态结构涉及到的文件或者内存数据结构,LevelDb日知录后半部分主要介绍动态视角下的LevelDb,就是说整个系统是怎么运转起来的。 LevelDb作为存储系统,数据记录的存储介质包括内存以及磁盘文件,如果像上面说的,当LevelDb运行了一段时间,此时我们给LevelDb进行透视拍照,那么您会看到如下一番景象:
从图中可以看出,构成LevelDb静态结构的包括六个主要部分:内存中的MemTable和Immutable MemTable以及磁盘上的几种主要文件:Current文件,Manifest文件,log文件以及SSTable文件。当然,LevelDb除了这 六个主要部分还有一些辅助的文件,但是以上六个文件和数据结构是LevelDb的主体构成元素。LevelDb的Log文件和Memtable与Bigtable论文中介绍的是一致的,当应用写入一条Key:Value记录的时候,LevelDb会 先往log文件里写入,成功后将记录插进Memtable中,这样基本就算完成了写入操作,因为一次写入操作只涉及一次磁盘顺序写和一次内存写入,所以这 是为何说LevelDb写入速度极快的主要原因。
Log文件在系统中的作用主要是用于系统崩溃恢复而不丢失数据,假如没有Log文件,因为写入的记录刚开始是保存在内存中的,此时如果系统崩溃,内存中的 数据还没有来得及Dump到磁盘,所以会丢失数据(Redis就存在这个问题)。为了避免这种情况,LevelDb在写入内存前先将操作记录到Log文件 中,然后再记入内存中,这样即使系统崩溃,也可以从Log文件中恢复内存中的Memtable,不会造成数据的丢失。
当Memtable插入的数据占用内存到了一个界限后,需要将内存的记录导出到外存文件中,LevleDb会生成新的Log文件和Memtable,原先 的Memtable就成为Immutable Memtable,顾名思义,就是说这个Memtable的内容是不可更改的,只能读不能写入或者删除。新到来的数据被记入新的Log文件和 Memtable,LevelDb后台调度会将Immutable Memtable的数据导出到磁盘,形成一个新的SSTable文件。SSTable就是由内存中的数据不断导出并进行Compaction操作后形成 的,而且SSTable的所有文件是一种层级结构,第一层为Level 0,第二层为Level 1,依次类推,层级逐渐增高,这也是为何称之为LevelDb的原因。
SSTable中的文件是Key有序的,就是说在文件中小key记录排在大Key记录之前,各个Level的SSTable都是如此,但是这里需要 注意的一点是:Level 0的SSTable文件(后缀为.sst)和其它Level的文件相比有特殊性:这个层级内的.sst文件,两个文件可能存在key重叠,比如有两个 level 0的sst文件,文件A和文件B,文件A的key范围是:{bar, car},文件B的Key范围是{blue,samecity},那么很可能两个文件都存在key=”blood”的记录。对于其它Level的 SSTable文件来说,则不会出现同一层级内.sst文件的key重叠现象,就是说Level L中任意两个.sst文件,那么可以保证它们的key值是不会重叠的。这点需要特别注意,后面您会看到很多操作的差异都是由于这个原因造成的。 SSTable中的某个文件属于特定层级,而且其存储的记录是key有序的,那么必然有文件中的最小key和最大key,这是非常重要的信 息,LevelDb应该记下这些信息。Manifest就是干这个的,它记载了SSTable各个文件的管理信息,比如属于哪个Level,文件名称叫 啥,最小key和最大key各自是多少。下图是Manifest所存储内容的示意:
图中只显示了两个文件(manifest会记载所有SSTable文件的这些信息),即Level 0的test.sst1和test.sst2文件,同时记载了这些文件各自对应的key范围,比如test.sstt1的key范围是“an”到 “banana”,而文件test.sst2的key范围是“baby”到“samecity”,可以看出两者的key范围是有重叠的。
Current文件是干什么的呢?这个文件的内容只有一个信息,就是记载当前的manifest文件名。因为在LevleDb的运行过程中,随着 Compaction的进行,SSTable文件会发生变化,会有新的文件产生,老的文件被废弃,Manifest也会跟着反映这种变化,此时往往会新生 成Manifest文件来记载这种变化,而Current则用来指出哪个Manifest文件才是我们关心的那个Manifest文件。 收起阅读 »
LevelDb本质上是一套存储系统以及在这套存储系统上提供的一些操作接口。为了便于理解整个系统及其处理流程,我们可以从两个不同的角度来看待 LevleDb:静态角度和动态角度。从静态角度,可以假想整个系统正在运行过程中(不断插入删除读取数据),此时我们给LevelDb照相,从照片可以 看到之前系统的数据在内存和磁盘中是如何分布的,处于什么状态等;从动态的角度,主要是了解系统是如何写入一条记录,读出一条记录,删除一条记录的,同时 也包括除了这些接口操作外的内部操作比如compaction,系统运行时崩溃后如何恢复系统等等方面。
本节所讲的整体架构主要从静态角度来描述,之后接下来的几节内容会详述静态结构涉及到的文件或者内存数据结构,LevelDb日知录后半部分主要介绍动态视角下的LevelDb,就是说整个系统是怎么运转起来的。 LevelDb作为存储系统,数据记录的存储介质包括内存以及磁盘文件,如果像上面说的,当LevelDb运行了一段时间,此时我们给LevelDb进行透视拍照,那么您会看到如下一番景象:
从图中可以看出,构成LevelDb静态结构的包括六个主要部分:内存中的MemTable和Immutable MemTable以及磁盘上的几种主要文件:Current文件,Manifest文件,log文件以及SSTable文件。当然,LevelDb除了这 六个主要部分还有一些辅助的文件,但是以上六个文件和数据结构是LevelDb的主体构成元素。LevelDb的Log文件和Memtable与Bigtable论文中介绍的是一致的,当应用写入一条Key:Value记录的时候,LevelDb会 先往log文件里写入,成功后将记录插进Memtable中,这样基本就算完成了写入操作,因为一次写入操作只涉及一次磁盘顺序写和一次内存写入,所以这 是为何说LevelDb写入速度极快的主要原因。
Log文件在系统中的作用主要是用于系统崩溃恢复而不丢失数据,假如没有Log文件,因为写入的记录刚开始是保存在内存中的,此时如果系统崩溃,内存中的 数据还没有来得及Dump到磁盘,所以会丢失数据(Redis就存在这个问题)。为了避免这种情况,LevelDb在写入内存前先将操作记录到Log文件 中,然后再记入内存中,这样即使系统崩溃,也可以从Log文件中恢复内存中的Memtable,不会造成数据的丢失。
当Memtable插入的数据占用内存到了一个界限后,需要将内存的记录导出到外存文件中,LevleDb会生成新的Log文件和Memtable,原先 的Memtable就成为Immutable Memtable,顾名思义,就是说这个Memtable的内容是不可更改的,只能读不能写入或者删除。新到来的数据被记入新的Log文件和 Memtable,LevelDb后台调度会将Immutable Memtable的数据导出到磁盘,形成一个新的SSTable文件。SSTable就是由内存中的数据不断导出并进行Compaction操作后形成 的,而且SSTable的所有文件是一种层级结构,第一层为Level 0,第二层为Level 1,依次类推,层级逐渐增高,这也是为何称之为LevelDb的原因。
SSTable中的文件是Key有序的,就是说在文件中小key记录排在大Key记录之前,各个Level的SSTable都是如此,但是这里需要 注意的一点是:Level 0的SSTable文件(后缀为.sst)和其它Level的文件相比有特殊性:这个层级内的.sst文件,两个文件可能存在key重叠,比如有两个 level 0的sst文件,文件A和文件B,文件A的key范围是:{bar, car},文件B的Key范围是{blue,samecity},那么很可能两个文件都存在key=”blood”的记录。对于其它Level的 SSTable文件来说,则不会出现同一层级内.sst文件的key重叠现象,就是说Level L中任意两个.sst文件,那么可以保证它们的key值是不会重叠的。这点需要特别注意,后面您会看到很多操作的差异都是由于这个原因造成的。 SSTable中的某个文件属于特定层级,而且其存储的记录是key有序的,那么必然有文件中的最小key和最大key,这是非常重要的信 息,LevelDb应该记下这些信息。Manifest就是干这个的,它记载了SSTable各个文件的管理信息,比如属于哪个Level,文件名称叫 啥,最小key和最大key各自是多少。下图是Manifest所存储内容的示意:
图中只显示了两个文件(manifest会记载所有SSTable文件的这些信息),即Level 0的test.sst1和test.sst2文件,同时记载了这些文件各自对应的key范围,比如test.sstt1的key范围是“an”到 “banana”,而文件test.sst2的key范围是“baby”到“samecity”,可以看出两者的key范围是有重叠的。
Current文件是干什么的呢?这个文件的内容只有一个信息,就是记载当前的manifest文件名。因为在LevleDb的运行过程中,随着 Compaction的进行,SSTable文件会发生变化,会有新的文件产生,老的文件被废弃,Manifest也会跟着反映这种变化,此时往往会新生 成Manifest文件来记载这种变化,而Current则用来指出哪个Manifest文件才是我们关心的那个Manifest文件。 收起阅读 »
【转载】LevelDb日知录之一:初识LevelDb
郑重声明:本文转载自郎格科技系列博客,原文地址:http://www.samecity.com/blog/Article.asp?ItemID=84
说起LevelDb也许您不清楚,但是如果作为IT工程师,不知道下面两位大神级别的工程师,那您的领导估计会Hold不住了:Jeff Dean和Sanjay Ghemawat。这两位是Google公司重量级的工程师,为数甚少的Google Fellow之二。Jeff Dean其人:
http://research.google.com/people/jeff/index.html
Google大规模分布式平台Bigtable和MapReduce主要设计和实现者。
Sanjay Ghemawat其人:
http://research.google.com/people/sanjay/index.html
Google大规模分布式平台GFS,Bigtable和MapReduce主要设计和实现工程师。
LevelDb就是这两位大神级别的工程师发起的开源项目,简而言之,LevelDb是能够处理十亿级别规模Key-Value型数据持久性存储的C++ 程序库。正像上面介绍的,这二位是Bigtable的设计和实现者,如果了解Bigtable的话,应该知道在这个影响深远的分布式存储系统中有两个核心 的部分:Master Server和Tablet Server。其中Master Server做一些管理数据的存储以及分布式调度工作,实际的分布式数据存储以及读写操作是由Tablet Server完成的,而LevelDb则可以理解为一个简化版的Tablet Server。
LevelDb有如下一些特点:
首先,LevelDb是一个持久化存储的KV系统,和Redis这种内存型的KV系统不同,LevelDb不会像Redis一样狂吃内存,而是将大部分数据存储到磁盘上。
其次,LevleDb在存储数据时,是根据记录的key值有序存储的,就是说相邻的key值在存储文件中是依次顺序存储的,而应用可以自定义key大小比较函数,LevleDb会按照用户定义的比较函数依序存储这些记录。
再次,像大多数KV系统一样,LevelDb的操作接口很简单,基本操作包括写记录,读记录以及删除记录。也支持针对多条操作的原子批量操作。
另外,LevelDb支持数据快照(snapshot)功能,使得读取操作不受写操作影响,可以在读操作过程中始终看到一致的数据。
除此外,LevelDb还支持数据压缩等操作,这对于减小存储空间以及增快IO效率都有直接的帮助。LevelDb性能非常突出,官方网站报道其随机写性能达到40万条记录每秒,而随机读性能达到6万条记录每秒。总体来说,LevelDb的写操作要大大快于读操作,而顺序读写操作则大大快于随机读写操作。 收起阅读 »
说起LevelDb也许您不清楚,但是如果作为IT工程师,不知道下面两位大神级别的工程师,那您的领导估计会Hold不住了:Jeff Dean和Sanjay Ghemawat。这两位是Google公司重量级的工程师,为数甚少的Google Fellow之二。Jeff Dean其人:
http://research.google.com/people/jeff/index.html
Google大规模分布式平台Bigtable和MapReduce主要设计和实现者。
Sanjay Ghemawat其人:
http://research.google.com/people/sanjay/index.html
Google大规模分布式平台GFS,Bigtable和MapReduce主要设计和实现工程师。
LevelDb就是这两位大神级别的工程师发起的开源项目,简而言之,LevelDb是能够处理十亿级别规模Key-Value型数据持久性存储的C++ 程序库。正像上面介绍的,这二位是Bigtable的设计和实现者,如果了解Bigtable的话,应该知道在这个影响深远的分布式存储系统中有两个核心 的部分:Master Server和Tablet Server。其中Master Server做一些管理数据的存储以及分布式调度工作,实际的分布式数据存储以及读写操作是由Tablet Server完成的,而LevelDb则可以理解为一个简化版的Tablet Server。
LevelDb有如下一些特点:
首先,LevelDb是一个持久化存储的KV系统,和Redis这种内存型的KV系统不同,LevelDb不会像Redis一样狂吃内存,而是将大部分数据存储到磁盘上。
其次,LevleDb在存储数据时,是根据记录的key值有序存储的,就是说相邻的key值在存储文件中是依次顺序存储的,而应用可以自定义key大小比较函数,LevleDb会按照用户定义的比较函数依序存储这些记录。
再次,像大多数KV系统一样,LevelDb的操作接口很简单,基本操作包括写记录,读记录以及删除记录。也支持针对多条操作的原子批量操作。
另外,LevelDb支持数据快照(snapshot)功能,使得读取操作不受写操作影响,可以在读操作过程中始终看到一致的数据。
除此外,LevelDb还支持数据压缩等操作,这对于减小存储空间以及增快IO效率都有直接的帮助。LevelDb性能非常突出,官方网站报道其随机写性能达到40万条记录每秒,而随机读性能达到6万条记录每秒。总体来说,LevelDb的写操作要大大快于读操作,而顺序读写操作则大大快于随机读写操作。 收起阅读 »
Zabbix 2.2 LTS升级到Zabbix 3.0 LTS
Zabbix 3.0 LTS正式发布了,详细的功能,大家自行Google。将生产的Zabbix从2.2升级到了3.0记录一下。分为三个阶段:
1.升级前准备工作:
1.1 Zabbix Server部署
1.2 对照老版本的zabbix_server.conf进行修改,不能直接替换。
1.3 COPY相关脚本到新编译的目录下
alertscripts和externalscripts 里面的相关脚本复制到新的安装目录下。
2.Zabbix 前端部署
2.1 将新的前端PHP代码也COPY到对应的目录下。
[root@lb-node2 ~]# cp -r /usr/local/src/zabbix-3.0.0/frontends/php /usr/local/apache/htdocs/zabbix-3.0.0-frontend
2.2 修改前端PHP的配置文件
[root@lb-node2 ~]# cd /usr/local/apache/htdocs/zabbix-3.0.0-frontend/conf
[root@lb-node2 conf]# mv zabbix.conf.php.example zabbix.conf.php
[root@lb-node2 conf]# vim zabbix.conf.php
2.3 把之前准备好的中文字体COPY过去。
Cp xxx.ttf /usr/local/apache/htdocs/zabbix/fonts
3.开始升级:
3.1 先备份
验证并邮件通知相关干系人。做事情,一定要有头有尾!
收起阅读 »
- 升级前的准备
- 升级过程
- 升级后的检查
1.升级前准备工作:
1.1 Zabbix Server部署
[root@lb-node2 ~]# cd /usr/local/src
[root@lb-node2 src]# wget http://jaist.dl.sourceforge.net/project/zabbix/ZABBIX%20Latest%20Stable/3.0.0/zabbix-3.0.0.tar.gz
[root@lb-node2 src]# tar zxf zabbix-3.0.0.tar.gz
[root@lb-node2 src]# cd zabbix-3.0.0
[root@lb-node2 zabbix-3.0.0]#./configure --prefix=/usr/local/zabbix-3.0.0 --enable-server \
--with-mysql --enable-ipv6 --with-net-snmp --with-libcurl --with-libxml2 \
--with-openipmi --with-ldap --enable-java
[root@lb-node2 zabbix-3.0.0]# make install
1.2 对照老版本的zabbix_server.conf进行修改,不能直接替换。
[root@lb-node2 zabbix-3.0.0]# cd /usr/local/zabbix-3.0.0
[root@lb-node2 zabbix-3.0.0]# vim etc/zabbix_server.conf
1.3 COPY相关脚本到新编译的目录下
alertscripts和externalscripts 里面的相关脚本复制到新的安装目录下。
2.Zabbix 前端部署
2.1 将新的前端PHP代码也COPY到对应的目录下。
[root@lb-node2 ~]# cp -r /usr/local/src/zabbix-3.0.0/frontends/php /usr/local/apache/htdocs/zabbix-3.0.0-frontend
2.2 修改前端PHP的配置文件
[root@lb-node2 ~]# cd /usr/local/apache/htdocs/zabbix-3.0.0-frontend/conf
[root@lb-node2 conf]# mv zabbix.conf.php.example zabbix.conf.php
[root@lb-node2 conf]# vim zabbix.conf.php
注意:可以直接使用老的文件替换即可,内容是一样的。
2.3 把之前准备好的中文字体COPY过去。
Cp xxx.ttf /usr/local/apache/htdocs/zabbix/fonts
3.开始升级:
3.1 先备份
- 1.邮件通知相干系人,将对Zabbix进行版本升级,约定升级时间。
- 2.在约定时间到来前,对新的Zabbix Server再一次进行环境确认。
- 3.关闭老版本的Zabbix Server,并进行代码备份(如果使用的软连接,则可以不用)
- 4.对Zabbix数据库进行备份。(非常重要,用来升级失败的恢复!)
- 启动新的Zabbix服务器。(注意:日志文件,启动前把老的日志文件先重命名)
- 完全确认Zabbix数据库升级完毕后,再创建前端访问的软连接,对外提供访问。
日志:
Zabbix Server启动的时候可以关注下日志,2.x的升级会自动进行数据库的升级操作
16527:20160219:153133.851 starting automatic database upgrade
验证并邮件通知相关干系人。做事情,一定要有头有尾!
收起阅读 »
如何有效删除Redis中比较大的Hash Key
生产上由于业务设计原因,有一些500M的Hash Key,现在已经没有用了,需要删除,如果直接删除会造成Redis的卡顿影响线上正常的业务。那么处理有两个方案:
Python脚本:
于是变有了这个脚本,很Low,很实用:
使用方法:
手动修改脚本里面的IP地址和端口,然后:
收起阅读 »
- 在一个夜深人静的时刻,流量低点进行操作(运维真是苦逼啊!)
- 写个脚本,把Hash里面的内容一条一条删除(Python大法好啊!)
Python脚本:
于是变有了这个脚本,很Low,很实用:
# -*- coding: UTF-8 -*-
'''
python redis_hash_del.py HASH_KEY_NAME
'''
# Import python libs
import sys
import redis
# Args Input filter
if len(sys.argv) <= 1:
print "python sys.argv[0] HASH_KEY_NAME"
sys.exit()
else:
hashkey = sys.argv[1]
# redis_hash_del online
def redis_hash_del(hashkey):
'''
delete redis hash key
'''
r = redis.Redis(host='192.168.0.118',port=6379,db=0)
if r.exists(hashkey):
hashkey_all = r.hkeys(hashkey)
for i in range(len(hashkey_all)):
r.hdel(hashkey, hashkey_all[i])
print i
else:
print "KEY NOT EXISTS"
if __name__ == "__main__":
redis_hash_del(hashkey)
[/i]
使用方法:
手动修改脚本里面的IP地址和端口,然后:
[i]python redis_hash_del.py HASH_KEY_NAME[/i]
收起阅读 »
Windows下Git客户端和Github设置
第一步:安装Git For Windows
找到.ssh文件夹,用文本编辑器打开“id_rsa.pub”文件,复制内容到剪贴板 打开 https://github.com/settings/ssh ,点击 Add SSH Key 按钮,粘贴进去保存即可。
收起阅读 »
- msysgit是Windows版的Git,从https://git-for-windows.github.io/下载,然后按默认选项安装即可。
- 下载链接:https://github.com/git-for-windows/git/releases/latest
- 然后各种下一步,建议使用默认选项。
- 安装完成后,在开始菜单里找到“Git”->“Git Bash”,可以打开命令窗口,就说明Git安装成功!
git config --global user.name "Your Name"git config --global user.email "email@example.com"2.生产密钥对:注意还是在Git Bash里面操作。2.1.执行:
cd ~/.ssh如果返回“… No such file or directory”,说明没有生成过SSH Key,直接进入第3步生产新的Key。否则进入第2步备份!2.2.如果之前已经生成过了,需要进行备份:
mkdir key_backup mv id_isa* key_backup2.3.生成新的Key:(引号内的内容替换为你自己的邮箱)
ssh-keygen -t rsa -C "your_email@youremail.com"直接回车,不要修改默认路劲。
Enter passphrase (empty for no passphrase): Enter same passphrase again:设置一个密码短语,在每次远程操作之前会要求输入密码短语!闲麻烦可以直接回车,不设置。第三步:在GitHub上提交公钥:[list=1]
收起阅读 »
Mesos + marathon + Docker实战
如果要评价2015年最火的技术,那么非Docker莫属,当你开始使用并部署上Docker之后,那么你会发现想真正用起来,缺少很多组件。比如本文要介绍的分布式集群管理就是其中之一。
本文为实战分享,所以相关理论较少,需要大家自行Google。
Mesos:Mesos采用与Linux Kernel相同的机制,只是运行在不同的抽象层次上。Mesos Kernel利用资源管理和调度的API在整个数据中心或云环境中运行和提供引用(例如,Hadoop、Spark、Kafaka、ElasticSearch)。
ZooKeeper:ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和HBase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、名字服务、分布式同步、组服务等。
Marathon:Marathon是一个Mesos框架,能够支持运行长服务,比如Web应用等。它是集群的分布式Init.d,能够原样运行任何Linux二进制发布版本,如Tomcat、Play等等。它也是一种私有的PaSS,实现服务的发现,为部署提供提供REST API服务,有授权和SSL、配置约束,通过HAProxy实现服务发现和负载平衡。
好的,架构图看起来像这样。
下面我们就准备开始实战部署了。首先要说明下实验环境:
Zookeeper伪集群部署
在部署mesos集群之前,我们必须先部署一个可用的zookeeper集群,后面mesos会连接到zookeeper上。
下面就是zoo.cfg配置文件的修改了。那么我们首先要熟悉下zookeeper配置文件。
[root@linux-node1 ~]# cat/usr/local/zookeeper/conf/zoo.cfg
dataDir:数据目录
dataLogDir:日志目录
clientPort:客户端连接端口
tickTime:Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
initLimit:Zookeeper的Leader 接受客户端(Follower)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 5个心跳的时间(也就是tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
syncLimit:表示 Leader 与 Follower 之间发送消息时请求和应答时间长度,最长不能超过多少个tickTime 的时间长度,总的时间长度就是 2*2000=4 秒。
server.A=B:C:D:
A 是一个数字,表示这个是第几号服务器;
B 是这个服务器的 ip 地址;
C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;
D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
Zookeeper配置文件修改
如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
Mesos 集群部署
Mesos集群有MesosMaster和Mesos Slave两个角色。
安装mesosphere仓库
需要在Mesos Master和MesosSlave节点均安装:
Mesos Master部署
[root@linux-node1 ~]# yum -y install mesos marathon
安装完毕后,增加zookeeper配置
Mesos Slave部署
Mesos的Web管理界面
Mesos安装完毕后,Mesos Master会启动一个Web服务,监听在5050端口。
http://${HOST_IP}:5050
这时候你将得到一个像这样的页面但可能在‘Tasks’表格没有任何的条目。
下面我们来运行第一mesos任务,注意刷新查看Mesos的Web界面,你会在Active Tasks看到我们测试的任务。
使用Marathon调用Mesos 运行Docker容器
配置Mesos运行Docker容器
[root@linux-node1 ~]# yum install -y docker
[root@linux-node1 ~]# systemctl start docker
首先先测试下,保证手动创建Docker容器没问题。
[root@linux-node1 ~]# docker pull nginx
再所有mesos-slave上增加配置参数,并重启
接下来,我们要使用我们marathon来创建一个nginx的Docker容器,通过Mesos进行调度。 我们上面安装mesos-master的时候,已经安装了marathon。默认监听在8080端口,通过使用http://{HOST}:8080/来打开marathon。如下图所示:
我相信读者会有疑问,我们并没有对marathon做任何的配置,它是怎么知道Mesos在哪里的呢?答案是通过zookeeper,marathon启动的时候会读取/etc/mesos/zk配置文件,通过Zookeeper来找到Mesos Master。marathon有自己的REST API,我们通过API的方式来创建一个nginx的docker容器:
首先创建如下的配置文件nginx.json:
现在你就可以通过31984来访问到nginx了。当然了,你也可以在mesos-slave上来寻找一下这个容器:
如果你想创建同样的容器,可以点击上图中德Scale Application来体验一下。同样的,你也可以通过marathon的Web界面来进行容器的创建、扩展和销毁。
欢迎大家关注《运维社区》微信,经常会有干货发出哦。
赶紧常按识别上面二维码,关注我们吧! 收起阅读 »
本文为实战分享,所以相关理论较少,需要大家自行Google。
Mesos:Mesos采用与Linux Kernel相同的机制,只是运行在不同的抽象层次上。Mesos Kernel利用资源管理和调度的API在整个数据中心或云环境中运行和提供引用(例如,Hadoop、Spark、Kafaka、ElasticSearch)。
ZooKeeper:ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和HBase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、名字服务、分布式同步、组服务等。
Marathon:Marathon是一个Mesos框架,能够支持运行长服务,比如Web应用等。它是集群的分布式Init.d,能够原样运行任何Linux二进制发布版本,如Tomcat、Play等等。它也是一种私有的PaSS,实现服务的发现,为部署提供提供REST API服务,有授权和SSL、配置约束,通过HAProxy实现服务发现和负载平衡。
好的,架构图看起来像这样。
下面我们就准备开始实战部署了。首先要说明下实验环境:
Zookeeper伪集群部署
在部署mesos集群之前,我们必须先部署一个可用的zookeeper集群,后面mesos会连接到zookeeper上。
[root@linux-node1 ~]# cd /usr/local/srczookeeper配置文件详解
[root@linux-node1 src]# wget http://mirrors.cnnic.cn/apache/zookeeper/stable/zookeeper-3.4.6.tar.gz
[root@linux-node1 src]# tar zxf zookeeper-3.4.6.tar.gz
[root@linux-node1 src]# mv zookeeper-3.4.6 /usr/local/zookeeper
[root@linux-node1 src]# ln -s /usr/local/zookeeper-3.4.6/ /usr/local/zookeeper
[root@linux-node1 ~]# cd /usr/local/zookeeper/conf/
[root@linux-node1 conf]# mv zoo_sample.cfg zoo.cfg
下面就是zoo.cfg配置文件的修改了。那么我们首先要熟悉下zookeeper配置文件。
[root@linux-node1 ~]# cat/usr/local/zookeeper/conf/zoo.cfg
dataDir:数据目录
dataLogDir:日志目录
clientPort:客户端连接端口
tickTime:Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
initLimit:Zookeeper的Leader 接受客户端(Follower)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 5个心跳的时间(也就是tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
syncLimit:表示 Leader 与 Follower 之间发送消息时请求和应答时间长度,最长不能超过多少个tickTime 的时间长度,总的时间长度就是 2*2000=4 秒。
server.A=B:C:D:
A 是一个数字,表示这个是第几号服务器;
B 是这个服务器的 ip 地址;
C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;
D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
Zookeeper配置文件修改
如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
[root@linux-node1 conf]# grep '^[a-z]' zoo.cfg创建三个目录用来存放zookeeper数据
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zk1
clientPort=2181
server.1=192.168.56.11:3181:4181
server.2=192.168.56.11:3182:4182
server.3=192.168.56.11:3183:4183
[root@linux-node1 ~]# mkdir -p /data/zk1 /data/zk2/data/zk3生成三份zookeeper配置文件
[root@linux-node1 ~]# echo "1" >/data/zk1/myid
[root@linux-node1 ~]# echo "2" >/data/zk2/myid
[root@linux-node1 ~]# echo "3" >/data/zk3/myid
[root@linux-node1 conf]# cp zoo.cfg zk1.cfg修改zk2和zk3的配置,使用对应的数据目录和端口。
[root@linux-node1 conf]# cp zoo.cfg zk2.cfg
[root@linux-node1 conf]# cp zoo.cfg zk3.cfg
[root@linux-node1 conf]# sed -i 's/zk1/zk2/g'zk2.cfg启动Zookeeper
[root@linux-node1 conf]# sed -i 's/2181/2182/g'zk2.cfg
[root@linux-node1 conf]# sed -i 's/zk1/zk3/g'zk3.cfg
[root@linux-node1 conf]# sed -i 's/2181/2183/g'zk3.cfg
/usr/local/zookeeper/bin/zkServer.sh start/usr/local/zookeeper/conf/zk1.cfg查看Zookeeper角色
/usr/local/zookeeper/bin/zkServer.sh start/usr/local/zookeeper/conf/zk2.cfg
/usr/local/zookeeper/bin/zkServer.sh start/usr/local/zookeeper/conf/zk3.cfg
[root@linux-node1 ~]#/usr/local/zookeeper/bin/zkServer.sh status /usr/local/zookeeper/conf/zk1.cfg连接Zookeeper
JMX enabled by default
Using config: /usr/local/zookeeper/conf/zk1.cfg
Mode: follower
[root@linux-node1 ~]#/usr/local/zookeeper/bin/zkServer.sh status /usr/local/zookeeper/conf/zk2.cfg
JMX enabled by default
Using config: /usr/local/zookeeper/conf/zk2.cfg
Mode: follower
[root@linux-node1 ~]#/usr/local/zookeeper/bin/zkServer.sh status /usr/local/zookeeper/conf/zk3.cfg
JMX enabled by default
Using config: /usr/local/zookeeper/conf/zk3.cfg
Mode: leader
[root@linux-node1 ~]# /usr/local/zookeeper/bin/zkCli.sh -server192.168.56.11:2181
通过上面的例子可以看到,目前zk3是leader,其它两个节点是follower。本文由于实验环境局限使用的是伪分布式,注意生产环境不建议使用。Mesos 集群部署
Mesos集群有MesosMaster和Mesos Slave两个角色。
安装mesosphere仓库
需要在Mesos Master和MesosSlave节点均安装:
# rpm -Uvh http://repos.mesosphere.com/el/7/noarch/RPMS/mesosphere-el-repo-7-1.noarch.rpm
Mesos Master部署
[root@linux-node1 ~]# yum -y install mesos marathon
安装完毕后,增加zookeeper配置
[root@linux-node1 ~]# vim /etc/mesos/zk
zk://192.168.56.11:2181,192.168.56.11:2182,192.168.56.11:2183/mesos
[root@linux-node1 ~]# systemctl start mesos-master mesos-slave
[root@linux-node1 ~]# systemctl start marathon
Mesos Slave部署
[root@linux-node2 ~]# yum -y install mesos marathon
[root@linux-node2 ~]# systemctl start mesos-slave
Mesos的Web管理界面
Mesos安装完毕后,Mesos Master会启动一个Web服务,监听在5050端口。
http://${HOST_IP}:5050
这时候你将得到一个像这样的页面但可能在‘Tasks’表格没有任何的条目。
下面我们来运行第一mesos任务,注意刷新查看Mesos的Web界面,你会在Active Tasks看到我们测试的任务。
[root@linux-node1~]# MASTER=$(mesos-resolve `cat /etc/mesos/zk`)
[root@linux-node1~]# mesos-execute --master=$MASTER --name="cluster-test"--command="sleep 60"
使用Marathon调用Mesos 运行Docker容器
配置Mesos运行Docker容器
[root@linux-node1 ~]# yum install -y docker
[root@linux-node1 ~]# systemctl start docker
首先先测试下,保证手动创建Docker容器没问题。
[root@linux-node1 ~]# docker pull nginx
再所有mesos-slave上增加配置参数,并重启
linux-node1:
[root@linux-node1 ~]# echo 'docker,mesos' | tee/etc/mesos-slave/containerizers
docker,mesos
[root@linux-node1 ~]# systemctl restart mesos-slave
linux-node2:
[root@linux-node2 ~]# echo 'docker,mesos' | tee/etc/mesos-slave/containerizers
docker,mesos
[root@linux-node2 ~]# systemctl restart mesos-slave
接下来,我们要使用我们marathon来创建一个nginx的Docker容器,通过Mesos进行调度。 我们上面安装mesos-master的时候,已经安装了marathon。默认监听在8080端口,通过使用http://{HOST}:8080/来打开marathon。如下图所示:
我相信读者会有疑问,我们并没有对marathon做任何的配置,它是怎么知道Mesos在哪里的呢?答案是通过zookeeper,marathon启动的时候会读取/etc/mesos/zk配置文件,通过Zookeeper来找到Mesos Master。marathon有自己的REST API,我们通过API的方式来创建一个nginx的docker容器:
首先创建如下的配置文件nginx.json:
[root@linux-node1 ~]# cat nginx.json然后调用
{
"id":"nginx",
"cpus":0.2,
"mem":20.0,
"instances": 1,
"constraints": [["hostname", "UNIQUE",""]],
"container": {
"type":"DOCKER",
"docker": {
"image": "nginx",
"network": "BRIDGE",
"portMappings": [
{"containerPort": 80, "hostPort": 0,"servicePort": 0, "protocol": "tcp" }
]
}
}
}
# curl -X POST http://192.168.56.11:8080/v2/apps-d @nginx.json \
-H "Content-type: application/json"
现在你就可以通过31984来访问到nginx了。当然了,你也可以在mesos-slave上来寻找一下这个容器:
[root@linux-node1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
58df0c7f15f9 nginx "nginx -g 'daemonoff" 7 minutes ago Up 7 minutes 443/tcp, 0.0.0.0:31984->80/tcp mesos-0dc69732-fd81-4190-8d7e-f389f80b1f50-S1.56436b54-0fed-4951-ae94-e52889948d67
如果你想创建同样的容器,可以点击上图中德Scale Application来体验一下。同样的,你也可以通过marathon的Web界面来进行容器的创建、扩展和销毁。
欢迎大家关注《运维社区》微信,经常会有干货发出哦。
赶紧常按识别上面二维码,关注我们吧! 收起阅读 »
中小企业自动化部署实践
之前在高效运维微信公众号分享的文章之一,先也发布到运维社区,欢迎讨论。
我们今天的话题是中小企业如何实现自动化部署,为什么定位中小企业呢?因为中小企业常面临着运维人员有限,成本投入有限,但是版本更新快,而且服务器数量却并不少的局面。基本不会投入运维开发来开发自动化部署平台,那么我们今天就拿运维工程师都熟悉的Shell进行举例,谈谈如何来进行一个自动化部署的设计。
1.1 统一认识
在开始之前我们需要先统一认识,在IT管理里面有三大核心要素是PPT,也就是人员/组织架构(People)、流程(Process)、技术/工具(Tech/Tool)。所以说设计一个自动化部署系统,并不是上线几个工具,写几个自动化脚本这么简单。设计一个流程,除了流程本身要和我们的组织架构、人员和技术挂钩,而且还要根据企业的实际情况来做,不能好高骛远,一上来就设计一个庞大的自动化部署平台,可能并不符合企业现状,又浪费了资源。
其次,所有架构和流程的设计都是基于业务需求的,那么不同的业务场景,不同的需求可能出现不同的自动化部署的流程和步骤,所以本文仅供大家参考。
最后,还有一点就是流程和思路很重要,具体的实现方法很多,看团队的技术水平,可以使用Python、Shell、PHP等来实现,不要被某些工具所束缚就行。
1.2 确定目标
好的,我们统一了认识,接下面来确定下目标。中小企业的部署现状就是更新快,可能测试不到位,那么就需要快速回滚,单业务的集群规模在基本上在100台以内。而且由于本文篇幅有限,无法从开发、测试开始阐述,我们需要简化流程,主要是聊聊生产环境的自动化部署系统的流程设计和规划。
那么我们要实现的两大目标是:
1.3 流程设计
我们开始,本次的重点就是流程设计。上面说了,由于篇幅有限我们简化流程。完整的上线流程,可能经历开发环境、测试环境(功能测试、性能测试、预生产测试)、生产环境。那么我就来谈谈生产环境如何自动化部署,前提是假如现在新的功能已经开发和测试就绪(代码review也在测试阶段完成)。Git或者svn仓库已经存放了可以上线的代码。
我相信有读者目前的上线是使用管理工具,批量在所有服务器上执行svn update或者git pull,我还见过每次上线执行rsync进行代码部署的。那么我们下面的流程会和这些完全不一样,不要惊讶,原本上面的方法也没有什么错,只要符合企业需求就可以。
直接上部署流程图:
流程分析:
我想,看到这样的流程可能很多朋友在心中会有一些疑问,我们慢慢来分别阐述下,这样设计的思路、设计原则和目的。
1.获取代码:这里疑问最少,我们可以通过svn或者git进行获取,也可以指定svn版本号或者git的tag,commit id等,或者直接获取最新代码都可以,注意,你需要在专用的部署服务器进行这样的操作,而不是各个Web服务器。
2.编译:这个是可选的,如果是Java代码需要进行编译,比如Ant就可以方便的帮你完成,Python和PHP则不需要进行编译操作,可以忽略。总之,最后你有了一个目录,这个目录里面是准备上线的代码。这里的细节是包名(目录名)的设计,可以涉及到环境、包名、版本号和时间。如下面的名称:
prod_web_xxxxx_2015-09-09-10-10
3.匹配环境配置文件:说明你这个部署系统(脚本)可以支持多个环境。这里有人会问配置文件不应该在代码仓库里面吗。不是的!至少重要的和差异性的配置文件是需要单独进行管理的,尤其是涉及到支付、验证类的配置。最佳实践是你最好给配置文件单独做一个版本库进行管理,同时可以通过目录来区分是测试还是生产,只有相关的负责人才有权限进行更新和提交。那么在这里你需要将配置文件copy到代码目录下。
4.打包:直接使用tar czf 打一个包就可以了,同时你可以在打包的时候给这个包生成一个md5文件。
5.COPY代码包到目标服务器:现在可以将需要部署的代码包。COPY到目标服务器,比如你可以使用SCP,scp完毕后可以使用md5sum验证一下包的完整性。
6.将部署节点拿出集群:如果部署的时候,直接部署和重启Web服务,让负载均衡的健康检查工作自动将节点踢出集群的朋友需要想一想了,这做法也太暴力了。我们知道负载均衡的健康检查也是有检查的时间间隔、次数的,如果你直接重启了后端Web服务,那么在负载均衡在判断后端主机是否下线的时间范围内,用户的请求可能就会失败。所以,我们要提前将要部署的后端节点拿出集群,比如Haproxy,你可以通过socat和Haproxy Unix Socket进行通信,实现部署节点的开启和关闭,如下所示:
关闭节点:
启用节点:
7.解压软件包:在目标服务器上解压这个软件包,无论你是用管理工具如Saltstack还是SSH都可以轻松搞定。
8. 创建软连接:好的,这就是我们设计的重点了,我们使用软连接的方式来管理包的更新。比如我们的Web根路径是/var/www/html/webroot,我们把所有的代码都存放在/data目录下,那么webroot实际上是一个软连接,它链接到当前的版本,比如prod_web_xxxxx_2015-09-09-10-10。这样的话,webroot实际是这样
webroot -> /data/prod_web_xxxxx_2015-09-09-10-10/
我想,很多朋友,看到这里就明白了,这回滚绝对是秒级啊,只需要重新创建一个软连接即可。
9.COPY差异文件:同一个集群中,存在不同的配置文件,这很常见,比如我需要在某个节点跑一些定时任务,比如Java可以使用Quartz来实现,只需要一个crontab.xml即可,那么我们就需要把这个差异文件在这个时候scp进去。
10.重启Web服务:这个是可选的,如果是Java,运行的Tomcat,就需要重启Tomcat,别忘记清理相关的Tomcat缓存哦。
11.自动化测试:如果有的话,当然好了,你调用一个接口就可以进行测试。然后等待测试完毕再继续。如果没有测试团队提供这样的接口,那么curl可以帮你轻松的实现,把重要的接口访问一遍,判断下返回码或者返回内容即可。
12.加入集群:好的,这个节点部署完毕了,把他加入集群吧。还记得刚才说的socat吗?
13.继续下一个节点:说了这么多,原来只是一个节点啊。那么继续吧,可能这个只是for循环中的一部分哦,是不是想到了shell该怎么写了。
部署小技巧
这里把实际使用的时候可能有用的小技巧分享下:
分组部署:为什么要分组?上面的流程中,你会发现,每次部署都会在重启和自动化测试那里等待好久。因为你要等待Web服务的重启,比如Tomcat。那么如何减少这个时间呢?答案就是分组部署,将该业务的服务器进行分组,比如group1、group2、group3,那么部署group1到重启那里后,流程不往下走了,直接部署group2,当group2部署完毕,停下来开始对group1进行自动化测试,测试完毕添加到集群,然后继续部署group3。当group3部署完毕后,再来自动化测试group2,然后你懂的。
日志记录:没有日志记录功能的脚本就是耍流氓!你必须清楚的知道目前脚本在干啥,干到哪里了,如果有报错就可以及时的定位问题。
部署服务器双机:如果这台部署服务器宕机会怎么样?所以这台部署服务器必须是双机的。包括部署脚本应该是使用svn或者git来做版本控制。而且应该有详细的部署脚本的设计、使用文档。别忘了,文档化建设是流程设计必备的内容之一。
回滚流程
我想经过部署流程,大家很容易就想到了下面的流程,没有问题,我们这里可以简单的阐述下:
好的,我们的流程设计结束了,想在脑子里想明白,然后拿起Shell开始实现吧。会有很多小细节需要注意哦,我相信这难不倒你。
FAQ:
你们是否考虑使用Jenkins来实现自动化部署呢?
实际上,我们测试环境的自动化部署是使用的Jenkins。开发可以自助进行部署操作,同时也集成了代码审查和代码质量管理的流程。但是我们生产环境没有使用Jenkins,主要是我们自动化测试还跟不上,往往很多发布需要人肉测试。整个流程无法完美衔接,所以就分开了。所以我们生产部署其实产品发起,测试审核(测试),然后测试人员进行部署上线。而且生产环境并不是测试人员ssh到服务器执行我们编写的脚本(他们没有权限),我们基于SaltStack开发了Job管理平台,测试人员在Job管理平台上进行部署操作。
我们是否可以将线上部署修改为本文设计的流程?
如果你觉得使用没有问题,欢迎使用,而且后期还会提供Shell脚本模板。这个流程的设计背景是一个电商的架构,物理机+虚拟机300+的规模,使用了SOA。但是,当时重构部署流程也经历了很长一段的时间,而且需要运维顶着很大的压力和责任,一定要充分测试,分批上线。
部署的一致性怎么保证的,比如刚更新的服务器和集群中的其它服务器版本不一致?
首先,日常的变动和更新是不会有这样的问题,如果有大的变动,不推荐在运维部门来实现,比如在SOA的各个服务之间,应该加入API版本号的实现,实现多个版本并存。如果你发现有不一致的情况,试试Nginx的ip_hash,或者Haproxy的source的负载均衡算法,让某个用户的请求一直落在某个节点,即实现了会话保持,也解决了你的疑虑。当然有很多缺点,看你的选择了。
有没有完整的自动化部署的流程图可以参考?
还真有,之前画过一个,请大家参考。目前我们IAAS这块主要以OpenStack为主,Mesos+Docker也正在研究中。
收起阅读 »
我们今天的话题是中小企业如何实现自动化部署,为什么定位中小企业呢?因为中小企业常面临着运维人员有限,成本投入有限,但是版本更新快,而且服务器数量却并不少的局面。基本不会投入运维开发来开发自动化部署平台,那么我们今天就拿运维工程师都熟悉的Shell进行举例,谈谈如何来进行一个自动化部署的设计。
1.1 统一认识
在开始之前我们需要先统一认识,在IT管理里面有三大核心要素是PPT,也就是人员/组织架构(People)、流程(Process)、技术/工具(Tech/Tool)。所以说设计一个自动化部署系统,并不是上线几个工具,写几个自动化脚本这么简单。设计一个流程,除了流程本身要和我们的组织架构、人员和技术挂钩,而且还要根据企业的实际情况来做,不能好高骛远,一上来就设计一个庞大的自动化部署平台,可能并不符合企业现状,又浪费了资源。
其次,所有架构和流程的设计都是基于业务需求的,那么不同的业务场景,不同的需求可能出现不同的自动化部署的流程和步骤,所以本文仅供大家参考。
最后,还有一点就是流程和思路很重要,具体的实现方法很多,看团队的技术水平,可以使用Python、Shell、PHP等来实现,不要被某些工具所束缚就行。
1.2 确定目标
好的,我们统一了认识,接下面来确定下目标。中小企业的部署现状就是更新快,可能测试不到位,那么就需要快速回滚,单业务的集群规模在基本上在100台以内。而且由于本文篇幅有限,无法从开发、测试开始阐述,我们需要简化流程,主要是聊聊生产环境的自动化部署系统的流程设计和规划。
那么我们要实现的两大目标是:
- 一键上线
- 秒级回滚
1.3 流程设计
我们开始,本次的重点就是流程设计。上面说了,由于篇幅有限我们简化流程。完整的上线流程,可能经历开发环境、测试环境(功能测试、性能测试、预生产测试)、生产环境。那么我就来谈谈生产环境如何自动化部署,前提是假如现在新的功能已经开发和测试就绪(代码review也在测试阶段完成)。Git或者svn仓库已经存放了可以上线的代码。
我相信有读者目前的上线是使用管理工具,批量在所有服务器上执行svn update或者git pull,我还见过每次上线执行rsync进行代码部署的。那么我们下面的流程会和这些完全不一样,不要惊讶,原本上面的方法也没有什么错,只要符合企业需求就可以。
直接上部署流程图:
流程分析:
我想,看到这样的流程可能很多朋友在心中会有一些疑问,我们慢慢来分别阐述下,这样设计的思路、设计原则和目的。
1.获取代码:这里疑问最少,我们可以通过svn或者git进行获取,也可以指定svn版本号或者git的tag,commit id等,或者直接获取最新代码都可以,注意,你需要在专用的部署服务器进行这样的操作,而不是各个Web服务器。
2.编译:这个是可选的,如果是Java代码需要进行编译,比如Ant就可以方便的帮你完成,Python和PHP则不需要进行编译操作,可以忽略。总之,最后你有了一个目录,这个目录里面是准备上线的代码。这里的细节是包名(目录名)的设计,可以涉及到环境、包名、版本号和时间。如下面的名称:
prod_web_xxxxx_2015-09-09-10-10
3.匹配环境配置文件:说明你这个部署系统(脚本)可以支持多个环境。这里有人会问配置文件不应该在代码仓库里面吗。不是的!至少重要的和差异性的配置文件是需要单独进行管理的,尤其是涉及到支付、验证类的配置。最佳实践是你最好给配置文件单独做一个版本库进行管理,同时可以通过目录来区分是测试还是生产,只有相关的负责人才有权限进行更新和提交。那么在这里你需要将配置文件copy到代码目录下。
4.打包:直接使用tar czf 打一个包就可以了,同时你可以在打包的时候给这个包生成一个md5文件。
5.COPY代码包到目标服务器:现在可以将需要部署的代码包。COPY到目标服务器,比如你可以使用SCP,scp完毕后可以使用md5sum验证一下包的完整性。
6.将部署节点拿出集群:如果部署的时候,直接部署和重启Web服务,让负载均衡的健康检查工作自动将节点踢出集群的朋友需要想一想了,这做法也太暴力了。我们知道负载均衡的健康检查也是有检查的时间间隔、次数的,如果你直接重启了后端Web服务,那么在负载均衡在判断后端主机是否下线的时间范围内,用户的请求可能就会失败。所以,我们要提前将要部署的后端节点拿出集群,比如Haproxy,你可以通过socat和Haproxy Unix Socket进行通信,实现部署节点的开启和关闭,如下所示:
关闭节点:
echo "disable server www_example_com/web-node1" | socat /usr/local/haproxy/haproxy.sock stdio
启用节点:
echo "enable server www_example_com/web-node1" | socat /usr/local/haproxy/haproxy.sock stdio
7.解压软件包:在目标服务器上解压这个软件包,无论你是用管理工具如Saltstack还是SSH都可以轻松搞定。
8. 创建软连接:好的,这就是我们设计的重点了,我们使用软连接的方式来管理包的更新。比如我们的Web根路径是/var/www/html/webroot,我们把所有的代码都存放在/data目录下,那么webroot实际上是一个软连接,它链接到当前的版本,比如prod_web_xxxxx_2015-09-09-10-10。这样的话,webroot实际是这样
webroot -> /data/prod_web_xxxxx_2015-09-09-10-10/
我想,很多朋友,看到这里就明白了,这回滚绝对是秒级啊,只需要重新创建一个软连接即可。
9.COPY差异文件:同一个集群中,存在不同的配置文件,这很常见,比如我需要在某个节点跑一些定时任务,比如Java可以使用Quartz来实现,只需要一个crontab.xml即可,那么我们就需要把这个差异文件在这个时候scp进去。
10.重启Web服务:这个是可选的,如果是Java,运行的Tomcat,就需要重启Tomcat,别忘记清理相关的Tomcat缓存哦。
11.自动化测试:如果有的话,当然好了,你调用一个接口就可以进行测试。然后等待测试完毕再继续。如果没有测试团队提供这样的接口,那么curl可以帮你轻松的实现,把重要的接口访问一遍,判断下返回码或者返回内容即可。
12.加入集群:好的,这个节点部署完毕了,把他加入集群吧。还记得刚才说的socat吗?
13.继续下一个节点:说了这么多,原来只是一个节点啊。那么继续吧,可能这个只是for循环中的一部分哦,是不是想到了shell该怎么写了。
部署小技巧
这里把实际使用的时候可能有用的小技巧分享下:
分组部署:为什么要分组?上面的流程中,你会发现,每次部署都会在重启和自动化测试那里等待好久。因为你要等待Web服务的重启,比如Tomcat。那么如何减少这个时间呢?答案就是分组部署,将该业务的服务器进行分组,比如group1、group2、group3,那么部署group1到重启那里后,流程不往下走了,直接部署group2,当group2部署完毕,停下来开始对group1进行自动化测试,测试完毕添加到集群,然后继续部署group3。当group3部署完毕后,再来自动化测试group2,然后你懂的。
日志记录:没有日志记录功能的脚本就是耍流氓!你必须清楚的知道目前脚本在干啥,干到哪里了,如果有报错就可以及时的定位问题。
部署服务器双机:如果这台部署服务器宕机会怎么样?所以这台部署服务器必须是双机的。包括部署脚本应该是使用svn或者git来做版本控制。而且应该有详细的部署脚本的设计、使用文档。别忘了,文档化建设是流程设计必备的内容之一。
回滚流程
我想经过部署流程,大家很容易就想到了下面的流程,没有问题,我们这里可以简单的阐述下:
- 列出回滚版本:ls –l可以了吧,只要列出能回滚的版本即可。
- 目标服务器移除集群:同部署操作。
- 执行回滚:删除旧的软连接,创建到指定版本的新软连接
- 重启:可选的
- 自动化测试:同部署操作
- 加入集群:同部署操作
- Next:继续下一个节点
- 执行回滚:对,不要列出来了,直接就用上一个版本即可。所以注意,部署的时候你需要记录上一个版本是什么。
- 重启:可选。顾不了那么多了,现在是和时间赛跑。那么注意了,你的上一个版本需要是一个可用的版本,如果你无法记录,那么可能需要把列出版本再加上了。
好的,我们的流程设计结束了,想在脑子里想明白,然后拿起Shell开始实现吧。会有很多小细节需要注意哦,我相信这难不倒你。
FAQ:
你们是否考虑使用Jenkins来实现自动化部署呢?
实际上,我们测试环境的自动化部署是使用的Jenkins。开发可以自助进行部署操作,同时也集成了代码审查和代码质量管理的流程。但是我们生产环境没有使用Jenkins,主要是我们自动化测试还跟不上,往往很多发布需要人肉测试。整个流程无法完美衔接,所以就分开了。所以我们生产部署其实产品发起,测试审核(测试),然后测试人员进行部署上线。而且生产环境并不是测试人员ssh到服务器执行我们编写的脚本(他们没有权限),我们基于SaltStack开发了Job管理平台,测试人员在Job管理平台上进行部署操作。
我们是否可以将线上部署修改为本文设计的流程?
如果你觉得使用没有问题,欢迎使用,而且后期还会提供Shell脚本模板。这个流程的设计背景是一个电商的架构,物理机+虚拟机300+的规模,使用了SOA。但是,当时重构部署流程也经历了很长一段的时间,而且需要运维顶着很大的压力和责任,一定要充分测试,分批上线。
部署的一致性怎么保证的,比如刚更新的服务器和集群中的其它服务器版本不一致?
首先,日常的变动和更新是不会有这样的问题,如果有大的变动,不推荐在运维部门来实现,比如在SOA的各个服务之间,应该加入API版本号的实现,实现多个版本并存。如果你发现有不一致的情况,试试Nginx的ip_hash,或者Haproxy的source的负载均衡算法,让某个用户的请求一直落在某个节点,即实现了会话保持,也解决了你的疑虑。当然有很多缺点,看你的选择了。
有没有完整的自动化部署的流程图可以参考?
还真有,之前画过一个,请大家参考。目前我们IAAS这块主要以OpenStack为主,Mesos+Docker也正在研究中。
收起阅读 »
运维工程师如何-快速-有效的学习好Python-并开发出运维平台-口水篇
运维工程师用不用学习Python?呵呵!
我一直在自学Python。分享下自己的经验。尤其对于有多年工作经验,日常工作也比较忙,没有充足的时间来参加培训的朋友。
首先,你要坚信自己可以搞定一个运维平台,觉得难的,洗洗睡吧!没睡的我们就开始。
知识积累
功能添加
基础设施
杂七杂八
然并卵
北京雾霾怎么办?调用API获取PM2.5指标。超过500直接给老板发送一个请假邮件。超过2000直接发送-世界那么大,我想去看看! 收起阅读 »
我一直在自学Python。分享下自己的经验。尤其对于有多年工作经验,日常工作也比较忙,没有充足的时间来参加培训的朋友。
首先,你要坚信自己可以搞定一个运维平台,觉得难的,洗洗睡吧!没睡的我们就开始。
知识积累
- 用实用的例子学习Python 《Python Unix/Linux系统管理指南》 PDF自己网上搜。
- 学习HTML、CSS、JS、AJAX、JQuery 《w3school在线教程》http://www.w3school.com.cn/
- 学习Django 《Django Book》 http://docs.30c.org/djangobook2/
- 学习SaltStack 《SaltStack技术入门与实战》。http://item.jd.com/11804150.html 这广告做的,好机智啊。
功能添加
- 开始吧,注意开始之前先要进行运维标准化的建设,那我们从CMDB开始,CMDB三板斧(数据采集、数据管理和API、数据展现)。
- 增加Cobbler API和IPMI。在CMDB的资产中加入安装、重装等调用,并且进行安装。
- 增加SaltStack API。进行配置管理和远程执行,在CMDB中加入角色的列,根据角色调用Salt API进行部署。
- 增加Zabbix API。根据CMDB的角色做好监控,增加主机和链接模板。需要提前定义好。
- 增加GateOne API。直接嵌入,在CMDB的列表中,加入Console功能,直接调用Key连接。
- Job管理。Job编排、Crontab管理。
- 增加WAF管理,WAF Dashboard显示。编辑规则。
- 增加W3af管理。进行安全扫描。
- 内网DNS怎么办,Cobbler来管理还是Bind+DLZ。写个增删改查的API。
基础设施
- OpenStack API拿过来做一些统计吧,不要重复造轮子,用Horizon就好。
- Docker你用后发现,没有管理平台不行啊。折腾吧。或者直接mesos marathon
- 自动化扩容不用折腾。SaltStack+OpenStack/Docker+Etcd_Pillar+Etcd。使用Salt-Cloud就行,别搞各种共有云的API了,都封装好了。
- 代码部署,直接做成Job的一种。Job类型有。脚本执行、代码更新、Redis管理、产品经理提的各种需求。
- 登陆验证。这么重要的系统必须要有验证啊。双因素验证,比如加入OTP,比如google authenticator。
杂七杂八
- 平台病:如果你按照上面的功能做的差不多的时候,你马上就会犯一个平台的病:这Redis管理、Memcached管理是不是都可以搞过来啊,然后github一搜,发现复制粘贴就可以搞定。
- 可视化:http://echarts.baidu.com/ http://www.hcharts.cn/ 你随便选一个,高端大气上档次。
- 一开始就要考虑到各种权限管理,用户、组、角色、项目。例如:让用户像GitHub一样设置Key,根据权限将Key通过Salt进行部署,这样用户登录后,有权限的机器就可以直接通过GateOne链接。
- 角色还是很有必要使用的,用来管理复杂权限的设置
然并卵
北京雾霾怎么办?调用API获取PM2.5指标。超过500直接给老板发送一个请假邮件。超过2000直接发送-世界那么大,我想去看看! 收起阅读 »