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

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

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

扫描二维码登录本站

QQ登录

只需一步,快速开始

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

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

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

参加活动:0

组织活动:0

发表于 2018-9-1 16:52:06 | 显示全部楼层 |阅读模式 来自- 广东广州
本帖最后由 adminlily 于 2018-9-1 17:14 编辑 2 m, T; w6 W1 y: K$ K& B

( i. F/ [$ e: B1 p1 S% q/ Q

& I/ J4 v2 \0 \

- K% F, X8 v, D) _  ]
  最近几年DevOps的概念越来越火,各个企业也逐渐意识到DevOps对项目研发效率的重要性,也有不少第三方企业提供整套流程成熟的解决方案。而我们侥幸,在这些第三方平台尚未崛起时,制定了一套适合自己的DevOps流程。

3 j' A  }0 I' U0 q
. h: Y4 [/ j% P4 x& h
先申明一下,因为我们公司规模较小,和在座各位朋友任职的一线互联网公司可能没有可比性。所以,我分享的一部分流程或方案,仅供参考。

0 y6 ?! l1 @# f& [+ [

: J$ I: @6 g; [1 k% c
背景, H$ ?8 J0 e, h, f6 M% R9 ^
" l7 S1 z' ^* t  P* D8 O) X" Z7 W' X

5 _5 o; m% U: _/ b0 u& a

' O8 b" Z5 w( H: M/ l5 {" n先说下背景,我们公司做的大概可以理解成SaaS服务,即从服务器硬件到系统环境到服务都归我们管。而且每家客户都有很多个性化的需求,在我接手重构前,我们平均半个月才能接入一家,经过我们几个月的改造,我们现在可以接入一家客户大概可以控制在1人天。之前,我们开发流程比较混乱,没有文档,没有各种开发流程,现在我们逐渐规范,形成稳定的流程和体系。

  g$ L( m2 @2 _9 |+ H
# k9 Y4 @1 I1 F# e
Java项目改造* o3 r8 ^( @: ^( d: F3 y/ U
0 C. b  W6 Y8 O' M7 o8 f/ t1 [. S$ g% H
下面我们聊聊Java项目,我们把一个Git库中的2个项目(接口、后台管理)进行拆分:
- ]& l5 a" k1 d5 ]1 h$ E/ o) e
* Q4 L/ l& V) ]" B  H! O
1、接口服务% [8 A- ~; V: \: q' O- x( R' D# t

/ R: \) q1 F' z; e" T- y! _
2、后台服务2 L) `5 v( W; l) I

3 T$ S7 e: S5 S0 X
3、html5包
; I. J) I# K* f
% z! V% ~0 U) o5 s% T- s9 Y, ^8 s9 \% J) A$ N% Y
4、公共包服务
8 o6 w, J% |. L. |) E/ F7 z
! f4 q9 }8 H* h  ]- L& ?& s5 F
7 i6 Z- g( i  o8 t: G
我们主要做了前后端分离,代码Git库分支化管理(事实上大部分小公司都可以这么拆分)。

% O) L4 y9 w! p

$ {& P6 a9 z4 ~0 P
我们采用和其他公司不同的方式,定义公共版为主分支,为每个客户建立1个额外分支(事实上分为开发分支、集成分支),发现公版的bug,到主分支改,改完后合并到各个分支,这样就不必重复切换到每个客户项目中改bug。
: R- F1 U1 H3 Y9 S
& P: H! T* V% Y7 X* k: r2 z
Jenkins
+ v; g3 J6 j( q+ F  y& E
2 \3 N/ `" }* d2 L6 q
使用Jenkins编译,包含我们Java项目、H5项目、安卓项目、iOS项目。
' @# ^! Q" G, u; m
- \- q, K- u& _2 F" K5 G$ Z
开发人员只需要本地调试后,提交代码到Git库的某个项目分支上,由Jenkins自动编译。如果编译错误会通过邮件反馈到影响代码的开发人员邮箱中,另外测试人员一键部署后,测试出问题,也可以通过Jira提单给开发人员。开发人员收到后,继续提交代码,不再像我们之前,必须通知开发人员,开发人员本地打包。
% c' R! G7 h1 J) J$ o
流程如下:

; G: y' N9 o. p3 I  I# U, g
1.png

# \' R8 ?" q; s; @
这里我们做了一点偷懒,我们版本号的维护也交给了Jenkins,通过脚本由Jenkins自动增加版本号。
% C& b! C, ~1 s1 _" J) o

& }* A# ?) h: |* j) M7 ^
我们还将所有项目中状态抽取出来,做成无状态项目(大部分公司都是这么做的,尤其之前听阿里分享,他们做到自动识别环境),这样,测试环境、生成环境的war包都是相同的。

" R6 E' n& P* x: L( C
1 t4 c, S7 a7 Y
自动化部署
* u& K0 D+ ?6 s3 A) Q5 s6 j9 t- A: f5 x) r" b0 C
然后我们做了一个自动化部署的小平台,主要功能如下:

6 m/ V: e& i2 `$ S
' J5 U/ ]9 B0 m+ u1 @9 c
1、升级、显示当前版本9 S" h; e# U8 v* ]1 j' h/ x$ m6 n
2 W: b% x* V8 y: K$ G; z) r
9 ~. E: m/ t9 B: a0 Q. C7 e8 U
2、对war包有效期,真实性校验% b) j2 I1 f& G* e4 _0 I% q3 h
& ]: `( e6 s; d$ p4 W5 L
: E- f. r3 z6 |+ i& l& G" i) T
& x; U" C4 u& i9 ~% H2 V) L* O
3、开发人员将公共SQL放入公共.sql里, k+ T7 d5 z* L, ^* y0 B4 n
& A& j6 n9 t, b# R9 L3 D0 ^( e  W
) t7 a1 P9 @; f0 m4 R5 [5 ?
4、各个客户定制化需求的SQL放入各个客户.sql里
$ J7 D; g$ J3 d

. z* z9 V3 j  `# A1 b' a2 S' }# J6 D. n! I0 ^: w- y3 F4 W
项目经理升级时,自动提示未执行的SQL,点击执行即可。

9 w( L# }8 X: I# b. s. p2 W
9 G8 s$ ]0 D9 \9 B4 I* G# A. w" |
- Q1 a# q& ~7 L

5 v9 _( b4 w- G. W" ?" v) n. Q
客户端; c6 |4 y/ m6 c) p8 R

; }+ u. Y4 Q. o8 Q
接下来,我们聊客户端:

% f* X. z- U! @& c$ O
5 Q! ?0 X( [! l" R
客户端内容不多,我们有安卓、IOS客户端,也是经过一轮无状态抽取,然后抽取服务器地址,配置后,由Jenkins自动打包,同时打包测试环境包、生成环境包。
8 H% C7 j& b* y" ]. X* j$ z
1.png

9 T. z+ w* G8 D" ]# E5 D. W$ W8 ?
" O  _0 D$ L2 v% P3 x5 w
测试组0 O9 \! B; l4 x+ H! l

  _2 ~" c$ O) [& a0 v9 p
测试人员从Jira提单后,开发人员解决后,会看到具体解决的版本号,然后进入OSS存储,安装Android程序,或者IOS程序,一键部署Java项目。
: Y! D6 i( ]. o9 Q* O: C
因为安卓和IOS均是同时发2个包,Java项目、H5项目无状态,所以生产环境和测试环境都可快速部署测试。
  P+ P0 D$ H9 a" Q& L0 ?/ S4 r; z( e
1.png
* g# q+ T* l2 s% U, N9 ]
9 t. Z; O' @. t1 ]7 R
运维组

  ]5 Q' `/ P% I$ a
2 s5 E% u$ \0 |+ Z4 w6 S
运维组重构先看看之前的图:

/ e0 L6 s+ C9 ^( P4 S* u
1.png

. p% [+ w; W0 d( E! Y
因为各个时期部署的系统版本以及服务器型号等都不通,所以线上环境比较混乱。
+ \# Y- j6 }( O
6 H  r3 q% u1 f( x3 g8 B
我们采用Docker容器统一方案解决此问题,使得每个客户机器环境均相同。我知道在座的各位都是Docker大神,我就不多讲了。

% }2 X! G9 U( z& y$ m# k2 M
, W% ]+ s7 i1 c8 h0 i  i$ o! l
看看我们现在的管理图:

+ p- v! Q9 ?' P; c7 ?
1.png
( k" k, O& b1 P5 H1 E
我们用的是Portainer框架,简单二次开发了一点功能。

3 ~1 T5 D& Y$ N

$ C7 z$ W9 c# Y1 n' D" \1 }
我们用了TLS认证,所以,管理者并不是通过Linux密码控制,而是通过配置平台,然后分配权限给各个项目经理所在的team中,然后,项目经理对team成员权限进行管理分配。

' Z  P8 H" `# |8 S
2 H$ b1 x9 i' D% Y* B: c
该方案优点:
& B; x9 _) l0 ?) q. h5 z0 I  P

$ I2 t. N% H4 |: T
  • 在Docker下,所有客户生产环境相同。

    + ^8 g% ^$ M( N2 ~7 q6 g3 I
' P$ R; ?! _) \; t9 t/ s
6 A) R8 X' ^- g3 Q  ?
  • 易于备份、迁移、恢复。

    ' y1 Q% A8 m2 D: W, P
# u' z- X; L  `4 X

+ M* E4 p; [  v/ Q" K7 N
  • 可建高可用环境,发包时采用灰度发包,蓝绿部署不中断服务。

    " c: l+ F( F8 T' X' p- n

7 D9 k1 `. a' W4 k1 N
  • 可支持弹性伸缩设计,支持扩展。
    : T8 f2 G0 Z/ g3 B+ j, h4 |
$ X7 z. k+ }9 Y- t7 Z) T5 e/ y, Z% }
  • 支持负载均衡,域名转发,意外切换容器等。
    # I- l& Q0 ~6 j! @

' s% r* D7 G7 D" P

  W+ C  T8 T% n) K: F0 u
  • 有利于转型微服务架构。
    2 g( K  j( a' Z6 Q" I

2 G- U' ]+ g5 W$ l
& i+ {# v& v+ ]5 y. o
快速搭建环境, d- q/ z! _" G. H0 j' w

' s7 x' C8 C) i, Q
而建立Docker集群需要我们自动化完成,这里我采用了Ansible工具来实施,我们可通过指令分发,指令获取所有机器某个包的版本,执行不同的代码。
' O1 X' N$ i; d
" O) S4 E& Z7 m9 Q7 N! A7 Z
这里我建立了各种仓库,方便Java开发,建立了一个私有仓库,一个Maven官方代理仓库,一个阿里云代理仓库;Docker上我为了方便开发打包其他环境,创建了Docker私有仓库;还有一些为了解决统一管理Linux服务器而创建npm仓库;以及安卓所要使用的Gradle私有仓库;未来,我们可能还会创建更多仓库,能支持的仓库列表都在下面:

/ E# Z. P  u, a
1.png

$ {6 Q" Y; {' l! {
$ Z+ f! y- G4 l: }8 o

1 i% A" ^* S7 u5 ^大数据篇

. {; x; H$ a7 |  m5 [# H0 o6 T/ C7 d- A; d1 s- u
大数据一直以来是很多公司核心产品,对于小公司,如何低成本实施呢,我研究了一套强大的大数据框架Superset,并对其做了部分的二次开发。他能实现各种大数据图表展示,如下图:
0 }5 S8 R( Q' Y1 j8 S4 B( V
1.png
8 {. m9 v& w/ R( K0 Y3 E% L8 Y5 x
我们采用iframe的形式将部分功能加入到我们管理后台。

7 [6 J- p, \5 q( s9 r

3 L. B. T# Z  l. z. Z+ e
接口篇  u" q! ]! ]! n' X" w0 ^

# S# W4 q9 ~5 e" K; N6 [
我们采用了RESTful风格的API,也许很多人说RESTful不是很简单,10分钟上手,30分钟精通,事实上绝对比这要复杂的多。有很多的细节,很多的约束,经过几个月的协调开发后,都未必能避免出现不太和谐的接口。
$ t: g, v0 w1 }, V+ ^* I" G6 x. u4 Q

: i& U% ?9 U% T2 G/ M& l$ S9 x
之前,我们项目,各种接口文档都存在,主要有一下:
" I( I3 b4 K2 s

3 r, I: f) c7 O) J
  • Swagger
    0 c* |+ W. w. ^: _" N

. Y, K! [; b. q9 j3 N& G
  • 阿里的RAP

    7 I8 M* s1 x; A& {2 X& r( u4 }
2 J$ G- C- S' E7 X$ c

1 s- L8 Z: b/ e0 [! n- y9 C
  • Word文档

    ) g7 c# Q* r4 b0 r9 b* l7 L* ]3 w' C
! q7 j- u) U4 v- ^
9 Y% i% U! @1 E
  • 其它
    3 S6 J' U! z3 `3 O4 P
5 p: K) y1 r" J% [7 F& [! f
对了,之前的接口是这样的:
8 j1 ?# y5 j( J* {  C& X

0 b2 {5 D) f! m; o
  • …/A项目/模块1/getProducts ----接口

    ! w0 k, h! I' X! t

0 a+ O7 ?7 I# q
+ B) g) x, ]  M. X4 Q
  • …/A项目/模块1/Products.html ----页面
    ) B# G) r  U, M0 {

" d* M' J: g4 n7 |1 H
4 r6 r& F, e5 m8 y
  • …/A项目/模块1/Products.js ----静态资源

    " ]: X) f- g+ j1 m* o1 t

0 O- |  t2 k, Y1 z- x, c

$ K3 W5 ?: X: v5 B, t; P

; g0 C! }2 F$ O7 C2 K  L+ @; b  y
留下了很多的坑,这里不对RESTful再做详细介绍,有兴趣,大家可以自己了解下。我们统一了一个接口文档为postman,可能很多朋友会说postman怎么能作为接口文档,我只想说,他适合小公司,不仅有入参、出参示例(可以多个例子),还能在tests里写接口说明,也方便前端调试,调用服务器使用。

! f3 O3 ]+ R; F9 a

9 X( u& y- C2 J5 M  J1 G( A+ o& v
规范篇
& O6 u6 M) U7 ^5 c( ?
% e5 X6 r0 }' |' w) }. A
我们制定了一些规范和约束,比如,原来项目经理发现问题,会立马找开发,现在规定为先联系测试,由测试提单给开发。

" l/ h/ L8 q( L5 J3 c# b$ L7 m
/ I2 ]7 S) ~3 j! S
Q&A
4 w$ ]+ R& d6 j- Y$ P: o
( \! k& s/ _& w: a4 C) X9 U& U
Q:请问Portainer仅用于测试环境还是在生产也用这一套?4 o/ b, G5 z4 j/ w9 o" W" q, b, x/ C
- a1 s$ Y: r7 ^( O) d3 ]4 L

% [/ T! \$ k4 ~1 y: b! c  J- `A:因为Portainer是直接通过docker api执行的,并没有在服务器上装有什么客户端(也就是无侵入,这也是我们选用他的原因),我们只是在Docker里面配置了个http的TLS证书,加上我们对它做了一些改造,所以我们使用了Portainer应用生产环境。

& j1 r7 V& Y! E3 r: i2 c

4 b- _% Z2 B! L# y* h/ O, d
Q:请问下测试的时候接口模拟您这边是如何处理的?

2 N( `1 s3 e+ u/ u9 i( H

7 p* B2 v) `+ t  A/ G" F8 p! Z
A:Ostman默认录入了几个多种情况下的出参,其次,我们前端每个人都有一套独立环境,通过Web端管理部署(数据库和测试人员共用),不会受后台开发人员对接口修改而中断服务。其次我们有少量前端页面使用了mock.js。
- s1 F- W" w" ?8 _5 H2 {
7 Z* w9 I0 ~1 Y# a$ \' s* }
Q:请问Docker里跑Java应用性能怎么调优,默认是共享资源池,对Java来说CPU切换很费性能,除了绑定CPU,但这样就没有弹性之说,麻烦说下?

: b* U! a" d) }, }3 ~
2 x/ Z7 Q- ^7 ^4 A2 Y, M+ S
A:这个性能,我们对Java项目进行多次内存优化,通过ide的内存管理,线程查看等多重方法进行调优,单从war包体积上我们就缩小了60%,内存也下调很多。我们并不能自动伸缩,目前是通过Nginx配置多容器来实现负载均衡。

0 p& U/ Q8 l" `4 V7 g0 ]8 d6 [. }. N
, I, I" S! d! p1 s2 e) C
Q:如何实现分布式事务?如何保证数据一致性?
: V4 U9 S& V1 h* }# w

' Q. x- [/ j% e3 E5 g2 ]& p* D
A:我们在Nginx层通过策略保证同一个机器请求只会分布到一台机器上,用最少代价解决这个问题,其次我们项目中,大部分都使用全局uuid操作和插库。
& x( V; t( U6 R8 S0 [8 `

5 k& w; {& N8 k9 ~" s/ w' x
Q:贵司的业务模式跟我们很像,感觉很受用。想问下,多客户、多版本共存的情况下,版本升级这块儿是怎么做的?
& k2 @; g) ?* j/ B! _

4 Y& f4 O3 L4 H( B' C! M
A:我们使用的是Git分支化管理,由Jenkins定义版本号,SQL分为公共和私有的部分,比如某个客户升级2.0.0版本,会自动检测上个版本到此时的SQL语句,提示项目经理点击,自动执行。(我们现在回滚项目版本,不支持SQL回滚,所以我们SQL一般只增不减、不改),我们可以随时查看某客户线上版本和SQL执行到什么地方。

- `9 K& l7 r/ G- Q( L% {# Q

* o- v/ W/ k7 x0 e; ?; n3 W- Q
Q:日志如何存储和分析?用什么工具?系统异常如何监控?

. O; {0 e+ R/ q' `. m

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

1 i% v/ ]6 _$ W

" y' t! q/ q' _, i- g

7 t4 H$ O2 c! e5 h; w$ B
关于日志收集,目前我们并没有很多公司搞的很高大尚,因为这块,还在改造中。我们就是多容器映射了本地磁盘目录,然后对这些目录日志文件进行合并,对那种error级别的日志,筛选出来。

7 ^# w: X4 p2 q% `$ H
( l% x$ V+ m* b3 k2 J
原创:邵磊
9 O2 b- H5 H' K6 \
. g: G* {: Q8 u/ x4 x2 D: U" H' ^
$ _- k; h2 C  A% T3 t0 n

本版积分规则

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

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

Baidu

GMT+8, 2018-11-14 13:08 , Processed in 0.240666 second(s), 32 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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