基于Kubernetes Jenkins CICD

释放双眼,带上耳机,听听看~!
传统构建jenkins会有许多的问题,我们需要采用一种更高效可靠的方式来完成这个CI/CD流程,而Docker虚拟化容器技能很好的解决这个痛点,又特别是在Kubernetes集群环境下面能够更好来解决上面的问题

一、在Kubernetes 安装 Jenkins优点

目前很多公司采用Jenkins集群搭建复合需求的CI/CD流程,但是会存在一些问题

  • 主Master发生单点故障时,整个流程都不可用
  • 每个Slave的环境配置不一样,来完成不同语言的编译打包,但是这些差异化的配置导致管理起来不方便,维护麻烦
  • 资源分配不均衡,有的slave要运行的job出现排队等待,而有的salve处于空闲状态
  • 资源有浪费,每台slave可能是物理机或者虚拟机,当slave处于空闲状态时,也不能完全释放掉资源

正因为上面的问题,我们需要采用一种更高效可靠的方式来完成这个CI/CD流程,而Docker虚拟化容器技能很好的解决这个痛点,又特别是在Kubernetes集群环境下面能够更好来解决上面的问题

基于Kubernetes Jenkins CICD

如上图我们可以看到Jenkins master和Jenkins slave以Pod形式运行在Kubernetes集群的Node上,Master运行在其中一个节点,并且将其配置数据存储到一个volume上去,slave运行在各个节点上,但是它的状态并不是一直处于运行状态,它会按照需求动态的创建并自动删除

这种方式流程大致为: 当Jenkins Master接受到Build请求后,会根据配置的Label动态创建一个运行在Pod中的Jenkins Slave并注册到Master上,当运行完Job后,这个Slave会被注销并且这个Pod也会自动删除,恢复到最初的状态(这个策略可以设置)

  • 服务高可用,当Jenkins Master出现故障时,Kubernetes会自动创建一个新的Jenkins Master容器,并且将Volume分配给新创建的容器,保证数据不丢失,从而达到集群服务高可用的作用
  • 动态伸缩,合理使用资源,每次运行Job时,会自动创建一个Jenkins Slave,Job完成后,Slave自动注销并删除容器,资源自动释放,并且Kubernetes会根据每个资源的使用情况,动态分配slave到空闲的节点上创建,降低出现因某节点资源利用率高,降低出现因某节点利用率高出现排队的情况
  • 扩展性好,当Kubernetes集群的资源严重不足导致Job排队等待时,可以很容器的添加一个Kubernetes Node到集群,从而实现扩展

二、Kubernetes 安装Jenkins

这里我们使用k8s的pv进行存储数据,当然也可以使用storage class对象来自动创建

创建pv需要使用nfs,我这里直接创建一台nfs服务器

我们在k8s集群的任意一个节点配置一台nfs集群,其他节点主要是挂载
for i in k8s-01 k8s-02 k8s-03 k8s-04;do ssh root@$i "yum install nfs-utils rpcbind -y";done

#我这里使用单独的NFS服务器,IP为192.168.0.100
#NFS服务节点操作如下
mkdir -p /data1/k8s-vloume
echo "/data1/k8s-vloume  *(rw,no_root_squash,sync)" >/etc/exports
systemctl start rpcbind
systemctl enable rpcbind
systemctl enable nfs
systemctl restart nfs
#IP改成网段

其他k8s节点直接启动rpcbind并且挂载目录就可以

#挂载
systemctl start rpcbind
systemctl enable rpcbind
mkdir /data1/k8s-vloume -p
mount -t nfs 192.168.0.100:/data1/k8s-vloume /data1/k8s-vloume


#创建完成你们自己测一下就可以了

这里需要创建一个命名空间

kubectl create namespace abcdocker

#在创建一下jenkins存储yaml的目录
mkdir -p /opt/jenkins 

接下来我们开始创建Jenkins Deployment

vim /opt/jenkins/jenkins_deployment.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: jenkins         #deployment名称
  namespace: abcdocker      #命名空间
spec:
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      terminationGracePeriodSeconds: 10     #优雅停止pod
      serviceAccount: jenkins               #后面还需要创建服务账户
      containers:
      - name: jenkins
        image: jenkins/jenkins:lts               #镜像版本
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080                #外部访问端口
          name: web
          protocol: TCP
        - containerPort: 50000              #jenkins save发现端口
          name: agent
          protocol: TCP
        resources:
          limits:
            cpu: 1000m
            memory: 1Gi
          requests:
            cpu: 500m
            memory: 512Mi
        livenessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60          #容器初始化完成后,等待60秒进行探针检查
          timeoutSeconds: 5
          failureThreshold: 12          #当Pod成功启动且检查失败时,Kubernetes将在放弃之前尝试failureThreshold次。放弃生存检查意味着重新启动Pod。而放弃就绪检查,Pod将被标记为未就绪。默认为3.最小值为1
        readinessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        volumeMounts:                       #需要将jenkins_home目录挂载出来
        - name: jenkinshome
          subPath: jenkins
          mountPath: /var/jenkins_home
        env:
        - name: LIMITS_MEMORY
          valueFrom:
            resourceFieldRef:
              resource: limits.memory
              divisor: 1Mi
        - name: JAVA_OPTS
          value: -Xmx$(LIMITS_MEMORY)m -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85 -Duser.timezone=Asia/Shanghai
      securityContext:
        fsGroup: 1000
      volumes:
      - name: jenkinshome
        persistentVolumeClaim:
          claimName: opspvc             #这里将上面创建的pv关联到pvc上

#这里不进行创建

因为要保证Jenkins持久化缓存数据,我们创建了一个PV

cat >/opt/jenkins/jenkins_pv.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: opspv
spec:
  capacity:
    storage: 20Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  nfs:
    server: 192.168.0.100
    path: /data1/k8s-vloume

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: opspvc
  namespace: abcdocker
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 20Gi
EOF

#注意修改NFS挂载目录以及NFS Server
#nfs后面的目录是nfs挂载的目录,因为pod会执行mount -t ip:/data1/所以后面是nfs挂载目录,而并非是宿主机的目录

另外还需要一个拥有相关权限的serviceAccount的Jenkins用户,这里我们手动赋予Jenkins一些必要的权限,当然直接给cluster-admin的集群角色权限也是可以的

cat >/opt/jenkins/jenkins_rbac.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
  namespace: abcdocker

---

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: jenkins
rules:
  - apiGroups: ["extensions", "apps"]
    resources: ["deployments"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["create","delete","get","list","patch","update","watch"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create","delete","get","list","patch","update","watch"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get","list","watch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: jenkins
  namespace: abcdocker
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: jenkins
subjects:
  - kind: ServiceAccount
    name: jenkins
    namespace: abcdocker
EOF

现在还缺少一个svc,因为我们虽然现在jenkins已经在内部可以访问,但是我们在外面是无法访问的。接下来我们创建一个svc

cat >/opt/jenkins/jenkins_svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: jenkins
  namespace: abcdocker
  labels:
    app: jenkins
spec:
  selector:
    app: jenkins
  type: NodePort
  ports:
  - name: web
    port: 8080
    targetPort: web
    nodePort: 30002
  - name: agent
    port: 50000
    targetPort: agent
EOF

接下来我们进行创建

[root@abcdocker-k8s01 jenkins]# ll
total 16
-rw-r--r-- 1 root root 2453 Aug 29 17:42 jenkins_deployment.yaml
-rw-r--r-- 1 root root  407 Aug 29 17:43 jenkins_pv.yaml
-rw-r--r-- 1 root root 1120 Aug 29 17:43 jenkins_rbac.yaml
-rw-r--r-- 1 root root  289 Aug 29 17:43 jenkins_svc.yaml

这里可以直接使用kubectl apple -f .,我为了排查错误,进行一个顺序执行

#这里我先执行pv然后在执行rbac,依次deployment和svc
[root@abcdocker-k8s01 jenkins]# kubectl apply -f jenkins_pv.yaml 
persistentvolume/opspv created
persistentvolumeclaim/opspvc created
[root@abcdocker-k8s01 jenkins]# kubectl apply -f jenkins_rbac.yaml 
serviceaccount/jenkins created
clusterrole.rbac.authorization.k8s.io/jenkins created
clusterrolebinding.rbac.authorization.k8s.io/jenkins created
[root@abcdocker-k8s01 jenkins]# kubectl apply -f jenkins_deployment.yaml 
deployment.extensions/jenkins created
[root@abcdocker-k8s01 jenkins]# kubectl apply -f jenkins_rbac.yaml 
serviceaccount/jenkins unchanged
clusterrole.rbac.authorization.k8s.io/jenkins unchanged
clusterrolebinding.rbac.authorization.k8s.io/jenkins unchanged
[root@abcdocker-k8s01 jenkins]# kubectl apply -f jenkins_svc.yaml 
service/jenkins created

创建完毕后,我们进行检查

#首先查看pvc状态
kubectl get pv,pvc -n abcdocker 
NAME                     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   REASON   AGE
persistentvolume/opspv   20Gi       RWX            Delete           Bound    abcdocker/opspvc                           65s

NAME                           STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/opspvc   Bound    opspv    20Gi       RWX                           65s


#接下来查看rbac
kubectl get serviceaccounts -n abcdocker |grep jenkins
jenkins   1         104s

#最后检查pod和svc
kubectl get pod,svc -n abcdocker
NAME                          READY   STATUS    RESTARTS   AGE
pod/jenkins-6b874b8d7-dhv57   1/1     Running   0          8m26s

NAME              TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                          AGE
service/jenkins   NodePort   10.254.154.161           8080:30002/TCP,50000:21866/TCP   62s

#需要说明一下8080端口为我们jenkins访问端口
#50000端口为jenkins save发现端口

Pod正常运行了,我们就可以通过浏览器访问集群任意IP的svc端口

基于Kubernetes Jenkins CICD

管理员密码文件路径,也可以在pod 日志里面看到

cat /data1/k8s-vloume/jenkins/secrets/initialAdminPassword
6d3c67495bcb43c2a74d97309702dab7

#因为我们持久化在/data/k8s下,所以jenkins的所有配置都在这下面

直接选择推荐安装就可以

基于Kubernetes Jenkins CICD

等待安装完毕

基于Kubernetes Jenkins CICD

安装完成后我们进入jenkins主页面

基于Kubernetes Jenkins CICD

接下来就是配置Jenkins

我们需要安装k8s插件,让Jenkins构建Job可以动态生成Slave的Pod

点击Jenkins-->插件-->安装插件Kubernetes

基于Kubernetes Jenkins CICD

安装完毕后会重启Jenkins,然后我们就可以配置插件

Manage Jenkins >>Configure System 找到插件

基于Kubernetes Jenkins CICD

在配置上拉到最下面,ADD一个Kubernetes

基于Kubernetes Jenkins CICD

Name   配置的名称
Kubernetes URL  这里的URL是K8s内部的URL,实际上就是svcname 这里不需要修改直接复制就行
Kubernetes Namespace k8s的命名空间 (实际上就是Jenkins所在的命名空间)

https://kubernetes.default.svc.cluster.local

svcname+default+后面参数复制就可以

基于Kubernetes Jenkins CICD

Jenkins URL   这里的URL是jenkins的svc名称加上命名空间,实际上就是在k8s集群内部访问jenkins的一个方法,这里也不需要修改
http://jenkins.abcdocker.svc.cluster.local:8080

#其他默认即可

基于Kubernetes Jenkins CICD

添加一个 Jenkins Slave Pod模板

基于Kubernetes Jenkins CICD

Name   = Pod 名称
Namespave   = Pod命名空间
Labels   =  Pod标签

基于Kubernetes Jenkins CICD

接下来是容器的模板配置

Name  容器的名称
Docker image  镜像,这里直接使用我的镜像
#jenkins 2.176.x版本以上使用:registry.cn-beijing.aliyuncs.com/abcdocker/jenkins:v1.2
#jenkins 2.176.x版本以下使用:registry.cn-beijing.aliyuncs.com/abcdocker/jenkins:v1.1
#jenkins 2.176以上版本有maven命令使用:registry.cn-beijing.aliyuncs.com/abcdocker/jenkins:v1.4

#镜像里面主要是运行了kubectl命令和Docker的配置,下面我们还需要将kubeconfig挂载进来


########
如果需要自定义maven仓库可以使用下面的dockerfile
[root@k8s-01 jenkins]# cat Dockerfile
FROM registry.cn-beijing.aliyuncs.com/abcdocker/jenkins:v1.2
MAINTAINER abcdocker "i4t.com"
COPY maven /usr/local/maven
RUN cd /usr/local/maven

红色代表不可以修改,否则jenkins slave启动会提示错误,反复重启

基于Kubernetes Jenkins CICD

如果jenkins提示权限错误,请在配置中添加jenkins rbac创建的serviceaccounts

基于Kubernetes Jenkins CICD

上面说了,镜像主要是用于kubectl,kubectl是需要kubeconfig文件,所以我们还需要创建一个volume的配置

基于Kubernetes Jenkins CICD

如果我们想在容器里面执行docker命令,需要将docker.sock挂载进去

还需要将kubeconfig挂在进容器

基于Kubernetes Jenkins CICD

基于Kubernetes Jenkins CICD

然后我们点击保存即可

接下来添加一个job,来测试一下jenkins是否可以在slave节点上执行

基于Kubernetes Jenkins CICD

接下来进行配置Jenkins

这里的label标签就是我们在配置中配置的标签

基于Kubernetes Jenkins CICD

配置标签的地方

基于Kubernetes Jenkins CICD

添加一个shell命令,测试docker和kubectl

基于Kubernetes Jenkins CICD

现在我们先看一下Pod是否可以动态获取

$ kubectl get pod -n abcdocker
NAME                      READY   STATUS    RESTARTS   AGE
jenkins-6b874b8d7-xxwwr   1/1     Running   0          31h

#目前只有一个jenkins在运行,接下来我们进行构建项目

容器正在创建,目前属于等待状态

基于Kubernetes Jenkins CICD

这里可以看到已经新启动了一个pod节点

$ kubectl get pod -n abcdocker
NAME                      READY   STATUS              RESTARTS   AGE
jenkins-6b874b8d7-xxwwr   1/1     Running             0          2d
jenkins-slave-423xz       0/1     ContainerCreating   0          5s

等待容器创建成功,Jenkins就会绑定到这个Pod节点上,进行执行任务

基于Kubernetes Jenkins CICD

如果遇到pod一直重启的情况,请使用kubectl get pod -n xxx -o wide查看pod运行节点,使用docker ps过滤出pod,通过docker logs -f查看错误日志

当Jenkins slave节点执行完毕任务后,默认情况下执行完job就会被删除

$ kubectl get pod -n abcdocker
NAME                      READY   STATUS    RESTARTS   AGE
jenkins-6b874b8d7-xxwwr   1/1     Running   0          2d

如果想让job等待30分钟释放,可以在下图添加

基于Kubernetes Jenkins CICD

小结 Jenkins Master收到Build请求时,会根据配置的Label动态创建一个运行在Pod中的Jenkins Slave并注册到Master上,当Job运行完,这个Slave会被注销并且这个Pod也会自动删除,恢复到最初状态


三、项目演示 使用Jenkins Pipline部署

Jenkins Pipline介绍

Gitlab配置

接下来我们在代码仓库创建一个分支

基于Kubernetes Jenkins CICD

配置root用户免密

首先先查看服务器公钥

基于Kubernetes Jenkins CICD

上git配置key

基于Kubernetes Jenkins CICD

接下来在服务器上提交git代码就可以

基于Kubernetes Jenkins CICD

上传代码

#这里需要有git命令
yum install -y git 
git config --global user.name "root"
git config --global user.email "admin@example.com"

#克隆
git clone git@10.4.82.15:root/abcdocker-test.git
cd abcdocker-test
wget http://down.i4t.com/hello-world-war-master.zip
unzip hello-world-war-master.zip
mv hello-world-war-master/* .
rm -rf hello-world-war-master*

#提交代码


#接下来看图就行了

gitlab配置完毕

基于Kubernetes Jenkins CICD


四、配置Dockerfile

首先我们需要自定义一个tomcat基础镜像,也可以使用dockerhub提供的

cat >>Dockerfile <<EOF
FROM centos
MAINTAINER www.i4t.com "cyh@i4t.com"
WORKDIR /tmp
## Please see https://i4t.com/3552.html   install JDK
COPY jdk1.8.0_66.tar.gz /tmp
    RUN tar zxf /tmp/jdk1.8.0_66.tar.gz -C /usr/local/ && rm -rf /tmp/jdk1.8.0_66.tar.gz && \
        ln -s /usr/local/jdk1.8.0_66 /usr/local/jdk
#/etc/profile
    ENV JAVA_HOME /usr/local/jdk
    ENV CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV PATH $PATH:$JAVA_HOME/bin
# add apache
# Please see i4t.com && baidu.com
    COPY apache-tomcat-8.5.39.tar.gz /tmp
    RUN tar zxf apache-tomcat-8.5.39.tar.gz -C /usr/local  && rm -rf /tmp/apache-tomcat-8.5.39.tar.gz && \
        mv /usr/local/apache-tomcat-8.5.39 /usr/local/tomcat && \
        rm -rf /usr/local/tomcat/webapps/docs examples host-manager manager
EXPOSE 8080
ENTRYPOINT /usr/local/tomcat/bin/startup.sh && tail -f /usr/local/tomcat/logs/catalina.out
EOF

###接下来需要下载相对应的安装包  (Dockerfile和JDK和tomcat需要放在一个目录下)
wget http://down.i4t.com/jdk1.8.0_66.tar.gz
wget http://down.i4t.com/apache-tomcat-8.5.39.tar.gz

接下来可以进行打包

docker build -t registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:v2 .

#如果不想自己做tomcat镜像,也可以使用dockerhub上的镜像。也可以使用我这里打包好的镜像

现在我们已经完成tomcat镜像的创建,接下来配置Jenkins,每次打包上线自动替换ROOT目录

五、编写jenkins Pipline

Jenkins pipline 语法介绍

配置gitlab账号密码

由于Jenkins需要使用gitlab账号密码,这里我们做一下免密

基于Kubernetes Jenkins CICD

基于Kubernetes Jenkins CICD

基于Kubernetes Jenkins CICD

配置如下

基于Kubernetes Jenkins CICD

创建Jenkins pipline项目

基于Kubernetes Jenkins CICD

我这里添加参数化构建

基于Kubernetes Jenkins CICD

接下来编写jenkins pipline脚本

node('abcdocker-slave') {
    stage('Git Clone') {
         checkout([$class: 'GitSCM', branches: [[name: '${git}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'gitlab_password', url: 'http://192.168.0.100/root/abcdocker-test.git']]])    

    }
    stage('Maven Build') {
           sh '''
        /usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true -f $WORKSPACE

        echo FROM registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:test2 >$WORKSPACE/target/Dockerfile
        echo RUN  rm -rf /usr/local/tomcat/webapps/* >>$WORKSPACE/target/Dockerfile
        echo COPY hello-world-war-1.0.0 /usr/local/tomcat/webapps/ROOT >>$WORKSPACE/target/Dockerfile
           '''

      echo "3.Docker Build Stage"
           sh '''
        docker build -t registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:${git} ${WORKSPACE}/target/
        docker login --username=用户名 registry.cn-beijing.aliyuncs.com --password 镜像密码
        docker push registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:${git}
              '''
    }
    stage('Deploy') {
      echo "4. Deploy Stage"
      sh'kubectl set image deployment/tomcat -n abcdocker-test my-tomcat=registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:${git}'
    }
}

Pipline脚本讲解

node('abcdocker-slave') {

#这里代表node节点运行在标签为abcdocker-slave上,前面已经定义了,这里就不在定义

gitlab拉取代码配置

    stage('Git Clone') {
         checkout([$class: 'GitSCM', branches: [[name: '${git}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'gitlab_password', url: 'http://192.168.0.100/root/abcdocker-test.git']]])    
    }

#这里就是一个选择git地址,然后分支。不会生成可以参考pipline语法

在下图生成的配置直接拷贝到pipline里面ji

基于Kubernetes Jenkins CICD

Java maven打包步骤

我这里使用阿里云的镜像仓库,演示一下如何上传。

这里需要注意的是,我们的jenkins slave节点的Pod镜像需要使用下面我提供的版本,否则没有maven命令

registry.cn-beijing.aliyuncs.com/abcdocker/jenkins:v1.4

    stage('Maven Build') {
        sh '''
        /usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true -f $WORKSPACE
        echo FROM registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:test2 >$WORKSPACE/target/Dockerfile
        echo RUN  rm -rf /usr/local/tomcat/webapps/* >>$WORKSPACE/target/Dockerfile
        echo COPY hello-world-war-1.0.0 /usr/local/tomcat/webapps/ROOT >>$WORKSPACE/target/Dockerfile
        '''
      echo "3.Docker Build Stage"
           sh '''
          docker build -t registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:${git} ${WORKSPACE}/target/
          docker login --username=cyh60441314 registry.cn-beijing.aliyuncs.com --password XXXX密码
          docker push registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:${git}
              '''
    }

接下来是使用kubectl set替换镜像

    stage('Deploy') {
      echo "4. Deploy Stage"
      sh'kubectl set image deployment/tomcat -n abcdocker-test my-tomcat=registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:${git}'
    }

命令参数解释

kubectl set image deployment/SVC_NAME -n namespace_name container_name=images:v1

#注意后面是容器名称,并不是svc名称

完整Jenkins Pipline脚本如下

node('abcdocker-slave') {
    stage('Git Clone') {
         checkout([$class: 'GitSCM', branches: [[name: '${git}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'gitlab_password', url: 'http://192.168.0.100/root/abcdocker-test.git']]])    

    }
    stage('Maven Build') {
        sh '''
        /usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true -f $WORKSPACE

        echo FROM registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:test2 >$WORKSPACE/target/Dockerfile
        echo RUN  rm -rf /usr/local/tomcat/webapps/* >>$WORKSPACE/target/Dockerfile
        echo COPY hello-world-war-1.0.0 /usr/local/tomcat/webapps/ROOT >>$WORKSPACE/target/Dockerfile
        '''

      echo "3.Docker Build Stage"
           sh '''
          docker build -t registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:${git} ${WORKSPACE}/target/
          docker login --username=用户名 registry.cn-beijing.aliyuncs.com --password harbor密码
          docker push registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:${git}
              '''
    }
    stage('Deploy') {
      echo "4. Deploy Stage"
      sh'kubectl set image deployment/tomcat -n abcdocker-test my-tomcat=registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:${git}'
    }
}

然后jenkins我们点击保存

创建tomcat svc环境

#创建命名空间
kubectl create namespace abcdocker-test

创建tomcat deploy文件

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    name: tomcat
  name: tomcat
  namespace: abcdocker-test
spec:
  replicas: 1
  selector:
    matchLabels:
      name: tomcat
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: tomcat
        name: tomcat
    spec:
      containers:
      - env:
        - name: JAVA_OPTS
          value: -server -d64 -XX:MetaspaceSize=256m
        - name: MAX_HEAP
          value: 512m
        - name: MIN_HEAP
          value: 512m
        image: registry.cn-beijing.aliyuncs.com/abcdocker/tomcat:v2
        imagePullPolicy: IfNotPresent
        name: my-tomcat
        ports:
        - containerPort: 8080
          protocol: TCP
        resources:
          limits:
            memory: 1536Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File

创建svc

apiVersion: v1
kind: Service
metadata:
  name: my-tomcat-svc
  namespace: abcdocker-test
  labels:
    app: tomcat
spec:
  selector:
    app: tomcat
  type: NodePort
  ports:
  - name: web
    port: 8080
    #targetPort: 8080
    nodePort: 30005

创建之后我们查看状态

[root@k8s-01 ~]# kubectl get pod,svc -n abcdocker-test
NAME                          READY   STATUS    RESTARTS   AGE
pod/tomcat-855dccd5bc-wkn5z   1/1     Running   0          27m

NAME                    TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/my-tomcat-svc   NodePort   10.254.62.11           8080:30005/TCP   26h

访问页面,查看是否正常 (集群任意IP+30005)

基于Kubernetes Jenkins CICD

项目部署

接下来我们演示一下环境部署

基于Kubernetes Jenkins CICD

点击Build

基于Kubernetes Jenkins CICD

我这里没有区分环境,这里也是可以区分环境的

基于Kubernetes Jenkins CICD

日志分析

基于Kubernetes Jenkins CICD

基于Kubernetes Jenkins CICD

基于Kubernetes Jenkins CICD

基于Kubernetes Jenkins CICD

替换镜像

基于Kubernetes Jenkins CICD

效果图

基于Kubernetes Jenkins CICD

Jenkins上也可以看到每个步骤的构建时间

基于Kubernetes Jenkins CICD

给TA打赏
共{{data.count}}人
人已打赏
Jenkins

Jenkins theme生成定制主题css

2019-4-24 18:20:35

报错锦集

ERROR 2006 (HY000): MySQL server has gone away No connection. Trying to reconnect... Connection id: 125 Current database: *** NONE ***

2022-12-1 19:03:29

22 条回复 A文章作者 M管理员
  1. IT废柴

    强烈建议在文档中记述k8s的版本.
    比如, 新版本的deployment已经从“apiVersion: extensions/v1beta1”改到“apiVersion: apps/v1”了.

  2. IT废柴

    此处笔误:
    cat /data/k8s/jenkins/secrets/initialAdminPassword
    ->
    cat /data1/k8s-vloume/jenkins/secrets/initialAdminPassword

  3. 华军

    slave pod 不断重启
    Waiting for agent to connect (83/100): jnlp-5xf64
    Feb 29, 2020 11:34:49 AM INFO org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
    Waiting for agent to connect (84/100): jnlp-5xf64
    Feb 29, 2020 11:34:50 AM INFO org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
    Waiting for agent to connect (85/100): jnlp-5xf64
    Feb 29, 2020 11:34:51 AM INFO org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
    Waiting for agent to connect (86/100): jnlp-5xf64
    Feb 29, 2020 11:34:52 AM INFO org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
    Waiting for agent to connect (87/100): jnlp-5xf64
    Feb 29, 2020 11:34:53 AM INFO org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
    Waiting for agent to connect (88/100): jnlp-5xf64
    Feb 29, 2020 11:34:54 AM INFO org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
    Waiting for agent to connect (89/100): jnlp-5xf64
    Feb 29, 2020 11:34:55 AM INFO org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
    Waiting for agent to connect (90/100): jnlp-5xf64
    Feb 29, 2020 11:34:56 AM INFO org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher launch
    Waiting for agent to connect (91/100): jnlp-5xf64
    Error in provisioning; agent=KubernetesSlave name: jnlp-z5286, template=PodTemplate{inheritFrom=”, name=’jnlp’, namespace=’abcdocker’, hostNetwork=false, label=’jnlp’, serviceAccount=’jenkins’, nodeSelector=”, nodeUsageMode=EXCLUSIVE, workspaceVolume=EmptyDirWorkspaceVolume [memory=false], volumes=[HostPathVolume [mountPath=/var/run/docker.sock, hostPath=/var/run/docker.sock], HostPathVolume [mountPath=/home/jenkins/.kube, hostPath=/root/.kube]], containers=[ContainerTemplate{name=’jnlp’, image=’registry.cn-beijing.aliyuncs.com/abcdocker/jenkins:v1.2′, workingDir=’/home/jenkins/agent’, command=’/bin/sh -c’, args=’cat’, ttyEnabled=true, resourceRequestCpu=”, resourceRequestMemory=”, resourceLimitCpu=”, resourceLimitMemory=”, livenessProbe=org.csanchez.jenkins.plugins.kubernetes.ContainerLivenessProbe@651c1a74}]}
    java.lang.IllegalStateException: Agent is not connected after 100 seconds, status: Running
    at org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher.launch(KubernetesLauncher.java:209)
    at hudson.slaves.SlaveComputer.lambda$_connect$0(SlaveComputer.java:292)
    at jenkins.util.ContextResettingExecutorService$2.call(ContextResettingExecutorService.java:46)
    at jenkins.security.ImpersonatingExecutorService$2.call(ImpersonatingExecutorService.java:71)
    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)

    • 新闻联播老司机

      你看一下Jenkins的日志,还有几个相关pod日志。 多半是有的地方写错了

  4. IT废柴

    >这里可以直接使用kubectl apple -f .,
    这地方写错了, 应该是kubectl apply -f .

  5. IT废柴

    容器中jenkins user的uid为1000, 因此需要修改下目录权限
    chown -R 1000:1000 /data1/k8s-vloume

    要不然会出现以下错误:
    touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied
    Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?

  6. IT废柴

    如何设置才能环境变量才能使/usr/local/maven/bin/mvn简化成mvn?

  7. IT废柴

    #################################
    如果需要自定义maven仓库可以使用下面的dockerfile
    [root@k8s-01 jenkins]# cat Dockerfile
    FROM registry.cn-beijing.aliyuncs.com/abcdocker/jenkins:v1.2
    MAINTAINER abcdocker “i4t.com”
    COPY maven /usr/local/maven
    RUN cd /usr/local/maven
    #################################
    这意思是自定义maven仓库的设定信息,比如用户名/密码之类的都在
    /usr/local/maven/conf/settings.xml里固定是吗?
    可不可以挂载外部主机的~/.m2/settings.xml文件?如何操作?

    • 新闻联播老司机

      可以固定在外面,用ds不要用deployment,然后所有主机挂在就可以了

    • 新闻联播老司机

      我后面不是给dockerfile了嘛。你都可以直接把你们环境的maven整个目录打包进去

    • IT废柴

      能把你from 官方镜像之后的完整dockerfile放出来吗?
      registry.cn-beijing.aliyuncs.com/abcdocker/jenkins:v1.1
      registry.cn-beijing.aliyuncs.com/abcdocker/jenkins:v1.2
      registry.cn-beijing.aliyuncs.com/abcdocker/jenkins:v1.4

    • 新闻联播老司机

      FROM debian:stretch

      ENV JAVA_HOME=/usr/local/newhope/java1.8 \ PATH=/usr/local/newhope/java1.8/bin:$PATH \ TIMEZONE=Asia/Shanghai \ LANG=zh_CN.UTF-8

      RUN echo “${TIMEZONE}” > /etc/timezone \ && echo “$LANG UTF-8” > /etc/locale.gen \ && apt-get update -q \ && ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \ && mkdir -p /usr/local/newhope/java1.8 \ && mkdir -p /home/jenkins/.jenkins \ && mkdir -p /home/jenkins/agent \ && mkdir -p /usr/share/jenkins \ && mkdir -p /root/.kube

      COPY java1.8 /usr/local/newhope/java1.8 COPY kubectl /usr/local/bin/kubectl COPY jenkins-slave /usr/local/bin/jenkins-slave COPY slave.jar /usr/share/jenkins

      java/字符集/DinD/svn/jnlp
      RUN mkdir /usr/java/jdk1.8.0_121/bin -p \ && ln -s /usr/local/newhope/java1.8 /usr/java/jdk1.8.0_121 \ && DEBIAN_FRONTEND=noninteractive apt-get install -yq curl apt-utils dialog locales apt-transport-https build-essential bzip2 ca-certificates sudo jq unzip zip gnupg2 software-properties-common \ && update-locale LANG=$LANG \ && locale-gen $LANG \ && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales \ &&curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo “$ID”)/gpg |apt-key add – \ && add-apt-repository “deb arch=amd64 https://download.docker.com/linux/$(. /etc/os-release; echo “$ID”) $(lsb_release -cs) stable” \ && apt-get update -y \ && apt-get install -y docker-ce=17.09.1~ce-0~debian \ && sudo apt-get install -y subversion \ && groupadd -g 10000 jenkins \ && useradd -c “Jenkins user” -d $HOME -u 10000 -g 10000 -m jenkins \ && usermod -a -G docker jenkins \ && sed -i ‘/^root/a\jenkins ALL=(ALL:ALL) NOPASSWD:ALL’ /etc/sudoers

      USER root

      WORKDIR /home/jenkins

      ENTRYPOINT “jenkins-slave”

    • 新闻联播老司机

      maven的配置几乎不咋变化,及时变化从新修改打包也很方便,时间不会太慢

  8. IT废柴

    ClusterRole这块的设定怎么改才能让该Jenkins可以执行其他namespace的命令(scale)
    Jenkins所在的namespace:abcdocker
    应用所在的namespace:devops
    scale命令不行,其他get命令可以
    kubectl -n devops scale deploy/devdiscovery –replicas=0
    出现以下错误:
    Error from server (Forbidden): deployments.apps “discovery” is forbidden: User “system:serviceaccount:abcdocker:jenkins” cannot update resource “deployments/scale” in API group “apps” in the namespace “devops”

  9. 夜下寒星

    请教下,我想把sqlcmd的命令,跑在jenkins-slave节点,但是sqlcmd命令,无法通过dockerfile直接编译,基于你的镜像跑了个容器,然后把这命令安装好后,再打包这个镜像,打包后的镜像无法在jenkins中正常连接,不知道是少了什么命令,请指教下,谢谢!

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索