Jenkins介绍
Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建、测试和部署软件。Jenkins 支持各种运行方式,可通过系统包、Docker 或者通过一个独立的 Java 程序。
传统部署方式存在的问题
使用Jenkins + Docker做CI/CD的好处
Jenkins安装
下载Jenkins安装介质
https://jenkins.io/zh/download/
简单起见,这里直接选择docker版本进行安装: https://hub.docker.com/r/jenkins/jenkins
1 | docker pull jenkins/jenkins |
更多有关Jenkins docker版本的说明可以参阅这里。
启动Jenkins容器
1 | docker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:latest |
第一次启动时会提示记录一下安装密码。
安装配置Jenkins实例
输入刚才的安装密码输入,点击“继续”按钮。
选择“安装推荐的插件”即可,继续。。。
安装过程都是全自动的,可能会比较慢,冲杯咖啡稍等片刻。。。
第一次登陆,需要创建管理员账号,并配置一下Jenkins的地址。之后就可以使用Jenkins了。
创建你的第一个Job任务
新建一个Job,输入名称,任务类型选择流水线
。
配置Job任务
可以通过选择sample来参考一下如何编写job脚本。
编写pipeline script并保存。
1 | node { |
运行Job任务
点击屏幕左侧的”立即构建”菜单,执行任务构建。
点击左侧下方”Build History”里的小圆点,可以查看具体的构建日志,以便排查问题。
好了,现在可以开始编写正式的流水线代码了。
CI/CD 持续集成/持续部署过程
总体思路
编写相关脚本,通过Jenkis的job任务调用这些脚本,进而达到自动化集成/部署的效果。
需要编写的脚本如下:
- Jenkis流水线脚本
- Dockerfile
- 主要执行shell脚本
- 模板文件(可选)
- k8s部署脚本
编写Jenkis流水线脚本
1 | node { |
编写Dockerfile
1 | FROM hub.mooc.com/kubernetes/tomcat:8.0.51-alpine |
主要执行shell脚本
build-image-web.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
if [ "$[BUILD_DIR]" == "" ];then
echo "env 'BUILD_DIR' is not set"
exit 1
fi
# BUILD_DIR 和 JOB_NAME 是Jenkins自带的环境变量
DOCKER_DIR=${BUILD_DIR}/${JOB_NAME}
if [ ! -d "$[DOCKER_DIR]" ];then
mkdir -p ${DOCKER_DIR}
fi
echo "docker workspace ${DOCKER_DIR}"
JENKINS_DIR=${WORKSPACE}/${MODULE}
echo "jenkins workspace: ${JENKINS_DIR}"
if [ ! -f ${JENKINS_DIR}/target/*.war ];then
echo "target war file not found ${JENKINS_DIR}/target/*.war"
exit 1
fi
cd ${DOCKER_DIR}
rm -rf *
unzip -oq ${JENKINS_DIR}/target/*.war -d ./ROOT
mv ${JENKINS_DIR}/Dockerfile .
if [ -d ${JENKINS_DIR}/dockerfiles ];then
mv ${JENKINS_DIR}/dockerfiles .
fi
VERSION=$(date +%Y%m%d%H%M%S)
IMAGE_NAME=hub.mooc.com/kubernetes/${JOB_NAME}:${VERSION}
# 将当前构建的docker image & tag写到一个文件里,以便后续deploy.sh脚本获取
echo "${IMAGE_NAME}" > ${WORKSPACE}/IMAGE
echo "building image: ${IMAGE_NAME}"
docker build -t ${IMAGE_NAME}
docker push ${IMAGE_NAME}
为
build-image-web.sh
添加执行权限。
1 | chmod +x build-image-web.sh |
在Jenkins所在机器上登录下镜像仓库,确保其可以推送docker镜像
1 | docker login hub.mooc.com |
编写模板文件(可选)
编写template模板文件。直接拿一个k8s的yaml文件进行修改即可。替换其中的一些变量名字,如:name, image, host等。
在vim中替换的命令为
%s/要替换的目标字符串/结果字符串/g
即:%s/web-demo//g
web.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50#deploy
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{name}}
spec:
selector:
matchLabels:
app: {{name}}
replicas: 1
template:
metadata:
labels:
app: {{name}}
spec:
containers:
- name: {{name}}
image: {{image}}
ports:
- containerPort: 8080
#service
apiVersion: v1
kind: Service
metadata:
name: {{name}}
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: {{name}}
type: ClusterIP
#ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{name}}
spec:
rules:
- host: {{host}}
http:
paths:
- path: /
backend:
serviceName: {{name}}
servicePort: 80
编写k8s部署脚本
deploy.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
name=${JOB_NAME}
image=$(cat ${WORKSPACE}/IMAGE)
host=${HOST}
echo "---> deploying ... name: ${name}, image: ${image}, host: ${host}"
# $(dirname "${BASH_SOURCE[0]} 获取脚本当前运行的目录
cp $(dirname "${BASH_SOURCE[0]}")/template/web.yaml
echo "---> copy success"
# 用sed命令进行查找替换
sed -i "s,{{name}},${name},g" web.yaml
sed -i "s,{{image}},${image},g" web.yaml
sed -i "s,{{host}},${host},g" web.yaml
# 部署到k8s
echo "---> ready to apply"
kubectl apply -f web.yaml
echo "---> apply is finished"
# 健康检查
count=60
success=0
# 设置数组分隔符
IFS=","
# 为了避免k8s部署还没开始就进行健康检查,sleep 5秒再进行
# 更靠谱的方式其实应该判断k8s服务信息里的".metadata.annotations.deployment.kubernetes.io/revision"来判断,这个值每次部署后会自动加1
sleep 5
while [ ${count} -gt 0 ]
do
# 从k8s获取服务信息
replicas=$(kubectl get deploy ${name} -o go-template='{{.status.replicas}},{{.status.updatedReplicas}},{{.status.readyRelicas}},{{.status.availableRelicas}}')
echo replicas
# 转换成数组
arr=(${replicas})
if [ "${arr[0]}" == "${arr[1]}" -a "${arr[1]}" == "${arr[2]}" -a "${arr[2]}" == "${arr[3]}" ]; then
echo "health check success!"
success=1
break
fi
((count--))
sleep 2
done
if [ ${success} -ne 1 ]; then
echo "health check failed!"
exit 1
fi
# 打印log以便调试
cat web.yaml
设置执行权限1
chmod +x deploy.sh