本文主要演示如何在阿里云Serverless Kubernetes服务上快速搭建jenkins持续集成环境,并基于提供的示例应用快速完成应用源码编译、镜像构建和推送以及应用部署的流水线。
先决条件:
阿里云Serverless Kubernetes集群。
(1)下载部署文件
$ git clone https://github.com/AliyunContainerService/jenkins-on-serverless.git
$ cd jenkins-on-serverless
(2)jenkins_home持久化配置
serverless kubernetes目前不支持云盘,要持久化jenkins_home的话, 需要挂载nfs volume, 修改serverless-k8s-jenkins-deploy.yaml中注释部分字段:
#volumeMounts:
# - mountPath: /var/jenkins_home
# name: jenkins-home
.....
#volumes:
# - name: jenkins-home
# nfs:
# path: /
# server:
(3)部署jenkins
$ kubectl apply -f serverless-k8s-jenkins-deploy.yaml
(1)配置Kubernetes Cloud动态创建slave pod:
系统管理 -> 系统设置 -> Cloud -> Kubernetes URL:
系统管理 -> 系统设置 -> Cloud -> Kubernetes URL:
Kubernetes.Credentials:
点击添加证书:
系统管理 -> 系统设置 -> Cloud -> Jenkins URL and tunnel:
保存配置。
(2)创建jenkins-docker-cfg secret用于镜像仓库权限设置
本示例中使用了阿里云镜像服务提供的北京区域镜像仓库:
$ docker login -u xxx -p xxx registry.cn-beijing.aliyuncs.com
Login Succeeded
$ kubectl create secret generic jenkins-docker-cfg --from-file=/root/.docker/config.json
(3)构建demo-pipeline并访问应用服务
根据自己镜像仓库信息修改构建参数,并填写kubeconfig中的apiserver url, 本示例中源码仓库分支为serverless,镜像为registry.cn-beijing.aliyuncs.com/haoshuwei/jenkins-java-demo:serverless 请根据提示信息进行替换
完成。
(1)示例项目中使用的源码仓库,分支为serverless
https://github.com/AliyunContainerService/jenkins-demo.git
(2)kaniko 构建和推送docker镜像说明
kaniko可以不依赖docker daemon并在用户空间执行完成Dockerfile中的每一行命令,最终完成docker镜像的构建和推送。
kaniko -f `pwd`/Dockerfile -c `pwd` --destination=${origin_repo}/${repo}:${image_tag}
(3)部署应用到Kubernetes集群插件说明
对应的Pipeline语法为:
step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: 'https://kubernetes.default.svc.cluster.local:443', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
声明的变量ORIGIN_REPO,REPO,IMAGE_TAG可在构建执行时把deployment.yaml文件中对应的变量值替换为实际值:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: jenkins-java-demo
spec:
replicas: 2
selector:
matchLabels:
app: jenkins-java-demo
template:
metadata:
labels:
app: jenkins-java-demo
spec:
containers:
- name: jenkins-java-demo
image: ${ORIGIN_REPO}/${REPO}:${IMAGE_TAG}
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: jenkins-java-demo
spec:
ports:
- port: 80
targetPort: 8080
name: jenkins-java-demo
selector:
app: jenkins-java-demo
type: LoadBalancer
(4)Jenkinsfile说明
pipeline{
// 定义groovy脚本中使用的环境变量
environment{
// 本示例中使用DEPLOY_TO_K8S变量来决定把应用部署到哪套容器集群环境中,如“Production Environment”, “Staging001 Environment”等
IMAGE_TAG = sh(returnStdout: true,script: 'echo $image_tag').trim()
ORIGIN_REPO = sh(returnStdout: true,script: 'echo $origin_repo').trim()
REPO = sh(returnStdout: true,script: 'echo $repo').trim()
BRANCH = sh(returnStdout: true,script: 'echo $branch').trim()
API_SERVER_URL = sh(returnStdout: true,script: 'echo $api_server_url').trim()
}
// 定义本次构建使用哪个标签的构建环境,本示例中为 “slave-pipeline”
agent{
node{
label 'slave-pipeline'
}
}
// "stages"定义项目构建的多个模块,可以添加多个 “stage”, 可以多个 “stage” 串行或者并行执行
stages{
// 定义第一个stage, 完成克隆源码的任务
stage('Git'){
steps{
git branch: '${BRANCH}', credentialsId: '', url: 'https://github.com/AliyunContainerService/jenkins-demo.git'
}
}
// 添加第二个stage, 运行源码打包命令
stage('Package'){
steps{
container("maven") {
sh "mvn package -B -DskipTests"
}
}
}
// 添加第三个stage, 运行容器镜像构建和推送命令, 用到了environment中定义的groovy环境变量
stage('Image Build And Publish'){
steps{
container("kaniko") {
sh "kaniko -f `pwd`/Dockerfile -c `pwd` --destination=${ORIGIN_REPO}/${REPO}:${IMAGE_TAG}"
}
}
}
stage('Deploy to Kubernetes') {
parallel {
stage('Deploy to Production Environment') {
when {
expression {
"$BRANCH" == "serverless"
}
}
steps {
container('kubectl') {
step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: '$API_SERVER_URL', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
}
}
}
stage('Deploy to Staging001 Environment') {
when {
expression {
"$BRANCH" == "latest"
}
}
steps {
container('kubectl') {
step([$class: 'KubernetesDeploy', authMethod: 'certs', apiServerUrl: '$API_SERVER_URL', credentialsId:'k8sCertAuth', config: 'deployment.yaml',variableState: 'ORIGIN_REPO,REPO,IMAGE_TAG'])
}
}
}
}
}
}
}