这是一个k8s集群结合jenkins做持续集成,以及jenkins流水线在k8s集群中运行。java编译后、nodejs编译后docker镜像制作。
准备环境 K8s集群1.15.10
Docker-ce 19.03
nfs卷
服务器信息
1 2 3 4 192.168.137.100:k8s-master/k8s-node 192.168.137.101:k8s-master/k8s-node 192.168.137.102:k8s-master/k8s-node 192.168.137.5:nfs服务、docker私有镜像仓库
nfs服务部署 nfsinstall.sh
1 2 3 4 5 6 # !/bin/bash docker run -d --restart=always --name nfs_server --privileged -p 2049:2049 \ -v /data/nfs:/nfsroot \ -h nfsserver \ -e SHARED_DIRECTORY=/nfsroot \ huisebug/nfs-server:latest
执行脚本即可在服务器上部署一个nfs服务
docker私有镜像仓库 创建私有仓库带有简单的密码认证,用户名admin,密码huisebug
dockerregistryinstall.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # !/bin/bash dockerregistryinstall(){ mkdir -p /data/dockerregistry/auth docker run --entrypoint htpasswd registry:2 -Bbn admin huisebug > /data/dockerregistry/auth/htpasswd docker run -d -p 80:5000 --restart=always --name registry \ -v /data/dockerregistry/auth/:/auth \ -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ -v /data/dockerregistry/data:/var/lib/registry \ registry:2 } dockerregistryinstall
Jenkins部署 新建jenkins命名空间 jenkins-ns.yaml
1 2 3 4 5 6 7 apiVersion: v1 kind: Namespace metadata: name: jenkins labels: name: jenkins
持久化存储jenkins和maven 准备好2个nfs数据卷用于jenkins持久化和maven仓库持久化(此处我是使用1个,采用不同目录进行区分)
因为jenkins的kubernetes插件功能不是很完善,所以这里的pvc在pod中是不支持subpath的,所以需要在pv的path下写好对应的路径
登录到nfs所在机器192.168.137.5,建立pv所需的路径
1 2 3 cd /data/nfs mkdir -p jenkins/home mkdir -p jenkins/maven
jenkins-pv-pvc jenkins-pv-pvc.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 apiVersion: v1 kind: PersistentVolume metadata: name: jenkins labels: app: jenkins spec: capacity: storage: 20Gi accessModes: - ReadWriteOnce - ReadWriteMany persistentVolumeReclaimPolicy: Retain volumeMode: Filesystem nfs: server: 192.168.137.5 path: /jenkins/home --- kind: PersistentVolumeClaim apiVersion: v1 metadata: labels: app: jenkins name: jenkins namespace: jenkins spec: accessModes: - ReadWriteOnce - ReadWriteMany resources: requests: storage: 20Gi storageClassName: "" volumeMode: Filesystem volumeName: jenkins
maven-pv-pvc maven-pv-pvc.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 apiVersion: v1 kind: PersistentVolume metadata: name: maven labels: app: maven spec: capacity: storage: 20Gi accessModes: - ReadWriteOnce - ReadWriteMany nfs: server: 192.168.137.5 path: /jenkins/maven persistentVolumeReclaimPolicy: Retain volumeMode: Filesystem --- kind: PersistentVolumeClaim apiVersion: v1 metadata: labels: app: maven name: maven namespace: jenkins spec: accessModes: - ReadWriteMany resources: requests: storage: 20Gi storageClassName: "" volumeMode: Filesystem volumeName: maven
Jenkins-rbac jenkins需要建立pod权限以调用k8s集群建立jenkins构建节点pod
jenkins-rbac.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 apiVersion: v1 kind: ServiceAccount metadata: name: jenkins namespace: jenkins --- kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: jenkins namespace: 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: RoleBinding metadata: name: jenkins namespace: jenkins roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: jenkins subjects: - kind: ServiceAccount name: jenkins namespace: jenkins
Jenkins jenkins.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 apiVersion: extensions/v1beta1 kind: Deployment metadata: name: jenkins namespace: jenkins spec: template: metadata: labels: app: jenkins spec: terminationGracePeriodSeconds: 10 serviceAccount: jenkins containers: - name: jenkins image: jenkins/jenkins:lts imagePullPolicy: IfNotPresent ports: - containerPort: 8080 name: web protocol: TCP - containerPort: 50000 name: agent protocol: TCP resources: limits: cpu: 1000m memory: 1Gi requests: cpu: 500m memory: 512Mi livenessProbe: httpGet: path: /login port: 8080 initialDelaySeconds: 60 timeoutSeconds: 5 failureThreshold: 12 readinessProbe: httpGet: path: /login port: 8080 initialDelaySeconds: 60 timeoutSeconds: 5 failureThreshold: 12 volumeMounts: - 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: jenkins --- apiVersion: v1 kind: Service metadata: name: jenkins namespace: jenkins labels: app: jenkins spec: type: NodePort selector: app: jenkins ports: - name: web port: 8080 targetPort: web nodePort: 30000 - name: agent port: 50000 targetPort: agent
注意事项:
如果jenkins提示权限问题
因为jenkins镜像中使用的账户是jenkins,而非root用户,所以需要将jenkins使用的pv下的path路径加上jenkins中提交的subpath重新授权
登录到nfs所在机器192.168.137.5
1 2 cd /data/nfs/jenkins/home chown -R 1000 jenkins/
授权后重新部署jenkins
1 kubectl delete -f Jenkins.yaml && kubectl apply -f Jenkins.yaml
get_k8s_admin_cert jenkins构建节点的docker镜像内置了kubectl客户端,用于job完成打包到部署的流程,所以需要执行get_k8s_admin_cert.sh脚本获取k8s管理员证书建立secret
因为jenkins的kubernetes插件功能不是很完善,所以这里的secret的key不能单独指定
get_k8s_admin_cert.sh
1 2 3 # !/bin/bash # 建立jenkins构建节点pod中kubectl客户端所需的k8s管理员证书 kubectl -n jenkins create secret generic k8sadmin --from-file=/root/.kube/config
验证访问 访问http://192.168.137.101:30000
准备完毕
Jenkins配置 安装kubernetes插件 因为网络原因需要将jenkins代理设置位置:http://jenkins访问url/pluginManager/advanced
将升级站点处的url地址修改为:http://mirror.xmission.com/jenkins/updates/current/update-center.json
然后点击提交
切换到插件管理进行插件安装
等待安装完毕即可
配置kubernetes节点信息 系统管理–节点管理—Configure Clouds
安装了kubernetes插件这里就会出现kubernetes可选项
Kubernetes Cloud details配置 点击Kubernetes Cloud details按钮即可开始配置
名称:kubernetes
kubernetes地址:https://kubernetes.default.svc.cluster.local
kubernetes命名空间:jenkins 即 jenkins服务所在的命名空间namespace
配置完毕后点击连接测试,查看是否可以连接成功
jenkins地址:http://jenkins.jenkins.svc.cluster.local:8080 即jenkins服务在k8s集群中使用完整的svc名称的访问地址
其他项默认即可
Pod Templates配置 因为我们需要定义一些功能,所以需要自定义jenkins构建节点pod的配置
点击添加pod模板后再点击Pod Template details按钮即可开始配置
注意事项:
命令空间填写和jenkins同一命名空间
标签列表就是后续job调用这个pod运行的标签,后续需要写到job中去
容器列表名称的pod模板中的容器名必须为jnlp,这样就只会有一个容器
容器镜像必须是以jenkins/jnlp-slave镜像为基础的镜像,可以以此为基础镜像增加服务,此处我的镜像增加了mvn、nodejs、docker、kubectl
如果pod模板中容器名称不是jnlp,那么就会认为是一个额外的容器,就会默认建立一个容器名为jnlp使用镜像jenkins/jnlp-slave的容器。然后将模板中的容器名称作为pod中的第2个容器的容器名,镜像使用你填写的镜像
pipline工作中调用的容器永远是容器名为jnlp的容器
卷挂载(非必须的)
注意事项:
docker打包的时候需要将调度的k8s-node的docker.sock挂载到容器中,便于容器中的docker服务进行打包,然后推送镜像到私有仓库,推送镜像需要认证私有仓库信息。认证的时候是根据挂载的docker.sock的,所以k8s-node的docker服务需要将私有仓库信息添加到insecure-registries中,比如此处我的私有镜像仓库为172.168.137.5
java项目打包的时候会下载很多依赖插件,所以此处需要将maven的仓库持久化存储,加快打包效率,注意我的jenkinsbuild镜像中使用的是root用户运行的,所以maven的仓库数据是放在/root/.m2的。
secret认证是用于kubectl客户端连接k8s集群,便于k8s镜像发布,secret的创建在之前的get_k8s_admin_cert.sh已经建立
其他的配置默认即可,例如:代理的空闲存活时间(分)代表jenkins构建节点pod的存活时间,一般默认即可
Jenkins自由风格Job验证
限制项目的运行节点
此处就对应之前pod template中的标签列表
构建操作,执行一个shell 1 2 3 4 5 java -version mvn -v nodejs -v docker info kubectl get pod -n jenkins
保存后点击构建
会出现下面的状态,正在创建pod以获取输出,如果一直没有变化,那么就是pod建立失败,需要查看一下kubernetes节点配置是否正确,大多数原因是因为pod的配置
等待建立构建的pod,可以在终端查看到
pod建立成功将会在jenkins控制台进行输出,也会输出pod的建立yaml,可以根据来排查问题
成功获取到了上述shell执行结果
Jenkins认证凭证
添加好jenkins认证凭证,可以用于后续的job拉取git仓库代码、pipline中使用git函数利用凭证的ID字段进行认证,上面的ID是可以手动定义的,后续将会用到
Jenkins Pipline 构建定制化的持续集成是必须的工作,pipline的使用就不过多介绍,此处介绍本次使用的pipline过程
参考github地址:https://github.com/huisebug/jenk8s-pipline.git 和 https://github.com/huisebug/jenk8s-install.git
build.groovy:流水线pipline文件
dockerfile:java环境Dockerfile,nodejs项目Dockerfile,jenkins构建节点的Dockerfile
jenkins:jenkins部署到k8s中的yaml
projects:存放需要打包的项目的信息,文件目录名区分项目,project_info文件中写入:项目名称#服务名称=服务的git代码地址
scripts:存放docker镜像制作的脚本
build.groovy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 //当前的jenkins管理节点 node { //配置全局变量 env.project = env.JOB_BASE_NAME.split("\\+")[0] env.app_name = env.JOB_BASE_NAME.split("\\+")[1] env.branch = env.JOB_BASE_NAME.split("\\+")[2] println(env.project) println(env.app_name) println(env.branch) /* 因为jenkins的版本原因,使用git方式拉取了jenkinsfile的项目所有源代码文件 在系统workspace目录下建立了一个job名+@script的文件目录来存放jenkinsfile源代码所有文件 pipline执行的时候是以job名称为文件目录名称下 类似于 [root@localhost workspace]# tree . ├── jenkins+java+master │ └── java-ci ├── jenkins+java+master@script │ ├── build.groovy │ └── projects │ └── jenkins │ └── project_info */ //jenkinsfile的源代码存放目录名称,此处是:job名称+@script env.tempsuffix = '@script' env.JenkinsfileREPO = env.JOB_BASE_NAME + env.tempsuffix //获取代码仓库地址,作为全局变量提供给打包k8s节点使用 if (env.app_name == '') { env.app_name = 'none' env.git_repository = sh returnStdout: true, script: 'cat ../'+env.JenkinsfileREPO+'/projects/'+env.project+'project_info|grep '+env.project+'_repo|awk -F "=" \'{print $2}\'' env.ci_dir = env.project+'-ci' } else { env.git_repository = sh returnStdout: true, script: 'cat ../'+env.JenkinsfileREPO+'/projects/'+env.project+'/project_info|grep '+env.project+'#'+env.app_name+'_repo|awk -F "=" \'{print $2}\'' env.ci_dir = env.app_name+'-ci' } } //CI打包k8s节点,这里就是匹配之前的pod template中的标签列表 node('jenkinsbuildnode') { echo "本次build的项目的源代码地址: "+env.git_repository stage('CI打包') { /*tools { maven '3.6.2' jdk '1.8.0_242' nodejs '10.19.0' npm '5.8.0' }*/ script { /*判断是否推送到生产仓库 try { timeout(time: 70, unit: 'SECONDS') { def userInput = input(id: 'userInput', ok: '确定', message: '是否推送镜像到生产环境', parameters: [booleanParam(defaultValue: false, description: '', name: '发布到master仓库')]) //println userInput println userInput.getClass() if(userInput==true){ env.to_master_registry = "go" }else { env.to_master_registry = "" } } } catch(Exception ex) { println("Catching exception") echo 'do nothing, continue.......' env.to_master_registry = "" }*/ dir(env.ci_dir) { echo "拉取git代码" checkout([$class: 'GitSCM', branches: [[name: branch]], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'CleanBeforeCheckout']], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'huisebug', url: git_repository]]]) git_commit_hash = sh (script: "git log -n 1 --pretty=format:'%H'", returnStdout: true) env.git_commit_hash = '-'+git_commit_hash[0..4] project = sh returnStdout: true, script: 'cat app.info|grep devlang|awk -F ":" \'{print $2}\'' project = project.replace("\r","").replace(" ", "").replace('\n', '') echo "项目类型是"+project println project.class def version = sh returnStdout: true, script: ''' cat app.info |grep version|awk -F ":" '{print $2}' ''' env.ver = version.replace("\r", "").replace("\n", "").replace(" ", "") echo '打包版本'+env.ver if (project == 'NodeJs'||project == 'nodejs') { sh 'mkdir -pv target' //sh 'find ./ -type f -exec dos2unix -q {} \\;' sh 'npm cache clean --force' sh 'npm config set registry http://registry.npm.taobao.org/' sh 'cnpm install' if (env.JOB_BASE_NAME.tokenize('+')[3] == 'dev') { sh 'npm run build:dev' } else if (env.JOB_BASE_NAME.tokenize('+')[3] == 'test') { sh 'npm run build:test' } else if (env.JOB_BASE_NAME.tokenize('+')[3] == 'sg') { sh 'npm run build:sg' } else { sh 'npm run build' } sh 'mv dist target/' echo project+'nodejs container Preparing....' } else if (project == 'Java'||project == 'java') { echo project+' java container Preparing....' sh 'mvn -Dmaven.test.skip=true clean package' } else if (project == 'Python'||project == 'python') { sh 'mkdir -pv target' //sh 'find ./ -type f -exec dos2unix -q {} \\;' sh 'cp -rf `ls|grep -v app.info|grep -v target|xargs` target/' echo project+' python container Preparing....' } else if (project == 'HTML'||project == 'html') { sh 'mkdir -pv target/dist' //sh 'find ./ -type f -exec dos2unix -q {} \\;' sh 'cp -rf `ls|grep -v app.info|grep -v target|xargs` target/dist' echo project+' html container Preparing....' } else { sh 'mkdir -pv target/dist' //sh 'find ./ -type f -exec dos2unix -q {} \\;' sh 'cp -rf `ls|grep -v app.info|grep -v target|xargs` target/dist' echo project+' html container Preparing....' } } } } stage('docker镜像制作') { script { sh 'mkdir -pv dockerbuild' dir('dockerbuild') { deleteDir() echo "拉取docker镜像制作脚本,代码分支一般默认是master",凭证信息credentialsId: 'huisebug' ,直接使用jenkins存放的凭证的ID env.git_repo = 'https://github.com/huisebug/jenk8s-pipline.git' checkout([$class: 'GitSCM', branches: [[name: 'master']], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'CleanBeforeCheckout']], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'huisebug', url: git_repo]]]) println('需要执行打包的容器名称有:') sh 'bash scripts/dockerbuild.sh'+' '+env.WORKSPACE+'/'+env.ci_dir+' '+env.app_name+' '+env.ver+' '+env.git_commit_hash+' '+env.project+' '+project+' '+env.to_master_registry } } } }
pipline会首先在jenkins本地node执行build.groovy,根据当前的job名称来获取项目名称+服务名称+代码分支,例如:jenkins+java+master,然后去匹配projects文件目录中的信息,最终得到此次job的运行的服务名,git地址,分支信息传递到整个pipline的全局变量中
然后运行在jenkins构建节点pod中运行拉取项目服务代码、项目服务编译、docker镜像制作
scripts/ dockerbuild.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 # !/bin/bash # 脚本参数,$1 :ci路径 $2 :服务名称 $3 :打包版本 $4 :代码哈希 $5 项目名称 $6 :项目类型(Html or Java or Nodejs) $7 :生产仓库(可选) # 私库地址 REGISTRY='192.168.137.5' # 私库存放服务的仓库名 WAREHOUSE_NAME='huisebug' # 项目的CI目录名称 if [ x$2 != xnone ];then app_name=$5-$2 ci_dir=$2-ci else app_name=$5 ci_dir=$5-ci fi # java项目镜像制作 java() { BASE_IMAGE=${REGISTRY}/base/openjdk:8 APP_HOME=/data/projects/${app_name} EXE_CMD="java -jar" EXE_BIN=${APP_HOME}/bin/${app_name}.jar EXE_CONF='-Dlog_host=${log_host}' # jvm内存参数,临时设置,后续可以传参自定义 EXE_LEVEL="-Xms1680M -Xmx1680M -Xmn1260M -Xss1M" # jvm其他参数调优 EXE_OPTION="-server -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:MaxDirectMemorySize=1g -XX:+ExplicitGCInvokesConcurrent -XX:CMSInitiatingOccupancyFraction=80 -XX:-UseCMSInitiatingOccupancyOnly -Dsun.rmi.dgc.server.gcInterval=2592000000 -Dsun.rmi.dgc.client.gcInterval=2592000000 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${APP_HOME}/log/java.hprof -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps" cat > run.sh << \EOF # !/bin/bash # 环境变量当前主机名 log_host=`hostname` # jvm内存参数设置 java_mem=`env|grep java_mem|awk -F '=' '{print $2}'` # 服务日志是否在控制台输出,即容器即生命 log_echo=`env|grep log_echo|awk -F '=' '{print $2}'` # 判断变量java_mem是否为空,不存在即为空 if [[ x$java_mem == x ]];then EXE_LEVEL="" else EXE_LEVEL=$java_mem fi # 额外的jvm参数 if [[ x$general_para != x ]];then EXT_OPTION=$general_para else EXT_OPTION="" fi # 程序的参数 if [[ x$application_para != x ]];then APP_OPTION=$application_para else APP_OPTION="" fi EOF echo "if [[ x\${log_echo} != x ]];then" >> run.sh echo ${EXE_CMD} \${EXE_LEVEL} ${EXE_OPTION} \${EXT_OPTION} ${EXE_CONF} ${EXE_BIN} \${APP_OPTION} >> run.sh echo "else" >> run.sh EXE_CMD="nohup java -jar" echo ${EXE_CMD} \${EXE_LEVEL} ${EXE_OPTION} \${EXT_OPTION} ${EXE_CONF} ${EXE_BIN} \${APP_OPTION} >> run.sh echo "tail -f /dev/null" >> run.sh echo "fi" >> run.sh # 准备好将要复制到镜像中的服务文件 rm -rf source mkdir -p source mv ../${ci_dir}/target/* source/ # 生成Dockerfile cat > Dockerfile << EOF FROM ${BASE_IMAGE} RUN for dir in data bin log conf; do mkdir -p ${APP_HOME}/\$dir; done ADD source ${APP_HOME}/bin COPY run.sh /root/run.sh CMD ["/bin/bash","/root/run.sh"] EOF } # web项目镜像制作,包含nodejs和html web() { # 此处只做拷贝文件,启动方式按照$BASE_IMAGE 的说明进行 BASE_IMAGE=${REGISTRY}/base/nginx:1.19 APP_HOME=/usr/share/nginx/html # 准备好将要复制到镜像中的服务文件,nodejs打包后的项目html全部放在dist目录下,在前面的pipline中已经将dist目录移动到了target目录中 rm -rf source mkdir -p source mv ../${ci_dir}/target/dist/* source/ # 生成dockerfile cat > Dockerfile << EOF FROM ${BASE_IMAGE} ADD source ${APP_HOME} EOF } if [[ x$6 == xJava || x$6 == xjava ]];then java $1 $2 $3 $4 $5 $6 $7 $8 else web $1 $2 $3 $4 $5 $6 $7 $8 fi # cat Dockerfile container_name=${app_name} time_char=`date "+%y%m%d%H%M"` container_version=$3-${time_char}$4 # 私有仓库的认证 docker login 192.168.137.5 -u admin -p huisebug >/dev/null 2>&1 docker build -t ${REGISTRY}/${WAREHOUSE_NAME}/${container_name}:${container_version} . # 生成镜像文件 docker push ${REGISTRY}/${WAREHOUSE_NAME}/${container_name}:${container_version} if [[ x$7 == xgo ]];then echo '开始推送到生产镜像仓库' # 生产镜像仓库地址 proimagerepo=192.168.137.5 # 生产镜像仓库认证 docker login ${proimagerepo} -u admin -p huisebug >/dev/null 2>&1 docker tag ${REGISTRY}/${WAREHOUSE_NAME}/${container_name}:${container_version} ${proimagerepo}/${WAREHOUSE_NAME}/${container_name}:${container_version} docker push ${proimagerepo}/${WAREHOUSE_NAME}/${container_name}:${container_version} echo '清除多余的标签' docker rmi ${proimagerepo}/${WAREHOUSE_NAME}/${container_name}:${container_version} fi
java的镜像制作过程中会需要项目的pom.xml中定义构建后的jar包名称,比如此处我的项目jar名称就应该为jenkins-java.jar。
java的docker镜像制作是可以后续在建立时使用docker的变量方式进行java传参和jar包传参;变量general_para是java参数传递,变量application_para是jar参数传递。
nodejs编译后就是web页面,所以nodejs和web直接copy到nginx容器即可
使用的基础docker镜像是存放在私有镜像仓库的,所以需要推送镜像到私有镜像仓库,参考java和nginx基础镜像Dockerfile:https://github.com/huisebug/jenk8s-install.git
projects 此处我准备的项目名称为:jenkins 所以建立了一个jenkins文件目录
jenkins文件目录下存放了project_info文件 project_info
1 2 3 jenkins# java_repo=https://github.com/huisebug/jenk8s-java.git jenkins# nodejs_repo=https://github.com/huisebug/jenk8s-nodejs.git jenkins# html_repo=https://github.com/huisebug/jenk8s-html.git
调试项目介绍 此处我准备了三个不同类型的项目
java:https://github.com/huisebug/jenk8s-java.git
nodejs:https://github.com/huisebug/jenk8s-nodejs.git
html:https://github.com/huisebug/jenk8s-html.git
三个项目中都会有一个特殊的配置文件app.info
项目中特殊的配置文件app.info 1 2 devlang:java version:1.1
1 2 devlang:html version:1.1
1 2 devlang:nodejs version:1.1
Jenkins流水线Job验证 job名称格式
注意job名称,以”+”号分割,分别是项目名称+服务名称+代码分支
流水线配置
使用git的方式拉取jenkinsfile(即build.groovy),轻量级检出的选项不勾选,勾选就会直接读取build.groovy的内容,不会clone整个项目代码,就无法获取到其他的项目代码
后续的项目我们只需要在建立job的时候复制然后建立就行了
java项目执行结果