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

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

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

扫描二维码登录本站

QQ登录

只需一步,快速开始

搜索
查看: 395|回复: 0

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

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

参加活动:0

组织活动:0

发表于 2018-9-1 16:52:06 | 显示全部楼层 |阅读模式 来自- 广东广州
本帖最后由 adminlily 于 2018-9-1 17:14 编辑 * v) g' n1 L( W( o' Y9 V
  |% H+ D: O/ v
, z$ g+ F! Y' R' R; @0 m' r) Z5 }
" E  |$ B/ B4 D" u: }4 m
  最近几年DevOps的概念越来越火,各个企业也逐渐意识到DevOps对项目研发效率的重要性,也有不少第三方企业提供整套流程成熟的解决方案。而我们侥幸,在这些第三方平台尚未崛起时,制定了一套适合自己的DevOps流程。

$ G; z3 M: o* Z

6 w$ R8 B) p" W* Q% k$ U: G
先申明一下,因为我们公司规模较小,和在座各位朋友任职的一线互联网公司可能没有可比性。所以,我分享的一部分流程或方案,仅供参考。
+ `( W2 N! l/ h6 ^7 ~
; c1 v0 J% x% i4 {/ h; U, X
背景
8 u0 D. J7 u0 s* n$ d- m# L. I, B) A9 Q  k6 K
  s: z- `9 m) ]- N+ A
) O1 j0 @( p  A0 Z' R
先说下背景,我们公司做的大概可以理解成SaaS服务,即从服务器硬件到系统环境到服务都归我们管。而且每家客户都有很多个性化的需求,在我接手重构前,我们平均半个月才能接入一家,经过我们几个月的改造,我们现在可以接入一家客户大概可以控制在1人天。之前,我们开发流程比较混乱,没有文档,没有各种开发流程,现在我们逐渐规范,形成稳定的流程和体系。

! x8 O3 a" {" {

4 f- R. W2 ?0 z8 x) \1 j
Java项目改造
1 H9 B$ L1 |* f! l

0 h2 c$ U: _$ `0 M) g6 q3 ~* w0 V* u
下面我们聊聊Java项目,我们把一个Git库中的2个项目(接口、后台管理)进行拆分:
- |" V# B0 r2 Q/ F( v0 |
- m6 v: V7 K/ p7 C" ^
1、接口服务& A9 V6 G3 K& f4 x- v$ A0 @' n3 _
/ I2 u) N7 M2 T0 e& D9 u/ V4 t7 n
2、后台服务
1 H5 S' c) |5 S, O% |, Q( p, I- P: n' h: L; R
3、html5包9 s1 X) S- m+ ?; U
7 _) N9 S5 R2 l/ C' Y, n
/ a& f. P/ c1 H* b' c3 \
4、公共包服务4 Z, S2 j) d3 Y  {( g2 _9 J* d, A
  C& a4 `% q* O2 ~- O3 c% r! w
) {# T7 a7 B1 T: d
我们主要做了前后端分离,代码Git库分支化管理(事实上大部分小公司都可以这么拆分)。

2 G" z; z1 q' B! h& `1 _  z
" y: ]( x' ]1 ]1 W9 F' A' _
我们采用和其他公司不同的方式,定义公共版为主分支,为每个客户建立1个额外分支(事实上分为开发分支、集成分支),发现公版的bug,到主分支改,改完后合并到各个分支,这样就不必重复切换到每个客户项目中改bug。

% B% F! x5 H8 O! j: O# W6 O
/ h% x$ k9 c' c: o
Jenkins
, ], i5 [! H7 N  h4 I
* a6 k3 j- h  ^
使用Jenkins编译,包含我们Java项目、H5项目、安卓项目、iOS项目。

! x) {! q9 u! V. |
# A% _% d: x/ _$ r' }+ ~
开发人员只需要本地调试后,提交代码到Git库的某个项目分支上,由Jenkins自动编译。如果编译错误会通过邮件反馈到影响代码的开发人员邮箱中,另外测试人员一键部署后,测试出问题,也可以通过Jira提单给开发人员。开发人员收到后,继续提交代码,不再像我们之前,必须通知开发人员,开发人员本地打包。
+ X4 s* Q/ B! X% L6 z0 R$ w8 [  ]
流程如下:
7 |; H' t2 m7 ?, y/ ^
1.png

/ }* S2 i, Q. o
这里我们做了一点偷懒,我们版本号的维护也交给了Jenkins,通过脚本由Jenkins自动增加版本号。

: U* T$ D6 v1 b1 J
1 ^2 }1 e2 u) r  x
我们还将所有项目中状态抽取出来,做成无状态项目(大部分公司都是这么做的,尤其之前听阿里分享,他们做到自动识别环境),这样,测试环境、生成环境的war包都是相同的。

: s& E4 y) k( C+ T
9 x+ h! T7 o. S, _
自动化部署
! j7 \; \6 h& g+ m9 N) T
. }  u6 ?1 k5 h% q* e5 C: Z然后我们做了一个自动化部署的小平台,主要功能如下:
$ ~8 A3 A2 }/ n' ~) F' s

, b) h% \; V0 h- L) K
1、升级、显示当前版本
" j+ k" l( z2 u! b! |9 s

( M  _" i. |" |( l: L9 [# S. E' @$ p* q' A
2、对war包有效期,真实性校验4 V) r3 @) ~+ L5 T3 F

* p0 T$ C* G9 E  x' o) [
# i( A, f4 m0 U6 @

5 ~5 A$ i, i/ U& G& ~
3、开发人员将公共SQL放入公共.sql里
2 `9 R5 f& X/ S; R  D7 x# L
7 K: a  B% n4 q; F. M, g, V. c% c1 A0 d& n) U  N: b# `
4、各个客户定制化需求的SQL放入各个客户.sql里1 P. V  |) p3 ^3 l& d

: ~7 ^3 o' `6 I1 V2 w
7 I$ ]( y* O5 J7 m8 r; ~1 ^6 a
项目经理升级时,自动提示未执行的SQL,点击执行即可。

  J, P" H4 {9 i

( v6 f; z9 s: O0 J; A4 D' z. t# N. [
; g' \& n, f3 x4 A" s2 g' Z$ q
客户端  @+ N- a6 j! }% Q, N
. H4 r0 ]( y. u( }- H& j3 ^/ n
接下来,我们聊客户端:
9 z. Z5 H7 u1 P
6 \# q1 I5 m; v$ w  T! v0 x
客户端内容不多,我们有安卓、IOS客户端,也是经过一轮无状态抽取,然后抽取服务器地址,配置后,由Jenkins自动打包,同时打包测试环境包、生成环境包。

4 M: p4 M: {5 `$ r
1.png
6 u( c, z$ g" U; Q8 N: k

! T  C- A9 ~. D! t6 [" c3 `1 \
测试组: k3 q* a8 A6 d- d2 a* }8 _7 U

* U, x4 ^! r* Z/ |, e$ p# ?- F
测试人员从Jira提单后,开发人员解决后,会看到具体解决的版本号,然后进入OSS存储,安装Android程序,或者IOS程序,一键部署Java项目。
& e6 v# _0 C$ l* F1 G
因为安卓和IOS均是同时发2个包,Java项目、H5项目无状态,所以生产环境和测试环境都可快速部署测试。
3 _  l% J( h: |
1.png

7 R; `  W9 ]2 }8 m* s$ Y

' `/ T, h5 [) f% ~; O7 k  Q
运维组
& e" K. ]  i+ t

# ?0 K/ R' Y  L( t% v1 ?
运维组重构先看看之前的图:

1 @" B$ t4 {. ?$ b; a" c) ^2 {
1.png
, g: m: ?& c7 ^& J& I' X
因为各个时期部署的系统版本以及服务器型号等都不通,所以线上环境比较混乱。
) {  z8 w0 o6 H0 O5 f! d! Q7 Y: X
! j5 ~6 h& x( w/ }' x
我们采用Docker容器统一方案解决此问题,使得每个客户机器环境均相同。我知道在座的各位都是Docker大神,我就不多讲了。
  s9 Z5 n; d' ^, J4 k+ ~

: `, S  P6 c% w* L7 f
看看我们现在的管理图:

  U& u5 }9 z" V
1.png

( w7 V  g4 }" @% W+ r3 ]
我们用的是Portainer框架,简单二次开发了一点功能。
/ r( k0 E5 }  p5 M5 H
9 g, I# ~  V- E
我们用了TLS认证,所以,管理者并不是通过Linux密码控制,而是通过配置平台,然后分配权限给各个项目经理所在的team中,然后,项目经理对team成员权限进行管理分配。

( Z6 J. U$ T3 J; [8 \* n( R. ^  N
) E) t+ v9 c2 C/ Z8 a8 B
该方案优点:

, ]( m8 H# z, f" t9 d) d6 Y* t

6 P5 w6 z; D! m
  • 在Docker下,所有客户生产环境相同。
    - ]( F9 ~2 @/ h. s5 U, z

( a5 Q% I( c8 @" }! `+ q. K
& l  D0 L7 z* C+ D+ k$ \
  • 易于备份、迁移、恢复。
    . m$ j, R) B9 r* U; m
# F6 D3 {' v& m3 ~, ]9 u1 r2 M

/ g! G( R# H2 z# d6 T# R
  • 可建高可用环境,发包时采用灰度发包,蓝绿部署不中断服务。
    * R7 C7 ^' \4 G7 Y1 A) b$ ^

) b( o, ]; f) K
  • 可支持弹性伸缩设计,支持扩展。

    9 I; Z# K- @$ p: A. s& Y  Z0 ~0 R

, I# [! G6 u4 V$ [7 T% E$ w
  • 支持负载均衡,域名转发,意外切换容器等。
    ( {1 ]0 @: }0 M  F
4 y( L1 V0 T  {' Y7 f: C7 A2 `) y
- D) d- L. G8 Y
  • 有利于转型微服务架构。
    5 D5 F) r' u7 o; I# H

* W# F5 f/ W) ]3 J: V9 w" R5 Y# S

5 [  g( s  R& D! C+ H
快速搭建环境
& t  [# [5 I, G
/ N% q' k2 @5 ]0 m) l' V
而建立Docker集群需要我们自动化完成,这里我采用了Ansible工具来实施,我们可通过指令分发,指令获取所有机器某个包的版本,执行不同的代码。
# P; c- ?1 V7 o

" u8 y  D9 D1 {2 C
这里我建立了各种仓库,方便Java开发,建立了一个私有仓库,一个Maven官方代理仓库,一个阿里云代理仓库;Docker上我为了方便开发打包其他环境,创建了Docker私有仓库;还有一些为了解决统一管理Linux服务器而创建npm仓库;以及安卓所要使用的Gradle私有仓库;未来,我们可能还会创建更多仓库,能支持的仓库列表都在下面:
9 h! `9 u, y+ l5 t) H2 A& B9 g# h
1.png

, R& T+ D% C" S/ {* O9 J! }

8 n7 Z& c7 _( w) C% a# W

3 {" i4 ^, `! M: V; g) W大数据篇
8 M' _& J% K- B. A1 U
% n) x9 x+ w( I8 x9 P
大数据一直以来是很多公司核心产品,对于小公司,如何低成本实施呢,我研究了一套强大的大数据框架Superset,并对其做了部分的二次开发。他能实现各种大数据图表展示,如下图:

0 L  l5 |1 l* s* i% ~8 \
1.png

* t6 z3 h) b: P! c- e) r
我们采用iframe的形式将部分功能加入到我们管理后台。
/ R1 K6 `: f3 n0 g& Y+ j

! W  q8 I. [. {* o4 X3 N
接口篇+ H* S% b) t* c% l
8 S% @- \3 i( j; }0 w
我们采用了RESTful风格的API,也许很多人说RESTful不是很简单,10分钟上手,30分钟精通,事实上绝对比这要复杂的多。有很多的细节,很多的约束,经过几个月的协调开发后,都未必能避免出现不太和谐的接口。
8 C4 a! W4 w) F4 h- L# @! a
, i& M) i3 q6 k( J( m+ }
之前,我们项目,各种接口文档都存在,主要有一下:
6 e: k/ i( [& L
  J- y( j  T" C) Z( _. o
  • Swagger

    ; B+ p# ?9 y8 u' u( h9 x" d2 v$ `

5 [% M- }2 H' D
  • 阿里的RAP
    , q5 f! P3 ?: ?
/ o  m. N/ T+ Y$ `8 a# _
( F# l1 t3 G% E( X
  • Word文档
    - Y& M! d: {3 e6 M0 g3 j2 w

0 p1 m( {6 i4 f; `# {) m: o

. Y+ C# n- \# T% t. t$ U3 U+ G# n8 Q
  • 其它
    $ ?( L) ~8 Q4 B# O+ \% n' ^

, t% k, h. X5 Q+ u) p" f) j
对了,之前的接口是这样的:
" b- C8 k: V( `3 Q7 j
% N" S3 s8 ~: f. O& ]0 x
  • …/A项目/模块1/getProducts ----接口
      y  Z7 f; f+ u+ y. O. u* [( k
- `: |- H5 {4 _: P- N( ]7 X

5 {2 v: g+ ^0 y- A  m5 T
  • …/A项目/模块1/Products.html ----页面
    0 X- H* g  T6 k$ v3 U1 o

5 U3 g# E( O  }) o* ^( E3 ^
/ E+ d% L# I( w& J2 n2 R
  • …/A项目/模块1/Products.js ----静态资源
    7 ?% V& e- B  V7 o& u; p
  J, y2 W2 ~: Y+ K* C/ G
4 @% j8 u; B0 o3 k0 T7 i6 M1 J7 N

: V5 Y' R5 G* b2 d
留下了很多的坑,这里不对RESTful再做详细介绍,有兴趣,大家可以自己了解下。我们统一了一个接口文档为postman,可能很多朋友会说postman怎么能作为接口文档,我只想说,他适合小公司,不仅有入参、出参示例(可以多个例子),还能在tests里写接口说明,也方便前端调试,调用服务器使用。
$ j5 ?5 E4 D- D6 m+ n8 g
7 y& M/ H/ T3 n$ Q9 V' g
规范篇
; d0 j) v7 e% U6 Z- h2 S

' g+ l' E( |; i0 S7 Q; K9 b" `
我们制定了一些规范和约束,比如,原来项目经理发现问题,会立马找开发,现在规定为先联系测试,由测试提单给开发。

) c1 D; Q0 _+ q1 d
! d! B2 l5 l: w8 j
Q&A
3 v) c& U0 I+ G

8 p( S- l- `2 d0 I7 N6 S
Q:请问Portainer仅用于测试环境还是在生产也用这一套?
5 X$ G# L  c. J% x, d" J% d
3 y- e9 I9 I9 _

  [' t' p# V/ Z! k, j% y  i0 mA:因为Portainer是直接通过docker api执行的,并没有在服务器上装有什么客户端(也就是无侵入,这也是我们选用他的原因),我们只是在Docker里面配置了个http的TLS证书,加上我们对它做了一些改造,所以我们使用了Portainer应用生产环境。

0 K) Q8 ]  o$ @
- {' U+ U$ ^' o4 u8 P1 i
Q:请问下测试的时候接口模拟您这边是如何处理的?

1 I5 R, O$ Q& Y3 H) S

* d7 J' O! H8 D& _  W, b
A:Ostman默认录入了几个多种情况下的出参,其次,我们前端每个人都有一套独立环境,通过Web端管理部署(数据库和测试人员共用),不会受后台开发人员对接口修改而中断服务。其次我们有少量前端页面使用了mock.js。

% j$ ]9 J- n2 l. a. F: Y* f- U

8 ?$ a; Z3 d% H& M  ~
Q:请问Docker里跑Java应用性能怎么调优,默认是共享资源池,对Java来说CPU切换很费性能,除了绑定CPU,但这样就没有弹性之说,麻烦说下?

. R- z$ g& h$ q8 v# |6 i
; q; t( }8 j+ @% _6 k- ^
A:这个性能,我们对Java项目进行多次内存优化,通过ide的内存管理,线程查看等多重方法进行调优,单从war包体积上我们就缩小了60%,内存也下调很多。我们并不能自动伸缩,目前是通过Nginx配置多容器来实现负载均衡。
! n; a: U! l7 z/ _% `1 d

: s$ W5 c3 c+ y2 s0 M
Q:如何实现分布式事务?如何保证数据一致性?

4 x5 \5 S7 x' P: ~
: p5 t0 T. l( X9 V; X, z/ H; D( a
A:我们在Nginx层通过策略保证同一个机器请求只会分布到一台机器上,用最少代价解决这个问题,其次我们项目中,大部分都使用全局uuid操作和插库。

$ U. z7 g$ I0 ~/ D; e

% y5 l. ^, c7 ^! m
Q:贵司的业务模式跟我们很像,感觉很受用。想问下,多客户、多版本共存的情况下,版本升级这块儿是怎么做的?

, R/ K% {$ d, _" |7 w
- O# H+ i# S' F, e: P' R
A:我们使用的是Git分支化管理,由Jenkins定义版本号,SQL分为公共和私有的部分,比如某个客户升级2.0.0版本,会自动检测上个版本到此时的SQL语句,提示项目经理点击,自动执行。(我们现在回滚项目版本,不支持SQL回滚,所以我们SQL一般只增不减、不改),我们可以随时查看某客户线上版本和SQL执行到什么地方。
; I$ v" g2 Q7 J$ j) Q
6 F& u/ G" T4 k% [4 M/ X
Q:日志如何存储和分析?用什么工具?系统异常如何监控?
" e7 T$ N; N; W+ d* a2 J

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

- P4 O* ~* g, w- v) m* S

; m& H% z" T4 {3 d% M
+ W% `, P( Q2 ]4 d) Q7 A  C
关于日志收集,目前我们并没有很多公司搞的很高大尚,因为这块,还在改造中。我们就是多容器映射了本地磁盘目录,然后对这些目录日志文件进行合并,对那种error级别的日志,筛选出来。

4 ?$ L! F# v# n; U' [

# H+ T3 L4 P) X" D. ]
原创:邵磊
6 Y4 I, p3 B% ~3 n0 V

7 h8 j  \1 p2 k: V" F) c8 e' `# J! E% G, h" M+ e9 ~8 x$ c7 w

本版积分规则

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

Baidu

GMT+8, 2019-8-17 21:17 , Processed in 0.216568 second(s), 32 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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