本帖最后由 adminlily 于 2020-1-22 09:02 编辑 ! O) n8 K" v& F/ B6 i- j8 K
, U& S3 [1 t" h7 ]( m) ]
一、持续交付工具链全图
3 }1 d) t6 ^! e+ j

5 k5 ?3 Z! w3 ?& Q! c5 n
上图源自网络。上图很清晰地列出了CD几个阶段使用的工具。
' e' I$ t% J6 A
CD的工具链很长,但并不是每个模块所有工具都那么流行;换言之,我们在每个模块用好一种工具就足够了。
7 U( r0 U) n+ j5 [# H3 X" W8 H
Build
, d. R% `2 T' a5 _+ r
在SCM的模块中:Git系列用的比较多,如Gitlab;
- Y2 a/ `! I" d$ O) q5 t) u* ^
在CI模块中:Jenkins显然是最流行的; 5 Y. N1 Q* ^+ _, j4 t+ G9 w
在Build模块中:Maven、docker用的较多; 4 {1 i. Q- q" u7 R2 c0 P
Test 在Testing模块中:Junit、Jmeter用的较多; 1 Q: _- }, y3 l, u: T3 c, u
Deploy 在配置管理模块中:前些年Puppet比较火,这两年Ansible用的比较多;、 在Artifact管理中:Dockerhub是在线的,docker registry是离线的。Openshift的集成镜像仓库用的就是docker registry技术。Quay是CoreOS的镜像仓库工具,有在线也有离线的,相信后续会被整合到Openshift中。
4 s; W* `) ~. K2 H
Run 在Cloud/IaaS/PaaS模块中:这两年PaaS的活跃程度超过IaaS,我接触比较多的是其中的Openshift。 1 J) D* A; h4 T* e! b& u/ h1 M
8 S$ M$ X0 t d
在编排模块中:K8S目前是主流,无可争议。
9 v& O) d% q# S+ T3 Q
在BI/Monitoring/Logging中:EFK之前用的比较多,但大家普遍看好普罗米修斯。
+ l- v. A% K1 g5 B4 g. x5 D
3 @1 N& S/ @# m6 r. R% F2 K* R5 k
二、红帽的Devops全图 1 z/ C+ U D2 {; P" ~& Q

9 T# D+ Z; I' H v& Z5 V2 O( A
上图是一个比较典型的Devops流程。包括产品立项、需求分析、应用设计、开发、测试、持续发布、生产运维、回顾阶段。 % A ^& k4 o7 A' O0 \
其中,Openshift可以涵盖中间5个阶段,CloudForms可以覆盖第七个阶段。只有第一个阶段目前红帽产品堆栈无法覆盖。
2 P% n6 o( e6 p3 a) L8 c$ k* q
我们将整个流程进一步技术细节化: 1 t; B* L$ M9 f

, Q- n0 i2 Q# p' X
Eclipse IDE工具红帽官网可以下载;Gitlab、Nexus、Jenkins、Openscap、EFK这些工具,红帽官网提供安加固过的容器镜像。
j1 ?7 U7 d9 `+ w5 A- L6 H4 Q2 Q8 H
而整个流程串起来,可以通过Jenkins和S2I一起完成的。关于这方面,主要有两种方式:在源码外构建pipeline部署、在源码中构建pipeline部署。
. [2 V3 P$ a* h4 y
0 G; F; B- c* F- e( f/ n$ V, O0 S7 P. u
三、在源码外构建pipeline部署应用--流程说明
% {' F$ Y7 I5 w. P. ^* h
在源码外构建pipeline的方式,是jenkins的pipeline调用Openshift的S2I、BC、DC等。代码构建是在Openshift中完成; * n* Q+ b ~4 W2 G4 L' E- Y$ g g

( w- `9 w5 Y4 e# _" v: \
本实验是根据EAP的基础镜像,构建一个基于Maven编译的应用,编译成功后,生成应用镜像,并在OCP中部署这个应用。
7 x1 b! p+ }, Z) l/ Q4 h2 S- C
在在本实验中,应用代码地址库链接、应用名称的变量,通过OCP的应用模板导入;bc和dc的操作,均由ocp完成。在bc阶段,项目中会有build pod, 3 \) p* G( j/ @ a; i

6 G: u3 i7 T' x L; Z3 S: ~# o3 A
在dc阶段,项目中会有deploy pod。 - {% X9 T( K8 b9 a$ |, e" n% a+ Q

* d; m; V6 u8 {, `6 ^
为了能够通过pipeline显示阶段,在OCP中引入jenkins plugin,jenkins plugin的脚本定义了build和deploy两个阶段。而两个阶段的任务执行,分别是调用bc和dc。 2 E5 q/ F2 ]* R2 w8 q0 f

) h6 _2 O+ U3 W: f+ I
因此,整个代码构建和部署,实际上均由OCP完成。Jenkins只是用来显示执行阶段。也可以根据需要,增加审批流。 ( e5 C i& o( n1 @9 g+ {
两个yaml文件 ! J( p. C! G# n2 q
创建两个yaml文件,一个是openshift-tasks-no-trigger.yaml,一个是pipeline-bc.yaml。
, ^+ {2 B$ l* p3 Y
第一个文件创建jkp-tasks引用的bc、dc、routes、rc等资源。 7 s9 \7 q& p- D9 s" E% V# }
第二个文件创建一个pipeline,定义应用的build和deploy阶段。 8 p l2 X4 K. D9 d
第一个文件: & C. e' U, z+ w% ~/ y
apiVersion: v1 kind: Template labels: template: openshift-tasks-no-trigger
8 {/ @" L% j' m
模板名称 metadata: name: openshift-tasks-no-trigger objects: - apiVersion: v1 kind: ImageStream metadata: labels: application: ${APPLICATION_NAME} name: ${APPLICATION_NAME} ' K! e( f z3 ]
创建的应用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 - o' U& b$ f$ }/ t4 E. x7 M* ]
构建应用的基础镜像 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
! U# w, w) e; W5 g3 R, @: ?
提示输入应用名称 - description: Git source URI for application name: SOURCE_URL required: true value: https://github.com/lbroudoux/openshift-tasks 2 v" O- C' D2 Z% J
提示输入源码地 - description: Git branch/tag reference name: SOURCE_REF value: master % N" _6 ]- }' B1 z* J
提示输入源码 branch地址 2 Q2 S9 @) a( P& K
$ _3 y# K0 p( P% t0 I! U0 f
第二个文件
: k3 f) e/ i3 L7 X b2 S4 ?
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 m. \9 b) V( D3 Q3 E
& m& w% s8 A8 V6 P! A0 I' k, L1 Z
实验验证
6 c' h( h3 o/ l5 l
根据yaml文件创建应用模板: # W' s/ M8 k. p( q


) P) k" Z" `6 V
模板执行成功以后,应用的bc、dc、rc、vip、routes、is等资源就已经创建好了: ' v8 p( L- }+ J; \
[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
2 H1 l: t! M- o0 C+ N' P4 @
接下来,创建jenkins pipeline:
' |4 w9 L u; }' E6 k) [2 s9 @* y2 Q- A

& k; n; q' i1 t! ~
pipeline创建成功以后,触发pipeline执行: 
Pipeline已经启动:
2 N* O( @. h7 p) I) j. ]* N3 |

7 Z7 \+ Q+ G; P- |9 B
此时会生成bc pod。查看build pod的log,build pod会先拉build image的镜像,再拉代码,然后进行build,成功以后push到OCP的内部镜像仓库。 6 t$ H% u- O l


2 ^' ~8 `2 m: ]; E6 q
pom和jar包下完完毕以后后,开始build: ! y: l, J9 N5 o% `7 o2 Y

! ~: w* w7 g7 }1 V# R# m) [$ C+ c
然后将成功的war包拷贝到EAP的部署目录中:
/ G+ a. U9 ^7 H* A3 W7 i

5 P5 p5 A2 W9 ~: q% m" ?) T
最后将build成功的应用镜像推送到集成镜像库:
# y( [ e5 L: ~! x

+ O( c2 ~& E- C
至此,build阶段完成。 / S7 ~ p" Y2 ~. w. i0 q' k3 @4 |
) W4 F" J* }# N
接下来,启动deploy过程: % {' [, q' w4 B" _- n6 I

2 _! [+ F* T+ V9 [
查看jenkins的日志,deploy的阶段,就是触发dc,很快,dc执行完毕,应用部署成功。 / D7 t2 U5 B$ A$ X& n# `3 V# d


# v/ j" Z7 M) N3 ~7 W* b
查看maven的日志,maven pod在此流程中,并不做编译工作,只是监听(该pod是为了pipeline的执行为存在):
& J/ g* g1 l, O# A+ J" u; G/ m1 r b

: |0 p$ |0 C3 P! j. `. U$ |: X# |# Z
应用部署成功以后,查看routes: ' I. m n$ w G$ g0 ^0 k- o7 s# ?; B/ a* z, ~

! e* K8 v F# i% l5 p+ h9 ]
通过浏览器,可以访问部署好的镜像:
" H$ B# s9 k# j, r' W- K

( ?4 `% r% v/ G) P% M$ I) C. ]' ^
1 _8 ?( d% `; g) B7 a* s
方法总结
+ D5 J# D, F7 O* U5 C& ^" H
此种武器主要利用OCP的S2I进行构建,只是通过Jenkins进行阶段显示。Jenkins的build调用OCP应用的bc、deploy调用的OCP应用的dc。当然,我们也可以根据需要增加审批流程,或者将pipeline做得更复杂。 1 {# ?& O3 q& F; i; V0 j' z
此这种方法的好处在于配置灵活。支持多用开发语言(在base image中增加不通的编译器即可)。通常情况下,红帽Openshift的CI/CD会推荐使用这种方式。
% V4 ~+ l. ~: p) T3 y
但是对于在很早以前就已经使用Jenkins做CI/CD的客户,可能会有一些学习成本。 ! _# H% h, h! ?6 k) o+ k. W
3 C. b$ H6 C# x0 r9 g# c7 K7 b/ u" r8 s
四、在源码内构建pipeline " N1 U" F+ D4 w& z* ~1 Q- h; D
实验中,我们部署的是一个基于JBoss EAP base image的应用,应用代码位于git代码库。
' K' o# x6 L1 q0 u4 ]( U

1 f6 ^/ ? ]& x3 H+ c7 i
在上图中,jenkins贯穿整个CI/CD,其中包括:
2 |. V5 _; P# q: ~4 O" [6 @7 i
获取源码----->编译----->生成应用(war包)---->拉取base image---->将应用(war包)与base image合并---->生成App Image---->部署App image。 ' `! }) g% [- j/ F$ {, \
在本实验中,涉及两个重要的配置文件:openshift-tasks-jenkinsfile和Jenkinsfile。
& ~' k% d2 S( A F
openshift-tasks-jenkinsfile是创建Jenkins master(执行openshift-tasks-jenkinsfile的模板时,如果项目中没有jenkins的master,会自动触发部署)。 5 M/ U4 ^# X2 h" ?) p6 J/ t: F

* s+ _$ L5 @. g
0 M8 V/ @8 ~! ?% [$ r
而部署openshift-tasks-jenkins file模板的时候,会提示输APPLICATION_NAME、DEV_PROJECT、SOURCE_URL、SOURCE_REF这几个变量,这些变量会被注入到模板中的BuildConfig部分,并进行覆盖。
1 J8 ~& U1 x: H3 F" k9 [9 Q: h

1 G/ }5 _/ M9 H: c. k6 S' P
openshift-tasks-jenkinsfile的BuildConfig部分定义了Jenkins file的地址。 2 B1 s: Z! R% j5 B ?

2 p7 m. a( S- {% R( H: C2 `* h2 S
openshift-tasks-jenkinsfile带着这几个参数,继续触发Jenkin file并注入参数。Jenkins file第一行注明了调用maven,因此会触发部署jenkins maven slave pod。
, F, h) Y' }4 A ]

2 R+ j+ X6 f5 ~- H
接下来,在jenkins slave pod中,根据Jenkins file定义的应用的'build'、test、deployInDev三个阶段进行执行,应用的bc和dc也在Jenkins File中生成,最终完成一应用的构建。 $ K* L" A, W8 \$ g; p. V

* N8 O+ f) T. H- K+ A C+ [8 G
接下来,我们先看:openshift-tasks-jenkinsfile完整的文件内容:
7 H; a* }- G( N4 ^# a6 j: @ I
apiVersion: v1 kind: Template labels: template: openshift-tasks-jenkinsfile metadata: name: openshift-tasks-jenkinsfile 9 s$ l) u5 X5 ~
模板的名称
2 F& C9 H) K8 |! ^7 O, [
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 
9 B5 o, `* w1 v: R
接下来,通过模板部署jenkins master: & V) }, `9 N) i8 X
& D2 y) E' u E- I

0 E& {. q e7 p1 W3 x
提示输入参数变量,这些参数,就是最终会传到Jenkinsfile的jenkins slave pod中的。这里,我们使用默认参数值。
, S' u: o* T+ V1 n/ O* b
 
2 X2 B# ?' O7 g! ~3 _
接下来,在项目中,会部署一个Jenkins的 master pod:
0 ?9 ]/ O7 s! F6 Z! a


. k8 k- y0 d r7 J4 x3 H
我们可以设置Jenkins Master所指向的slave pod的地址:registry.access.redhat.com/openshift3/jenkins-slave-maven-rhel7 ( I4 G8 r, H2 Z& q0 h" O

+ F6 K4 d0 p% C5 a1 e8 T
而Pipeline也被创建成功(根据jenkins file中的定义)
; x4 Z* v& `. Y# Q U2 h8 B! L

4 n4 c, o* a0 O$ o# ]
接下来,手工触发Pipeline: 7 ~" u3 n* q3 M

2 L, k+ F6 b% c5 A9 g! q. _: E4 j
接下来,我们关注Jenkins上的日志输出,由于信息较多,我只列出关键内容: 5 s9 A/ t7 v6 ]
获取代码: 4 S: n3 I6 P; u# M

' _- m( F+ Q/ y. M6 w9 H4 Q' P$ V5 x
下载maven相关的pom文件:
, e& K/ K7 t# `! L& [' \

+ j$ j8 u) a$ M/ j
下载构建需要的jar包:
( y) s. I" ^/ I; j, H1 s

' x w. r L+ ~% |+ e9 h8 }
下载完所需内容以后,进行Build,我们可以看一下build主任务:
9 y! _: e1 q S/ w' r

* l( F4 S7 [; e9 R6 R4 r
Build成功: @, D5 [% V& r$ V0 ^; q) n$ H

" e( k( B5 a+ t! P4 \
接下来进入test阶段,下面内容可以看出,test阶段是调用mvn test的命令: 2 W! @0 f4 k5 X" ?$ i9 C2 B

+ D3 J2 }, W: X1 p: j7 r
test成功:
; _0 z, m! N: L

K& A, v! U* @0 ~- j2 s
接下来是的devInDev阶段:
9 D1 R! p/ G4 T3 i. a. ~

' ^; E# {& `1 `7 h/ ~) d
在这个阶段,Jenkins会调用openshift的命令,创建bc和dc:
; s( p5 ?1 \7 L! R

( b3 I! X/ m, R8 | Q$ W- L) T
部署应用并为应用创建routes: 0 c6 S: e/ ]7 t! ?

) Q, z* W- f2 P, k- i% Q
截至到目前,pipeline执行完毕,应用也部署成功。 我们将视角切换到Openshift的界面,pipeline已经执行成功。 3 M- w0 G0 x! E) d& \* |

* W" I& X [# B/ i
接下来,我们通过浏览器访问应用的routes: n0 W2 K. x; X: v6 C

9 R! ?6 I6 H4 G9 y- I
可以看到应用部署已经成功: 7 r2 ?+ H) F- m, I; b* i0 O" b

1 v$ A" U9 x& H: s- T" s
9 o; ^( v& Y: ~1 z* Q
方法总结
+ Z+ _/ R" `' z- d+ Y
此种武器主要利用Jenkins进行代码的构建、应用的部署。对于较为复杂的应用编译,使用此种方法较为合适。另外,很多IT程度较高的客户,在docker大火之前,就已经基于Jenkins实现CI/CD了。这种情况下,如果新引入Openshift平台,使用此方法较可以延续以前的IT运维习惯,学习成本也相对较低(不需要大量修改现有的Jenkins)。 : w' y0 o1 U) W* f* J) j: K
此这种方法的劣势在于对于Slave Pod有一定要求,不同于开发语言,需要使用不同的slave pod。此外,很多时候,我们也需要对slave pod的镜像做一定的定制,如增加一些rpm包等。 ) F! R9 b, D+ b9 r Z) g8 x
|