在完成前文的jenkins server 在k8s环境部署之后,本文我们来测试在k8s集群环境中的jenkins pipeline构建项目和更新,具体环境要求如下:
1、jenkins pipeline插件安装成功
2、要更新的应用已提前部署
3、Jenkins slave中需要有kubectl、svn、mvn客户端且环境变量设置准确
4、Jenkis slave需要能和master的api-server进行正常通信(这里为了简便,前文构建jenkins server的时候直接对defalut这个service account做rabc授权。其他可选方案是使用~/.kube/config文件实现客户端的授权认证)
5、需要配置共享卷(slave编译完成之后把war包copy到共享卷位置)
1、点击“jenkins ”——“新建 ”——“pipeline”,输入项目的名称,点击“OK”
2、下拉到“pipeline”配置,填写脚本
具体脚本内容如下:
podTemplate(name: 'jenkins-slave', cloud: 'kubernetes',
namespace: 'default', label: 'jenkins-slave',
serviceAccount: 'default', containers: [
containerTemplate(
name: 'jenkins-slave',
image: 'harbor.59iedu.com/fjhb/jenkins-slave-toolkit:2018-08-10-v1',
args: '${computer.jnlpmac} ${computer.name}',
ttyEnabled: true,
privileged: false,
alwaysPullImage:true,
)
],
volumes: [
persistentVolumeClaim(mountPath: '/tmp/', claimName: 'tomcat-jcsj-data')
]) {
node('jenkins-slave') {
stage('svn-checkout') {
container('jnlp') {
sh """
svn checkout --username=yanglw --password=mypassword http://192.168.1.81/svn/fjhbjsb/k8s-pipeline-test --non-interactive
"""
}
}
stage('mvn-package') {
container('jnlp') {
sh """
mkdir -p /var/jenkins_home && cd k8s-pipeline-test && mvn clean package && cp -rpf target/*.war /tmp/
"""
}
}
stage('restart') {
container('jnlp') {
sh """
pod_name=`kubectl get pods -l name=jcsj-dev -o name | cut -d"/" -f2`
kubectl delete pod \$pod_name
"""
}
}
}
}
3、脚本释义
podTemplate节指定创建pod的模板和环境
Name:为pod的名称前缀
Cloud:为构建pod的云环境,需要和前面新建的云环境名称一样
Namespace:创建pod所在的namespace
Label: 创建pod对应的标签
serviceAccount:pod使用sa,这里使用default, 所以前文创建jenkins master deployment的时候多创建了一个default-role,这样自动创建出来的的jenkins-slave具有对应的api权限
containerTemplate节
指定创建容器的模板,当云环境里面配置pod模板后,容器模板以云环境的配置为准。
Volumes节
配置jenkins-slave pod挂载的卷,当云环境里面配置pod模板后,挂载卷以云环境配置为准
stage节为具体的pipeline步骤
这里第一步进行svn代码迁出;
第二步进行编译,并把包传到共享卷上面;
第三步对pod进行删除,因为应用采用deployment方式部署,所以可以实现重新创建pod,达到更新的效果。
在开始构建之前,有必要介绍一下jcsj-dev的环境,这个环境是需要提前部署好的。部署文件如下
# cat deploy.yml
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: jcsj-dev
namespace: default
spec:
replicas: 1
template:
metadata:
labels:
name: jcsj-dev
spec:
containers:
- name: jcsj-dev
image: tomcat:latest
imagePullPolicy: IfNotPresent
ports:
- name: web
containerPort: 8080
volumeMounts:
- mountPath: /usr/local/tomcat/webapps
name: tomcat-jcsj-data
volumes:
- name: tomcat-jcsj-data
persistentVolumeClaim:
claimName: tomcat-jcsj-data
---
apiVersion: v1
kind: Service
metadata:
name: jcsj-dev
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
nodePort: 8453
selector:
name: jcsj-dev
# cat pv.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: tomcat-jcsj-data
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
nfs:
path: /home/tomcat_jcsj
server: 192.168.115.6
persistentVolumeReclaimPolicy: Recycle
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: tomcat-jcsj-data
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
点击“立即构建”,构建过程中可以通过控制台输出看具体的日志信息
构建过程中观察jenkins master的日志输出:
# kubectl logs -f jenkins-master-588b89c75f-ztvgm
INFO: Started provisioning Kubernetes Pod Template from kubernetes with 1 executors. Remaining excess workload: 0
Aug 13, 2018 10:14:22 AM hudson.slaves.NodeProvisioner$2 run
INFO: Kubernetes Pod Template provisioning successfully completed. We have now 2 computer(s)
Aug 13, 2018 10:14:22 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Created Pod: jenkins-slave-gjjbh in namespace default
Aug 13, 2018 10:14:22 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for Pod to be scheduled (0/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:28 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Container is waiting jenkins-slave-gjjbh [jnlp]: ContainerStateWaiting(message=null, reason=ContainerCreating, additionalProperties={})
Aug 13, 2018 10:14:28 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for Pod to be scheduled (1/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:34 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (1/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:35 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (2/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:36 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (3/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:37 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (4/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:38 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (5/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:39 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (6/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:40 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (7/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:41 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (8/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:42 AM hudson.TcpSlaveAgentListener$ConnectionHandler run
INFO: Accepted JNLP4-connect connection #1 from /172.30.66.4:47408
Aug 13, 2018 10:14:42 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (9/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:43 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (10/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:44 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (11/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:45 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (12/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:46 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (13/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:47 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (14/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:48 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (15/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:49 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (16/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:50 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (17/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:51 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (18/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:52 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (19/100): jenkins-slave-gjjbh
Aug 13, 2018 10:14:53 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
INFO: Waiting for agent to connect (20/100): jenkins-slave-gjjbh
Aug 13, 2018 10:15:12 AM org.csanchez.jenkins.plugins.kubernetes.pipeline.ContainerExecDecorator$1 doLaunch
INFO: Created process inside pod: [jenkins-slave-gjjbh], container: [jnlp] with pid:[-1]
Aug 13, 2018 10:15:21 AM org.csanchez.jenkins.plugins.kubernetes.pipeline.ContainerExecDecorator$1 doLaunch
INFO: Created process inside pod: [jenkins-slave-gjjbh], container: [jnlp] with pid:[-1]
Aug 13, 2018 10:16:04 AM org.csanchez.jenkins.plugins.kubernetes.pipeline.ContainerExecDecorator$1 doLaunch
INFO: Created process inside pod: [jenkins-slave-gjjbh], container: [jnlp] with pid:[-1]
Aug 13, 2018 10:16:06 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesSlave _terminate
INFO: Terminating Kubernetes instance for agent jenkins-slave-gjjbh
Aug 13, 2018 10:16:06 AM jenkins.slaves.DefaultJnlpSlaveReceiver channelClosed
WARNING: Computer.threadPoolForRemoting [#8] for jenkins-slave-gjjbh terminated
java.nio.channels.ClosedChannelException
at org.jenkinsci.remoting.protocol.impl.ChannelApplicationLayer.onReadClosed(ChannelApplicationLayer.java:208)
at org.jenkinsci.remoting.protocol.ApplicationLayer.onRecvClosed(ApplicationLayer.java:222)
at org.jenkinsci.remoting.protocol.ProtocolStack$Ptr.onRecvClosed(ProtocolStack.java:832)
at org.jenkinsci.remoting.protocol.FilterLayer.onRecvClosed(FilterLayer.java:287)
at org.jenkinsci.remoting.protocol.impl.SSLEngineFilterLayer.onRecvClosed(SSLEngineFilterLayer.java:181)
at org.jenkinsci.remoting.protocol.impl.SSLEngineFilterLayer.switchToNoSecure(SSLEngineFilterLayer.java:283)
at org.jenkinsci.remoting.protocol.impl.SSLEngineFilterLayer.processWrite(SSLEngineFilterLayer.java:503)
at org.jenkinsci.remoting.protocol.impl.SSLEngineFilterLayer.processQueuedWrites(SSLEngineFilterLayer.java:248)
at org.jenkinsci.remoting.protocol.impl.SSLEngineFilterLayer.doSend(SSLEngineFilterLayer.java:200)
at org.jenkinsci.remoting.protocol.impl.SSLEngineFilterLayer.doCloseSend(SSLEngineFilterLayer.java:213)
at org.jenkinsci.remoting.protocol.ProtocolStack$Ptr.doCloseSend(ProtocolStack.java:800)
at org.jenkinsci.remoting.protocol.ApplicationLayer.doCloseWrite(ApplicationLayer.java:173)
at org.jenkinsci.remoting.protocol.impl.ChannelApplicationLayer$ByteBufferCommandTransport.closeWrite(ChannelApplicationLayer.java:311)
at hudson.remoting.Channel.close(Channel.java:1295)
at hudson.remoting.Channel.close(Channel.java:1263)
at hudson.slaves.SlaveComputer.closeChannel(SlaveComputer.java:708)
at hudson.slaves.SlaveComputer.access$800(SlaveComputer.java:96)
at hudson.slaves.SlaveComputer$3.run(SlaveComputer.java:626)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Aug 13, 2018 10:16:06 AM org.csanchez.jenkins.plugins.kubernetes.pipeline.PodTemplateStepExecution$PodTemplateCallback finished
INFO: Removing pod template and deleting pod jenkins-slave-7gnwx from cloud kubernetes
Aug 13, 2018 10:16:06 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesSlave _terminate
INFO: Terminated Kubernetes instance for agent default/jenkins-slave-gjjbh
Aug 13, 2018 10:16:06 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesSlave _terminate
INFO: Disconnected computer jenkins-slave-gjjbh
Terminated Kubernetes instance for agent default/jenkins-slave-gjjbh
Aug 13, 2018 10:16:06 AM org.csanchez.jenkins.plugins.kubernetes.pipeline.PodTemplateStepExecution$PodTemplateCallback finished
WARNING: Failed to delete pod for agent default/jenkins-slave-7gnwx: not found
Aug 13, 2018 10:16:07 AM org.jenkinsci.plugins.workflow.job.WorkflowRun finish
INFO: k8s-pipeline-test #1 completed: SUCCESS
本文仅介绍的pipeline方式构建项目的过程,实际应用中还需要解决若干问题,例如:
1、svn checkout步骤需要明文配置用户名和密码,存在安全性问题
2、 每次执行构建都需要全量迁出代码,效率不高
3、要更新的应用需要提前部署好,不能适配首次编译部署场景
4、对共享卷存在依赖,解耦问题需要解决
研究了pipeline的语法结合shell脚本,基本可以解决上述问题,以下是pipeline代码
podTemplate(name: 'jenkins-slave', cloud: 'kubernetes',
namespace: 'default', label: 'jenkins-slave')
{
node('jenkins-slave') {
stage('svn-checkout') {
container('jnlp') {
checkout([$class: 'SubversionSCM',
additionalCredentials: [],
excludedCommitMessages: '',
excludedRegions: '',
excludedRevprop: '',
excludedUsers: '',
filterChangelog: false,
ignoreDirPropChanges: false,
includedRegions: '',
locations: [[cancelProcessOnExternalsFail: true,
credentialsId: 'ef21f2d3-cb39-468a-aa19-9175d96a365f',
depthOption: 'infinity',
ignoreExternalsOption: true,
local: '.',
remote: 'http://192.168.1.81/svn/fjhbjsb/k8s-pipeline-test']],
quietOperation: true, workspaceUpdater: [$class: 'UpdateUpdater']])
}
}
stage('mvn-package') {
container('jnlp') {
sh """
mvn clean package
"""
}
}
stage('build-docker-image') {
container('jnlp') {
sh '''
IMAGE_NAME="harbor.59iedu.com/fjhb/jcsj:v$BUILD_NUMBER"
CONATINER_NAME="jcsj-dev"
echo "192.168.1.227 harbor.59iedu.com" >> /etc/hosts
sed -i "s/BUILD_NUMBER/$BUILD_NUMBER/g" tomcat.yaml
sed -i "s/BUILD_NUMBER=1/BUILD_NUMBER=$BUILD_NUMBER/g" rolling-update.sh
docker login harbor.59iedu.com -u admin -p Harbor12345
docker build -t $IMAGE_NAME .
docker push $IMAGE_NAME
'''
}
}
stage('apply update') {
container('jnlp') {
sh '''
NAMESPACE=default
DEPLOYMENT=tomcat-jcsj
REGISTRY=harbor.59iedu.com/fjhb/jcsj:v$BUILD_NUMBER
FILE=tomcat.yaml
STATUS=$(kubectl get deployment -l k8s-app=$DEPLOYMENT -o name -n $NAMESPACE)
if [ ! $STATUS ];then
kubectl create -f $FILE
else
kubectl set image deployment/$DEPLOYMENT $DEPLOYMENT=$REGISTRY --namespace=$NAMESPACE
fi
'''
}
}
}
}
其中,svn-checkout节代码通过“流水线语法”工具生成,同时需要给default sa用户相应的权限,否则无法实现apply update节配置
# kubectl create clusterrolebinding k8s-admin --clusterrole=cluster-admin --user=system:serviceaccount:default:default
文章转载地址如下:
https://blog.51cto.com/ylw6006/2159861
往期精彩文章
kubernetes全栈技术+企业案例演示【带你快速掌握和使用k8s】
突破运维和开发瓶颈、Python、k8s、DevOps转型一网打尽!
python运维开发实战-基础篇
python运维和开发实战-高级篇
python运维和开发实战-安装和创建Django项目
Docker公司禁止被列入美国"实体名单"的国家、企业使用
kubernetes面试题汇总
DevOps视频和资料免费领取
kubernetes技术分享-可用于企业内部培训
谈谈我的IT发展之路
kubernetes系列文章第一篇-k8s基本介绍
kubernetes系列文章第二篇-kubectl
了解pod和pod的生命周期-这一篇文章就够了
Kubernetes中部署MySQL高可用集群
Prometheus+Grafana+Alertmanager搭建全方位的监控告警系统-超详细文档
k8s1.18多master节点高可用集群安装-超详细中文官方文档
k8s中蓝绿部署、金丝雀发布、滚动更新汇总
运维常见问题汇总-tomcat篇
关于linux内核参数的调优,你需要知道
kubernetes挂载ceph rbd和cephfs
报警神器Alertmanager发送报警到多个渠道
jenkins+kubernetes+harbor+gitlab构建企业级devops平台
kubernetes网络插件-flannel篇
kubernetes网络插件-calico篇
kubernetes认证、授权、准入控制
限制不同的用户操作k8s资源
面试真题&技术资料免费领取-覆盖面超全~
Prometheus监控MySQL
Prometheus监控Nginx
Prometheus监控Tomcat
linux面试题汇总
测试通过storageclass动态生成pv
通过编写k8s的资源清单yaml文件部署gitlab服务
helm安装和使用-通过helm部署k8s应用
k8s基于Ingress-nginx实现灰度发布
k8s的Pod安全策略
Prometheus Operator-上篇-安装和使用篇
Prometheus Operator-下篇
通过kubeconfig登陆k8s的dashboard ui界面
通过token令牌登陆k8s dashboard ui界面
kubernetes集群的etcd数据库详细介绍
Linux网络流量监控工具
kubernetes搭建EFK日志管理系统
prometheus operator监控k8s集群之外的haproxy组件
kubernetes ConfigMap存储卷
学无止境,了解更多关于kubernetes/docker/devops/openstack/openshift/linux/IaaS/PaaS相关内容,想要获取更多资料和免费视频,可按如下方式进入技术交流群
扫码加群????
微信:luckylucky421302
长按指纹关注公众号????
点击在看少个 bug????