Jenkins安装部署
Jenkins宿主机
防火墙关闭(避免麻烦)
# 关闭防火墙(很重要!!)
systemctl stop firewalld
systemctl disable firewalld
Jenkins安装
使用yum安装,jdk使用官方文档指定的openjdk11,经测试,使用orcale jdk8,无法启动jenkins
wget -O /etc/yum.repos.d/jenkins.repo \
https://pkg.jenkins.io/redhat-stable/jenkins.repo
rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
yum upgrade
yum install java-11-openjdk
yum install jenkins
systemctl daemon-reload
Maven安装(可选)
这个可以不装,jenkins主要也是用容器来编译的
cd /opt
wget https://dlcdn.apache.org/maven/maven-3/3.9.2/binaries/apache-maven-3.9.2-bin.tar.gz
# 解压
tar -zxvf apache-maven-3.9.2-bin.tar.gz
# 创建本地库
mkdir -p /opt/repo/maven
# 配置中央库
vim /opt/apache-maven-3.9.2/conf/settings.xml
# 配置本地库位置
<localRepository>/opt/repo/maven</localRepository>
# 配置国内源
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
# 配置环境变量
vim /etc/profile.d/maven.sh
# 内容如下
export MAVEN_HOME=/opt/apache-maven-3.9.2
export PATH=$PATH:$MAVEN_HOME/bin
# 刷新环境变量
source /etc/profile
Docker安装
# 安装docker社区版
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine && \
yum install -y yum-utils device-mapper-persistent-data lvm2 && \
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo && \
yum makecache fast && \
yum install docker-ce
# 启动服务
systemctl enable docker
systemctl start docker
# 增加权限,jenkins的pipeline内执行docker命令时,默认使用jenkins用户执行shell(该用户没权限执行docker)
cd /var/run
chmod 777 docker.sock
模板镜像安装
我这边写了一个新项目,做了一下模板docker镜像,有了这些镜像,我们可以方便的实现😁:
- 基于容器隔离的多环境编译
- 基于容器隔离的服务部署
deploy
build.sh
# 清除构建缓存
docker builder prune -a -f
image_name="jdk11"
version="latest"
if [ `docker ps -a --format "{{.Image}}" | grep ${image_name}:${version} | wc -l` -gt 1 ]; then
echo "============================== 当前存在容器占用镜像 =============================="
exit 1
fi
if [ `docker images --format "{{.Repository}}:{{.Tag}}" | grep ${image_name}:${version} | wc -l` -gt 0 ]; then
docker rmi -f ${image_name}:${version}
fi
docker build -t $image_name .
Dockerfile
FROM centos:7
MAINTAINER Tony Chen <chenming7@ruijie.com.cn>
ENV JAVA_HOME="/opt/jdk_11"
ENV PATH="${JAVA_HOME}/bin:${PATH}"
# 添加tar
# 复制本地的jdk_11.tar.gz到容器内的/opt/jdk_11.tar.gz
COPY jdk_11.tar.gz /opt/jdk_11.tar.gz
RUN cd /opt && tar zxvf /opt/jdk_11.tar.gz
RUN mv /opt/jdk-11.0.19 /opt/jdk_11
compile
build.sh
# 清除构建缓存
docker builder prune -a -f
image_name="maven_jdk11"
version="latest"
if [ `docker ps -a --format "{{.Image}}" | grep ${image_name}:${version} | wc -l` -gt 1 ]; then
echo "当前存在容器占用镜像,请先清除容器后再构建镜像"
exit 1
fi
if [ `docker images --format "{{.Repository}}:{{.Tag}}" | grep ${image_name}:${version} | wc -l` -gt 0 ]; then
echo "存在残留同名镜像,正在清除"
docker rmi -f ${image_name}:${version}
fi
echo "开始构建镜像"
docker build --no-cache -t $image_name .
Dockerfile
FROM centos:7
MAINTAINER Tony Chen <chenming7@ruijie.com.cn>
ENV JAVA_HOME="/opt/jdk_11"
ENV PATH="${JAVA_HOME}/bin:${PATH}"
ENV MAVEN_HOME="/opt/maven_3.9.2"
ENV PATH="${MAVEN_HOME}/bin:${PATH}"
# 添加jdk和 maven
# 复制本地的jdk_11.tar.gz到容器内的/opt/jdk_11.tar.gz
COPY jdk_11.tar.gz /opt/jdk_11.tar.gz
COPY maven_3.9.2.tar.gz /opt/maven_3.9.2_11.tar.gz
RUN cd /opt && tar zxvf /opt/jdk_11.tar.gz
RUN mv /opt/jdk-11.0.19 /opt/jdk_11
RUN cd /opt && tar zxvf /opt/maven_3.9.2_11.tar.gz
RUN mv /opt/apache-maven-3.9.2 /opt/maven_3.9.2
安装步骤
如上图所示,找到你所需的镜像,安装镜像
bash build.sh
验证安装
访问 http://<jenkins_ip>:8080/
配置Jenkins的MAVEN_HOME(可选)
访问http://<jenkins_ip>:8080/manage/configure
部署目标机配置
Jenkins的作用在于编译打包,目标机则承接打包文件,启动对应服务
环境准备:
- docker:安装方法同上,记得赋权docker.sock
- 关闭防火墙
流水线总体设计
设计思路
编译环境隔离
我关注什么?
- 编译应该够快,别让我下半天依赖
- 编译无残留,我只要最后的jar
- 让我方便选择编译环境,JDK8? JDK11?
解决方案 - 编译要快?那么jenkins宿主机统一放置依赖本地库,编译时进行挂载
- 编译无残留?那我容器内编译完,干掉容器就得了
- 多种编译环境?那我预先做几个编译镜像,让用户执行流水线时进行选择就行
运行环境隔离
我关注什么?
- 不要裸机跑服务,中个木马,整台机器都得寄😭!
- 资源可调控,我想让哪个服务分配多少cpu和内存都行
- 部署要快,别让我等太久!
解决方案 - 不要裸机?那就容器内跑吧
- 资源可调?docker的参数一键搞定
- 部署要快?容器已经很快了,如果只传输编译后的打包jar,通过挂载jar形式运行容器,IO不会很久的
流水线
Jenkinsfile
pipeline {
agent any
environment {
// 宿主机配置
JENKINS_SSH_PASSWORD = "xxx"
// git配置
GIT_URL = "xx.xx.xx.xx"
GIT_PORT = "xxxx"
GIT_USERNAME = "xxxx@xxx.xx.xx"
GIT_PASSWORD = "xxx"
// 部署机配置
DEPLOY_SSH_USERNAME = "xxx"
DEPLOY_SSH_PASSWORD = "xxx"
DEPLOY_SSH_PORT = "xx"
DEPLOY_JAR_PATH = "/devops/jar"
DEPLOY_JAR_NAME = "${MODUEL}-${VERSION}.jar"
DEPLOY_JAR = "${MODUEL}/target/${DEPLOY_JAR_NAME}"
// docker配置
CONTAINER_NAME = "${PROJECT.toLowerCase().replace("/","-")}-${MODUEL.toLowerCase()}"
}
parameters {
choice(name: 'GIT', choices: ['gogs'], description: 'GIT仓库')
string(name: 'PROJECT', defaultValue: 'chenming7/MyWeb', description: '项目名')
string(name: 'MODUEL', defaultValue: 'Web', description: '模块名')
string(name: 'VERSION', defaultValue: '1.0-SNAPSHOT', description: '版本号')
string(name: 'PORT', defaultValue: '443', description: '暴露端口,只能写一个')
choice(name: 'COMPILE_SDK', choices: ['maven_jdk11'], description: '编译SDK')
choice(name: 'DEPLOY_SSH_HOST', choices: ['192.168.217.134'], description: '部署机IP')
choice(name: 'RUN_SDK', choices: ['jdk11'], description: '运行SDK')
}
stages {
stage('Maven Build') {
steps {
// 拉去源码
sh 'bash /var/lib/jenkins/shell/git.sh ${GIT} ${PROJECT}'
// 编译打包
sh "docker run -v $WORKSPACE:/opt/git -v /opt/repo/maven:/opt/repo/maven -w /opt/git --rm ${COMPILE_SDK} mvn package -pl ${MODUEL} -am"
}
// 该阶段的后处理
post {
// 成功时调用
success {
// archiveArtifacts可以让我们下载指定的文件
archiveArtifacts "${DEPLOY_JAR}"
echo "编译完毕"
}
}
}
stage('Deploy'){
steps {
sh 'bash /var/lib/jenkins/shell/deploy.sh ${DEPLOY_SSH_HOST} ${DEPLOY_JAR_PATH} ${DEPLOY_JAR} ${CONTAINER_NAME} ${DEPLOY_JAR_NAME} ${PORT} ${RUN_SDK}'
}
}
}
}
流水线相关脚本
git.sh
#!/bin/bash
GIT=$1
PROJECT=$2
function pull() {
git pull
}
function clone(){
if [ `ls -l | wc -l` -gt 1 ]; then
pull
else
case $GIT in
"gogs")
GIT_USERNAME="xxxx"
GIT_PASSWORD="xxxx"
GIT_URL="xx.xx.xx.xx"
GIT_PORT="xxxx"
git clone http://$GIT_USERNAME:$GIT_PASSWORD@$GIT_URL:$GIT_PORT/$PROJECT.git .
;;
"github")
echo "stop $2"
;;
*)
echo "example: git.sh gogs chenming7/MyWeb"
;;
esac
fi
}
clone
deploy.sh
#!/bin/bash
DEPLOY_SSH_HOST=$1
DEPLOY_JAR_PATH=$2
DEPLOY_JAR=$3
CONTAINER_NAME=$4
DEPLOY_JAR_NAME=$5
PORT=$6
RUN_SDK=$7
function deploy() {
case $DEPLOY_SSH_HOST in
"192.168.217.134")
DEPLOY_SSH_USERNAME="xxx"
DEPLOY_SSH_PASSWORD="xxxx"
DEPLOY_SSH_PORT="xxx"
sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST rm -rf $DEPLOY_JAR_PATH/*
sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST mkdir -p $DEPLOY_JAR_PATH
sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST chmod 777 -R $DEPLOY_JAR_PATH
sshpass -p $DEPLOY_SSH_PASSWORD scp -P $DEPLOY_SSH_PORT $DEPLOY_JAR $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST:$DEPLOY_JAR_PATH
if [ `sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST docker ps -a -f name=$CONTAINER_NAME | wc -l` -gt 1 ]; then
sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST docker rm -f $CONTAINER_NAME
fi
sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST docker run -v $DEPLOY_JAR_PATH/$DEPLOY_JAR_NAME:$DEPLOY_JAR_PATH/$DEPLOY_JAR_NAME -p $PORT:443 --name $CONTAINER_NAME -d $RUN_SDK java -jar $DEPLOY_JAR_PATH/$DEPLOY_JAR_NAME
;;
*)
echo "example: bash /var/lib/jenkins/shell/deploy.sh 192.168.217.134 /devops/jar Web/target/Web-1.0-SNAPSHOT.jar chenming7-myweb-web Web-1.0-SNAPSHOT.jar 443 jdk11"
;;
esac
}
deploy
评论区