本帖最后由 adminlily 于 2020-1-22 09:02 编辑
# P/ e, F# k) c3 Z. y/ I5 D7 s! Z& F. Q9 w9 n5 u! c) O W, h4 W0 ^7 A
一、持续交付工具链全图 4 l, L" I( {, ^; p" ~

4 |/ f' H% R7 N7 }
上图源自网络。上图很清晰地列出了CD几个阶段使用的工具。
: X* q8 Z, c: b/ K& C
CD的工具链很长,但并不是每个模块所有工具都那么流行;换言之,我们在每个模块用好一种工具就足够了。
5 p6 @8 O8 P; I: D
Build
! ? S; e+ s# c& }* j
在SCM的模块中:Git系列用的比较多,如Gitlab;
: H. P/ M Y! [3 K! Z& l; S d; ?% U
在CI模块中:Jenkins显然是最流行的; - x! W: `; r8 ?+ g3 [: m
在Build模块中:Maven、docker用的较多; # h, [4 D( ^& s+ H0 n8 s2 n
Test 在Testing模块中:Junit、Jmeter用的较多;
3 S9 ]! K: Y# o+ {# i# P5 A7 `
Deploy 在配置管理模块中:前些年Puppet比较火,这两年Ansible用的比较多;、 在Artifact管理中:Dockerhub是在线的,docker registry是离线的。Openshift的集成镜像仓库用的就是docker registry技术。Quay是CoreOS的镜像仓库工具,有在线也有离线的,相信后续会被整合到Openshift中。 9 ~' f; {& x0 n$ M" J; a, n, I
Run 在Cloud/IaaS/PaaS模块中:这两年PaaS的活跃程度超过IaaS,我接触比较多的是其中的Openshift。
! K, \, {: ] x0 `" O. l
. l' |+ X9 N1 U4 Z8 B3 M0 k5 Y
在编排模块中:K8S目前是主流,无可争议。
& a( ^- H0 g+ Q% R. C( g3 `
在BI/Monitoring/Logging中:EFK之前用的比较多,但大家普遍看好普罗米修斯。 % o$ w* U3 T0 u
5 \* U8 c4 A e1 b0 X
二、红帽的ITILxf.com" target="_blank" class="relatedlink">DevOps全图 . p6 V# F$ I) E6 I$ u

4 p( P* S" s$ M5 ^' I8 V
上图是一个比较典型的Devops流程。包括产品立项、需求分析、应用设计、开发、测试、持续发布、生产运维、回顾阶段。 8 a1 S2 F* s% ?% ?$ U
其中,Openshift可以涵盖中间5个阶段,CloudForms可以覆盖第七个阶段。只有第一个阶段目前红帽产品堆栈无法覆盖。
! o2 W" ?$ Z7 Y
我们将整个流程进一步技术细节化: 5 X$ m: n0 K/ l

, p& D6 V8 G3 ?% { h0 z4 ]
Eclipse IDE工具红帽官网可以下载;Gitlab、Nexus、Jenkins、Openscap、EFK这些工具,红帽官网提供安加固过的容器镜像。
6 \" S/ j4 r5 V9 ~8 [4 w3 k
而整个流程串起来,可以通过Jenkins和S2I一起完成的。关于这方面,主要有两种方式:在源码外构建pipeline部署、在源码中构建pipeline部署。
! G$ T% D: ^) W% g
% B* y( t5 c, Z# @. K0 m
三、在源码外构建pipeline部署应用--流程说明
, h$ f" V+ T8 O' A, |& Y% V. `
在源码外构建pipeline的方式,是jenkins的pipeline调用Openshift的S2I、BC、DC等。代码构建是在Openshift中完成;
6 O% i# G( @1 H* q, Z4 K

% P+ `, U8 [, E# X1 g
本实验是根据EAP的基础镜像,构建一个基于Maven编译的应用,编译成功后,生成应用镜像,并在OCP中部署这个应用。 7 m9 d4 i! e3 @
在在本实验中,应用代码地址库链接、应用名称的变量,通过OCP的应用模板导入;bc和dc的操作,均由ocp完成。在bc阶段,项目中会有build pod, : j( b2 a0 v4 ?+ @& u; }" c! n

8 \2 { `; Z. C) o
在dc阶段,项目中会有deploy pod。 ( C+ l0 g C9 F2 T! Z! | L! {- j

. {2 L! F0 L/ b$ r
为了能够通过pipeline显示阶段,在OCP中引入jenkins plugin,jenkins plugin的脚本定义了build和deploy两个阶段。而两个阶段的任务执行,分别是调用bc和dc。
9 Z; ^# V0 |% B* T

8 M# K* L0 e( E1 c# l0 U
因此,整个代码构建和部署,实际上均由OCP完成。Jenkins只是用来显示执行阶段。也可以根据需要,增加审批流。
: _. u2 m1 o. E! N" {2 T
两个yaml文件
# f5 t1 }+ Z, \3 w
创建两个yaml文件,一个是openshift-tasks-no-trigger.yaml,一个是pipeline-bc.yaml。 * s4 l; L- v0 v! ~+ h$ T: z
第一个文件创建jkp-tasks引用的bc、dc、routes、rc等资源。 7 L" W! I' S1 }$ U
第二个文件创建一个pipeline,定义应用的build和deploy阶段。 & Q4 u8 T* n! t( n: T; k9 ~
第一个文件: $ L8 J, }9 B7 ]6 o+ ~# B6 g( X# ^" q3 Y
apiVersion: v1 kind: Template labels: template: openshift-tasks-no-trigger - Q# t2 R4 O Q% n" J$ V
模板名称 metadata: name: openshift-tasks-no-trigger objects: - apiVersion: v1 kind: ImageStream metadata: labels: application: ${APPLICATION_NAME} name: ${APPLICATION_NAME}
, D( K) s- @; n$ t: C' q
创建的应用image stream名称 - apiVersion: v1 kind: Service metadata: annotations: description: The web server's http port. labels: application: ${APPLICATION_NAME} name: ${APPLICATION_NAME} spec: ports: - port: 8080 targetPort: 8080 selector: deploymentConfig: ${APPLICATION_NAME} - apiVersion: v1 id: ${APPLICATION_NAME}-http kind: Route metadata: annotations: description: Route for application's http service. labels: application: ${APPLICATION_NAME} name: ${APPLICATION_NAME} spec: to: name: ${APPLICATION_NAME} - apiVersion: v1 kind: BuildConfig metadata: labels: application: ${APPLICATION_NAME} name: ${APPLICATION_NAME} spec: output: to: kind: ImageStreamTag name: ${APPLICATION_NAME}:latest 将build成功的镜像打成latest的image stream tag。 source: git: ref: ${SOURCE_REF} uri: ${SOURCE_URL} type: Git strategy: sourceStrategy: forcePull: true from: kind: ImageStreamTag name: jboss-eap70-openshift:1.4 namespace: openshift * k' f" e9 ^1 \1 \
构建应用的基础镜像 type: Source triggers: - github: secret: kJZLvfQr3hZg type: GitHub - generic: secret: kJZLvfQr3hZg type: Generic - imageChange: {} type: ImageChange - type: ConfigChange - apiVersion: v1 kind: DeploymentConfig metadata: labels: application: ${APPLICATION_NAME} name: ${APPLICATION_NAME} spec: replicas: 1 selector: deploymentConfig: ${APPLICATION_NAME} strategy: resources: {} rollingParams: intervalSeconds: 1 maxSurge: 25% maxUnavailable: 25% timeoutSeconds: 600 updatePeriodSeconds: 1 type: Rolling template: metadata: labels: application: ${APPLICATION_NAME} deploymentConfig: ${APPLICATION_NAME} name: ${APPLICATION_NAME} spec: containers: - env: - name: MY_POD_IP valueFrom: fieldRef: apiVersion: v1 fieldPath: status.podIP - name: OPENSHIFT_KUBE_PING_LABELS value: application=${APPLICATION_NAME} - name: OPENSHIFT_KUBE_PING_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: HORNETQ_CLUSTER_PASSWORD value: kJZLvfQr3hZg - name: JGROUPS_CLUSTER_PASSWORD value: kJZLvfQr3hZg image: ${APPLICATION_NAME} imagePullPolicy: Always livenessProbe: failureThreshold: 3 httpGet: path: /ws/demo/healthcheck port: 8080 scheme: HTTP initialDelaySeconds: 45 periodSeconds: 45 successThreshold: 1 timeoutSeconds: 1 name: ${APPLICATION_NAME} ports: - containerPort: 8778 name: jolokia protocol: TCP - containerPort: 8080 name: http protocol: TCP - containerPort: 8888 name: ping protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /ws/demo/healthcheck port: 8080 scheme: HTTP initialDelaySeconds: 20 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 terminationGracePeriodSeconds: 60 triggers: - type: ConfigChange parameters: - description: The name for the application. name: APPLICATION_NAME required: true value: tasks
9 x) O% Q1 C; y1 _7 c( N
提示输入应用名称 - description: Git source URI for application name: SOURCE_URL required: true value: https://github.com/lbroudoux/openshift-tasks
) D# r6 l ^8 d% `0 H# v
提示输入源码地 - description: Git branch/tag reference name: SOURCE_REF value: master 2 n: g! a% n' l: W3 W
提示输入源码 branch地址 2 s/ G. C( S2 {% c! O9 `6 n: C2 G
0 U; j8 A/ [# ]. r/ ]: r3 c
第二个文件
. T! g/ j8 E2 k% o, l0 r6 E1 r
apiVersion: v1 kind: BuildConfig metadata: annotations: pipeline.alpha.openshift.io/uses: '[{"name": "jkp-tasks", "namespace": "", "kind": "DeploymentConfig"}]' labels: name: jkp-tasks-pipeline name: jkp-tasks-pipeline spec: strategy: jenkinsPipelineStrategy: jenkinsfile: |- node('maven') { stage 'build' openshiftBuild(buildConfig: 'jkp-tasks', showBuildLogs: 'true') 定义构建阶段,构建阶段是触发应用的buildConfig stage 'deploy' openshiftDeploy(deploymentConfig: 'jkp-tasks') 定义构建阶段,构建阶段是触发应用的deploymentConfig } type: JenkinsPipeline triggers: - github: secret: CzgPZAZ5m2 type: GitHub - generic: secret: CzgPZAZ5m2 type: Generic + Y) K0 A# A& {1 ?
4 b% z4 x* T) I0 _5 J9 E- D ^
实验验证
& _. [4 k) g5 u
根据yaml文件创建应用模板:
4 J8 {8 m; a2 ~( v# s2 k


9 I" U1 H/ T c
模板执行成功以后,应用的bc、dc、rc、vip、routes、is等资源就已经创建好了:
* I1 g/ }% m' w1 ~, V. M% o
[root@master ~]# oc get all NAME TYPE FROM LATEST buildconfigs/jkp-tasks Source Git@master 1 NAME TYPE FROM STATUS STARTED DURATION builds/jkp-tasks-1 Source Git@bd32abb Running 2 minutes ago NAME DOCKER REPO TAGS UPDATED imagestreams/jkp-tasks docker-registry.default.svc:5000/ocp-tasks/jkp-tasks NAME REVISION DESIRED CURRENT TRIGGERED BY deploymentconfigs/jkp-tasks 1 1 1 config NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD routes/jkp-tasks jkp-tasks-ocp-tasks.apps.example.com jkp-tasks <all> None NAME READY STATUS RESTARTS AGE po/jkp-tasks-1-build 1/1 Running 0 2m po/jkp-tasks-1-deploy 1/1 Running 0 2m po/jkp-tasks-1-kj8ds 0/1 ImagePullBackOff 0 2m NAME DESIRED CURRENT READY AGE rc/jkp-tasks-1 1 1 0 2m NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE svc/jkp-tasks 172.30.58.78 <none> 8080/TCP 2m - y" c' z c5 v5 G2 g
接下来,创建jenkins pipeline: " o9 u* V3 Q" M6 N( n

+ k2 \+ G8 {' z4 K* l
pipeline创建成功以后,触发pipeline执行: 
Pipeline已经启动:
5 v: b, V' I% [" \4 b8 ^3 F& M% n' m

( a9 b; D' } ^
此时会生成bc pod。查看build pod的log,build pod会先拉build image的镜像,再拉代码,然后进行build,成功以后push到OCP的内部镜像仓库。
8 @7 q! r8 F+ D7 J3 I" M$ S1 t


1 r; r. d: @. N4 Q
pom和jar包下完完毕以后后,开始build:
2 z: p; W# Z' d* j

. c% ]/ i" Q* F: j
然后将成功的war包拷贝到EAP的部署目录中: ' m A! k7 y0 A& p8 w! X) d

& ?% _/ q3 U4 d8 I
最后将build成功的应用镜像推送到集成镜像库:
# U, p( s2 m9 n

* X2 G: L$ O6 S( b- I* K
至此,build阶段完成。
. S2 v+ Z. q/ I& H- m0 K5 m; X
p( g; m" }& \1 I" w
接下来,启动deploy过程: 2 q6 q+ }1 \; l6 l y' O& I

; M/ m( n+ s6 G* d
查看jenkins的日志,deploy的阶段,就是触发dc,很快,dc执行完毕,应用部署成功。
4 L9 x) t" m3 P- ~


0 w! }5 h5 X# R5 q+ @! ~; S! m
查看maven的日志,maven pod在此流程中,并不做编译工作,只是监听(该pod是为了pipeline的执行为存在):
( d' S9 f& V; \" [" `3 s

3 `6 [$ k# z7 R1 a9 D
应用部署成功以后,查看routes: 7 l' M, X d" D* o, |0 j/ B' S

8 Z5 Q- X3 Q% P2 W
通过浏览器,可以访问部署好的镜像: , F- L$ y- V. S2 P2 D! V6 t; b

( F0 s! C$ o$ [: t2 l0 Z
# ^( s# Y7 X/ o+ v7 j
方法总结
- c6 v5 G1 [9 a' Q6 q0 Z/ l# g( V
此种武器主要利用OCP的S2I进行构建,只是通过Jenkins进行阶段显示。Jenkins的build调用OCP应用的bc、deploy调用的OCP应用的dc。当然,我们也可以根据需要增加审批流程,或者将pipeline做得更复杂。
2 e$ S9 d3 ^8 y1 S* b& q L
此这种方法的好处在于配置灵活。支持多用开发语言(在base image中增加不通的编译器即可)。通常情况下,红帽Openshift的CI/CD会推荐使用这种方式。 1 E- A S) X# y/ L( L$ k; J6 G
但是对于在很早以前就已经使用Jenkins做CI/CD的客户,可能会有一些学习成本。 % y9 H( {0 q$ R: u r; l& |" A1 C
" I- e: H+ y4 b* G& p' E
四、在源码内构建pipeline ) L; ~3 o6 o4 t! ^( U
实验中,我们部署的是一个基于JBoss EAP base image的应用,应用代码位于git代码库。
/ F7 g/ X0 O# n

1 \* \: v+ E+ v9 d1 u
在上图中,jenkins贯穿整个CI/CD,其中包括:
# ?2 C# U0 y3 v% ?/ E }! s$ w
获取源码----->编译----->生成应用(war包)---->拉取base image---->将应用(war包)与base image合并---->生成App Image---->部署App image。
. I. |; W0 `! F
在本实验中,涉及两个重要的配置文件:openshift-tasks-jenkinsfile和Jenkinsfile。 7 ]0 w& V! U: L2 G
openshift-tasks-jenkinsfile是创建Jenkins master(执行openshift-tasks-jenkinsfile的模板时,如果项目中没有jenkins的master,会自动触发部署)。
1 E0 H* B" w2 }; h o* k% T* x0 s

1 f- E ?8 y$ G) ]
) X/ c% N# g# c( d1 ]8 z- o
而部署openshift-tasks-jenkins file模板的时候,会提示输APPLICATION_NAME、DEV_PROJECT、SOURCE_URL、SOURCE_REF这几个变量,这些变量会被注入到模板中的BuildConfig部分,并进行覆盖。 . a# Y: ]$ g G# }( k6 O

% X3 H/ ~( F2 N# j- K$ j
openshift-tasks-jenkinsfile的BuildConfig部分定义了Jenkins file的地址。 4 V4 ]# s4 s, W# u* t( e# X

8 u7 H' B3 ^; g. b: z9 Q: h
openshift-tasks-jenkinsfile带着这几个参数,继续触发Jenkin file并注入参数。Jenkins file第一行注明了调用maven,因此会触发部署jenkins maven slave pod。
7 g2 r! t! U' {8 |/ M* ^. R

% j* K# Q! y/ M z8 S5 L2 D
接下来,在jenkins slave pod中,根据Jenkins file定义的应用的'build'、test、deployInDev三个阶段进行执行,应用的bc和dc也在Jenkins File中生成,最终完成一应用的构建。
2 R) Y0 W! C2 t' g G8 F* ]) X9 h

9 U9 v5 q- D- b# F# N4 E) p
接下来,我们先看:openshift-tasks-jenkinsfile完整的文件内容:
- x& d; ~9 T9 V" ^8 g3 ?% y
apiVersion: v1 kind: Template labels: template: openshift-tasks-jenkinsfile metadata: name: openshift-tasks-jenkinsfile
( q% U$ U+ v# s0 u) V# _7 n4 k
模板的名称 ! h! f' `6 W9 t% W- Y# x
objects: - apiVersion: v1 kind: BuildConfig BC阶段的定义 metadata: annotations: pipeline.alpha.openshift.io/uses: '[{"name": "jkf-tasks", "namespace": "", "kind": "DeploymentConfig"}]' labels: application: ${APPLICATION_NAME}-jenkinsfile name: ${APPLICATION_NAME}-jenkinsfile spec: source: git: ref: ${SOURCE_REF} uri: ${SOURCE_URL} type: Git strategy: jenkinsPipelineStrategy: jenkinsfilePath: Jenkinsfile type: JenkinsPipeline type: Generic 截至到目前,Jenkinsfile的bc定义完成。jenkinsPipelineStrategy和 jenkinsfilePath指定了这个bc阶段会调用的jenkins file的路径。 triggers: - github: secret: kJZLvfQr3hZg type: GitHub - generic: secret: kJZLvfQr3hZg type: Generic parameters: - description: The name for the application. name: APPLICATION_NAME required: true value: jkf-tasks 通过模板部署应用的时候,提示输入应用的名称,默认名称是jkf-tasks - description: The name of Dev project name: DEV_PROJECT required: true value: ocp-tasks 通过模板部署应用的时候,提示输入Dev project的名称,默认名称是ocp-tasks - description: Git source URI for application name: SOURCE_URL required: true value: https://github.com/lbroudoux/openshift-tasks 通过模板部署应用的时候,提示输入SOURCE_URL的名称,默认名称是https://github.com/lbroudoux/openshift-tasks - description: Git branch/tag reference name: SOURCE_REF value: master 通过模板部署应用的时候,提示输入SOURCE_REF的名称,默认名称是master。 接来下,查看Jenkins file完整的文件内容: node('maven') { 代码构建调用maven // define commands def mvnCmd = "mvn" // injection of environment variables is not done so set them here... 在此阶段注入参数变量对以下默认参数数值进行覆盖(从openshift-tasks-jenkinsfile template部署的时候,输入的参数变量带过来): def sourceRef = "master" def sourceUrl = "https://github.com/lbroudoux/openshift-tasks" def devProject = "ocp-tasks" def applicationName = "jkf-tasks" 以上代码定义了编译方式,使用maven、定义了源码的地址、在Openshift上的项目(构建在哪发生)、生成应用的名称。 stage 'build' git branch: sourceRef, url: sourceUrl sh "${mvnCmd} clean install -DskipTests=true" 以上代码定义了pipeline的构建阶段。调用mvn clean先清理编译环境,然后用mvn install进行构建。 stage 'test' sh "${mvnCmd} test" 以上代码定义了代码测试阶段 stage 'deployInDev' sh "rm -rf oc-build && mkdir -p oc-build/deployments" sh "cp target/openshift-tasks.war oc-build/deployments/ROOT.war" // clean up. keep the image stream 以上代码定义了在dev阶段部署操作:将编译好的war包,拷贝到 oc-build/deployments目录下 sh "oc project ${devProject}" 以上代码调用oc client,切换项目。 sh "oc delete bc,dc,svc,route -l application=${applicationName} -n ${devProject}" // create build. override the exit code since it complains about existing imagestream 以上代码清空项目中的内容。 sh "oc new-build --name=${applicationName} --image-stream=jboss-eap70-openshift --binary=true --labels=application=${applicationName} -n ${devProject} || true" // build image 以上代码根据jboss-eap70-openshift的base image,创建bc sh "oc start-build ${applicationName} --from-dir=oc-build --wait=true -n ${devProject}" 以上代码执行构建,即根据上一步指定的base image,加上本地oc-build目录下的内容(ROOT.war),生成应用的镜像。 // deploy image sh "oc new-app ${applicationName}:latest -n ${devProject}" sh "oc expose svc/${applicationName} -n ${devProject}" } 以上代码根据上一步生成的镜像,部署应用,并为应用创建root。 当然,在做maven编译的时候,需要用到pom文件,由于内容较多,不再贴出来,地址:https://github.com/stonezyg/openshift-tasks/blob/master/pom.xml。 方案验证 为了方便理解,将所有操作步骤贴出: 首先,根据yaml文件创建openshift-tasks-jenkins file模板。 #oc create -f https://raw.githubusercontent.co ... te-jenkinsfile.yaml -n ocp-tasks 
1 z' T* x! t; _( x- O3 t! D- l3 f
接下来,通过模板部署jenkins master:
) |8 f6 d+ z5 Q/ h1 ~9 O
+ P) `& S) H- L. @. h ]4 {

% ?8 m6 T# P( o' |
提示输入参数变量,这些参数,就是最终会传到Jenkinsfile的jenkins slave pod中的。这里,我们使用默认参数值。
& ^+ p' Y0 J$ v. T O# j9 R' ^% A
 
2 H7 _' Q3 Y4 m; O
接下来,在项目中,会部署一个Jenkins的 master pod:
5 z! j( l- F3 ?) f5 U


$ y' O- J. ?2 e1 ^( n1 d
我们可以设置Jenkins Master所指向的slave pod的地址:registry.access.redhat.com/openshift3/jenkins-slave-maven-rhel7 # A ]4 O9 N4 `3 ~- U

7 \7 U' J" x, [' q5 L! e: }
而Pipeline也被创建成功(根据jenkins file中的定义)
" d! ?. f) L6 E! x) C% ?, m

- X5 O& w- K3 e( @" R
接下来,手工触发Pipeline:
6 E: H% O" ?: e2 i" ^! _

' ^9 b. M% ?& D# \+ \
接下来,我们关注Jenkins上的日志输出,由于信息较多,我只列出关键内容: % T" ]2 `5 n" B5 m; V
获取代码: ' w- Y' T- O! r6 C* m6 H

+ e5 b# T/ J4 }
下载maven相关的pom文件: * J( Y7 F3 Q; y) R9 _ k9 f$ E

& ~! O3 C/ q5 o3 a
下载构建需要的jar包: 5 k: x! d; y- @$ D" S _2 N

" ~; T3 M1 ^$ d! H6 x
下载完所需内容以后,进行Build,我们可以看一下build主任务:
: W1 V2 R+ d3 {

( I% [& M0 q% |
Build成功: % ?: |+ s3 l1 q! K

2 @, o* k/ H" A- s4 V, Q) E
接下来进入test阶段,下面内容可以看出,test阶段是调用mvn test的命令:
- `! x' }) \/ d C) u% y9 S

& L. m6 q6 F( j) B6 M; d' ]
test成功:
& \ C2 r! r0 q }. B: p. J0 S

" ?" z8 W9 k9 C( s6 ^% t
接下来是的devInDev阶段: 9 v- E s6 E! U- {

; G6 D# e# k' `" S9 n
在这个阶段,Jenkins会调用openshift的命令,创建bc和dc:
# w; ^$ m' ], d2 c2 T( x

1 v" _& o7 o& J2 ]
部署应用并为应用创建routes:
4 V' t8 `+ p- T. \: u5 h

( a. ^3 I5 N( o- S7 [+ c
截至到目前,pipeline执行完毕,应用也部署成功。 我们将视角切换到Openshift的界面,pipeline已经执行成功。
# l- ^# ]2 M6 u0 G7 X

- x8 z4 C+ f1 ?% o( N" V7 @( j v
接下来,我们通过浏览器访问应用的routes:
) d# s6 u Q/ [& f/ ~7 a; A0 T4 E

( W/ O" \) @3 p& q
可以看到应用部署已经成功: ! {# L+ p9 ^1 f& a/ z, `: Y

- t5 B* a" } M; N3 C6 p
4 }( y; T3 F2 T* w
方法总结
' M. p3 Q* ~2 G( n3 A" _0 @" R8 e% O
此种武器主要利用Jenkins进行代码的构建、应用的部署。对于较为复杂的应用编译,使用此种方法较为合适。另外,很多IT程度较高的客户,在docker大火之前,就已经基于Jenkins实现CI/CD了。这种情况下,如果新引入Openshift平台,使用此方法较可以延续以前的IT运维习惯,学习成本也相对较低(不需要大量修改现有的Jenkins)。 2 q6 l1 l- h- M: ~8 G3 T! d4 x
此这种方法的劣势在于对于Slave Pod有一定要求,不同于开发语言,需要使用不同的slave pod。此外,很多时候,我们也需要对slave pod的镜像做一定的定制,如增加一些rpm包等。
+ o- [: m1 c/ {7 K% c |