Jenkins 进阶篇

安装Jenkins

支持各平台:windows、linux、docker,
见官网,比较详细

证书凭据

作用范围分为全局和局部凭据
类型可以分为:

  1. Secret text - API token之类的token (如GitHub个人访问token),
  2. Username and password - 可以为独立的字段,如用户名和密码
  3. Secret file - 保存在文件中的加密内容
  4. SSH Username with private key - SSH 公钥/私钥对,
  5. Certificate - a PKCS#12 证书文件 和可选密码
  6. Docker Host Certificate Authentication credentials.
pipeline

合格的声明式流水线需要stages 和step 、post指令,来表明jenkins处于那个阶段,执行什么命令、执行结果。
jenkins的生命周期:构建、测试、部署, Jenkinsfile是整个生命周期的管理工具,可以说是粘合剂。
构建Build:一般包括代码的组装、编译和打包
测试Test:测试一般由其他插件提供测试结果和测试记录,报告和可视化工具;如junit
部署Deploy:当构建和测试阶段都成功执行完,该阶段才能执行

# currentBuild.result 获取当前构建的结果
pipeline {
    agent any
    stages {
        stage('Deploy') {
	            when {
	            expression {
	                currentBuild.result == null || currentBuild.result == 'SUCCESS' 
	               }
           }
           steps {
               sh 'make publish'
           }
        }
    }
}

变量
def singlyQuoted = 'Hello World'
echo '!!! ${singlyQuoted}'
结果:!!! Hello World
常用环境变量
变量名含义
BUILD_ID构建ID
BUILD_NUMBER构建号
BUILD_TAG等于字符串:“jenkins- ${JOB_NAME}- ${BUILD_NUMBER}”
BUILD_URL构建结果的URL
EXECUTOR_NUMBER用于识别当前构建的执行者的唯一编号
JAVA_HOMEjdk设置的系统变量
JENKINS_URL服务器的完整URL:https://example.com:port/jenkins/
JOB_NAME构建job名称
NODE_NAME构建节点名称
WORKSPACE工作空间的绝对路径

用法:echo “Running ${env.BUILD_ID} ON ${env.JENKINS_URL}”

设置环境变量
# 上面全局变量,下面stage内的为局部变量
pipeline {
    agent any
    environment { 
        CC = 'clang'
    }
    stages {
        stage('Example') {
            environment { 
                DEBUG_FLAGS = '-g'
            }
            steps {
                sh 'printenv'
            }
        }
    }
}
动态设置环境变量
pipeline {
    agent any 
    environment {
        // 使用 returnStdout
        CC = """${sh(
                returnStdout: true,
                script: 'echo "clang"'
            )}""" 
        // 使用 returnStatus
        EXIT_STATUS = """${sh(
                returnStatus: true,
                script: 'exit 1'
            )}"""
    }
    stages {
        stage('Example') {
            environment {
                DEBUG_FLAGS = '-g'
            }
            steps {
                sh 'printenv'
            }
        }
    }
}
处理凭据
  • Secret
    携带凭据Secret文本,Jenkins上已经配置好用户名和密码,通过凭据ID来使用,
    jenkins-bitbucket-common-creds 为凭据ID
# 用于Amazon Web 服务(AWS
environment {
     AWS_ACCESS_KEY_ID     = credentials('jenkins-aws-secret-key-id')
     AWS_SECRET_ACCESS_KEY = credentials('jenkins-aws-secret-access-key')
 }

environment {
    BITBUCKET_COMMON_CREDS = credentials('jenkins-bitbucket-common-creds')
}
# 实际Jenkins配置了3个环境变量
BITBUCKET_COMMON_CREDS 格式为 username:password
BITBUCKET_COMMON_CREDS_USR 仅含用户名
BITBUCKET_COMMON_CREDS_PSW  仅含密码
其他凭据处理

SSH User Private Key:提供key
Certificate:提供PKCS#12证书
Docker client certificate:用于处理docker主机证书的认证

# ssh 示例
# 可选 passphraseVariable 和 usernameVariable ,可删除
withCredentials(bindings: [sshUserPrivateKey(credentialsId: 'jenkins-ssh-key-for-abc', \
                                             keyFileVariable: 'SSH_KEY_FOR_ABC', \
                                             passphraseVariable: '', \
                                             usernameVariable: '')]) {
  // some block
}
# certficate示例
# 可选 aliasVariable 和 passwordVariable ,可删除
withCredentials(bindings: [certificate(aliasVariable: '', \
                                       credentialsId: 'jenkins-certificate-for-xyz', \
                                       keystoreVariable: 'CERTIFICATE_FOR_XYZ', \
                                       passwordVariable: 'XYZ-CERTIFICATE-PASSWORD')]) {
  // some block
}
处理参数
parameters {
      string(name: 'Greeting', defaultValue: 'Hello', description: 'How should I greet the world?')
}
    
处理故障
post {
	always {
		junit '**/target/*.xml'
	}
	failure {
		mail to: team@example.com, subject: 'The Pipeline failed :('
	}
}
使用多分支

选择windows 、linux节点

# stash 允许捕获与包含模式配置文件,以便再同一流水线重用。一旦流水线执行完成,就会从Jenkins master中删除在暂存文件
# unstash 会从Jenkins master中取回命名的stash到流水线的当前工作区
pipeline {
    agent none
    stages {
        stage('Build') {
            agent any
            steps {
                checkout scm
                sh 'make'
                stash includes: '**/target/*.jar', name: 'app' 
            }
        }
        stage('Test on Linux') {
            agent { 
                label 'linux'
            }
            steps {
                unstash 'app' 
                sh 'make check'
            }
            post {
                always {
                    junit '**/target/*.xml'
                }
            }
        }
        stage('Test on Windows') {
            agent {
                label 'windows'
            }
            steps {
                unstash 'app'
                bat 'make check' 
            }
            post {
                always {
                    junit '**/target/*.xml'
                }
            }
        }
    }
}
可选的步骤参数

pipeline遵循groovy语法

# 下面语句功能相同
git url: 'git://example.com/amazing-project.git', branch: 'master'
git([url: 'git://example.com/amazing-project.git', branch: 'master'])

# 参数可省略
sh 'echo hello' /* short form  */
sh([script: 'echo hello'])  /* long form */

并行执行parallel
stage('Build') {
    /* .. snip .. */
}

stage('Test') {
    parallel linux: {
        node('linux') {
            checkout scm
            try {
                unstash 'app'
                sh 'make check'
            }
            finally {
                junit '**/target/*.xml'
            }
        }
    },
    windows: {
        node('windows') {
            /* .. snip .. */
        }
    }
}
分支管理

Multibranch Pipeline 项目类型能够 在同一个项目的不同分支上实现不同的Jenkinsfile;
Jenkins 自动的扫描指定的存储库并为包含Jenkinsfile的仓库的每个分支创建合适的项目
默认情况下, Jenkins 不会自动的重新索引分支添加或删除的仓库(除非使用 组织文件夹), 所以周期性地重新索引有助于配置多分支流水线:
在这里插入图片描述

pipeline docker使用
agent {
        docker { image 'node:7-alpine' }
}

挂载到容器外~/.m2

agent {
        docker {
            image 'maven:3-alpine'
            args '-v $HOME/.m2:/root/.m2'
        }
    }

使用多个容器,对不同的stage用不同的环境

pipeline {
    agent none
    stages {
        stage('Back-end') {
            agent {
                docker { image 'maven:3-alpine' }
            }
            steps {
                sh 'mvn --version'
            }
        }
        stage('Front-end') {
            agent {
                docker { image 'node:7-alpine' }
            }
            steps {
                sh 'node --version'
            }
        }
    }
}

使用Dockerfile构建新容器

Dockerfile
FROM node:7-alpine

RUN apk add -U subversion

# 如下,Dockerfile放入源仓库根目录
agent { dockerfile true }
sidecar高级用法

Docker 流水线可以"在后台"运行一个容器 , 而在另外一个容器中工作。 利用这种sidecar 方式, 流水线可以为每个流水线运行 提供一个"干净的" 容器。

node {
    checkout scm
    /*
     * In order to communicate with the MySQL server, this Pipeline explicitly
     * maps the port (`3306`) to a known port on the host machine.
     */
    docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw" -p 3306:3306') { c ->
        /* Wait until mysql service is up */
        sh 'while ! mysqladmin ping -h0.0.0.0 --silent; do sleep 1; done'
        /* Run some tests which require MySQL */
        sh 'make check'
    }
}

示例:
下面的示例使用 withRun公开的项目, 它通过id 属性具有可用的运行容器的ID。使用该容器的 ID, 流水线通过自定义 Docker 参数生成一个到inside() 方法的链。

node {
    checkout scm
    docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw"') { c ->
        docker.image('mysql:5').inside("--link ${c.id}:db") {
            /* Wait until mysql service is up */
            sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done'
        }
        docker.image('centos:7').inside("--link ${c.id}:db") {
            /*
             * Run some tests which require MySQL, and assume that it is
             * available on the host name `db`
             */
            sh 'make check'
        }
    }
}
容器构建
node {
    checkout scm

    def customImage = docker.build("my-image:${env.BUILD_ID}")

    customImage.inside {
        sh 'make test'
    }
}

# 甚至可以直接通过push,dockerhub  或私有仓库, tag为可选参数
node {
    checkout scm
    def customImage = docker.build("my-image:${env.BUILD_ID}")
    customImage.push('latest')
}
# 指定dockerfile的路径,构建镜像
node {
    checkout scm
    def testImage = docker.build("test-image", "./dockerfiles/test") 

    testImage.inside {
        sh 'make test'
    }
}

# 使用其他名称的文件构建镜像,如dockerfiles,-f覆盖默认的dockerfile
node {
    checkout scm
    def dockerfile = 'Dockerfile.test'
    def customImage = docker.build("my-image:${env.BUILD_ID}", "-f ${dockerfile} ./dockerfiles") 
}
使用远程docker服务器withServer

注意:inside() 和 build() 不能正确的在Docker集群服务器中工作;会提示

cannot create /…@tmp/durable-/pid: Directory nonexistent

需要先在Jenkins配置证书:swarm-certs,再通过url访问docker服务器地址

node {
    checkout scm

    docker.withServer('tcp://swarm.example.com:2376', 'swarm-certs') {
        docker.image('mysql:5').withRun('-p 3306:3306') {
            /* do things */
        }
    }
}
使用自定义的镜像仓库

一般需要配置证书,如不需证书,删除’credentials-id’参数就好了

node {
    checkout scm

    docker.withRegistry('https://registry.example.com''credentials-id') {

        docker.image('my-custom-image').inside {
            sh 'make test'
        }
    }
}
共享库SCM

共享库的目录结构

(root)
+- src                     # Groovy source files
|   +- org
|       +- foo
|           +- Bar.groovy  # for org.foo.Bar class
+- vars
|   +- foo.groovy          # for global 'foo' variable
|   +- foo.txt             # help for 'foo' variable
+- resources               # resource files (external libraries only)
|   +- org
|       +- foo
|           +- bar.json    # static helper data for org.foo.Bar

# src 类似Java源目录结构。当执行流水线时,该目录被添加到类路径下
# var 目录定义可流水线访问的全局变量的脚本。每个*.groovy文件的基名都应该是Groovy标识符;*.txt, 为*.groovy文件的帮助文件
# resources 目录允许从外部库中使用的libraryResource步骤来加载非Groovy文件

全局共享库设置:Manage Jenkins » Configure System » Global Pipeline Libraries
在这里插入图片描述
库的使用:
在这里插入图片描述

@Library('my-shared-library') _
/* Using a version specifier, such as branch, tag, etc */
@Library('my-shared-library@1.0') _
/* Accessing multiple libraries with one statement */
@Library(['my-shared-library', 'otherlib@abc1234']) _

# 或
library 'my-shared-library'
# 指定主分支master
library 'my-shared-library@master'

简单库的编写

# vars/log.groovy
def info(message) {
    echo "INFO: ${message}"
}

def warning(message) {
    echo "WARNING: ${message}"
}

# 使用
# Jenkinsfile, 必须在script里面使用这种类型的全部变量
@Library('utils') _

pipeline {
    agent none
    stage ('Example') {
        steps {
             script { 
                 log.info 'Starting'
                 log.warning 'Nothing to do!'
             }
        }
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值