首先为什么要使用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集群有以下区别
- serverless集群的节点是虚拟的,关联到节点的资源将不可用,比如daemonset、NodePort等;jenkins也无法利用宿主机的docker.sock进行构建;
- 默认不支持k8s的服务发现,需要开启PrivateZone,才能支持服务发现
2.创建jenkins集群
最佳实践中已经说明如何创建。有以下几点问题需要注意。
- 存储使用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}"
}
}
}
}
最后顺利构建成功
最后
关于收费标准,一开始以为只根据request值收费,但是我想多了,有固定的几个参数,会自动根据你配置request的值选择特定的值,所以不要手抖多输了一个0。建议设置一下limitRange和resourceQutao。如果不设置reques值,会默认采用2G1C的配额。
https://help.aliyun.com/document_detail/114662.html?spm=a2c4g.11186623.6.582.55bbee6dZ1DPw4