1、k8s助力企业DevOps在企业落地实践 1.1 传统方式部署项目为什么发布慢,效率低?
1.2 上线一个功能,有多少时间被浪费了
1.3 如何解决上述问题
1.3 什么是DevOps
1.3.1 敏捷开发 提高开发效率,及时跟进用户需求,缩短开发周期。
敏捷开发包括编写代码和构建代码两个阶段,可以使用git或者svn来管理代码,用maven对代码进行构建
1.3.2 持续集成 持续集成强调开发人员提交了新代码之后,立刻自动的进行构建、(单元)测试。根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起。持续集成过程中很重视自动化测试验证结果,对可能出现的一些问题进行预警,以保障最终合并的代码没有问题。
常见的持续集成工具:
Jenkins
Jenkins是用Java语言编写的,是目前使用最多和最受欢迎的持续集成工具,使用Jenkins,可以自动监测到git或者svn存储库代码的更新,基于最新的代码进行构建,把构建好的源码或者镜像发布到生产环境。Jenkins还有个非常好的功能:它可以在多台机器上进行分布式地构建和负载测试
TeamCity
Travis CI
Go CD
Bamboo
GitLab CI
Codeship
它的好处主要有以下几点:
1)较早的发现错误:每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,哪个环节出现问题都可以较早的发现
2)快速的发现错误:每完成一部分代码的更新,就会把代码集成到主干中,这样就可以快速的发现错误,比较容易的定位错误
3)提升团队绩效:持续集成中代码更新速度快,能及时发现小问题并进行修改,使团队能创造出更好的产品
4)防止分支过多的偏离主干:经常持续集成,会使分支代码经常向主干更新,当单元测试失败或者出现bug,如果开发者需要在没有调试的情况下恢复仓库的代码到没有bug的状态,只有很小部分的代码会丢失
持续集成的目的是提高代码质量,让产品快速的更新迭代。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。
Martin Fowler说过,”持续集成并不能消除Bug,而是让它们非常容易发现和改正。”
马丁·福勒是一个软件开发方面的著作者和国际知名演说家,专注于面向对象分析与设计,统一建模语言,领域建模,以及敏捷软件开发方法,包括极限编程。
1.3.3 持续交付 持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」(production-like environments)中。交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。
如果所有的代码完成之后一起交付,会导致很多问题爆发出来,解决起来很麻烦,所以持续集成,也就是没更新一次代码,都向下交付一次,这样可以及时发现问题,及时解决,防止问题大量堆积。
1.3.4 持续部署 持续部署是指当交付的代码通过评审之后,自动部署到生产环境中。持续部署是持续交付的最高阶段。
Puppet,SaltStack和Ansible是这个阶段使用的流行工具。容器化工具在部署阶段也发挥着重要作用。 Docker和k8s是流行的工具,有助于在开发,测试和生产环境中实现一致性。 除此之外,k8s还可以实现自动扩容缩容等功能。
2、K8S在DevOps中的核心作用 Docker和K8S的出现使DevOps变得更加普及,更加容易实现。在传统运维中我们服务时需要针对不同的环境去安装不同的版本,部署方式也杂、多。那么有了docker之后,一次构建、到处运行,我们只需要要构建一次镜像,那么只要有docker的主机,就可以基于镜像把应用跑起来。
互动:docker可以实现DevOps的这个思想,但是存在一个问题,什么问题呢?
在众多微服务中,我们每天可能需要去处理各种服务的崩溃,而服务间的依赖调用关系也及其复杂,这对我们解决问题带来了很大的复杂度。要很好的解决这个问题。我们就需要用到容器编排工具。
Kubernetes 的出现主宰了容器编排的市场,也进化了过去的运维方式,将开发与运维联系的更加紧密。而且让 DevOps 这一角色变得更加清晰,它是目前可用的很流行的容器解决方案之一。
2.1 自动化 敏捷开发->持续集成->持续交付->持续部署
2.2 多集群管理 可以根据客户需求对开发、测试,生产环江部署多套kubernetes集群,每个环境使用独立的物理资源,避免相互之间互相影响
2.3 多环境一致性 Kubernetes是基于docker的容器编排工具,因为容器的镜像是不可变的,所以镜像把OS、业务代码、运行环境、程序库、目录结构都包含在内,镜像保存在我们的私有仓库,只要用户从我们提供的私有仓库拉取镜像,就能保证环境的一致性。
2.4 实时反馈和智能化报表 每次集成或交付,都会第一时间将结果通过多途径的方式反馈给你,也可以定制适合企业专用的报表平台。
3、安装Jenkins 3.1 安装和配置nfs 1 2 3 4 yum install nfs-utils -y exportfs -arv exporting *:/root/nfs_data chown 1000:1000 -R nfs_data/
3.2 创建名称空间 1 2 [root@master1 ~] namespace/jenkins-k8s created
3.3 创建pv 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@master1 k8s_jenkins] apiVersion: v1 kind: PersistentVolume metadata: name: jenkins-k8s-pv spec: capacity: storage: 10Gi accessModes: - ReadWriteMany nfs: server: 192.168.106.30 path: /root/nfs_data/ [root@master1 k8s_jenkins] persistentvolume/jenkins-k8s-pv created [root@master1 k8s_jenkins] jenkins-k8s-pv 10Gi RWX Retain Available 108s
3.4 创建pvc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@master1 k8s_jenkins] apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jenkins-k8s-pvc namespace: jenkins-k8s spec: accessModes: - ReadWriteMany resources: requests: storage: 10Gi [root@master1 k8s_jenkins] persistentvolumeclaim/jenkins-k8s-pvc created
3.5 创建一个sa账号 1 2 [root@master1 k8s_jenkins] serviceaccount/jenkins-k8s-sa created
3.6 授权新创建的sa账号 1 2 [root@master1 k8s_jenkins] clusterrolebinding.rbac.authorization.k8s.io/jenkins-k8s-sa-cluster created
3.7 通过deployment部署Jenkins 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 [root@master1 k8s_jenkins] 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.328 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 name: web protocol: TCP - containerPort: 50000 name: agent protocol: TCP resources: limits: cpu: 2000m memory: 2Gi 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 [root@master1 k8s_jenkins] deployment.apps/jenkins created chown 1000:1000 -R nfs_data/ [root@master1 k8s_jenkins] NAME READY STATUS RESTARTS AGE jenkins-99fd4d66f-2v5m4 1/1 Running 0 2m8s
3.8 创建Jenkins的svc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [root@master1 k8s_jenkins] 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 [root@master1 k8s_jenkins] service/jenkins-service created
3.9 登录Jenkins web界面 1 2 /var/jenkins_home/secrets/initialAdminPassword 8e789fe428d0400f9f6aa72555eb615a
3.10 在jenkins中安装kuberbetes、blueocean插件
3.11 配置jenkins访问k8s集群
点击连接测试,如果显示Connection test successful或者Connected to Kubernetes v1.20.6,说明测试成功,Jenkins可以和k8s进行通信
1 http://jenkins-service.jenkins-k8s.svc.cluster.local:8080
配置k8s集群的时候jenkins地址需要写上面域名的形式,配置之后执行如下:
应用——>保存
3.12 配置pod-template 1 http://192.168.106.23:30002/configureClouds/
在上面的pod template下添加容器
添加容器——>Container Template——>按如下配置——>
在每一个pod template右下脚都有一个高级,点击高级
在Service Account处输入jenkins-k8s-sa,这个sa就是我们最开始安装jenkins时的sa
(3)给上面的pod template添加卷
添加卷——>选择Host Path Volume
/var/run/docker.sock
/var/run/docker.sock
/root/.kube
/home/jenkins/.kube
上面配置好之后,Apply(应用)——>Save(保存)
添加自己的dockerhub凭据
首页——>系统管理àManage Credentials(管理凭据)——>点击Stores scoped to Jenkins下的第一行jenkins后的全局,显示如下
3.13 测试通过Jenkins部署应用发布到k8s开发环境、测试环境、生产环境 开发提交代码到代码仓库gitlab->jenkins检测到代码更新-à调用k8s api在k8s中创建jenkins slave pod:
Jenkins slave pod拉取代码—à通过maven把拉取的代码进行构建成war包或者jar包—>上传代码到Sonarqube,进行静态代码扫描- –>基于war包构建docker image–>把镜像上传到harbor镜像仓库–>基于镜像部署应用到开发环境–>部署应用到测试环境—>部署应用到生产环境。
3.13.1 创建名称空间 1 2 3 4 5 6 [root@master1 ~] namespace/development created [root@master1 ~] namespace/production created [root@master1 ~] namespace/qatest created
开始创建一个新任务 —>流水线
3.13.2 Pipeline script 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 node('test' ) { stage('Clone' ) { echo "1.Clone Stage" git url: "https://github.com/vorabend/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 vorabend/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 vorabend/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" } } }
3.13.3 jenkins-variable-test-deploy-rollout 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 node('test' ) { stage('git clone' ) { git url: "https://github.com/vorabend/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" } }
4、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.软件的每一次更改(提交到源代码管理系统)都要经过一个复杂的过程才能被发布。
4.1 为什么用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 语言等等。
4.2 jenkins pipeline入门 pipeline脚本是由groovy 语言实现的
但无需专门学习 groovy
pipeline支持两种语法:
-Declarative:声明式
-Scripted pipeline :脚本式
4.2.1 声明式pipeline语法: 官网:
1 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:
作用域:应用于全局最外层,表明该脚本为声明式pipeline 是否必须:必须
agent:
作用域:可用在全局与stage内
agent表明此pipeline在哪个节点上执行 是否必须:是 参数:any,none, label, node,docker,dockerfile
agent any
#运行在任意的可用节点上
agent none
#全局不指定运行节点,由各自stage来决定
agent { label ‘master’ }
#运行在指定标签的机器上,具体标签名称由agent配置决定
1 2 3 4 5 6 agent { node { label 'my-defined-label' customWorkspace 'xxxxxxx' } }
#node{ label ‘master’} 和agent { label ‘master’ }一样,但是node可以扩展节点信息,允许额外的选项 (比如 customWorkspace )。
agent { docker ‘python’ }
#使用指定的容器运行流水线
1 2 3 4 5 6 7 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调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 pipeline{ agent any stages{ stage("This is first stage" ){ steps("This is first step" ){ echo "This is a test" } } } post{ always{ echo "The process is ending" } } }
4.2.2 Pipeline 声明式语法:environment environment指令指定一系列键值对,这些键值对将被定义为所有step或stage-specific step的环境变量,具体取决于environment指令在Pipeline中的位置。该指令支持一种特殊的方法**credentials()**,可以通过其在Jenkins环境中的标识符来访问预定义的凭据。对于类型为“Secret Text”的凭据,该 **credentials()**方法将确保指定的环境变量包含Secret Text内容;对于“标准用户名和密码”类型的凭证,指定的环境变量将被设置为username:password并且将自动定义两个附加的环境变量:MYVARNAME_USR
和MYVARNAME_PSW
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 pipeline { agent any environment { CC = 'clang' } stages { stage('Example' ) { steps { sh 'printenv' sh 'hostname' sh 'df -Th' } } } }
在jenkins中建立流水线测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 Started by user admin [Pipeline] Start of Pipeline [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/pipeline-dec [Pipeline] { [Pipeline] withEnv [Pipeline] { [Pipeline] stage [Pipeline] { (Example) [Pipeline] sh + printenv JENKINS_HOME=/var/jenkins_home KUBERNETES_PORT=tcp://10.10.0.1:443 KUBERNETES_SERVICE_PORT=443 JENKINS_UC_EXPERIMENTAL=https://updates.jenkins.io/experimental CI=true RUN_CHANGES_DISPLAY_URL=http://192.168.106.23:30002/job/pipeline-dec/8/display/redirect?page=changes HOSTNAME=jenkins-99fd4d66f-2v5m4 SHLVL=0 NODE_LABELS=built-in HUDSON_URL=http://192.168.106.23:30002/ HOME=/var/jenkins_home BUILD_URL=http://192.168.106.23:30002/job/pipeline-dec/8/ HUDSON_COOKIE=54c49d57-c51c-43f5-b180-878199a885a4 JENKINS_SERVER_COOKIE=durable-d9414f3be5acaca373a0ff62ab3139106681e82fe79d6f8231fe369bf18c0c27 JENKINS_UC=https://updates.jenkins.io WORKSPACE=/var/jenkins_home/workspace/pipeline-dec REF=/usr/share/jenkins/ref NODE_NAME=built-in RUN_ARTIFACTS_DISPLAY_URL=http://192.168.106.23:30002/job/pipeline-dec/8/display/redirect?page=artifacts STAGE_NAME=Example EXECUTOR_NUMBER=0 JENKINS_SERVICE_PORT_50000_TCP_ADDR=10.10.78.99 RUN_TESTS_DISPLAY_URL=http://192.168.106.23:30002/job/pipeline-dec/8/display/redirect?page=tests BUILD_DISPLAY_NAME= JENKINS_VERSION=2.328 KUBERNETES_PORT_443_TCP_ADDR=10.10.0.1 JENKINS_INCREMENTALS_REPO_MIRROR=https://repo.jenkins-ci.org/incrementals HUDSON_HOME=/var/jenkins_home JOB_BASE_NAME=pipeline-dec PATH=/opt/java/openjdk/bin:/usr/local /sbin:/usr/local /bin:/usr/sbin:/usr/bin:/sbin:/bin JENKINS_SERVICE_PORT_8080_TCP_ADDR=10.10.78.99 JENKINS_SERVICE_SERVICE_HOST=10.10.78.99 JENKINS_SERVICE_PORT_50000_TCP_PORT=50000 BUILD_ID=8 JENKINS_SERVICE_SERVICE_PORT_AGENT=50000 KUBERNETES_PORT_443_TCP_PORT=443 BUILD_TAG=jenkins-pipeline-dec-8 JENKINS_SERVICE_PORT_50000_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP_PROTO=tcp JENKINS_URL=http://192.168.106.23:30002/ JENKINS_SERVICE_PORT_8080_TCP_PORT=8080 LANG=C.UTF-8 JOB_URL=http://192.168.106.23:30002/job/pipeline-dec/ JENKINS_SERVICE_PORT_8080_TCP_PROTO=tcp BUILD_NUMBER=8 JENKINS_NODE_COOKIE=f71b460a-a136-400f-8335-9446defdd1da RUN_DISPLAY_URL=http://192.168.106.23:30002/job/pipeline-dec/8/display/redirect JENKINS_SERVICE_SERVICE_PORT=8080 JENKINS_SERVICE_PORT=tcp://10.10.78.99:8080 JENKINS_SLAVE_AGENT_PORT=50000 HUDSON_SERVER_COOKIE=d9f003d95652fd08 JOB_DISPLAY_URL=http://192.168.106.23:30002/job/pipeline-dec/display/redirect JENKINS_SERVICE_PORT_50000_TCP=tcp://10.10.78.99:50000 KUBERNETES_PORT_443_TCP=tcp://10.10.0.1:443 KUBERNETES_SERVICE_PORT_HTTPS=443 JOB_NAME=pipeline-dec COPY_REFERENCE_FILE_LOG=/var/jenkins_home/copy_reference_file.log PWD=/var/jenkins_home/workspace/pipeline-dec JENKINS_SERVICE_PORT_8080_TCP=tcp://10.10.78.99:8080 JENKINS_SERVICE_SERVICE_PORT_WEB=8080 JAVA_HOME=/opt/java/openjdk KUBERNETES_SERVICE_HOST=10.10.0.1 WORKSPACE_TMP=/var/jenkins_home/workspace/pipeline-dec@tmp CC=clang [Pipeline] sh + hostname jenkins-99fd4d66f-2v5m4 [Pipeline] sh + df -Th Filesystem Type Size Used Avail Use% Mounted on overlay overlay 508G 8.5G 500G 2% / tmpfs tmpfs 64M 0 64M 0% /dev tmpfs tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup 192.168.106.30:/root/nfs_data/jenkins-home nfs4 500G 3.0G 498G 1% /var/jenkins_home /dev/mapper/centos-root xfs 508G 8.5G 500G 2% /etc/hosts shm tmpfs 64M 0 64M 0% /dev/shm tmpfs tmpfs 3.9G 12K 3.9G 1% /run/secrets/kubernetes.io/serviceaccount tmpfs tmpfs 3.9G 0 3.9G 0% /proc/acpi tmpfs tmpfs 3.9G 0 3.9G 0% /proc/scsi tmpfs tmpfs 3.9G 0 3.9G 0% /sys/firmware [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // withEnv [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: SUCCESS
4.2.3 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() }
1 2 3 4 5 6 7 8 9 10 11 12 13 pipeline { agent any options { timeout(time: 1, unit: 'HOURS' ) } stages { stage('Example' ) { steps { echo 'Hello World' } } } }
测试脚本代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Started by user admin [Pipeline] Start of Pipeline [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/pipeline-options [Pipeline] { [Pipeline] timeout Timeout set to expire in 1 hr 0 min [Pipeline] { [Pipeline] stage [Pipeline] { (Example) [Pipeline] echo Hello World [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // timeout [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: SUCCESS
4.2.4 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]这几种参数类型,其他高级参数化类型还需等待社区支持。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 pipeline{ agent any parameters { string(name: 'zy' , defaultValue: 'my name is zy' , description: 'My name is zy' ) booleanParam(name: 'zhangyu' , defaultValue: true , description: 'This is my name' ) } stages{ stage("stage1" ){ steps{ echo "$zy " echo "$zhangyu " } } } }
测试脚本代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Started by user admin [Pipeline] Start of Pipeline [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/pipeline-paramters [Pipeline] { [Pipeline] stage [Pipeline] { (stage1) [Pipeline] echo my name is zy [Pipeline] echo true [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: SUCCESS
4.2.5 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’) }
1 2 3 4 5 6 7 8 9 10 11 12 13 pipeline { agent any triggers { cron('H 4/* 0 0 1-5' ) } stages { stage('Example' ) { steps { echo 'Hello World' } } } }
通过tools可自动安装工具,并放置环境变量到PATH。如果agent none,这将被忽略。
Supported Tools(Global Tool Configuration ) maven jdk gradle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 pipeline { agent any tools { maven 'apache-maven-3.0.1' } stages { stage('Example' ) { steps { sh 'mvn --version' } } } }
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
提示提交者提供的一个可选的参数列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 pipeline { agent any stages { stage('Example' ) { input { message "Should we continue?" ok "Yes, we should." submitter "zy,lucky" parameters { string(name: 'PERSON' , defaultValue: 'zy' , description: 'Who should I say hello to?' ) } } steps { echo "Hello, ${PERSON} , nice to meet you." } } } }
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Started by user admin [Pipeline] Start of Pipeline [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/pipeline-input [Pipeline] { [Pipeline] stage [Pipeline] { (Example) [Pipeline] input Input requested Approved by admin [Pipeline] withEnv [Pipeline] { [Pipeline] echo Hello, zy, nice to meet you. [Pipeline] } [Pipeline] // withEnv [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: SUCCESS
4.2.8 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’ } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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' } } } }
4.2.9 Parallel Declarative Pipeline近期新增了对并行嵌套stage的支持,对耗时长,相互不存在依赖的stage可以使用此方式提升运行效率。除了parallel stage,单个parallel里的多个step也可以使用并行的方式运行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 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" } } } } }
4.3 Pipeline scripted 语法 Groovy脚本不一定适合所有使用者,因此jenkins创建了Declarative pipeline,为编写Jenkins管道提供了一种更简单、更有主见的语法。但是由于脚本化的pipeline是基于groovy的一种DSL语言,所以与Declarative pipeline相比为jenkins用户提供了更巨大的灵活性和可扩展性。
4.3.1 流程控制 pipeline脚本同其它脚本语言一样,从上至下顺序执行,它的流程控制取决于Groovy表达式,如if/else条件语句,举例如下:
1 2 3 4 5 6 7 8 9 node { stage('Example' ) { if (env.BRANCH_NAME == 'master' ) { echo 'I only execute on the master branch' } else { echo 'I execute elsewhere' } } }
4.4 Declarative pipeline和Scripted pipeline的比较 共同点: 两者都是pipeline代码的持久实现,都能够使用pipeline内置的插件或者插件提供的stage,两者都可以利用共享库扩展。 区别: 两者不同之处在于语法和灵活性。Declarative pipeline对用户来说,语法更严格,有固定的组织结构,更容易生成代码段,使其成为用户更理想的选择。但是Scripted pipeline更加灵活,因为Groovy本身只能对结构和语法进行限制,对于更复杂的pipeline来说,用户可以根据自己的业务进行灵活的实现和扩展。
5、jenkins+k8s+harbor实现DevOps 5.1 在Jenkins中添加harbor凭据 1 http://192.168.106.23:30002/credentials/store/system/domain/_/newCredentials
5.2 编写Jenkins pipeline 因为镜像要上传到harbor私有镜像仓库,所以需要在harbor上创建一个项目,项目名称是jenkins-demo,如下所示:
新建一个任务——>输入一个任务名称处输入jenkins-harbor——>流水线——>确定——>在Pipeline script处输入如下内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 node('test' ) { stage('Clone' ) { echo "1.Clone Stage" git url: "https://github.com/vorabend/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.106.21/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.106.21 -u ${dockerHubUser} -p ${dockerHubPassword} " sh "docker push 192.168.106.21/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" } } }
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 Started by user admin [Pipeline] Start of Pipeline [Pipeline] node Still waiting to schedule task ‘test-915fx’ is offline Agent test-kklcw is provisioned from template test --- apiVersion: "v1" kind: "Pod" metadata: labels: jenkins: "slave" jenkins/label-digest: "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3" jenkins/label: "test" name: "test-kklcw" namespace: "jenkins-k8s" spec: containers: - env: - name: "JENKINS_SECRET" value: "********" - name: "JENKINS_AGENT_NAME" value: "test-kklcw" - name: "JENKINS_NAME" value: "test-kklcw" - name: "JENKINS_AGENT_WORKDIR" value: "/home/jenkins/agent" - name: "JENKINS_URL" value: "http://jenkins-service.jenkins-k8s.svc.cluster.local:8080/" image: "xianchao/jenkins-jnlp:v1" imagePullPolicy: "IfNotPresent" name: "jnlp" resources: limits: {} requests: {} tty: true volumeMounts: - mountPath: "/home/jenkins/.kube" name: "volume-1" readOnly: false - mountPath: "/var/run/docker.sock" name: "volume-0" readOnly: false - mountPath: "/home/jenkins/agent" name: "workspace-volume" readOnly: false workingDir: "/home/jenkins/agent" hostNetwork: false nodeSelector: kubernetes.io/os: "linux" restartPolicy: "Never" serviceAccountName: "jenkins-k8s-sa" volumes: - hostPath: path: "/run/docker.sock" name: "volume-0" - hostPath: path: "/root/.kube" name: "volume-1" - emptyDir: medium: "" name: "workspace-volume" Running on test-kklcw in /home/jenkins/agent/workspace/jenkins-harbor [Pipeline] { [Pipeline] stage [Pipeline] { (Clone) [Pipeline] echo 1.Clone Stage [Pipeline] git The recommended git tool is: NONE No credentials specified Cloning the remote Git repository Cloning repository https://github.com/vorabend/jenkins-sample.git > git init /home/jenkins/agent/workspace/jenkins-harbor Fetching upstream changes from https://github.com/vorabend/jenkins-sample.git > git --version > git --version > git fetch --tags --progress -- https://github.com/vorabend/jenkins-sample.git +refs/heads/*:refs/remotes/origin/* Avoid second fetch Checking out Revision fa8fe9a9fe430e8b01d6eeba8ec8748df8485fa9 (refs/remotes/origin/master) > git config remote.origin.url https://github.com/vorabend/jenkins-sample.git > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* > git rev-parse refs/remotes/origin/master^{commit} > git config core.sparsecheckout > git checkout -f fa8fe9a9fe430e8b01d6eeba8ec8748df8485fa9 > git branch -a -v --no-abbrev > git checkout -b master fa8fe9a9fe430e8b01d6eeba8ec8748df8485fa9 Commit message: "Update k8s-prod-harbor.yaml" > git rev-list --no-walk fa8fe9a9fe430e8b01d6eeba8ec8748df8485fa9 [Pipeline] script [Pipeline] { [Pipeline] sh + git rev-parse --short HEAD [Pipeline] } [Pipeline] // script [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Test) [Pipeline] echo 2.Test Stage [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Build) [Pipeline] echo 3.Build Docker Image Stage [Pipeline] sh + docker build -t 192.168.106.21/jenkins-demo/jenkins-demo:fa8fe9a . Sending build context to Docker daemon 182.8kB Step 1/5 : FROM golang:1.10.4-alpine ---> bd36346540f3 Step 2/5 : ADD . /go/src/app ---> 98a8e12316ef Step 3/5 : WORKDIR /go/src/app ---> Running in 7347102f918d Removing intermediate container 7347102f918d ---> 3e592ccb3e95 Step 4/5 : RUN go build -v -o /go/src/app/jenkins-app ---> Running in 05b4398d4924 [91mapp [0mRemoving intermediate container 05b4398d4924 ---> 3aaed6e21425 Step 5/5 : CMD ["./jenkins-app" ] ---> Running in c8af5e8d68d0 Removing intermediate container c8af5e8d68d0 ---> 52bc7b4f0384 Successfully built 52bc7b4f0384 Successfully tagged 192.168.106.21/jenkins-demo/jenkins-demo:fa8fe9a [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Push) [Pipeline] echo 4.Push Docker Image Stage [Pipeline] withCredentials Masking supported pattern matches of $dockerHubPassword [Pipeline] { [Pipeline] sh Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure. Affected argument(s) used the following variable(s): [dockerHubPassword] See https://jenkins.io/redirect/groovy-string-interpolation for details. + docker login 192.168.106.21 -u admin -p **** WARNING! Using --password via the CLI is insecure. Use --password-stdin. WARNING! Your password will be stored unencrypted in /home/jenkins/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/ Login Succeeded [Pipeline] sh + docker push 192.168.106.21/jenkins-demo/jenkins-demo:fa8fe9a The push refers to repository [192.168.106.21/jenkins-demo/jenkins-demo] 458946453feb: Preparing 18a2205f79a7: Preparing ac1c7fa88ed0: Preparing cc5fec2c1edc: Preparing 93448d8c2605: Preparing c54f8a17910a: Preparing df64d3292fd6: Preparing df64d3292fd6: Waiting c54f8a17910a: Waiting 18a2205f79a7: Pushed 93448d8c2605: Pushed ac1c7fa88ed0: Pushed c54f8a17910a: Pushed 458946453feb: Pushed df64d3292fd6: Pushed cc5fec2c1edc: Pushed fa8fe9a: digest: sha256:47642efdfa34bdde22be762db8ff7c3f969eacaba4a788ddc891acac41204b66 size: 1785 [Pipeline] } [Pipeline] // withCredentials [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Deploy to dev) [Pipeline] echo 5. Deploy DEV [Pipeline] sh + sed -i s/<BUILD_TAG>/fa8fe9a/ k8s-dev-harbor.yaml [Pipeline] sh + sed -i s/<BRANCH_NAME>/null/ k8s-dev-harbor.yaml [Pipeline] sh + kubectl apply -f k8s-dev-harbor.yaml --validate=false deployment.apps/jenkins-demo configured service/demo unchanged [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Promote to qa) [Pipeline] input Input requested Approved by admin [Pipeline] echo This is a deploy step to YES [Pipeline] sh + sed -i s/<BUILD_TAG>/fa8fe9a/ k8s-qa-harbor.yaml [Pipeline] sh + sed -i s/<BRANCH_NAME>/null/ k8s-qa-harbor.yaml [Pipeline] sh + kubectl apply -f k8s-qa-harbor.yaml --validate=false deployment.apps/jenkins-demo configured service/demo unchanged [Pipeline] sh + sleep 6 [Pipeline] sh + kubectl get pods -n qatest NAME READY STATUS RESTARTS AGE jenkins-demo-575cd7896b-df4jk 0/1 Terminating 5 3d5h jenkins-demo-74fd584b5f-zdlmh 1/1 Running 0 8s [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Promote to pro) [Pipeline] input Input requested Approved by admin [Pipeline] echo This is a deploy step to YES [Pipeline] sh + sed -i s/<BUILD_TAG>/fa8fe9a/ k8s-prod-harbor.yaml [Pipeline] sh + sed -i s/<BRANCH_NAME>/null/ k8s-prod-harbor.yaml [Pipeline] sh + cat k8s-prod-harbor.yaml apiVersion: apps/v1 kind: Deployment metadata: name: jenkins-demo namespace: production spec: replicas: 1 selector: matchLabels: app: jenkins-demo template: metadata: labels: app: jenkins-demo spec: containers: - image: 192.168.106.21/jenkins-demo/jenkins-demo:fa8fe9a imagePullPolicy: IfNotPresent name: jenkins-demo env: - name: branch value: null --- apiVersion: v1 kind: Service metadata: name: jenkins-demo namespace: production spec: selector: app: jenkins-demo type : NodePort ports: - port: 18888 targetPort: 18888 nodePort: 31890 [Pipeline] sh + kubectl apply -f k8s-prod-harbor.yaml --record --validate=false deployment.apps/jenkins-demo configured service/jenkins-demo configured [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: SUCCESS
6、Jenkins接入Sonarqube 6.1 在node2上安装Sonarqube 1 2 3 4 5 6 7 8 9 10 11 [root@node2 ~] vm.max_map_count = 655360 [root@node2 ~] [root@node2 ~] [root@node2 ~]
6.2 在Jenkins中安装sonarqube插件 安装插件Sonarqube Scanner
6.3 访问Sonarqube web界面创建token 1 http://192.168.106.22:9000/admin/users
把copy后面的一串token记录下来
1 24282ae327541a70abf505f108d88fa64ff7bd6d
6.4 连接Sonarqube web 在控制节点上解压压缩包microservic-test.zip,以下命令成不成功,取决于版本是否合适
1 [root@master1 microservic-test]
7、Jenkins+k8s+nexus+gitlab+harbor+sonarqube+springloud构建DevOps 7.1 安装nexus 概念:
Nexus服务器是一个代码包管理的服务器,可以理解 Nexus 服务器是一个巨大的 Library 仓库。Nexus 可以支持管理的工具包括 Maven , npm 等,对于 JAVA 开发来说,只要用到 Maven 管理就可以了。
Nexus服务器作用:因为传统的中央仓库在国外,其地理位置比较远,下载速度比较缓慢。因此,当公司开发人员数量越来越多时,如果不架设一台自己的Nexus服务器,会产生大量的流量阻塞带宽,并且在出现一些不可抗原因(光缆被挖断)导致无法连接到中央仓库时,开发就会因为无法下载相关依赖包而进度停滞。因此在本地环境部署一台私有的Nexus服务器来缓存所有依赖包,并且将公司内部开发的私有包也部署上去,方便其他开发人员下载,是非常有必要的。因为 Nexus 有权限控制,因此外部人员是无法得到公司内部开发的项目包的。
在日志中,会看到一条消息: Started Sonatype Nexus OSS 3.20.1-01 这意味着Nexus Repository Manager可以使用了。
1 2 [root@node2 ~] Started Sonatype Nexus OSS 3.37.3-02