目录

1.k8s助力DevOps在企业落地实践

1.1 传统方式部署项目为什么发布慢,效率低?

1.2 上线一个功能,有多少时间被浪费了?

1.3 如何解决发布慢,效率低的问题呢?

1.5 什么是DevOps?

1.5.1 敏捷开发

1.5.2 持续集成(CI)

1.5.3 持续交付

1.5.4 持续部署

2.为什么大厂都在用DevOps?

2.1 神州泰岳DevOps生态体系建设与实践-神州泰岳云资源运营事业部经理张凯分享

2.2 DevOps在金融行业的应用-张安全分享

2.3 哪些企业在用DevOps?

2.4 DevOps在5G领域的的展望

3.K8S在DevOps中的核心作用

3.1 自动化

3.2 多集群管理

3.3 多环境一致性

3.4 实时反馈和智能化报表

4.基于Jenkins+K8S+harbor+git等技术链助力DevOps在企业落地实践

4.1 神州泰岳k8s+DevOps+微服务生态体系建设与实践

4.2 百度:基于k8s构建亿级PV流量的DevOps平台 

4.3 发布应用到测试环境

4.5 整个DevOps流程图

5.基于Jenkins+k8s+Git+DockerHub等技术链构建企业级DevOps容器云平台

5.1 安装Jenkins

5.1.1 安装nfs服务,可以选择自己的任意一台机器,我选择的是k8s的控制节点xianchaomaster1

5.1.2 在kubernetes中部署jenkins

5.2 配置Jenkins

5.2.1 获取管理员密码

5.2.2 安装插件

5.3 测试jenkins的CI/CD

5.3.1 在Jenkins中安装kubernetes插件

5.3.2 配置jenkins连接到我们存在的k8s集群

5.3.3 配置pod-template

5.3.4 添加自己的dockerhub凭据

5.3.5 测试通过Jenkins部署应用发布到k8s开发环境、测试环境、生产环境

6.  基于Jenkins+k8s+Git+harbor构建DevOps容器云平台

Jenkins实现k8s应用按照指定版本回滚

7. Jenkins Pipeline语法介绍

7.1 Jenkins Pipeline介绍

7.2 为什么用Jenkins Pipeline?

7.3 Jenkins pipeline 入门

7.4 Pipeline 声明式语法Declarative

7.4.1 environment

7.4.2 options

7.4.3 parameters

7.4.4 triggers

7.4.5 tools

7.4.6   input

7.4.7 when

7.4.8 Parallel

7.5 Pipeline Scripted语法

1.流程控制

2.Declarative pipeline和Scripted pipeline的比较

8、jenkins+k8s+harbor实现DevOps

9、Jenkins接入Sonarqube

10、Jenkins+k8s+nexus+gitlab+harbor+sonarqube+springloud构建DevOps

11.1 安装sonarqube

11.2  Jenkins界面添加harbor凭据

11.3 安装nexus

11.4 安装gitlab

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-g5j9tCrashLoopBackOff状态,查看日志:

[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地址:

https://192.168.40.180:6443

(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_USRMYVARNAME_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和pollSCMupstream。

用域:被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会看到如下流程,可以手动点击确认

9Jenkins接入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可以使用了。现在转到浏览器并打开

http://your-ip-addr:8081

第一步:

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

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐