基于Jenkins+K8S构建DevOps自动化运维管理平台
基于Jenkins+K8S构建DevOps自动化运维管理平台
目录
2.1 神州泰岳DevOps生态体系建设与实践-神州泰岳云资源运营事业部经理张凯分享
4.基于Jenkins+K8S+harbor+git等技术链助力DevOps在企业落地实践
4.1 神州泰岳k8s+DevOps+微服务生态体系建设与实践
5.基于Jenkins+k8s+Git+DockerHub等技术链构建企业级DevOps容器云平台
5.1.1 安装nfs服务,可以选择自己的任意一台机器,我选择的是k8s的控制节点xianchaomaster1
5.3.5 测试通过Jenkins部署应用发布到k8s开发环境、测试环境、生产环境
6. 基于Jenkins+k8s+Git+harbor构建DevOps容器云平台
2.Declarative pipeline和Scripted pipeline的比较
10、Jenkins+k8s+nexus+gitlab+harbor+sonarqube+springloud构建DevOps
11.5 Jenkins+k8s+nexus+sonarqube+harbor+gitlab构建DevOps
文档中的YAML文件配置直接复制粘贴可能存在格式错误,故实验中所需要的YAML文件以及本地包均打包至网盘
链接:https://pan.baidu.com/s/1x0J-1cIq-RN7Yyak6JZJ_Q
提取码:vqh5
1.k8s助力DevOps在企业落地实践
1.1 传统方式部署项目为什么发布慢,效率低?
1.2 上线一个功能,有多少时间被浪费了?
1.3 如何解决发布慢,效率低的问题呢?
1.5 什么是DevOps?
1.5.1 敏捷开发
提高开发效率,及时跟进用户需求,缩短开发周期。
敏捷开发包括编写代码和构建代码两个阶段,可以使用git或者svn来管理代码,用maven对代码进行构建
1.5.2 持续集成(CI)
持续集成强调开发人员提交了新代码之后,立刻自动的进行构建、(单元)测试。根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起。持续集成过程中很重视自动化测试验证结果,对可能出现的一些问题进行预警,以保障最终合并的代码没有问题。
常见的持续集成工具:
1. Jenkins
Jenkins是用Java语言编写的,是目前使用最多和最受欢迎的持续集成工具,使用Jenkins,可以自动监测到git或者svn存储库代码的更新,基于最新的代码进行构建,把构建好的源码或者镜像发布到生产环境。Jenkins还有个非常好的功能:它可以在多台机器上进行分布式地构建和负载测试
2. TeamCity
3. Travis CI
4. Go CD
5. Bamboo
6. GitLab CI
7. Codeship
它的好处主要有以下几点:
1)较早的发现错误:每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,哪个环节出现问题都可以较早的发现
2)快速的发现错误:每完成一部分代码的更新,就会把代码集成到主干中,这样就可以快速的发现错误,比较容易的定位错误
3)提升团队绩效:持续集成中代码更新速度快,能及时发现小问题并进行修改,使团队能创造出更好的产品
4)防止分支过多的偏离主干:经常持续集成,会使分支代码经常向主干更新,当单元测试失败或者出现bug,如果开发者需要在没有调试的情况下恢复仓库的代码到没有bug的状态,只有很小部分的代码会丢失
持续集成的目的是提高代码质量,让产品快速的更新迭代。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。
Martin Fowler说过,"持续集成并不能消除Bug,而是让它们非常容易发现和改正。"
互动:Martin Fowler是谁?
马丁·福勒
马丁·福勒是一个软件开发方面的著作者和国际知名演说家,专注于面向对象分析与设计,统一建模语言,领域建模,以及敏捷软件开发方法,包括极限编程。
与持续集成相关的还有持续交付和持续部署。
1.5.3 持续交付
持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」(production-like environments)中。交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。
如果所有的代码完成之后一起交付,会导致很多问题爆发出来,解决起来很麻烦,所以持续集成,也就是没更新一次代码,都向下交付一次,这样可以及时发现问题,及时解决,防止问题大量堆积。
1.5.4 持续部署
持续部署是指当交付的代码通过评审之后,自动部署到生产环境中。持续部署是持续交付的最高阶段。
Puppet,SaltStack和Ansible是这个阶段使用的流行工具。容器化工具在部署阶段也发挥着重要作用。 Docker和k8s是流行的工具,有助于在开发,测试和生产环境中实现一致性。 除此之外,k8s还可以实现自动扩容缩容等功能。
互动:举个例子,形象说明持续集成、持续交付、持续部署之间的关系
2.为什么大厂都在用DevOps?
2.1 神州泰岳DevOps生态体系建设与实践-神州泰岳云资源运营事业部经理张凯分享
传统软件服务企业的痛点?
解决之道:DevOps
本图摘自:张乐-《DevOps道法术器》
2.2 DevOps在金融行业的应用-张安全分享
标准的敏捷开发流程:
2.3 哪些企业在用DevOps?
2.4 DevOps在5G领域的的展望
3.K8S在DevOps中的核心作用
Docker和K8S的出现使DevOps变得更加普及,更加容易实现。在传统运维中我们服务时需要针对不同的环境去安装不同的版本,部署方式也杂、多。那么有了docker之后,一次构建、到处运行,我们只需要要构建一次镜像,那么只要有docker的主机,就可以基于镜像把应用跑起来。
互动:docker可以实现DevOps的这个思想,但是存在一个问题,什么问题呢?
在众多微服务中,我们每天可能需要去处理各种服务的崩溃,而服务间的依赖调用关系也及其复杂,这对我们解决问题带来了很大的复杂度。要很好的解决这个问题。我们就需要用到容器编排工具。
Kubernetes 的出现主宰了容器编排的市场,也进化了过去的运维方式,将开发与运维联系的更加紧密。而且让 DevOps 这一角色变得更加清晰,它是目前可用的很流行的容器解决方案之一。
3.1 自动化
敏捷开发->持续集成->持续交付->持续部署
3.2 多集群管理
可以根据客户需求对开发,测试,生产环境部署多套kubernetes集群,每个环境使用独立的物理资源,相互之间避免影响
3.3 多环境一致性
Kubernetes是基于docker的容器编排工具,因为容器的镜像是不可变的,所以镜像把 OS、业务代码、运行环境、程序库、目录结构都包含在内,镜像保存在我们的私有仓库,只要用户从我们提供的私有仓库拉取镜像,就能保证环境的一致性。
3.4 实时反馈和智能化报表
每次集成或交付,都会第一时间将结果通过多途径的方式反馈给你,也可以定制适合企业专用的报表平台。
4.基于Jenkins+K8S+harbor+git等技术链助力DevOps在企业落地实践
4.1 神州泰岳k8s+DevOps+微服务生态体系建设与实践
开发代码->提交代码到代码仓库->Jenkins调k8s API->动态生成Jenkins Slave Pod->Slave Pod拉取git上的代码->编译代码->打包镜像->推送镜像到镜像仓库harbor或者docker hub->通过k8s编排服务发布到测试、生产平台-> Slave Pod工作完成之后自动删除>通过Ingress发布服务
4.2 百度:基于k8s构建亿级PV流量的DevOps平台
功能图:
架构图:
4.3 发布应用到测试环境
4.4 发布应用到生产环境
4.5 整个DevOps流程图
5.基于Jenkins+k8s+Git+DockerHub等技术链构建企业级DevOps容器云平台
K8s版本:
[root@xianchaomaster1 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
xianchaomaster1 Ready control-plane,master 76d v1.23.1
xianchaonode1 Ready <none> 76d v1.23.1
jenkins版本:
最新版
5.1 安装Jenkins
5.1.1 安装nfs服务,可以选择自己的任意一台机器,我选择的是k8s的控制节点xianchaomaster1
(1)在xianchaomaster1和xianchaonode1上安装nfs服务
注意:如果已经安装过nfs,这个步骤可以忽略
[root@xianchaomaster1 ~]# yum install nfs-utils -y
[root@xianchaomaster1 ~]# systemctl start nfs
[root@xianchaomaster1 ~]# systemctl enable nfs
[root@xianchaonode1 ~]# yum install nfs-utils -y
[root@xianchaonode1 ~]# systemctl start nfs
[root@xianchaonode1 ~]# systemctl enable nfs
(2)在xianchaomaster1上创建一个nfs共享目录
[root@xianchaomaster1 ~]# mkdir /data/v2 -p
[root@xianchaomaster1 ~]# vim /etc/exports
/data/v1 *(rw,no_root_squash)
/data/v2 *(rw,no_root_squash)
#新增加一行/data/v2 *
#使配置文件生效
[root@xianchaomaster1 ~]# exportfs -arv
5.1.2 在kubernetes中部署jenkins
(1)创建名称空间
[root@xianchaomaster1 ~]# kubectl create namespace jenkins-k8s
(2)创建pv
#更新资源清单文件
[root@xianchaomaster1]# kubectl apply -f pv.yaml
#查看pv是否创建成功
[root@xianchaomaster1]# kubectl get pv
pv.yaml文件内容如下:
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins-k8s-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.40.180
path: /data/v2
(3)创建pvc
#更新资源清单文件
[root@xianchaomaster1]# kubectl apply -f pvc.yaml
#查看pvc是否创建成功
[root@xianchaomaster1]# kubectl get pvc -n jenkins-k8s
pvc.yaml文件内容如下:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: jenkins-k8s-pvc
namespace: jenkins-k8s
spec:
resources:
requests:
storage: 10Gi
accessModes:
- ReadWriteMany
(4)创建一个sa账号
[root@xianchaomaster1]# kubectl create sa jenkins-k8s-sa -n jenkins-k8s
(5)把上面的sa账号做rbac授权
[root@xianchaomaster1]# kubectl create clusterrolebinding jenkins-k8s-sa-cluster -n jenkins-k8s --clusterrole=cluster-admin --serviceaccount=jenkins-k8s:jenkins-k8s-sa
(6)通过deployment部署jenkins
[root@xianchaonode1 ~]# docker pull jenkins/jenkins:2.394
[root@xianchaonode1 ~]# docker save -o jenkins2.394 jenkins/jenkins:2.394
[root@xianchaonode1 ~]# ctr -n=k8s.io images import jenkins2.394
备注:jenkins安装的时候,每次镜像都要下载最新的,安装最新版jenkins,如何下载最新的镜像?
去dockerhub上按照我视频方式去获取
[root@xianchaonode1 ~]# docker load -i jenkins-slave-latest.tar.gz
[root@xianchaonode1 ~]# ctr -n=k8s.io images import jenkins-slave-latest.tar.gz
备注:jenkins-slave-latest.tar.gz这个里面封装的镜像是jenkins-slave-latest:v1,这个jenkins-slave-latest:v1镜像制作方法如下:
[root@xianchaomaster1]#cd /root/slave
[root@xianchaomaster1 slave]# cat dockerfile
FROM jenkins/jnlp-slave:4.13.3-1-jdk11
USER root
# 安装Docker
RUN apt-get update && apt-get install -y \
docker.io
# 将当前用户加入docker用户组
RUN usermod -aG docker jenkins
RUN curl -LO https://dl.k8s.io/release/stable.txt
RUN curl -LO https://dl.k8s.io/release/$(cat stable.txt)/bin/linux/amd64/kubectl
RUN chmod +x kubectl
RUN mv kubectl /usr/local/bin/
ENV DOCKER_HOST unix:///var/run/docker.sock
[root@xianchaomaster1 slave]# docker build -t=jenkins-slave-latest:v1 .
[root@xianchaomaster1 slave]# docker save -o jenkins-slave-latest.tar.gz jenkins-slave-latest:v1
#更新资源清单文件
[root@xianchaomaster1]# kubectl apply -f jenkins-deployment.yaml
#查看jenkins是否创建成功
[root@xianchaomaster1 jenkins]# kubectl get pods -n jenkins-k8s
NAME READY STATUS RESTARTS AGE
jenkins-74b4c59549-g5j9t 0/1 CrashLoopBackOff 3 67s
#看到jenkins-74b4c59549-g5j9t是CrashLoopBackOff状态,查看日志:
[root@xianchaomaster1]# kubectl logs jenkins-74b4c59549-g5j9t -n jenkins-k8s
日志信息显示:
touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
#报错显示没有权限操作/var/jenkins_home/copy_reference_file.log文件,解决办法如下:
[root@xianchaomaster1]# kubectl delete -f jenkins-deployment.yaml
[root@xianchaomaster1]# chown -R 1000.1000 /data/v2
[root@xianchaomaster1]# kubectl apply -f jenkins-deployment.yaml
#查看pod是否创建成功:
[root@xianchaomaster1]# kubectl get pods -n jenkins-k8s
显示如下,说明部署成功了:
NAME READY STATUS RESTARTS AGE
jenkins-74b4c59549-6xpnk 1/1 Running 0 66
jenkins-deployment.yaml文件内容如下:
kind: Deployment
apiVersion: apps/v1
metadata:
name: jenkins
namespace: jenkins-k8s
spec:
replicas: 1
selector:
matchLabels:
app: jenkins
template:
metadata:
labels:
app: jenkins
spec:
serviceAccount: jenkins-k8s-sa
containers:
- name: jenkins
image: jenkins/jenkins:2.394
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: web
protocol: TCP
- containerPort: 50000
name: agent
protocol: TCP
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
readinessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
volumeMounts:
- name: jenkins-volume
subPath: jenkins-home
mountPath: /var/jenkins_home
volumes:
- name: jenkins-volume
persistentVolumeClaim:
claimName: jenkins-k8s-pvc
(7)把jenkins前端加上service,提供外部网络访问
#更新资源清单文件
[root@xianchaomaster1]# kubectl apply -f jenkins-service.yaml
#查看service是否创建成功
[root@xianchaomaster1]# kubectl get svc -n jenkins-k8s
#通过上面可以看到service的8080端口在物理机映射的端口是30002
jenkins-service.yaml文件内容如下:
apiVersion: v1
kind: Service
metadata:
name: jenkins-service
namespace: jenkins-k8s
labels:
app: jenkins
spec:
selector:
app: jenkins
type: NodePort
ports:
- name: web
port: 8080
targetPort: web
nodePort: 30002
- name: agent
port: 50000
targetPort: agent
5.2 配置Jenkins
在浏览器访问jenkins的web界面:
http://192.168.40.180:30002/login?from=%2F
5.2.1 获取管理员密码
在nfs服务端,也就是我们的master1节点获取密码:
[root@xianchaomaster1 ~]# cat /data/v2/jenkins-home/secrets/initialAdminPassword
把上面获取到的密码拷贝到上面管理员密码下的方框里
点击继续,出现如下界面
5.2.2 安装插件
安装推荐的插件
插件安装好之后显示如下
5.2.3 创建第一个管理员用户
用户名和密码都设置成admin,线上环境需要设置成复杂的密码
修改好之后点击保存并完成,出现如下界面
点击保存并完成,出现如下界面
点击保存并完成,出现如下界面
点击开始使用Jenkins
5.3 测试jenkins的CI/CD
5.3.1 在Jenkins中安装kubernetes插件
(1)在jenkins中安装k8s插件
Manage Jnekins------>插件管理------>可选插件------>搜索kubernetes------>出现如下
选中kubernetes之后------>点击下面的直接安装------>安装之后选择重新启动jenkins---> http://192.168.40.180:30002/restart-->重启之后登陆jenkins,插件即可生效
(2)安装blueocean插件
Manage Jnekins------>插件管理------>可选插件------>搜索blueocean------>出现如下
选中BlueOcean之后------>点击下面的直接安装------>安装之后选择重新启动jenkins---> http://192.168.40.180:30002/restart-->重启之后登陆jenkins,插件即可生效
5.3.2 配置jenkins连接到我们存在的k8s集群
(1)访问http://192.168.40.180:30002/configureClouds/
新增一个云,在下拉菜单中选择kubernets并添加
(2)填写云kubernetes配置内容
名称: kubernetes
Kubernetes地址:
(3)测试jenkins和k8s是否可以通信
Kubernetes名称空间: jenkins-k8s-sa
点击连接测试,如果显示Connected to Kubernetes v1.23.1,说明测试成功,Jenkins可以和k8s进行通信
Jenkins地址:
http://jenkins-service.jenkins-k8s.svc.cluster.local:8080
5.3.3 配置pod-template
(1)配置pod template
添加Pod模板
点击Pod Template details
点击容器列表下的添加容器
名称:jnlp
Docker镜像:jenkins-slave-latest:v1
给上面的pod template添加卷
/var/run/docker.sock
/var/run/docker.sock
/root/.kube
/home/jenkins/.kube
[root@xianchaomaster1 ~]# scp -r /root/.kube/ xianchaonode1:/root/
在Service Account处输入jenkins-k8s-sa,这个sa就是我们最开始安装jenkins时的sa
上面配置好之后,Apply(应用)------>Save(保存)
5.3.4 添加自己的dockerhub凭据
首页------>系统管理àManage Credentials(管理凭据)------>点击Stores scoped to Jenkins下的第一行jenkins后的全局,显示如下
点击添加凭据,出现如下------>
username:xianchao
password:1989*****
ID:dockerhub
描述:随意写一段描述即可
上面改好之后选择确定即可
5.3.5 测试通过Jenkins部署应用发布到k8s开发环境、测试环境、生产环境
开发提交代码到代码仓库gitlab-àjenkins检测到代码更新-à调用k8s api在k8s中创建jenkins slave pod:
Jenkins slave pod拉取代码---à通过maven把拉取的代码进行构建成war包或者jar包--->上传代码到Sonarqube,进行静态代码扫描- -->基于war包构建docker image-->把镜像上传到harbor镜像仓库-->基于镜像部署应用到开发环境-->部署应用到测试环境--->部署应用到生产环境。
#下面在Pipeline Script输入的脚本内容在课件里面,大家可以找到
jenkins-pipeline-script.txt文件,复制里面内容到Pipeline Script
在k8s的控制节点创建名称空间:
[root@xianchaomaster1 ~]# kubectl create ns devlopment
[root@xianchaomaster1 ~]# kubectl create ns production
[root@xianchaomaster1 ~]# kubectl create ns qatest
回到首页:
开始创建一个新任务------>
输入一个任务名称:jenkins-variable-test-deploy------>
流水线------>
确定------>
在Pipeline script处输入如下内容
node('testhan') {
stage('Clone') {
echo "1.Clone Stage"
git url: "https://github.com/luckylucky421/jenkins-sample.git"
script {
build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
}
}
stage('Test') {
echo "2.Test Stage"
}
stage('Build') {
echo "3.Build Docker Image Stage"
sh "docker build -t xianchao/jenkins-demo:${build_tag} ."
}
stage('Push') {
echo "4.Push Docker Image Stage"
withCredentials([usernamePassword(credentialsId: 'dockerhub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
sh "docker login -u ${dockerHubUser} -p ${dockerHubPassword}"
sh "docker push xianchao/jenkins-demo:${build_tag}"
}
}
stage('Deploy to dev') {
echo "5. Deploy DEV"
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-dev.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-dev.yaml"
// sh "bash running-devlopment.sh"
sh "kubectl apply -f k8s-dev.yaml --validate=false"
}
stage('Promote to qa') {
def userInput = input(
id: 'userInput',
message: 'Promote to qa?',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "YES\nNO",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
if (userInput == "YES") {
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-qa.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-qa.yaml"
// sh "bash running-qa.sh"
sh "kubectl apply -f k8s-qa.yaml --validate=false"
sh "sleep 6"
sh "kubectl get pods -n qatest"
} else {
//exit
}
}
stage('Promote to pro') {
def userInput = input(
id: 'userInput',
message: 'Promote to pro?',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "YES\nNO",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
if (userInput == "YES") {
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-prod.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-prod.yaml"
// sh "bash running-production.sh"
sh "cat k8s-prod.yaml"
sh "kubectl apply -f k8s-prod.yaml --record --validate=false"
}
}
}
应用------>保存------>立即构建,在#1的Console Output可看到构建过程:
#在Console Output如果看到如下:
点击Input requested
点击继续
#上面可以看到已经把应用部署到dev环境了
#点击Input requested
点击继续
#通过上面可以看到把应用部署到了pro环境了
#验证是否在devlopment和production名称空间下有应用
[root@xianchaomaster1 ~]# kubectl get pods -n production
NAME READY STATUS RESTARTS AGE
jenkins-demo-784885d9c9-w6zlt 1/1 Running 0 60s
[root@xianchaomaster1 ~]# kubectl get pods -n devlopment
NAME READY STATUS RESTARTS AGE
jenkins-demo-784885d9c9-9wkcx 1/1 Running 0 5m38s
[root@xianchaomaster1 ~]# kubectl get pods -n qatest
NAME READY STATUS RESTARTS AGE
jenkins-demo-784885d9c9-wshpj 1/1 Running 0 3m56s
#通过上面可以看到jenkins对接k8s,可以把应用发布到k8s集群的开发、测试、生产环境了。
6. 基于Jenkins+k8s+Git+harbor构建DevOps容器云平台
需要有一台harbor服务,我的harbor安装在了192.168.40.182机器上
1.添加凭据
首页------>系统管理à管理凭据------>点击Stores scoped to Jenkins下的第一行jenkins,显示如下
点击这个全局凭据,出现如下------>
点击左侧的添加凭据,出现如下------>
username:admin
password:Harbor12345
ID:dockerharbor
描述:随意
上面改好之后选择确定即可
2.编写jenkins pipeline
因为镜像要上传到harbor私有镜像仓库,所以需要在harbor上创建一个项目,项目名称是jenkins-demo,如下所示:
上面项目创建成功之后,执行如下步骤:
#下面在Pipeline Script输入的脚本内容在课件里面,大家可以找到
jenkins-pipeline-harbor-script.txt文件,复制里面内容到Pipeline Script
新建一个任务------>输入一个任务名称处输入jenkins-harbor------>流水线------>确定------>在Pipeline script处输入如下内容
node('testhan') {
stage('Clone') {
echo "1.Clone Stage"
git url: "https://github.com/luckylucky421/jenkins-sample.git"
script {
build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
}
}
stage('Test') {
echo "2.Test Stage"
}
stage('Build') {
echo "3.Build Docker Image Stage"
sh "docker build -t 192.168.40.182/jenkins-demo/jenkins-demo:${build_tag} ."
}
stage('Push') {
echo "4.Push Docker Image Stage"
withCredentials([usernamePassword(credentialsId: 'dockerharbor', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
sh "docker login 192.168.40.182 -u ${dockerHubUser} -p ${dockerHubPassword}"
sh "docker push 192.168.40.182/jenkins-demo/jenkins-demo:${build_tag}"
}
}
stage('Deploy to dev') {
echo "5. Deploy DEV"
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-dev-harbor.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-dev-harbor.yaml"
// sh "bash running-devlopment.sh"
sh "kubectl apply -f k8s-dev-harbor.yaml --validate=false"
}
stage('Promote to qa') {
def userInput = input(
id: 'userInput',
message: 'Promote to qa?',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "YES\nNO",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
if (userInput == "YES") {
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-qa-harbor.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-qa-harbor.yaml"
// sh "bash running-qa.sh"
sh "kubectl apply -f k8s-qa-harbor.yaml --validate=false"
sh "sleep 6"
sh "kubectl get pods -n qatest"
} else {
//exit
}
}
stage('Promote to pro') {
def userInput = input(
id: 'userInput',
message: 'Promote to pro?',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "YES\nNO",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
if (userInput == "YES") {
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-prod-harbor.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-prod-harbor.yaml"
// sh "bash running-production.sh"
sh "cat k8s-prod-harbor.yaml"
sh "kubectl apply -f k8s-prod-harbor.yaml --record --validate=false"
}
}
}
应用------>保存------>立即构建即可,打开blue ocean会看到如下流程,可以手动点击确认
Jenkins实现k8s应用按照指定版本回滚
回到首页:
新建一个任务------>输入一个任务名称处输入jenkins-variable-test-deploy-rollout------>流水线------>确定------>在Pipeline script处输入如下内容
node('testhan') {
stage('git clone') {
git url: "https://github.com/luckylucky421/jenkins-rollout"
sh "ls -al"
sh "pwd"
}
stage('select env') {
def envInput = input(
id: 'envInput',
message: 'Choose a deploy environment',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "devlopment\nqatest\nproduction",
name: 'Env'
]
]
)
echo "This is a deploy step to ${envInput}"
sh "sed -i 's/<namespace>/${envInput}/' getVersion.sh"
sh "sed -i 's/<namespace>/${envInput}/' rollout.sh"
sh "bash getVersion.sh"
// env.WORKSPACE = pwd()
// def version = readFile "${env.WORKSPACE}/version.csv"
// println version
}
stage('select version') {
env.WORKSPACE = pwd()
def version = readFile "${env.WORKSPACE}/version.csv"
println version
def userInput = input(id: 'userInput',
message: '选择回滚版本',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "$version\n",
name: 'Version'
]
]
)
sh "sed -i 's/<version>/${userInput}/' rollout.sh"
}
stage('rollout deploy') {
sh "bash rollout.sh"
}
}
点击应用->保存-立即构建
7. Jenkins Pipeline语法介绍
7.1 Jenkins Pipeline介绍
Jenkins pipeline (流水线)是一套运行于jenkins上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排与可视化。它把持续提交流水线(Continuous Delivery Pipeline)的任务集成到Jenkins中。
pipeline 是jenkins2.X 最核心的特性, 帮助jenkins 实现从CI到CD与DevOps的转变。
持续提交流水线(Continuous Delivery Pipeline)会经历一个复杂的过程: 从版本控制、向用户和客户提交软件,软件的每次变更(提交代码到仓库)到软件发布(Release)。这个过程包括以一种可靠并可重复的方式构建软件,以及通过多个测试和部署阶段来开发构建好的软件(称为Build)。
总结:
1.Jenkins Pipeline是一组插件,让Jenkins可以实现持续交付管道的落地和实施。
2.持续交付管道(CD Pipeline)是将软件从版本控制阶段到交付给用户或客户的完
整过程的自动化表现。
3.软件的每一次更改(提交到源代码管理系统)都要经过一个复杂的过程才能被发布。
7.2 为什么用Jenkins Pipeline?
本质上,Jenkins 是一个自动化引擎,它支持许多自动模式。 Pipeline向Jenkins中添加了一组强大的工具, 支持简单的CI到全面的CD pipeline。通过对一系列的相关任务进行建模, 用户可以利用pipeline的很多特性:
1、代码:Pipeline以代码的形式实现,使团队能够编辑,审查和迭代其CD流程。
2、可持续性:Jenkins重启或者中断后都不会影响Pipeline Job。
3、停顿:Pipeline可以选择停止并等待人工输入或批准,然后再继续Pipeline运行。
4、多功能:Pipeline支持现实复杂的CD要求,包括循环和并行执行工作的能力。
5、可扩展:Pipeline插件支持其DSL的自定义扩展以及与其他插件集成的多个选项。
DSL 是什么?
DSL 其实是 Domain Specific Language 的缩写,中文翻译为领域特定语言(下简称 DSL);而与 DSL相对的就是GPL,这里的GPL并不是我们知道的开源许可证,而是 General Purpose Language的简称,即通用编程语言,也就是我们非常熟悉的 Objective-C、Java、Python 以及 C 语言等等。
7.3 Jenkins pipeline 入门
pipeline脚本是由groovy 语言实现的
但无需专门学习 groovy
pipeline支持两种语法:
-Declarative:声明式
-Scripted pipeline :脚本式
声明式pipeline语法:
官网:
https://www.jenkins.io/doc/book/pipeline/syntax/
声明式语法包括以下核心流程:
1.pipeline : 声明其内容为一个声明式的pipeline脚本
2.agent: 执行节点(job运行的slave或者master节点)
3.stages: 阶段集合,包裹所有的阶段(例如:打包,部署等各个阶段)
4.stage: 阶段,被stages包裹,一个stages可以有多个stage
5.steps: 步骤,为每个阶段的最小执行单元,被stage包裹
6.post: 执行构建后的操作,根据构建结果来执行对应的操作
根据上面流程创建一个简单的pipeline
pipeline{
agent any
stages{
stage("This is first stage"){
steps("This is first step"){
echo "I am xianchao"
}
}
}
post{
always{
echo "The process is ending"
}
}
}
Pipeline:
作用域:应用于全局最外层,表明该脚本为声明式pipeline
是否必须:必须
agent:
作用域:可用在全局与stage内
agent表明此pipeline在哪个节点上执行
是否必须:是
参数:any,none, label, node,docker,dockerfile
agent any
#运行在任意的可用节点上
agent none
#全局不指定运行节点,由各自stage来决定
agent { label 'master' }
#运行在指定标签的机器上,具体标签名称由agent配置决定
agent {
node {
label 'my-defined-label'
customWorkspace 'xxxxxxx'
}
}
#node{ label 'master'} 和agent { label 'master' }一样,但是node可以扩展节点信息,允许额外的选项 (比如 customWorkspace )。
agent { docker 'python' }
#使用指定的容器运行流水线
如:
agent {
docker {
image 'maven:3-alpine'
label 'my-defined-label'
args '-v /tmp:/tmp'
}
}
#定义此参数时,执行Pipeline或stage时会动态的在具有label 'my-defined-label'标签的node提供docker节点去执行Pipelines。 docker还可以接受一个args,直接传递给docker run调用。
agent {
// Equivalent to "docker build -f Dockerfile.build --build-arg version=1.0.2 ./build/
dockerfile {
filename 'Dockerfile.build'
dir 'build'
label 'my-defined-label'
additionalBuildArgs '--build-arg version=1.0.2'
}
}
7.4 Pipeline 声明式语法Declarative
7.4.1 environment
environment指令指定一系列键值对,这些键值对将被定义为所有step或stage-specific step的环境变量,具体取决于environment指令在Pipeline中的位置。该指令支持一种特殊的方法credentials(),可以通过其在Jenkins环境中的标识符来访问预定义的凭据。对于类型为“Secret Text”的凭据,该 credentials()方法将确保指定的环境变量包含Secret Text内容;对于“标准用户名和密码”类型的凭证,指定的环境变量将被设置为username:password并且将自动定义两个附加的环境变量:MYVARNAME_USR和MYVARNAME_PSW。
pipeline {
agent any
environment {
CC = 'clang'
}
stages {
stage('Example') {
steps {
sh 'printenv'
}
}
}
}
7.4.2 options
options指令允许在Pipeline本身内配置Pipeline专用选项。Pipeline本身提供了许多选项,例如buildDiscarder,但它们也可能由插件提供,例如 timestamps。
可用选项
buildDiscarder: pipeline保持构建的最大个数。用于保存Pipeline最近几次运行的数据,例如:options { buildDiscarder(logRotator(numToKeepStr: '1')) }
disableConcurrentBuilds: 不允许并行执行Pipeline,可用于防止同时访问共享资源等。例如:options { disableConcurrentBuilds() }
skipDefaultCheckout:跳过默认设置的代码check out。例如:options { skipDefaultCheckout() }
skipStagesAfterUnstable: 一旦构建状态进入了“Unstable”状态,就跳过此stage。例如:options { skipStagesAfterUnstable() }
timeout: 设置Pipeline运行的超时时间,超过超时时间,job会自动被终止,例如:options { timeout(time: 1, unit: 'HOURS') }
retry: 失败后,重试整个Pipeline的次数。例如:options { retry(3) }
timestamps: 预定义由Pipeline生成的所有控制台输出时间。例如:options { timestamps() }
pipeline {
agent any
options {
timeout(time: 1, unit: 'HOURS')
}
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
7.4.3 parameters
parameters指令提供用户在触发Pipeline时的参数列表。这些参数值通过该params对象可用于Pipeline stage中,具体用法如下:
作用域:被最外层pipeline所包裹,并且只能出现一次,参数可被全局使用
好处:使用parameters好处是能够使参数也变成code,达到pipeline as code,pipeline中设置的参数会自动在job构建的时候生成,形成参数化构建
可用参数
string
A parameter of a string type, for example: parameters { string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '') }
booleanParam
A boolean parameter, for example: parameters { booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '') }
目前只支持[booleanParam, choice, credentials, file, text, password, run, string]这几种参数类型,其他高级参数化类型还需等待社区支持。
pipeline{
agent any
parameters {
string(name: 'xianchao', defaultValue: 'my name is xianchao', description: 'My name is xiancaho')
booleanParam(name: 'luckylucky421302', defaultValue: true, description: 'This is my wechat')
}
stages{
stage("stage1"){
steps{
echo "$xianchao"
echo "$luckylucky421302"
}
}
}
}
开始构建
控制台输出观察构建结果:
7.4.4 triggers
triggers指令定义了Pipeline自动化触发的方式。目前有三个可用的触发器:cron和pollSCM和upstream。
用域:被pipeline包裹,在符合条件下自动触发pipeline
cron
接受一个cron风格的字符串来定义Pipeline触发的时间间隔,例如:
triggers { cron('H 4/* 0 0 1-5') }
pollSCM
接受一个cron风格的字符串来定义Jenkins检查SCM源更改的常规间隔。如果存在新的更改,则Pipeline将被重新触发。例如:triggers { pollSCM('H 4/* 0 0 1-5') }
pipeline {
agent any
triggers {
cron('H 4/* 0 0 1-5')
}
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
7.4.5 tools
通过tools可自动安装工具,并放置环境变量到PATH。如果agent none,这将被忽略。
Supported Tools(Global Tool Configuration)
maven
jdk
gradle
pipeline {
agent any
tools {
#工具名称必须在Jenkins 管理Jenkins → 全局工具配置中预配置。
maven 'apache-maven-3.0.1'
}
stages {
stage('Example') {
steps {
sh 'mvn --version'
}
}
}
}
# The tool name must be pre-configured in Jenkins under Manage Jenkins → Global Tool Configuration
7.4.6 input
stage 的 input 指令允许你使用 input step提示输入。 在应用了 options 后,进入 stage 的 agent 或评估 when 条件前,stage 将暂停。 如果 input 被批准, stage 将会继续。 作为 input 提交的一部分的任何参数都将在环境中用于其他 stage
配置项
message
必需的。 这将在用户提交 input 时呈现给用户。
id
input 的可选标识符, 默认为 stage 名称。
ok
`input`表单上的"ok" 按钮的可选文本。
submitter
可选的以逗号分隔的用户列表或允许提交 input 的外部组名。默认允许任何用户。
submitterParameter
环境变量的可选名称。如果存在,用 submitter 名称设置。
parameters
提示提交者提供的一个可选的参数列表。
pipeline {
agent any
stages {
stage('Example') {
input {
message "Should we continue?"
ok "Yes, we should."
submitter "xianchao,lucky"
parameters {
string(name: 'PERSON', defaultValue: 'xianchao', description: 'Who should I say hello to?')
}
}
steps {
echo "Hello, ${PERSON}, nice to meet you."
}
}
}
}
7.4.7 when
when指令允许Pipeline根据给定的条件确定是否执行该阶段。该when指令必须至少包含一个条件。如果when指令包含多个条件,则所有子条件必须为stage执行返回true。这与子条件嵌套在一个allOf条件中相同(见下面的例子)。
更复杂的条件结构可使用嵌套条件建:not,allOf或anyOf。嵌套条件可以嵌套到任意深度。
内置条件
branch
当正在构建的分支与给出的分支模式匹配时执行,例如:when { branch 'master' }。请注意,这仅适用于多分支Pipeline。
environment
当指定的环境变量设置为给定值时执行,例如: when { environment name: 'DEPLOY_TO', value: 'production' }
expression
当指定的Groovy表达式求值为true时执行,例如: when { expression { return params.DEBUG_BUILD } }
not
当嵌套条件为false时执行。必须包含一个条件。例如:when { not { branch 'master' } }
allOf
当所有嵌套条件都为真时执行。必须至少包含一个条件。例如:when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } }
anyOf
当至少一个嵌套条件为真时执行。必须至少包含一个条件。例如:when { anyOf { branch 'master'; branch 'staging' } }
pipeline {
agent any
stages {
stage('Example Build') {
steps {
echo 'Hello World'
}
}
stage('Example Deploy') {
when {
allOf {
branch 'production'
environment name: 'DEPLOY_TO', value: 'production'
}
}
steps {
echo 'Deploying'
}
}
}
}
7.4.8 Parallel
Declarative Pipeline近期新增了对并行嵌套stage的支持,对耗时长,相互不存在依赖的stage可以使用此方式提升运行效率。除了parallel stage,单个parallel里的多个step也可以使用并行的方式运行。
pipeline {
agent any
stages {
stage('Non-Parallel Stage') {
steps {
echo 'This stage will be executed first.'
}
}
stage('Parallel Stage') {
when {
branch 'master'
}
parallel {
stage('Branch A') {
agent {
label "for-branch-a"
}
steps {
echo "On Branch A"
}
}
stage('Branch B') {
agent {
label "for-branch-b"
}
steps {
echo "On Branch B"
}
}
}
}
}
}
7.5 Pipeline Scripted语法
Groovy脚本不一定适合所有使用者,因此jenkins创建了Declarative pipeline,为编写Jenkins管道提供了一种更简单、更有主见的语法。但是由于脚本化的pipeline是基于groovy的一种DSL语言,所以与Declarative pipeline相比为jenkins用户提供了更巨大的灵活性和可扩展性。
1.流程控制
pipeline脚本同其它脚本语言一样,从上至下顺序执行,它的流程控制取决于Groovy表达式,如if/else条件语句,举例如下:
node {
stage('Example') {
if (env.BRANCH_NAME == 'master') {
echo 'I only execute on the master branch'
} else {
echo 'I execute elsewhere'
}
}
}
2.Declarative pipeline和Scripted pipeline的比较
共同点:
两者都是pipeline代码的持久实现,都能够使用pipeline内置的插件或者插件提供的stage,两者都可以利用共享库扩展。
区别:
两者不同之处在于语法和灵活性。Declarative pipeline对用户来说,语法更严格,有固定的组织结构,更容易生成代码段,使其成为用户更理想的选择。但是Scripted pipeline更加灵活,因为Groovy本身只能对结构和语法进行限制,对于更复杂的pipeline来说,用户可以根据自己的业务进行灵活的实现和扩展。
8、jenkins+k8s+harbor实现DevOps
1.添加凭据
首页------>系统管理à管理凭据------>点击Stores scoped to Jenkins下的第一行jenkins,显示如下
点击这个全局凭据,出现如下------>
点击左侧的添加凭据,出现如下------>
username:admin
password:Harbor12345
ID:dockerharbor
描述:随意
上面改好之后选择确定即可
2.编写jenkins pipeline
因为镜像要上传到harbor私有镜像仓库,所以需要在harbor上创建一个项目,项目名称是jenkins-demo,如下所示:
上面项目创建成功之后,执行如下步骤:
新建一个任务------>输入一个任务名称处输入jenkins-harbor------>流水线------>确定------>在Pipeline script处输入如下内容
node('testhan') {
stage('Clone') {
echo "1.Clone Stage"
git url: "https://github.com/luckylucky421/jenkins-sample.git"
script {
build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
}
}
stage('Test') {
echo "2.Test Stage"
}
stage('Build') {
echo "3.Build Docker Image Stage"
sh "docker build -t 192.168.40.132/jenkins-demo/jenkins-demo:${build_tag} ."
}
stage('Push') {
echo "4.Push Docker Image Stage"
withCredentials([usernamePassword(credentialsId: 'dockerharbor', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
sh "docker login 192.168.40.132 -u ${dockerHubUser} -p ${dockerHubPassword}"
sh "docker push 192.168.40.132/jenkins-demo/jenkins-demo:${build_tag}"
}
}
stage('Deploy to dev') {
echo "5. Deploy DEV"
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-dev-harbor.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-dev-harbor.yaml"
// sh "bash running-devlopment.sh"
sh "kubectl apply -f k8s-dev-harbor.yaml --validate=false"
}
stage('Promote to qa') {
def userInput = input(
id: 'userInput',
message: 'Promote to qa?',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "YES\nNO",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
if (userInput == "YES") {
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-qa-harbor.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-qa-harbor.yaml"
// sh "bash running-qa.sh"
sh "kubectl apply -f k8s-qa-harbor.yaml --validate=false"
sh "sleep 6"
sh "kubectl get pods -n qatest"
} else {
//exit
}
}
stage('Promote to pro') {
def userInput = input(
id: 'userInput',
message: 'Promote to pro?',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "YES\nNO",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
if (userInput == "YES") {
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-prod-harbor.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-prod-harbor.yaml"
// sh "bash running-production.sh"
sh "cat k8s-prod-harbor.yaml"
sh "kubectl apply -f k8s-prod-harbor.yaml --record --validate=false"
}
}
}
应用------>保存------>立即构建即可,打开blue ocean会看到如下流程,可以手动点击确认
9、Jenkins接入Sonarqube
1.在192.168.40.180上安装sonarqube:
docker run -d --name postgres10 -p 5432:5432 -e POSTGRES_USER=sonar -e POSTGRES_PASSWORD=123456 postgres
docker run -d --name sonarqube7.9 -p 9000:9000 --link postgres10 -e SONARQUBE_JDBC_URL=jdbc:postgresql://postgres10:5432/sonar -e SONARQUBE_JDBC_USERNAME=sonar -e SONARQUBE_JDBC_PASSWORD=123456 -v sonarqube_conf:/opt/sonarqube/conf -v sonarqube_extensions:/opt/sonarqube/extensions -v sonarqube_logs:/opt/sonarqube/logs -v sonarqube_data:/opt/sonarqube/data sonarqube
在jenkins中安装sonarqube插件:
系统管理->插件管理->可选插件:搜索sonar,找到Sonarqube Scanner
选择Sonarqube Scanner直接安装,安装之后重启jenkins即可
在sonarqube的web界面创建一个token:
选择Generate出现如下:
把copy后面的一串token记录下来:
2b91be9d40a28385d8b2f61b0fc0a52efd5abf97
回到k8s的master1节点:
cd /root/microservic-test
mvn sonar:sonar -Dsonar.host.url=http://192.168.40.181:9000 -Dsonar.login=2b91be9d40a28385d8b2f61b0fc0a52efd5abf97
这样就可以把代码上传到sonarqube了
10、Jenkins+k8s+nexus+gitlab+harbor+sonarqube+springloud构建DevOps
11.1 安装sonarqube
在192.168.40.131上操作:
docker run -d --name postgres10 -p 5432:5432 -e POSTGRES_USER=sonar -e POSTGRES_PASSWORD=123456 postgres
docker run -d --name sonarqube7.9 -p 9000:9000 --link postgres10 -e SONARQUBE_JDBC_URL=jdbc:postgresql://postgres10:5432/sonar -e SONARQUBE_JDBC_USERNAME=sonar -e SONARQUBE_JDBC_PASSWORD=123456 -v sonarqube_conf:/opt/sonarqube/conf -v sonarqube_extensions:/opt/sonarqube/extensions -v sonarqube_logs:/opt/sonarqube/logs -v sonarqube_data:/opt/sonarqube/data sonarqube
在jenkins中安装sonarqube插件:
系统管理->插件管理->可选插件:搜索sonar,找到Sonarqube Scanner->选择Sonarqube Scanner直接安装
安装之后重启jenkins即可
在sonarqube的web界面创建一个token:
选择Generate出现如下:
把copy后面的一串token记录下来:
2b91be9d40a28385d8b2f61b0fc0a52efd5abf97
回到k8s的控制节点:
cd /root/microservic-test
mvn sonar:sonar -Dsonar.host.url=http://192.168.40.131:9000 -Dsonar.login=2b91be9d40a28385d8b2f61b0fc0a52efd5abf97
这样就可以把代码上传到sonarqube了
注意:开发写的代码目前不支持这个版本的sonarqube,所以这个上传到sonarqube是有问题的,会报错版本不支持,结果大家可以不用看,会用就可以
11.2 Jenkins界面添加harbor凭据
需要自己找机器安装好harbor,harbor机器ip:192.168.40.132
1.添加凭据
首页------>系统管理à管理凭据------>点击Stores scoped to Jenkins下的第一行jenkins,显示如下
点击这个全局凭据,出现如下------>
点击左侧的添加凭据,出现如下------>
username:admin
password:Harbor12345
ID:dockerharbor
描述:随意
上面改好之后选择确定即可
11.3 安装nexus
概念:
Nexus服务器是一个代码包管理的服务器,可以理解 Nexus 服务器是一个巨大的 Library 仓库。Nexus 可以支持管理的工具包括 Maven , npm 等,对于 JAVA 开发来说,只要用到 Maven 管理就可以了。
Nexus服务器作用:因为传统的中央仓库在国外,其地理位置比较远,下载速度比较缓慢。因此,当公司开发人员数量越来越多时,如果不架设一台自己的Nexus服务器,会产生大量的流量阻塞带宽,并且在出现一些不可抗原因(光缆被挖断)导致无法连接到中央仓库时,开发就会因为无法下载相关依赖包而进度停滞。因此在本地环境部署一台私有的Nexus服务器来缓存所有依赖包,并且将公司内部开发的私有包也部署上去,方便其他开发人员下载,是非常有必要的。因为 Nexus 有权限控制,因此外部人员是无法得到公司内部开发的项目包的。
下面将介绍如何将自己的maven构件发布到nexus私服 上呢?
在192.168.40.133上安装:
docker run -d -p 8081:8081 -p 8082:8082 -p 8083:8083 -v /etc/localtime:/etc/localtime --name nexus3 sonatype/nexus3
在日志中,会看到一条消息: Started Sonatype Nexus OSS 3.20.1-01 这意味着Nexus Repository Manager可以使用了。现在转到浏览器并打开
第一步:
1、在 pom.xml 文件中声明发布的宿主仓库和 release 版本发布的仓库。
<!-- 发布构件到Nexus -->
<distributionManagement>
<repository>
<id>releases</id>
<name>nexus-releases</name>
<url>http://192.168.40.133:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>nexus-snapshots</name>
<url>http://192.168.40.133:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
第二步:在 settings.xml 文件中配置
由于用 Maven 分发构件到远程仓库需要认证,须要在~/.m2/settings.xml或者中加入验证信息:
<servers>
<server>
<id>public</id>
<username>admin</username>
<password>123456</password>
</server>
<server>
<id>releases</id>
<username>admin</username>
<password>123456</password>
</server>
<server>
<id>snapshots</id>
<username>admin</username>
<password>123456</password>
</server>
</servers>
注意: settings.xml 中 server 元素下 id 的值必须与 POM 中 repository 或 snapshotRepository 下 id 的值完全一致 。
11.4 安装gitlab
在192.168.40.135上安装
docker run -d -p 443:443 -p 80:80 -p 222:22 --name gitlab --restart always -v /home/gitlab/config:/etc/gitlab -v /home/gitlab/logs:/var/log/gitlab -v /home/gitlab/data:/var/opt/gitlab gitlab/gitlab-ce gitlab/gitlab-ce
改配置:
cat /home/gitlab/config/gitlab.rb
增加如下三行:
external_url 'http://192.168.40.135'
gitlab_rails['gitlab_ssh_host'] = '192.168.40.135'
gitlab_rails['gitlab_shell_ssh_port'] = 222
重启docker:
docker restart gitlab
登录192.168.40.135即可登录:
第一次登录注册账号密码之后,报错如下:
Your account is pending approval from your GitLab administrator and hence bl
可通过如下方法实现:
[root@xianchaomaster1 ~]# docker exec -it gitlab sh
irb(main):004:0> u=User.where(id:1).first
=> #<User id:1 @root>
irb(main):005:0> u.password='12345678'
=> "12345678"
irb(main):006:0> u.password_confirmation='12345678'
=> "12345678"
irb(main):007:0> u.save!
=> true
再次登录192.168.40.135
用户名是root
密码是12345678
# -d:后台运行
# -p:将容器内部端口向外映射
# --name:命名容器名称
# -v:将容器内数据文件夹或者日志、配置等文件夹挂载到宿主机指定目录
在Jenkins安装git插件
系统管理-插件管理-可选插件-搜索git安装即可
在Jenkins上添加gitlab凭据
Jenkins-凭据-全局凭据
在gitlab上新建项目:
创建密钥对:
[root@localhost ~]# ssh-keygen -t rsa
#一路回车
上传密钥:
[root@localhost ~]# cat ~/.ssh/id_rsa.pub #查看公钥
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8KZUe+PJykjZzJherolD+vXsw8/aL3OMyX/x1HF6Rz73dNZFCERQxA6t/9ahRrya8iY7IIloLjzi5iX666mzYI3fAEq1Ga3Dz2MWqEeWZGdbNKvL9lf0qTy0aLBIRe2fnQwrkrP2YakiqzDRpyjQgr05VkrnF5bVLX2HCHuC2GXwnHUAuJEkjb1f9vmII7YP0BmYDMOMpricQ1LeFnQ9cc2ZvPw6212yiXOrbhrbiMtjCYTPoRA8EIfmRAPcNcVl4GT3fZxAVocDk70rA/tEWCgu+zzFFH+aWhaIXMdkC70FEWLD28AxLWwwKj22KA9ezqp0eoxofzU3tSCIymVU9 root@localhost.localdomain
提交本地代码到gitlab:
[root@localhost ~]# yum install git -y
[root@localhost ~]# unzip microservic-test.zip
[root@localhost ~]# cd microservic-test
[root@localhost microservic-test]# git init #建仓
[root@localhost microservic-test]# git add * #把当前文件夹所有代码提交
[root@localhost microservic-test]# git commit -m "add microservic-test" #代码提交到缓冲区
[root@localhost microservic-test]# git remote add origin http://192.168.40.135/root/microservic-test.git
#代码提交到远程仓库
[root@localhost microservic-test]# git push -u origin master
#最后一步push推送过去,push的时候,会让你输入账号和密码,这里的用户名和密码就是gitlab上注册的用户了
回到gitlab首页,可以看到,已经有项目了:
11.5 Jenkins+k8s+nexus+sonarqube+harbor+gitlab构建DevOps
jenkins-jnlp-v2.tar.gz这个压缩包封装的镜像带有mvn命令
[root@xianchaonode1 ~]# docker load -i jenkins-jnlp-v2.tar.gz
在http://192.168.40.180:30002/configureClouds/,把Container Template镜像改成jenkins-jnlp-v2.tar.gz压缩包解压之后的镜像xianchao/jenkins-jnlp:v2
修改gitlab上portal.yaml文件:
把image镜像变成:192.168.40.132/microservice/jenkins-demo:v1
注意:microservice需要在harbor里提前创建这个仓库
打开Jenkins,新建流水线,流水线名字是mvn-gitlab-harbor-springcloud
在Pipeline Script处输入如下内容:
node('testhan') {
stage('Clone') {
echo "1.Clone Stage"
git credentialsId: 'gitlab', url: 'http://192.168.40.135/root/microservic-test.git '
script {
build_tag = sh(returnStdout: true, script: 'git rev-parse --shortHEAD').trim()
}
}
stage('Test') {
echo "2.Test Stage"
}
stage('mvn') {
sh "mvn clean package -D maven.test.skip=true"
}
stage('Build') {
echo "3.Build Docker Image Stage"
sh "cd /home/jenkins/agent/workspace/mvn-gitlab-harbor-springcloud/portal-service"
sh "docker build --tag 192.168.40.132/microservice/jenkins-demo:v1 /home/jenkins/agent/workspace/mvn-gitlab-harbor-springcloud/portal-service/"
}
stage('Push') {
echo "4.Push Docker Image Stage"
withCredentials([usernamePassword(credentialsId: 'dockerharbor',passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
sh "docker login 192.168.40.132 -u ${dockerHubUser} -p ${dockerHubPassword}"
sh "docker push 192.168.40.132/microservice/jenkins-demo:v1"
}
}
stage('Promoteto pro') {
sh "kubectl apply -f /home/jenkins/agent/workspace/mvn-gitlab-harbor-springcloud/k8s/portal.yaml"
}
}
立即构建即可
注意事项:
url: http://192.168.40.135/root/microservic-test.git
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)