请选择 进入手机版 | 继续访问电脑版

IT运维管理,ITIL,ITSS,ITSM,ISO20000-ITIL先锋论坛

 找回密码
 微信、QQ、手机号一键注册

扫描二维码登录本站

QQ登录

只需一步,快速开始

艾拓先锋
搜索
查看: 280|回复: 0

小型公司DevOps落地实践案例详解

[复制链接]
来自- 广东广州

参加活动:0

组织活动:0

发表于 2018-9-1 16:52:06 | 显示全部楼层 |阅读模式 来自- 广东广州
本帖最后由 adminlily 于 2018-9-1 17:14 编辑 4 m% y0 p% O( V3 ]

2 l  r- y9 j/ E4 K3 R8 Z
6 ]7 o0 M0 J- J! Q8 o* `
( }" I1 ~* e# b1 j+ {
  最近几年DevOps的概念越来越火,各个企业也逐渐意识到DevOps对项目研发效率的重要性,也有不少第三方企业提供整套流程成熟的解决方案。而我们侥幸,在这些第三方平台尚未崛起时,制定了一套适合自己的DevOps流程。
, T5 |' E. d: V

2 c4 R/ {8 A3 c4 n; `' ~' w0 w+ }
先申明一下,因为我们公司规模较小,和在座各位朋友任职的一线互联网公司可能没有可比性。所以,我分享的一部分流程或方案,仅供参考。
6 c" I% r! N# A

* D+ R1 \# r  p- _3 E/ C
背景
( l& K3 k$ \; ], q! Z* w( j- t" C" Y5 H
. ~: V9 A, {. I1 Y; b, _6 O" t: @
0 ~; n9 v( ^; F- c* o* [/ ^
先说下背景,我们公司做的大概可以理解成SaaS服务,即从服务器硬件到系统环境到服务都归我们管。而且每家客户都有很多个性化的需求,在我接手重构前,我们平均半个月才能接入一家,经过我们几个月的改造,我们现在可以接入一家客户大概可以控制在1人天。之前,我们开发流程比较混乱,没有文档,没有各种开发流程,现在我们逐渐规范,形成稳定的流程和体系。

. G: _0 R, w5 `' l9 p9 n6 H
. G6 f/ h$ K  U
Java项目改造. D: J1 x9 o" z4 k% R. M) {  C0 W
7 l9 K# U6 L$ }, m
下面我们聊聊Java项目,我们把一个Git库中的2个项目(接口、后台管理)进行拆分:

. c+ n1 F2 J% T: R  p* i" y6 K0 l
' Z# B, w8 J2 O' V
1、接口服务% l' \# X- I( Y" N/ V+ Y& C0 r( x0 \) j

9 {" A$ J* [8 @* g
2、后台服务
# T3 ]0 h! [! e" {9 w9 Z: ~! I+ i# H* w6 O, o* a
3、html5包
! e6 T# P6 c( l* {" D( V: ^  T5 U9 S+ p+ t4 l) E
7 [+ z9 R, P' J4 g* }/ M  y- M
4、公共包服务
+ w6 d- X. x+ u# v: e9 w& Q

, t( s& c; Q, ~$ A( t

$ c9 `) |+ C- N1 W
我们主要做了前后端分离,代码Git库分支化管理(事实上大部分小公司都可以这么拆分)。
* {. S# L: H& `8 _. k3 j

0 N+ f7 h! a2 h, H- ^
我们采用和其他公司不同的方式,定义公共版为主分支,为每个客户建立1个额外分支(事实上分为开发分支、集成分支),发现公版的bug,到主分支改,改完后合并到各个分支,这样就不必重复切换到每个客户项目中改bug。
' b! N) m+ [0 m6 h, O' K( [

5 p, S- f: H/ y3 `5 p  D; @2 v
Jenkins
! x  b, |) C4 @+ F0 A& X& P+ |

; P5 K7 d8 c5 t
使用Jenkins编译,包含我们Java项目、H5项目、安卓项目、iOS项目。

5 b) @" f6 H9 z+ `2 [; p

  ~" s8 s9 B5 K$ [+ w
开发人员只需要本地调试后,提交代码到Git库的某个项目分支上,由Jenkins自动编译。如果编译错误会通过邮件反馈到影响代码的开发人员邮箱中,另外测试人员一键部署后,测试出问题,也可以通过Jira提单给开发人员。开发人员收到后,继续提交代码,不再像我们之前,必须通知开发人员,开发人员本地打包。
4 {! g% r& a3 E9 Q, P
流程如下:
2 F8 k% l) [  P) z7 n
1.png
$ L3 m7 Q5 E, M, @& p0 ?. A7 ~4 `( Y0 K
这里我们做了一点偷懒,我们版本号的维护也交给了Jenkins,通过脚本由Jenkins自动增加版本号。

4 ]: }. ~: x# ]9 R! O  M( Q* r
9 I+ W8 u+ \& w, \
我们还将所有项目中状态抽取出来,做成无状态项目(大部分公司都是这么做的,尤其之前听阿里分享,他们做到自动识别环境),这样,测试环境、生成环境的war包都是相同的。

$ L* |3 A) [6 O; x

2 i* f, p0 g$ L. R
自动化部署  a9 r& d7 u+ _# Z) ~) K
# \) j! r/ M4 a: \
然后我们做了一个自动化部署的小平台,主要功能如下:
9 I, s  _5 i" ~" _, L4 p- U& E3 p
! w$ Y* ^" j4 @( q, t3 s! Y
1、升级、显示当前版本6 O+ a+ P- M0 a4 z5 m

5 h8 q+ ^2 a, T9 u; B8 _9 S8 K" w
  l5 R$ l+ d  x- R
2、对war包有效期,真实性校验0 Y# \! _9 x9 Y: M8 }) n; A: s% o. z
- T3 j  z( j# a  M
' w1 N% s$ F9 @  i# y4 D/ C( F

# Y+ r$ E: F3 h
3、开发人员将公共SQL放入公共.sql里
6 }) E' C6 w. S0 M9 r6 d+ r# l4 ^% a+ b2 {2 C6 D
) h  I( @% i" @* B( ^8 I
4、各个客户定制化需求的SQL放入各个客户.sql里
9 i, I7 Y) P8 F! ^* t4 d9 Q6 W- T/ w
; t8 c7 f. i& G8 u% k

+ V# m' r! S+ S/ D9 {8 E- P
项目经理升级时,自动提示未执行的SQL,点击执行即可。
" i7 j* g2 I( u* N$ R

% a2 [( _! u( l$ `) C  ~
$ [9 }$ c, |2 B7 r2 m! M) z8 Y" m& O3 u
客户端' c7 p. T1 q8 g) d3 |

6 Z+ [2 Z: i+ x' g0 c) L
接下来,我们聊客户端:

, S8 k2 Z$ D6 a- s5 n
  s# G& r: _$ A3 x
客户端内容不多,我们有安卓、IOS客户端,也是经过一轮无状态抽取,然后抽取服务器地址,配置后,由Jenkins自动打包,同时打包测试环境包、生成环境包。
; [3 e. r( @  `6 r3 N2 m+ v( n
1.png

( M5 T8 ~  q* h! v$ Z+ e

& z  E. E* l9 B: w
测试组
! q  ]1 V+ S$ R9 J2 @$ {. |; k1 A* S( C6 S* i
测试人员从Jira提单后,开发人员解决后,会看到具体解决的版本号,然后进入OSS存储,安装Android程序,或者IOS程序,一键部署Java项目。
( B1 }/ Q( R" H6 ~4 |
因为安卓和IOS均是同时发2个包,Java项目、H5项目无状态,所以生产环境和测试环境都可快速部署测试。
" b/ K- H; j1 |; E: `& F4 A( w1 M
1.png
. d% C  i6 y/ P) U/ h# o5 _
% ]% G6 f3 j  z
运维组
: A/ H1 b+ g7 F6 ]

+ @, u, E( ]9 T# Y1 {
运维组重构先看看之前的图:

( U, x8 }! b2 X3 A7 \
1.png

( e5 j2 J8 g1 h" [) i
因为各个时期部署的系统版本以及服务器型号等都不通,所以线上环境比较混乱。
& W5 @& b0 k5 M6 w* W9 B3 d

% [* D7 b* V& ]! C
我们采用Docker容器统一方案解决此问题,使得每个客户机器环境均相同。我知道在座的各位都是Docker大神,我就不多讲了。

- }  T* {. U6 X: [. P& d/ x1 ^

& g+ s* F$ m( D% n/ ^: Y
看看我们现在的管理图:

/ `) M: A  u6 V
1.png

: D" u( e3 r7 v! ]% v$ J
我们用的是Portainer框架,简单二次开发了一点功能。

% V. p1 A4 O8 t* @# `. r2 l

$ w# p% X4 }6 x" ^0 `
我们用了TLS认证,所以,管理者并不是通过Linux密码控制,而是通过配置平台,然后分配权限给各个项目经理所在的team中,然后,项目经理对team成员权限进行管理分配。

- n  {* e2 R: ]( K1 K4 B, u

1 h$ C" B0 f- H
该方案优点:
  h8 V) G2 R$ J) p/ F# A: C; I
+ }& r# y: e6 S
  • 在Docker下,所有客户生产环境相同。
    * i0 d1 n0 \6 D- N5 o& T7 \. u9 j

0 [; a! M, f9 C3 m- F( G
/ d2 \1 [4 O# @8 E4 }
  • 易于备份、迁移、恢复。
    ) M% o6 _- \2 _5 r# t# w
& K6 ~0 y, z+ U+ I: u
, j5 K( `7 A/ C- z. [
  • 可建高可用环境,发包时采用灰度发包,蓝绿部署不中断服务。

    5 g# y  V* p/ E: _6 a) v

& L4 P9 h2 Y% y9 E, h
  • 可支持弹性伸缩设计,支持扩展。

    7 ~5 u9 R* {8 |+ ]7 K% x
: M, r* M) M% C5 H' H
  • 支持负载均衡,域名转发,意外切换容器等。

    ' A) `0 m1 e2 N! J- j+ c9 l3 Z
# R5 q" u' t( A' C

. S7 @' n9 {+ F" k4 m5 G2 g
  • 有利于转型微服务架构。

    6 q6 i& \$ ]1 X% l* m

. L, L* J( P# P% j9 A; O1 |+ Q* E
# @! n" R+ ^9 H5 K
快速搭建环境
3 i) S/ u7 {2 c: q+ W6 b' @
4 T4 {7 T! b* r/ H; B/ o
而建立Docker集群需要我们自动化完成,这里我采用了Ansible工具来实施,我们可通过指令分发,指令获取所有机器某个包的版本,执行不同的代码。

4 Q( |7 W* `3 z4 c, \
( X. ?: z; {  y* G1 F" K
这里我建立了各种仓库,方便Java开发,建立了一个私有仓库,一个Maven官方代理仓库,一个阿里云代理仓库;Docker上我为了方便开发打包其他环境,创建了Docker私有仓库;还有一些为了解决统一管理Linux服务器而创建npm仓库;以及安卓所要使用的Gradle私有仓库;未来,我们可能还会创建更多仓库,能支持的仓库列表都在下面:

& z5 h* N7 V8 K9 O6 c
1.png
6 g3 n5 u4 Y# N+ L7 \! g  n

9 |. O  I; P) _2 H. e: h4 A
! D# R! P3 c8 a# P% r! t5 R0 k" [
大数据篇

4 w1 F6 @* `5 l7 D% m
- K5 ^; Y3 x+ j" `2 u; G大数据一直以来是很多公司核心产品,对于小公司,如何低成本实施呢,我研究了一套强大的大数据框架Superset,并对其做了部分的二次开发。他能实现各种大数据图表展示,如下图:
0 J- v& c; w* [# ?
1.png

- F( N) M! ]# F3 G- g$ e2 v" s
我们采用iframe的形式将部分功能加入到我们管理后台。

4 C& H9 v6 y/ R+ u
  A! f' M* Q% m3 l5 C
接口篇+ ~4 ]1 h0 K" Q- J5 o

& Z3 H5 U  R8 W" j; _, c
我们采用了RESTful风格的API,也许很多人说RESTful不是很简单,10分钟上手,30分钟精通,事实上绝对比这要复杂的多。有很多的细节,很多的约束,经过几个月的协调开发后,都未必能避免出现不太和谐的接口。

: g" I* n& ~. S+ Q% f
5 b- ?3 ?; t0 g5 [! c7 ^6 k
之前,我们项目,各种接口文档都存在,主要有一下:

( k( v$ `6 F2 H) e

. s0 d: G0 O+ h; Q3 B$ O8 S
  • Swagger

    8 z* e) x/ M( Q, I+ M5 B
( ]( T* b' m- t, h
  • 阿里的RAP
    ' d: d& i, f6 c' `6 e
( N2 V7 [7 \8 Z- t4 i8 Y+ h& c2 }

: x9 T& y: \: w2 Y' L
  • Word文档
    , t* A$ A5 {; p( n
" Z; B# y- f) Q3 n! k# x$ i7 Z8 ]: @1 N

$ Z' ~7 o, }% I& ~" i9 t
  • 其它

    6 i( {+ d) @# u) v# e, [+ _

4 z* n7 ^. \9 C6 k  X$ X" x  j1 f
对了,之前的接口是这样的:

# H2 d; g! n! u4 ~% w

) k1 ^7 y* ]+ x# E. `. {
  • …/A项目/模块1/getProducts ----接口

    5 ], E* P% F* Y+ d, [
4 l( f$ A( a% b/ G& Z. v/ w1 h
# c5 O* f+ M- u* @+ X4 F4 N
  • …/A项目/模块1/Products.html ----页面
    : |8 \1 \' C7 g+ X5 V

* x9 ]0 J7 m- d
7 U5 p0 |7 o! H! R
  • …/A项目/模块1/Products.js ----静态资源

    ( c$ S% g' [1 M6 e) `/ l

$ ?7 z) ?+ \" q. U6 p$ U

4 V" k7 \' J3 v1 {4 T. p  D5 x
6 A( e. {+ p/ G5 f8 O( h8 c+ B
留下了很多的坑,这里不对RESTful再做详细介绍,有兴趣,大家可以自己了解下。我们统一了一个接口文档为postman,可能很多朋友会说postman怎么能作为接口文档,我只想说,他适合小公司,不仅有入参、出参示例(可以多个例子),还能在tests里写接口说明,也方便前端调试,调用服务器使用。

( ]/ P; k1 i2 {! J7 N

7 O+ @# n' N, z" o, z2 R% i
规范篇
* e2 j) J1 ~$ e6 L; m9 m) r
$ ~: ]- x( b7 z. {/ ?8 s! v
我们制定了一些规范和约束,比如,原来项目经理发现问题,会立马找开发,现在规定为先联系测试,由测试提单给开发。
1 I) L  n* D& P3 A4 G
4 F" x# Q$ [$ T; z8 Z: ~
Q&A1 l( D. ^3 x! j# T, u) B

/ N9 {7 a& @4 |5 _+ g7 K
Q:请问Portainer仅用于测试环境还是在生产也用这一套?
8 l  B7 \, X& S7 b2 b8 J$ R
  @' u9 b& |% f5 `# e
% A) \$ q1 B" ~, [5 p& g
A:因为Portainer是直接通过docker api执行的,并没有在服务器上装有什么客户端(也就是无侵入,这也是我们选用他的原因),我们只是在Docker里面配置了个http的TLS证书,加上我们对它做了一些改造,所以我们使用了Portainer应用生产环境。
7 r1 h8 {9 H0 r8 m1 f+ L! m

3 f  `$ @* ~7 u6 s, i9 B% w
Q:请问下测试的时候接口模拟您这边是如何处理的?

( s! `0 O" F/ {$ z! x
( S' V# [# [- R; j: M$ v
A:Ostman默认录入了几个多种情况下的出参,其次,我们前端每个人都有一套独立环境,通过Web端管理部署(数据库和测试人员共用),不会受后台开发人员对接口修改而中断服务。其次我们有少量前端页面使用了mock.js。
% r/ h( A. D# `; [5 A; z

) s  {4 b" R3 ]* [1 v4 u' w; F; p- T
Q:请问Docker里跑Java应用性能怎么调优,默认是共享资源池,对Java来说CPU切换很费性能,除了绑定CPU,但这样就没有弹性之说,麻烦说下?
4 C( m- R5 @- f1 Y9 D! ^  U* D

0 L$ w9 ?7 b2 k: N8 n9 E$ @& y* U7 w3 \4 Q
A:这个性能,我们对Java项目进行多次内存优化,通过ide的内存管理,线程查看等多重方法进行调优,单从war包体积上我们就缩小了60%,内存也下调很多。我们并不能自动伸缩,目前是通过Nginx配置多容器来实现负载均衡。

9 v$ {& S6 H9 [2 [0 @

( l* l8 Z: n/ Y
Q:如何实现分布式事务?如何保证数据一致性?

' S" I& Y  x, N' c+ C  M& s" ~

" @0 a/ ?8 f/ m+ n
A:我们在Nginx层通过策略保证同一个机器请求只会分布到一台机器上,用最少代价解决这个问题,其次我们项目中,大部分都使用全局uuid操作和插库。

  |  p2 j. j, c" Y+ W* Q  @
4 u" O7 s5 s6 k
Q:贵司的业务模式跟我们很像,感觉很受用。想问下,多客户、多版本共存的情况下,版本升级这块儿是怎么做的?
3 M4 `/ P) D' E) Y. V

4 p* S: q0 l9 r* t' e8 d- G
A:我们使用的是Git分支化管理,由Jenkins定义版本号,SQL分为公共和私有的部分,比如某个客户升级2.0.0版本,会自动检测上个版本到此时的SQL语句,提示项目经理点击,自动执行。(我们现在回滚项目版本,不支持SQL回滚,所以我们SQL一般只增不减、不改),我们可以随时查看某客户线上版本和SQL执行到什么地方。
$ z6 X' {5 U) U# T- x: g
* d' Q( L: C2 F4 N
Q:日志如何存储和分析?用什么工具?系统异常如何监控?

7 x- e+ @( k6 |' F4 h

! z' ~" A3 ]& j' A* d3 P
A:先说说异常如何检测吧,我们做了一套http监控框架,以任务的形式添加,然后会对已配置的线上环境、多容器进行监控,比如任务为http://xx.com/..../messages?token={token},在配置任务执行时间及频率,然后配置项目列表,其中项目编辑的信息有host,可理解为http://xx.com/这块,还有变量列表,支持随意定义,比如token 11111111 用户token信息,这种k、v、说明文字,执行任务的时候,自动替换host和占位符。系统只记录变更,我们项目接口统一了出参,当状态码异常时显示,此方案可实现监控各种容器、各种测试、生产环境。

5 N* O0 a) ]) t$ ~8 K

% F) {* C3 m: p5 Z) f
+ y/ g" I$ _- V4 ]( @; b
关于日志收集,目前我们并没有很多公司搞的很高大尚,因为这块,还在改造中。我们就是多容器映射了本地磁盘目录,然后对这些目录日志文件进行合并,对那种error级别的日志,筛选出来。

# G0 s. }- [* R5 j" E9 `: s
. W6 g  ?# ^4 Y4 E( i# q  B
原创:邵磊

( c$ `7 {: T0 h  c1 V; Q, C# f  i: Y' v, P5 P6 j' g
- l5 c, t. i$ j( H- @. p: K$ }- ?

本版积分规则

选择云运维时代的王牌讲师-长河老师,助你轻松入门ITIL Foundation培训课程

QQ|小黑屋|手机版|Archiver|艾拓先锋网 ( 粤ICP备11099876号-1|网站地图

Baidu

GMT+8, 2019-3-20 03:31 , Processed in 0.233056 second(s), 30 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表