使用serverless构建jenkins

首先为什么要使用serverless呢,因为原来我们的jenkins使用过的本地的服务器,才构建任务比较多的时候,经常会消耗很多服务器的资源,在平时不用的时候,资源又浪费了。

官方已经有最佳实践
https://help.aliyun.com/document_detail/106865.html?spm=a2c4g.11186623.6.927.32b2711cW9zbjf

这里根据最佳实践进行操作并补充说明。

1.第一步先创建一个serverless集群

 ~/  kubectl get node
NAME              STATUS   ROLES   AGE   VERSION
virtual-kubelet   Ready    agent   43h   v1.11.2

serverless 与 普通的k8s集群有以下区别

  1. serverless集群的节点是虚拟的,关联到节点的资源将不可用,比如daemonset、NodePort等;jenkins也无法利用宿主机的docker.sock进行构建;
  2. 默认不支持k8s的服务发现,需要开启PrivateZone,才能支持服务发现

2.创建jenkins集群

最佳实践中已经说明如何创建。有以下几点问题需要注意。

  1. 存储使用NAS实现,之前的K8s使用的是Flexvolume插件,以storageclass的方式创建。但是遇到一个问题,Flexvolume插件默认的是以ds的方式进行部署,后来尝试了一下发现不需要手动安装Flexvolume也可以实现,但是利用nas-controller动态创建PV的时候,就是挂载nas提示权限问题,可能是操作的问题,为了先完成任务,直接手动创建PV+PVC的方式将jenkins_home挂载出来,jenkins就runing起来了。

3.配置jenkins

配置中增加云的配置,最佳实践中没有说明如何创建如何

待续...

问题:

1.docker打包方式

之前采用直接利用宿主机docker的方式进行打包,但是使用serverless以后就无法使用宿主机了。

hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock'),

这里使用另外一种方案 https://github.com/GoogleContainerTools/kaniko
使用如下命令进行docker容器的build和push

/kaniko/executor -c `pwd` --dockerfile=./Dockerfile --destination=$IMAGE_NAME

2.本地镜像缓存问题

原本镜像可以缓存在宿主机,每次拉取镜像可以很快,上了serverless无法缓存,但是阿里云还是提供了一种方式imagecache。
https://help.aliyun.com/document_detail/141241.html?spm=a2c4g.11186623.6.592.440d2e14PLj1jV
可以在5秒钟以后将jenkins job需要的镜像拉取完毕

以下是一个完整的pipeline

def registry = 'xxx'
def library = 'example'
def name = 'xxx'

podTemplate(label: 'java',containers: [
    containerTemplate(
            name: 'jnlp',
            image: 'registry-vpc.cn-hangzhou.aliyuncs.com/thundersdata-public/jnlp-slave:3.35-5',
            resourceRequestCpu: '0.25',
            resourceRequestMemory: '500Mi',
            ttyEnabled: true),
    containerTemplate(
            name: 'maven',
            alwaysPullImage: true,
            image: 'registry-vpc.cn-hangzhou.aliyuncs.com/thundersdata/maven-docker-serverless:apm',
            resourceRequestCpu: '1',
            resourceRequestMemory: '1000Mi',
            ttyEnabled: true,
            command: 'cat'),
    containerTemplate(
            name: 'docker',
            image: 'registry-vpc.cn-hangzhou.aliyuncs.com/thundersdata-public/kaniko',
            resourceRequestCpu: '0.25',
            resourceRequestMemory: '500Mi',
            envVars: [
            ## 修改docker默认的认证文件路径, 测试发现默认/home/jenkins/会覆盖,所有换了个目录
            envVar(key: 'DOCKER_CONFIG', value: '/kaniko/.docker'),],
            ttyEnabled: true,
            command: 'sh'
            )
  ],
serviceAccount: 'pods',
slaveConnectTimeout: 60,
volumes: [
    persistentVolumeClaim(mountPath: '/root/.m2', claimName: 'maven-package-hostdisk', readOnly:false),
    secretVolume(secretName: 'registry', mountPath: '/kaniko/.docker')],
    imagePullSecrets: [ 'regsecret' ]
)

{
node ('java') {
    echo 'ready go'
    def path = pwd()
    def branch_ = ''
    def author = ''
    def version = ''
    def image

    branch_='dev'
    stage("clone code"){
        git credentialsId: 'xxx', branch: branch_, url: 'xxx'
        sh 'git log --no-merges --pretty=format:"%an" -1 > author.txt'
        sh 'git log --no-merges --pretty=format:"%h" --abbrev=8 -1 > version.txt'
        sh 'url=`cat .git/config|grep git`&&url=${url##*/}&&echo ${url%.*} > name.txt'
        author = readFile("author.txt")
        version = readFile("version.txt")
        image = "${registry}/${library}/${name}"
    }

    container('maven'){
        stage('copy dockerfile'){
            sh "cp -u /docker/* ."
        }

        stage("maven package"){
            if (moduleName!=''){
                sh "mvn -s settings.xml package -pl ${moduleName} -DskipTests -U"
                sh "cp -r ${childName}/target ."
                sh "if [ -e ${childName}/Dockerfile ]; then  cp ${childName}/Dockerfile ./; fi"
            } else {
                sh 'mvn -s settings.xml package -DskipTests -U'
            }
        }
    }
    container('docker') {
        stage('build and push docker image') {
            sh "/kaniko/executor -c `pwd` --dockerfile=./Dockerfile --destination=${image}:${version}"
        }
    }
}
}

最后顺利构建成功


image.png

最后

关于收费标准,一开始以为只根据request值收费,但是我想多了,有固定的几个参数,会自动根据你配置request的值选择特定的值,所以不要手抖多输了一个0。建议设置一下limitRange和resourceQutao。如果不设置reques值,会默认采用2G1C的配额。
https://help.aliyun.com/document_detail/114662.html?spm=a2c4g.11186623.6.582.55bbee6dZ1DPw4

20191213170746.jpg

你可能感兴趣的:(使用serverless构建jenkins)