jenkins自动部署教程
文章目录
- 参考文章
- jenkins+k8s+git自动部署
- 缺陷记录
- 部署步骤
- jenkins+ansible+git自动部署
- 缺陷记录
- 实践步骤如下:
- jenkins凭证credentials
- jenkins传递参数到shell脚本以及ansible启动脚本
- jenkins自动部署注意点
- jenkins:解决root无法su到jenkins用户
- 安装jenkins
- 安装maven
- jenkins用户执行权限诸多问题
- 解决方案1:
- 解决方案2:
- 解决方案3:
- 解决方案四:
参考文章
jenkins pipeline基础语法与示例
Linux 下 Jenkins 安装及将 Jenkins 设置为 root 权限
jenkins:解决root无法su到jenkins用户
jenkins+k8s+git自动部署
缺陷记录
部署好之后,kubectl查看服务运行状态正常,但就是外界访问不到
jenkins的pipeline如下:
pipeline {
//说明流水线哪一个节点运行
agent any
options {
// 默认15分钟 timeout (15)
timeout(time: 13, unit: 'MINUTES')
}
environment {
build_dir="/opt/k8s-cicd/build-workspace"
project_name="hello-world"
host="k8s-web.muoo.com"
}
stages {
stage('build') {
steps{
git 'https://gitee.com/goodshred/k8s-hello-world.git'
sh "mvn -Dmaven.test.failure.ignore=true clean package"
sh 'echo "curUser=${USER}"'
//script {
//本质还是不应该写在这里,碰到无权限问题应该手动去操作linux机器,比如配置两台机器的免密登陆,使用root权限给某个文件赋予允许jenkins执行的权限
//chmod: changing permissions of ‘/opt/k8s-cicd/script/build.sh’: Operation not permitted
//我是用的root创建的脚本文件,因此jenkins用户无法更改其权限
//sh "chmod +x /opt/k8s-cicd/script/build.sh"
//sh "chmod +x /opt/k8s-cicd/script/deploy.sh"
// }
sh "${build_dir}/script/build.sh"
sh "${build_dir}/script/deploy.sh"
}
}
}
post {
success {
script {
echo "post==success"
}
}
failure {
script {
echo "post==failure"
}
}
//构建不稳定时
//随着项目的开发和持续扩展,使用Jenkins构建(build)项目越来越多,Jenkins服务器的磁盘可能被大日志文件占满造成无法继续构建项目的异常(一般会出现构建按钮为黄色)
unstable {
script {
echo "post==unstable "
}
}
}
}
创建目录结构如下:
Dockerfile文件
FROM openjdk:8-jdk-alpine
COPY hello-world-0.0.1-SNAPSHOT.jar /hello-world-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java", "-jar","/hello-world-0.0.1-SNAPSHOT.jar"]
build.sh文件:
#!/bin/bash
if [ "${build_dir}" == "" ];then
echo "env 'build_dir' is not set"
exit 1
fi
# 构建时候的工作名,比如Jenkins自动构建个项目,取名叫k8s-cicd,那么${JOB_NAME}=k8s-cicd,它是Jenkins自带的全局变量
# /opt/k8s-cicd/build-workspace/k8s-web-demo
docker_dir=${build_dir}/${JOB_NAME}
if [ ! -d ${docker_dir} ];then
mkdir -p ${docker_dir}
fi
echo "docker workspace: ${docker_dir}"
# ${WORKSPACE}/${MODULE}=/var/lib/jenkins/workspace/k8s-web-demo/
jenkins_dir=${WORKSPACE}/${MODULE}
export jenkins_dir=${jenkins_dir}
echo "jenkins_dir is ${jenkins_dir}"
if [ ! -f ${jenkins_dir}target/*jar ];then
echo "target file not found ${jenkins_dir}target/*jar"
exit 1
fi
\cp ${jenkins_dir}target/*jar ${docker_dir}
cd ${docker_dir}
# VERSION=$(date + %y%m%d%H%M%S%)
VERSION=$(date "+%y-%m-%d_%H-%M-%S")
IMAGE_NAME=goodshred/${project_name}:${VERSION}
echo ${IMAGE_NAME}
echo "${IMAGE_NAME}" > ${WORKSPACE}/IMAGE
echo "workspave is : ${WORKSPACE}======================"
cat ${WORKSPACE}/IMAGE
echo "build image ${IMAGE_NAME}"
docker build -t ${IMAGE_NAME} .
docker push ${IMAGE_NAME}
deploy.sh文件如下:
#!/bin/bash
name=${JOB_NAME}
image=$(cat ${ WORKSPACE}/IMAGE)
\cp ${build_dir}/template/web.yaml ${build_dir}/script/web.yaml
sed -i "s,{ {name}},${name},g" ${build_dir}/script/web.yaml
sed -i "s,{ {image}},${image},g" ${build_dir}/script/web.yaml
kubectl apply -f ${build_dir}/script/web.yaml
cat ${build_dir}/script/web.yaml
web.yaml如下:
apiVersion: v1
kind: Service
metadata:
name: { { name}}
namespace: default
labels:
app: { { name}}
spec:
type: NodePort
ports:
- port: 30009
targetPort: 19999
# type: NodePort # 在主机上暴露端口
nodePort: 19999 #service对外开放端口
selector:
app: { { name}}
---
apiVersion: extensions/v1beta1
#apps/v1,extensions/v1beta1需要根据自己k8s的版本选择
kind: Deployment #对象类型
metadata:
name: { { name}} #名称
labels:
app: { { name}} #标注
spec:
replicas: 1 #运行容器的副本数,修改这里可以快速修改分布式节点数量
selector:
matchLabels:
app: { { name}}
template:
metadata:
labels:
app: { { name}}
spec:
containers: #docker容器的配置
# { {name}}
- name: { { name}}
#image: goodshred/hello-world:latest
## 192.168.1.253:8081/pasq/dockertest:0.0.1 # pull镜像的地址 ip:prot/dir/images:tag
# { {image}}
image: { { image}}
imagePullPolicy: IfNotPresent #pull镜像时机,
ports:
- containerPort: 19999 #容器对外开放端口
部署步骤
jenkins的pipeline如下:
pipeline {
//说明流水线哪一个节点运行
agent any
options {
// 默认15分钟 timeout (15)
timeout(time: 13, unit: 'MINUTES')
}
environment {
build_dir="/opt/k8s-cicd/build-workspace"
project_name="hello-world"
host="k8s-web.muoo.com"
}
stages {
stage('build') {
steps{
git 'https://gitee.com/goodshred/k8s-hello-world.git'
sh "mvn -Dmaven.test.failure.ignore=true clean package"
sh 'echo "curUser=${USER}"'
//script {
//本质还是不应该写在这里,碰到无权限问题应该手动去操作linux机器,比如配置两台机器的免密登陆,使用root权限给某个文件赋予允许jenkins执行的权限
//chmod: changing permissions of ‘/opt/k8s-cicd/script/build.sh’: Operation not permitted
//我是用的root创建的脚本文件,因此jenkins用户无法更改其权限
//sh "chmod +x /opt/k8s-cicd/script/build.sh"
//sh "chmod +x /opt/k8s-cicd/script/deploy.sh"
// }
sh "${build_dir}/script/build.sh"
sh "${build_dir}/script/deploy.sh"
}
}
}
post {
success {
script {
echo "post==success"
}
}
failure {
script {
echo "post==failure"
}
}
//构建不稳定时
//随着项目的开发和持续扩展,使用Jenkins构建(build)项目越来越多,Jenkins服务器的磁盘可能被大日志文件占满造成无法继续构建项目的异常(一般会出现构建按钮为黄色)
unstable {
script {
echo "post==unstable "
}
}
}
}
创建目录结构如下:
Dockerfile文件
FROM openjdk:8-jdk-alpine
COPY hello-world-0.0.1-SNAPSHOT.jar /hello-world-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java", "-jar","/hello-world-0.0.1-SNAPSHOT.jar"]
build.sh文件:
#!/bin/bash
if [ "${build_dir}" == "" ];then
echo "env 'build_dir' is not set"
exit 1
fi
# 构建时候的工作名,比如Jenkins自动构建个项目,取名叫k8s-cicd,那么${JOB_NAME}=k8s-cicd,它是Jenkins自带的全局变量
# /opt/k8s-cicd/build-workspace/k8s-web-demo
docker_dir=${build_dir}/${JOB_NAME}
if [ ! -d ${docker_dir} ];then
mkdir -p ${docker_dir}
fi
echo "docker workspace: ${docker_dir}"
# ${WORKSPACE}/${MODULE}=/var/lib/jenkins/workspace/k8s-web-demo/
jenkins_dir=${WORKSPACE}/${MODULE}
export jenkins_dir=${jenkins_dir}
echo "jenkins_dir is ${jenkins_dir}"
if [ ! -f ${jenkins_dir}target/*jar ];then
echo "target file not found ${jenkins_dir}target/*jar"
exit 1
fi
\cp ${jenkins_dir}target/*jar ${docker_dir}
cd ${docker_dir}
# VERSION=$(date + %y%m%d%H%M%S%)
VERSION=$(date "+%y-%m-%d_%H-%M-%S")
IMAGE_NAME=goodshred/${project_name}:${VERSION}
echo ${IMAGE_NAME}
echo "${IMAGE_NAME}" > ${WORKSPACE}/IMAGE
echo "workspave is : ${WORKSPACE}======================"
cat ${WORKSPACE}/IMAGE
echo "build image ${IMAGE_NAME}"
docker build -t ${IMAGE_NAME} .
docker push ${IMAGE_NAME}
deploy.sh文件如下:
#!/bin/bash
name=${JOB_NAME}
image=$(cat ${ WORKSPACE}/IMAGE)
\cp ${build_dir}/template/web.yaml ${build_dir}/script/web.yaml
sed -i "s,{ {name}},${name},g" ${build_dir}/script/web.yaml
sed -i "s,{ {image}},${image},g" ${build_dir}/script/web.yaml
kubectl apply -f ${build_dir}/script/web.yaml
cat ${build_dir}/script/web.yaml
web.yaml如下:
apiVersion: v1
kind: Service
metadata:
name: { { name}}
namespace: default
labels:
app: { { name}}
spec:
type: NodePort
ports:
- port: 30009
targetPort: 19999
# type: NodePort # 在主机上暴露端口
nodePort: 19999 #service对外开放端口
selector:
app: { { name}}
---
apiVersion: extensions/v1beta1
#apps/v1,extensions/v1beta1需要根据自己k8s的版本选择
kind: Deployment #对象类型
metadata:
name: { { name}} #名称
labels:
app: { { name}} #标注
spec:
replicas: 1 #运行容器的副本数,修改这里可以快速修改分布式节点数量
selector:
matchLabels:
app: { { name}}
template:
metadata:
labels:
app: { { name}}
spec:
containers: #docker容器的配置
# { {name}}
- name: { { name}}
#image: goodshred/hello-world:latest
## 192.168.1.253:8081/pasq/dockertest:0.0.1 # pull镜像的地址 ip:prot/dir/images:tag
# { {image}}
image: { { image}}
imagePullPolicy: IfNotPresent #pull镜像时机,
ports:
- containerPort: 19999 #容器对外开放端口
jenkins+ansible+git自动部署
缺陷记录
最后一行java -jar没有执行,或者执行失败。
实践步骤如下:
jenkinsfile
pipeline{
agent any
environment {
GIT_USERNAME1 = credentials('git_username')
GIT_PASSWORD1 = credentials('git_password')
}
stages{
stage('部署'){
steps{
//${WORKSPACE}=/var/lib/jenkins/workspace
// sh """
// bash -e ${WORKSPACE}/sh/build.sh ${BRANCH} ${GIT_USERNAME} ${GIT_PASSWORD}
// """
// python deploy.py ${BRANCH} ${GIT_USERNAME} ${GIT_PASSWORD}
//python deploy.py $env.BRANCH $env.GIT_USERNAME $env.GIT_PASSWORD
sh """
cd /root/ansible/role/demo/playbook/
python deploy.py ${ BRANCH} ${ GIT_USERNAME1} ${ GIT_PASSWORD1}
"""
}
}
}
}
start.sh
#!/bin/bash
# 对于source命令而言,这个地方很重要
CURRENT_PATH=$(cd `dirname $0`; pwd)
# 不能写成source env.sh,除非我执行该脚本用的./start.sh,如果是sh start.sh就要这样写
source ${CURRENT_PATH}/env.sh >/dev/null 2>&1
echo "name is========${name}"
JAR_NAME=hello-world-0.0.1-SNAPSHOT.jar
rm -rf ~/lmj/module-workspace/
mkdir -p ~/lmj/module-workspace/
cd ~/lmj/module-workspace/
git clone -b { { BRANCH}} https://{ { GIT_USERNAME}}:{ { GIT_PASSWORD}}@gitee.com/goodshred/ansible-jenkins-git-demo.git
cd ansible-jenkins-git-demo/
mvn -Dmaven.test.failure.ignore=true clean package
ps -ef | grep -w ${JAR_NAME} | grep -v grep | awk '{print $2}'
proc_id=`ps -ef|grep -w ${ JAR_NAME}|grep -v grep|awk '{print $2}'`
proc_msg=`ps -ef|grep -w ${ JAR_NAME}|grep -v grep|awk '{print $8 $9 $10}'`
if [ -n proc_id ]; then
kill -9 ${proc_id}
echo ${proc_id} ${proc_msg}
fi
JAVA_OPTS="-Xmx512m -Xms512m"
echo "nohup java ${JAVA_OPTS} -Dspring.profiles.active={ {BRANCH}} -jar target/${JAR_NAME} &"
nohup java ${JAVA_OPTS} -Dspring.profiles.active={ { BRANCH}} -jar target/${JAR_NAME} &
env_dev.json
{
"name": "env.develop"
}
deploy.yaml
---
- hosts: localhost
name: deploy hello world
gather_facts: no #不收集facts
roles:
- hw
vars:
name: { name}
GIT_USERNAME: { GIT_USERNAME}
GIT_PASSWORD: { GIT_PASSWORD}
BRANCH: { BRANCH}
deploy.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
import json
try:
reload(sys)
sys.setdefaultencoding("utf-8")
except:
pass
BRANCH=sys.argv[1]
GIT_USERNAME=sys.argv[2]
GIT_PASSWORD=sys.argv[3]
print("===================================================================")
# print(BRANCH+"========="+GIT_USERNAME+"======="+GIT_PASSWORD)
conf=json.load(open('env_dev.json'))
print("执行替换")
raw_yaml=open('deploy.yaml').read()
with open('deploy.yaml',"w+") as f:
f.write(raw_yaml.format(
name=conf["name"],
BRANCH=BRANCH,
GIT_USERNAME=GIT_USERNAME,
GIT_PASSWORD=GIT_PASSWORD
))
print("执行部署")
# os.system("cd playbook/ && ansible-playbook deploy.yaml -v")
os.system("ansible-playbook deploy.yaml -v")
templates/env.j2
#!/bin/bash
export name={ { name}}
export BRANCH={ { BRANCH}}
export GIT_USERNAME={ { GIT_USERNAME}}
export GIT_PASSWORD={ { GIT_PASSWORD}}
tasks/main.yaml
---
# tasks file for /root/ansible/role/lisi
# 这里的.路径是执行python的哪个路径,比如我是在playbook下执行的python deploy.py
# 那么生成的env.sh在playbook/env.sh
- name: delever
template:
src: env.j2
dest: env.sh
# 由于这里使用的是sh执行,因此在运行source env.sh这样是不对,需要使用绝对路径cd `dirname $0`/env.sh ,如果是./方式倒无所谓
- name: start
shell: "sh start.sh"
register: haha
# 会自动打印调试信息
- name: debug info
debug: var=haha
jenkins凭证credentials
pipeline{
agent any
environment {
GIT_USERNAME1 = credentials('git_username')
GIT_PASSWORD1 = credentials('git_password')
}
stages{
stage('部署'){
steps{
sh """
cd /root/ansible/role/demo/playbook/
python deploy.py ${ BRANCH} ${ GIT_USERNAME1} ${ GIT_PASSWORD1}
"""
}
}
}
}
jenkins传递参数到shell脚本以及ansible启动脚本
jenkins设置参数
这样我们在jenkinsfile中就可以通过${GIT_USERNAME}获取到
steps{
//${WORKSPACE}=/var/lib/jenkins/workspace
sh """
bash -e ${ WORKSPACE}/sh/build.sh ${ BRANCHE} ${ GIT_USERNAME} ${ PASSWORD}
"""
}
shell脚本中接收
#!/bin/bash
# 接受参数
GIT_URL=gitee.com
BRANCH=$1
GIT_USERNAME=$2
GIT_PASSWORD=$3
git clone -b ${BRANCH} https://${GIT_USERNAME}:${GIT_PASSWORD}@${GIT_URL}/goodshred/ansible-jenkins-git-demo.git
我们在ansible的deploy.yaml中可以这样接收
conf_file = sys.argv[1]
rio_flag = sys.argv[2]
steps {
sh "python deploy.py $env.DEPLOY_CONF_FILE $env.RIO_FLAG"
}
jenkins自动部署注意点
当前我的项目是这个:
所以${WORKSPACE}=/var/lib/jenkins/workspace/k8s-web-demo/
其git迁下来的代码在
WORKSPACE/ansible-jenkins-git-demo
mvn打包后的文件在
WORKSPACE/target/
jenkins:解决root无法su到jenkins用户
yum安装jenkins后root无法su到jenkins用户
cat /etc/passwd发jenkins用户后被yum安装设置为了/bin/false
sudo vim /etc/passwd改为/bin/bash
再次su jenkins发现用户变为了-bash-4.1#
在该用户下编辑环境变量
vim ~/.bash_profile
加入:
export PS1=’[\u@\h \W]$’
使脚本生效:
source ~/.bash_profile
再次su jenkins,发现正常
安装jenkins
yum install -y java # 我的java路径为:/opt/jdk8/jdk1.8.0_152
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key
vi /etc/sysconfig/jenkins 可在里面修改jenkins端口号
关闭防火墙
systemctl stop firewalld.service
systemctl disable firewalld.service
启动jenkins
service jenkins start/stop/restart
安装maven
wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
yum -y install apache-maven
find / -name mvn
mvn --version
打印的结果里可以看到maven的安装路径:/opt/maven/apache-maven-3.6.3
vim /etc/maven/settings.xml 在mirrors节点下添加阿里镜像源
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
我的git路径为:/usr/bin/git
参考文章:https://www.jianshu.com/p/cc67d1740649
我自己创建的用户名密码是lmj/lmj,但是这个不是jenkins登陆linux的shell的用户,jenkins操作shell脚本的用户名身份是jenkins,它的权限比较低。
jenkins用户执行权限诸多问题
解决方案1:
Jenkins 安装好后,会自动创建一个 jenkins 用户。jenkins 在构建工程时,默认的权限是不够写入文件的。这时就需要把它的权限提升为root。
1.将 jenkins 账号加入到 root 组中。
gpasswd -a jenkins root
2.修改/etc/sysconfig/jenkins文件,添加如下配置。
JENKINS_USER=“root”
JENKINS_GROUP=“root”
3.重启 Jenkins
systemctl restart jenkins
4.验证
groups jenkins
查看jenkins是在哪个用户组,显示的是root。
解决方案2:
将所有自动部署的脚本项目啊等等都移动到/home/jenkins目录下操作
解决方案3:
遇到权限问题,就到linux上使用root登陆,然后执行权限不足的那段代码(比如创建文件夹),第一次需要半自动(人工参与),以后就可以完全自动化。
解决方案四:
使用su切换到jenkins,执行自动部署里面的shell脚本代码。遇到问题就手动解决。
还没有评论,来说两句吧...