背景:
紧跟Kubernetes中spinnaker的使用一。完成了简单的各种Triggers触发器,还有deploy Mainfest部署一个kubernetes的简单流水线。这里根据实际的环境想更深入一下流水线步骤:参数化的构建,webhook的触发,邮件的发送,jenkins流水线的集成等等
首先明确一下pipeline是由多个stage组成的:
关于默认的stage可以参照官网:https://spinnaker.io/docs/reference/pipeline/stages/。环境主要是kubernetes环境这里注重于:
从一条 pipeline开始
创建application
创建应用 pipeline-test,Permissions权限给运维组读写执行权限(其他组权限看个人需求,这里仅用作演示)
创建流水线pipeline
创建pipeline流水线---Parameters-test1
Parameters-关于参数化构建
准备前提:
参数化的构建是在Configuration步骤的
按照常用的惯例将Kubernetes中spinnaker的使用一中的流水线拿来做实验!
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: nginxdemo
name: nginxdemo
namespace: dev
spec:
replicas: 1
selector:
matchLabels:
k8s-app: nginxdemo
template:
metadata:
labels:
k8s-app: nginxdemo
name: nginxdemo
namespace: dev
spec:
containers:
- image: 'harbor.xxxx.com/spinnaker/spinnaker-nginx-demo:1.2.4'
imagePullPolicy: Always
name: nginxdemo
ports:
- containerPort: 80
name: web
protocol: TCP
imagePullSecrets:
- name: harbor-layame
定义参数Parameters:
定义image参数,设置默认镜像tag为nginx:1.18.0
deploy Mainfest
这里的stage name是可以自定义名称的,直接设置stage name为发布应用:
Manifest Configuration
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: nginxdemo
name: nginxdemo
namespace: dev
spec:
replicas: 1
selector:
matchLabels:
k8s-app: nginxdemo
template:
metadata:
labels:
k8s-app: nginxdemo
name: nginxdemo
namespace: dev
spec:
containers:
- image: '${ parameters.image }'
imagePullPolicy: Always
name: nginxdemo
ports:
- containerPort: 80
name: web
protocol: TCP
增加webhook stage 保存流水线
{
"msgtype": "text",
"text": {
"content": "流水线 ${execution['name']}运行中, 运行用户 ${execution['trigger']['user']}"
}
集群中操作
确保dev namespace存在(这里将存在的deployments删除,方便对比!)
run流水线并验证部署结果
pipelines界面Start Manual Execution 选择Parameters-test1流水线image使用默认的nginx:1.18.0, Run
OK 结果如下:流水线状态SUCCEEDED,微信webhook收到通知,dev namespace下deployments部署成功。
增加parameters replicas参数
为什么选择relicas副本数做例子呢?为了强调参数化部署非字符串的的数值时要将值tolnt
replicas: '${#toInt(parameters.replicas)}'
Manifest Configuration如下:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: nginxdemo
name: nginxdemo
namespace: dev
spec:
replicas: '${#toInt(parameters.replicas)}'
selector:
matchLabels:
k8s-app: nginxdemo
template:
metadata:
labels:
k8s-app: nginxdemo
name: nginxdemo
namespace: dev
spec:
containers:
- image: '${ parameters.image }'
imagePullPolicy: Always
name: nginxdemo
ports:
- containerPort: 80
name: web
protocol: TCP
running 流水线。这里为了跟上次区分replicas我手动输入了2!
验证结果如下:
流水线回滚
临时回滚(忽略没有找到)
但是1.26.6版本貌似排版变了我找了一圈没有找到临时回滚还是直接整自动回滚了!
配置回滚
先说一下流水线中的stage
Configuration 默认的是不计算在内的。发布应用是第一个添加的那他的id为0, 部署通知是第二个stage 他的id是1, Manual Judgment是第三个建立的 他的id是2, Undo Rollout是最后添加的他的id是3。
这个地方貌似有点很绕。stage是从0开始的,按照创建stage的顺序来的。
创建Manual Judgment stage
人工判断stage 。增加rollback done选项。done约定俗成是完成,rollback是回滚。作为下一步Undo Rollout触发的条件!
Manual Judgment 回滚 stage 选择
强调一下Manual Judgment的id是2。所以这里的stages是2 ,一下表达式的含义是流水线stages2中judgmentInput 是rollback。
${ execution['stages'][2].context.judgmentInput == "rollback" }
已经验证过了.....具体集群中pod的image就不截图了。这里最需要注意的的表达式的使用!
完善一下线上的流水线:
拿jenkins中spinnaker-nginx-demo pipeline 来搞。先说一下自己要实现的:
嗯gitlab触发jenkins打包镜像(这里重新定义镜像tag用时间)。然后将参数传播给spinnaker触发!
git仓库以及jenkins配置:
参照jenkins Trigger 触发器,当然了这里修改了一点参数化构建增加Dynimic Parameter(如何没有自己百度找插件)参数。定义名字data(可以自己定义名称,个人习惯就用data了)!
Default Value Script如下:
return new Date().format('yyyyMMddHHmm')
jenkins的流水线
就将镜像的tag修改为了data其实
//Docker 镜像仓库信息
registryServer = "harbor.xxxxx.com"
projectName = "${JOB_NAME}".split('-')[0]
repoName = "${JOB_NAME}"
imageName = "${registryServer}/${projectName}/${repoName}"
//pipeline
pipeline{
agent { node { label "build01"}}
//设置构建触发器
triggers {
GenericTrigger( causeString: 'Generic Cause',
genericVariables: [[defaultValue: '', key: 'branchName', regexpFilter: '', value: '$.ref']],
printContributedVariables: true,
printPostContent: true,
regexpFilterExpression: '',
regexpFilterText: '',
silentResponse: true,
token: 'spinnaker-nginx-demo')
}
stages{
stage("CheckOut"){
steps{
script{
srcUrl = "https://gitlab.xxxx.com/zhangpeng/spinnaker-nginx-demo.git"
branchName = branchName - "refs/heads/"
currentBuild.description = "Trigger by ${branchName}"
println("${branchName}")
checkout([$class: 'GitSCM',
branches: [[name: "${branchName}"]],
doGenerateSubmoduleConfigurations: false,
extensions: [],
submoduleCfg: [],
userRemoteConfigs: [[credentialsId: 'gitlab-admin-user',
url: "${srcUrl}"]]])
}
}
}
stage("Push Image "){
steps{
script{
withCredentials([usernamePassword(credentialsId: 'harbor-admin-user', passwordVariable: 'password', usernameVariable: 'username')]) {
sh """
sed -i -- "s/VER/${branchName}/g" app/index.html
docker login -u ${username} -p ${password} ${registryServer}
docker build -t ${imageName}:${data} .
docker push ${imageName}:${data}
docker rmi ${imageName}:${data}
"""
}
}
}
}
stage("Trigger File"){
steps {
script{
sh """
echo IMAGE=${imageName}:${data} >trigger.properties
echo ACTION=DEPLOY >> trigger.properties
cat trigger.properties
"""
archiveArtifacts allowEmptyArchive: true, artifacts: 'trigger.properties', followSymlinks: false
}
}
}
}
}
spinnaker中的pipeline设置
创建pipeline
在pipline-test应用(applications),中创建spinnaker-nginx-demo pipeline,这里我直接copy了Parameters-test1的流水线
Configuration中Automated Triggers 配置
jenkins 触发器并添加Property File(jenkins中的制品)trigger.properties(注意别多复制了空格)
注意:Parameters配置下删除了image参数 但是保留了replicas参数。自动触发默认参数仍是2 ,故后面的副本数量是2。
Deploy (Manifest) Configuration(发布应用 stage修改)
image: "${trigger['properties']['IMAGE']}"
Undo Rollout (Manifest)回滚应用的配置
git文件修改文件触发 and jenkins联动
登陆spinnakerweb验证
先选择一下done
就是下面这样的跳过了回滚的stage
验证镜像
rollback回滚验证
再触发一次 选择rollback
这里spinnaker显示jenkins构建80略慢.......
流水线webhook的信息
当然这里也可以把动作,构建参数个性化自定义一下?这里只是抛砖引玉简单的跑通。后续有好玩的可以更输入分享
后记
- 流水线stage在管道工具中的的id,这个地方一定要注意一下
- 非字符串参数的toInt
- 参数中偷懒复制名词的时候的空格
- 还一样比较坑的....我重装了一遍spinnaker练手。设置外部redis的时候配置文件携程了redis.yaml所以一直没有生效....找了好久的问题最后才发现,yaml vs yml切记。
- 只学习简单实用的功能,复杂的就不去研究了。深入研究请参考泽阳老师大佬的spinnaker课程。特别鸣谢泽阳大佬。jenkins spinnaker课程都是跟大佬的步伐来的!泽阳大佬的devops云学堂。