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

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

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

扫描二维码登录本站

QQ登录

只需一步,快速开始

搜索
查看: 665|回复: 0

DevOps实例-基于Docker的CI/CD

[复制链接]
发表于 2018-10-9 11:23:24 | 显示全部楼层 |阅读模式
本帖最后由 adminlily 于 2018-10-9 11:25 编辑
) S0 ?/ |! K" T1 u; L0 {6 [5 P1 j9 l. n, N
! s7 k7 V) j2 R* S6 p

4 \0 O( z0 u5 K4 }5 i: c
一、DevOps实战-基于Docker的CI/CD
( ]$ y& e4 V, k7 W- B

$ ]6 B9 o% \$ R& ?: u
在本篇博客,我们将使用如下技术一步步实现全部的持续部署流程。[Spring Boot, GitLab, Jenkins,Docker and Slack. ] 首先,我们会创建一个带有单元测试和集成测试的spring boot样品应用,然后将它push到GitLab.在push代码到gitlab上之后,Jenkins pipeline 将通过web hook自动获取到代码,然后运行测试用例。如果这些测试全部通过,没有任何错误信息,Jenkins将去编译代码,并且通过docker将代码部署到服务器上。最后,它将发送docker image到本地的docker私有仓库。如果整个测试流水线有任何一步失败,它将通过Slack去通知用户。
: z  x  B7 p0 a

) z! D# w9 Q1 q' X. X
在开始持续部署操作之前,让我们先看下整个架构图:
1.png
图1:基于docker的CI/CD流水线
! C# B  {$ _6 _6 V" `& `0 t
2 u& i# Q! Y4 O5 B- A+ R
二、准备工作

+ H6 _3 _% I1 [! ~
2 v/ s. z# O2 K2 n& Q
注意:在该方案中,我们需要Spring Boot应用。你可以去github上面克隆样本应用https://github.com/onedaywillcom ... uousDeliveryApp.git)这是一个Hello World Spring Boot-Maven 应用,并且附带了一个单元测试和集成测试。
# o8 g3 ?7 g# U' w# ]

. \' K9 |* S3 c! h
首先,我们需要在gitlab的集成菜单上设置一下去触发Jenkins.

0 g0 l$ O. p! P) g6 k, V3 O
1.png

6 f7 [8 ?5 _9 N5 d  n$ V/ O+ \
图2:基于gitlab以及jenkins相关设置

7 w; ?/ l  U% _4 q3 g' d" G0 b
! R. W- t/ ?! K. v3 @/ j- ?
当所有的设置都在Jenkins上设置完之后,GitLab将准备好去随时触发Jenkins。
5 a' |0 E* U% N  U9 i' I0 S

6 T& ~' T" Z/ J

- w4 @, E0 g6 o' B
接下来,我们需要安装Jenkins,Docker以及一些其他相关的依赖。
0 y6 ~, ~4 r! }+ |
$ w; v/ y" l+ y1 o' T5 R+ r( J
下图是在AWS EC2上运行的一个实例,实例的外网ip为:52.11.94.229
1.png
图3:AWS实例

0 M7 c, M  h. I  [- K" y

$ @& S& A8 b7 C# D+ O9 q7 ~9 l( `
现在我们就可以ssh到实例上去安装下列依赖:

7 |( p; K0 s$ i$ L
+ c# u2 q$ u# {8 d: N0 v4 ~
# ssh to instance
ssh -i ~/.ssh/jenkinskeypair.pem ec2-user@52.11.194.229
# Update packages
sudo yum update -y
# Install Git
sudo yum install git -y
# Download Jekins repo
sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo # Import jenkins key
# Install Jenkins
sudo yum install jenkins -y
# Start Jenkins
sudo service jenkins start
# Enter to home directory
cd ~
# Download Java 8  
wget — no-cookies — no-check-certificate — header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept securebackup-cookie" "http://download.oracle.com/otn pub/java/jdk/8u60-b27/jdk-8u60-linux-x64.rpm" # Install Java 8
sudo yum localinstall jdk-8u60-linux-x64.rpm
# Check the java version
java -version
# Copy JAVA_HOME to bash_profile echo "export JAVA_HOME=/usr/java/jdk1.8.0_60/jre" >> ~/.bash_profile
# Run the bash_profile
source ~/.bash_profile
# Check JAVA_HOME is successfully installed as environment variable env
# Untar maven gz file  
tar xvf apache-maven-3.0.5-bin.tar.gz
#Move apache file to /usr/local dir
sudo mv apache-maven-3.0.5 /usr/local/apache-maven # Copy below Maven commands to bash_profile
echo "export M2_HOME=/usr/local/apache-maven" >> ~/.bash_profile echo "export M2=$M2_HOME/bin" >> ~/.bash_profile echo "export PATH=$M2PATH" >> ~/.bash_profile
# Run the bash_profile
source ~/.bash_profile
# Check Maven commands successfully installed as env. variable
env
# Install Docker
sudo yum install -y docker
# Start docker
sudo service docker start
# Add docker user to ec2-user and jenkins
sudo usermod -a -G docker ec2-usersudo usermod -a -G docker jenkins
# Check docker info
sudo docker info
# Exit from instance
exit
# Ssh again
ssh -i ~/.ssh/jenkinskeypair.pem ec2-user@52.11.194.229
# Now we are able to check info without
sudo docker info
# Finally restart jenkins & docker
sudo service docker restart
sudo service jenkins restart
3 J$ V' T) _0 n5 Y4 b; r+ H
) T: n% {5 t: |, |7 O' o7 }
Jenkins现在启动并且正常运行起来了,你可以访问http://52.11.194.229:8080,不过需要拷贝jenkins admin的密码(jenkins启动日志中会有)去解锁jenkins并且安装一些推荐的plugins。
1.png
图4:jenkins安装

! K9 H- s* S. Q1 P# W2 F
9 g0 ~5 J. L; x2 ^/ V
  t( a  S# L8 x: k% x8 Q- T
在jenkins中安装gitlab和slack插件:

3 E* ?1 ?  ~3 C' {; ]- ]$ W

$ Z5 ?* L7 p) d
跳转到(http://52.11.194.229:8080/pluginManager/available),选择gitlab和slack plugin使用不重启安装。

1 k7 s# X: s6 c2 Z+ z1 }. ^
+ ?: X7 [2 _6 ?- w3 L
在安装了slack和gitlab插件之后,我们可以接下来以下的操作(可选)。Slack插件需要有webhook配置,如果我们不去配置这个webhook,jenkins将会出现异常。因此,为了解决这个问题,我们将做如下操作(使用groovy脚本去管控):
sudo mkdir /var/lib/jenkins/init.groovy.dsudo vi /var/lib/jenkins/init.groovy.d/disable-slack-webhooks.groovy

6 J4 T4 ^' c; ~! G; T1 F) h5 b
( P, r; `' o6 }- d& i  I
groovy脚本disable-slack-webhooks.groovy内容如下:
9 b# _+ u! V$ s" j0 t' c4 N
- v0 z2 {0 f, U" ]2 F
import jenkins.model.Jenkinsimport hudson.model.RootActiondef j = Jenkins.instance;def removal = { lst ->   lst.each { x ->      if(x.getClass().name.contains("slack.webhook")) {         lst.remove(x)      }   }}removal(j.getExtensionList(RootAction.class))removal(j.actions)

. K) W5 d; _, O$ t. `
4 N5 D* j6 `: E

" a7 Q( h$ H8 `
给init.groovy.d目录添加权限,并重启jenkins:
7 Z$ z: j' s- W5 Y* w6 i" l& M( w0 f

6 t+ z  U! Z# \/ k4 T+ R; s
sudo chown jenkins:jenkins -R /var/lib/jenkins/init.groovy.dsudo service jenkins restart
! w& A3 F6 h- Z' `: z* a! @" }. u
. C& D% T$ f5 t4 M
现在,让我们开始去配置jenkins:

' b7 M' n( V6 _

# {5 ^$ g9 y" v- L
访问 (http://52.11.194.229:8080/configure) 去配置java_home和m2_home作为环境变量并且填写slack的通知设置。
1.png
+ B/ @! I  l7 X8 h
$ ~6 }% N  W" u. h/ S
, m1 S9 ?7 Z2 Q* Z, b- O" s9 R7 N
& t7 A6 f- M& G$ v. d( l' G% F
4 w% J- R+ o: c3 l; j. W  E5 h
三、Demo演示

7 H8 l% I% g6 L% I4 H8 @
现在我们已经全部配置完毕,并且运行在 jenkins上,现在我们需要创建一个pipeline job并且创建pipeline script。选择"Build when a change is pushed to GitLab"按钮,因为我们将要push代码到gitlab上,然后gitlab将会触发jenkins。

( u% O( X. ~! }; B/ K2 s
1.png
图9:jenkins触发构建
: [( Y8 V) s" x

2 F4 s- ^8 @  v7 p

: C+ E5 h' i0 T7 g5 @! d
拷贝以下pipeline script到pipeline job,在"准备(preparation)"阶段,Jenkins将从Gitlab上克隆样品spring boot应用,并在"Test"阶段进行测试,如果测试通过,它将切换到"编译(Build)"阶段,生成编译的结果并进入到最终的"部署(deployment)"阶段.

3 ^/ Z4 A" C" N- w9 t- k0 a. M
9 B# ^' b) I+ Y8 x) P, ~0 p- Z3 f7 h& H4 d
node {    def mvnHome    stage(‘Preparation’) { // for display purposes        git ‘git@gitlab.com:<myRepo>/ContinuousIntegrationAndContinuousDeliveryApp.git'        mvnHome = tool 'M2'    }               
stage('Test') {        try {            sh "'${mvnHome}/bin/mvn' test"        } catch (e) {            notifyStarted("Tests Failed in Jenkins!")            throw e        }     }    stage('Build') {        try {            sh "'${mvnHome}/bin/mvn' clean package -DskipTests"        }catch (e) {            notifyStarted("Build Failed in Jenkins!")            throw e        }     }    stage('Results') {        try{            archive 'target/*.jar'        }catch (e) {
            notifyStarted("ackaging Failed in Jenkins!")            throw e        }     }    }    stage('Deployment') {        try{            sh   '/var/lib/jenkins/workspace/Pipeline/runDeployment.sh'        }catch (e) {            notifyStarted("Deployment Failed in Jenkins!")            throw e        }     }    notifyStarted("All is well! Your code is tested,built,and deployed.")}def notifyStarted(String message) {  slackSend (color: '#FFFF00', message: "${message}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")}

1 v  h% ~8 C& E, D: Q# k$ P

  E$ `  W' V2 T, a
现在,切换到/var/lib/jenkins/workspace/Pipeline目录,创建一个runDeployment.sh脚本,部署目录并且在部署目录放置一个Dockerfile.

% Q8 e6 y1 L% y; Q. f# @1 @
& I$ Y3 _+ \) k' i+ @
cd  /var/lib/jenkins/workspace/Pipelinemkdir deployment#Copy below Dockerfilesudo vi deployment/DockerfileFROM centosRUN  yum install -y wgetRUN wget --no-cookies --no-check-certificate --header "Cookie:  gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u60-b27/jdk-8u60-linux-x64.rpm"RUN yum localinstall jdk-8u60-linux-x64.rpm -yEXPOSE 8090ADD  app.jar myApp.jarENTRYPOINT ["java","-jar","myApp.jar"]
# Create runDeployment.sh and copy below script with your docker username and password.sudo vi runDeployment.sh#!/bin/bash -execho "Deploying app.jar to docker folder"packageName=`ls target/continuousintegrationandcontinuousdeliveryapp*.jar`versionid=`echo $packageName | awk -F "-" '{ print $2}'`versionname=`echo $packageName | awk -F "-" '{ print $3}' | awk -F "." '{ print $1}'`version=`echo $versionid-$versionname`echo "version: $version"cp -r $packageName deployment/app.jardockerImageName=onedaywillcome/myappdockerpid=`docker ps -a | grep $dockerImageName | grep "Up" | awk -F " " '{ print $1 }'`if [[ $dockerpid != "" ]];then    docker kill $dockerpid   docker rm $dockerpidfidocker build -t $dockerImageName deployment/.docker run -d -p 8090:8090 $dockerImageNamedockerImageId=`docker images | grep $dockerImageName | grep latest | awk -F " " '{print $3}'`
docker tag $dockerImageId $dockerImageNameversiondocker login -u <DOCKER_USERNAME> -p <DOCKER_PASSWORD>docker push $dockerImageName:$version#Give jenkins ownershipt to deployment directory and runDeployment.shsudo chown jenkins:jenkins runDeployment.shsudo chmod 775 runDeployment.shsudo chown jenkins:jenkins -R deployment
/ n1 F8 q( X4 \. _- ~; f
9 K/ i( N1 o6 D
到此为止,所有的工作都已经完成。

6 j# q: ^: F1 y
/ z  v! R9 M6 k8 _5 h
当你现在去push你的代码到gitlab的时候,Gitlab将触发Jenkins,然后jenkins将首先进行测试,编译然后再服务器上部署,同时将编译生成的image镜像上传到Docker Registry,而在整个部署流水线中如果发生什么异常问题,它将通过Slack去通知你相关的异常点。
1.png
[img][/img]图10:部署流水线
4 f# m% @9 |+ q! ?) f8 c- U

, h! l8 S( \6 _% J6 Q! K" M/ a

) n& D: b4 V3 N. w+ }
我们的Spring boot应用现在就会运行起来了。
1.png
[img][/img]图11:spring-app
- t( V! r1 E1 Q# Y- g
) S% o1 Z& Y5 S9 V( u

3 ?! g, _. l) j
  v1 V% w! W6 R
应用相关的docker image文件也已经上传到Docker hub registry:
1.png
[img][/img]图12:docker hub镜像仓库

# O' O( O' [* T' l% \' z

. h% |  m9 C' h  k, x) d8 w6 E; C& L
样,我们就完成了一个持续集成持续部署(CI-CD)的Demo.
9 x: D$ c6 `  k6 U' U& Y. ~

  o. N$ m( T( R# K6 v: R9 j
四、总结:
2 J2 G2 [: O8 g9 [& Q
& X2 H: H2 S4 y5 ^6 ~
当然了,本篇博客只是一个很小的Demo,在实际企业内部使用过程中,这些环节需要更多的功能点以及安全方面的考虑。但是,站在企业研发者的角度去考虑这个问题,整个持续集成到持续测试很大程度上减少了时间损耗,这样开发人员在每次提交代码到主干分支,进行编译测试后就能很快的反馈测试结果,更佳方便了研发的效率;同时还有更重要的一点是,应用最终的产出物品是一个docker image,倘若在集成测试阶段可以正常的运行业务应用,那么最终使用该image镜像文件部署在预发布环境或者生产环境部署也依然会一切正常,因为业务代码以及业务应用运行时环境都被统一封装到了docker image中去了,这样也在很大程度上减少了业务应用多环境异构的情况,从此妈妈再也不用担心研发大人们的代码在本地和测试环境可以运行,而在生产环境不能正常运行了。

' U9 H! z% r& i- R

5 \6 m) Y6 D/ h3 W
原创: 彪哥 译

- {7 h$ z5 L# k% Q2 w
. g. r3 o' l5 S  [) ]- @) E& |
0?wx_fmt=gif.jpg

本版积分规则

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

Baidu

GMT+8, 2019-9-23 06:53 , Processed in 0.148111 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

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