- 1. 编写业务相关的 Jenkinsfile
- 2. 入参及环境变量的配置
- 2.1 配置说明
- 2.2 配置后的界面展示
- 3. 定义一个 kubernetes 的 agent
- 3.1 基于 docker in docker 构建
- 3.2 基于 kaniko 构建镜像
- 4. 拉取代码 & 执行编译
- 4.1 拉取代码
- 4.2 执行编译
- 5. 构建 & 推送 docker 镜像
- 6. 总结
- 7. 碎碎念
- 8. 参考资料
经过前一篇文章的介绍以后,大家对于声明式的 jenkinsfile 有了一定程度的了解。现在可以开始动手写一个专属于自己服务的 jenkinsfile 文件。
1. 编写业务相关的 Jenkinsfile注:解放双手,从写 jenkinsfile 开始。写不了吃亏,写不了上当。
思考一下编写一个 Jenkinsfile 需要几个部分,然后逐个实践一下,属于自己服务的 jenkinsfile 就完成了。
注:以下是笔者总结的几个基础部分,如有不同的建议欢迎评论。
接下来将会就每一个部分详细的介绍和说明。逐个介绍完成之后,将会提供一个完整的 jenkinsfile 的 demo。
2. 入参及环境变量的配置 2.1 配置说明此处主要示范 入参以及 环境变量如何配置,所以选择最简单的 agent 的方式进行示例。
注:某些 jenkins 集群,配置 agent 为 any 无法执行,所以此处选择了 label 的方式。
pipeline { agent { label 'node' // 此处需要自己选择合适的 node } parameters { string(name: 'branch', defaultValue: 'master', description: 'the branch') } environment { base_USER_CREDENTIALS = credentials('harbor') //配置正确的 harbor 用户 } stages { stage('input') { steps { echo "${env.branch}" } } stage('environment') { steps { echo "${base_USER_CREDENTIALS_USR}" echo "${env.BUILD_NUMBER}" //内置环境变量 } } } }
2.2 配置后的界面展示注:在 steps 块中执行多行 sh 时,有两种方式,""" (三个双引号)和'''(三个单引号),区别在于双引号里面的引用的变量会被计算展开。
- 配置了 parameters 后在触发编译时,需要填写该参数的值。
-
使用 credentials 获取环境变量
问:为什么使用 kubernetes 配置?
答:从可 *** 作性的角度上分析,kubernetes 的方式更方便。每次构建的时候都是基于配置生成的一个崭新的环境,构建结束后环境会自动销毁。即使多次构建也不会互相干扰。(ps 虽然写起来有一些复杂
Kubernetes 的容器集,是独立于 jenkins slave 的机器,为了让定义的 kubernetes agent 能够正常运行,需要包含以下三个部分
- 配置完成的 jnlp 容器 (jenkins 的 slave)
- 支持编译特定语言的容器(比如,go 、 c++)
- 能够将二进制打包为 docker 镜像的容器(比如, docker in docker 、kaniko)
以下分别介绍公司内部可以用的 docker in docker 和 kaniko。
3.1 基于 docker in docker 构建如上图,可以在 Container 中直接运行一个 Docker Daemon,然后 Container 中的 Docker CLI 工具 *** 作容器。
注:这种方式下,容器中的 Docker Daemon 完全独立于外部,具有良好的隔离特性。看起来,Container 类似一个 VM,但是 DinD 的作者自己也不是很推荐。
主要还是安全问题。DinD 需要以特权模式启动,这种嵌套会带来潜在的安全风险。
以下是一份 docker in docker 容器集的配置
metadata: labels: label-name: jenkins-demo spec: imagePullSecrets: - regcred containers: - name: jnlp resources: limits: cpu: 0.45 memory: 450Mi requests: cpu: 0.45 memory: 450Mi - name: streaming image: hub.xxxx.co/ubuntu:golang-1.16 //配置正确的 hub 地址 imagePullPolicy: Always command: - cat tty: true resources: limits: cpu: 1 memory: 1Gi requests: cpu: 1 memory: 1Gi - name: docker image: hub.xxx.co/compiling:1.1.11-cache //配置正确的 hub 地址 imagePullPolicy: IfNotPresent command: - cat tty: true resources: limits: cpu: 1 memory: 1Gi requests: cpu: 1 memory: 1Gi securityContext: privileged: true env: - name: DOCKER_HOST value: tcp://localhost:2375 - name: dind image: docker:18.05-dind resources: limits: cpu: 0.5 memory: 550Mi requests: cpu: 0.5 memory: 500Mi securityContext: privileged: true args: - "--mtu=1450" volumeMounts: - name: dind-storage mountPath: /var/lib/docker volumes: - name: dind-storage emptyDir: {}3.2 基于 kaniko 构建镜像
Google 发布了“ Kaniko ”,一种用于在未授权容器或 Kubernetes 集群中构建容器镜像的开源工具。虽然 Kaniko 也是根据用户给定的 Dockerfile 构建镜像,但是并不依赖于 Docker 守护进程,而是在用户空间中完全执行每个命令,并对更改的文件系统做快照。
以下是一份 kaniko 的容器集的配置
metadata: labels: label-name: jenkins-demo spec: imagePullSecrets: - regcred containers: - name: jnlp resources: limits: cpu: 0.45 memory: 450Mi requests: cpu: 0.45 memory: 450Mi - name: streaming image: hub.xxxx.co/ubuntu:golang-1.16 //配置正确的 hub 地址 imagePullPolicy: Always command: - cat tty: true resources: limits: cpu: 1 memory: 1Gi requests: cpu: 1 memory: 1Gi securityContext: privileged: true env: - name: DOCKER_HOST value: tcp://localhost:2375 - name: kaniko image: gcr.io/kaniko-project/executor:v1.7.0-debug command: - cat tty: true resources: limits: cpu: 2 memory: 2000Mi requests: cpu: 2 memory: 2000Mi volumeMounts: - name: jenkins-docker-cfg mountPath: /kaniko/.docker volumes: - name: jenkins-docker-cfg secret: secretName: regcred items: - key: .dockerconfigjson path: config.json4. 拉取代码 & 执行编译 4.1 拉取代码
git 命令,带有四个参数
- branch:执行拉取的分支
- credentialsID:访问该仓库的认证
- url: 拉取仓库的git地址
- changelog:是否打印信息
有了执行环境之后,接下来的一步就是「拉取代码 & 执行编译」,以下是一个拉取代码部分 jenkinsfile 的示例。
environment { BITBUCKET = 'bitbucket-ssh-access' } stages { stage('pull code') { steps { container('streaming') { buildName "#${env.BUILD_NUMBER}" git branch: "${env.branch}", credentialsId: "${env.BITBUCKET}", url: 'ssh://[email protected]/service.git' //配置正确的 git 地址 } } } }4.2 执行编译
此处编译的示例使用的 golang ,其他语言的后面系列文章会继续完善。在执行编译前需要将 go 的环境变量再次抛出。以下是执行编译部分 jenkinsfile 的示例
stage('excuting script') { steps { container('streaming') { sh """ export PATH="$PATH:/usr/lib/go-1.16/bin" export GOPROXY=https://mirrors.aliyun.com/goproxy/ make build // 代码库内已经完成了 makefile 文件的编写 """ } } }5. 构建 & 推送 docker 镜像
有了步骤 4 中编译的二进制结果,剩下的就是将二进制结果制作成镜像同时推送到 docker hub。至此你将收获一个完整的自动化构建 jenkinsfile 的完整版本。
注:不论是 docker in docker 还是 kaniko 都使用挂载 emptyDir 的方式,来实现容器间数据的共享。
以下是执行构建、推送 docker 镜像的部分 jenkinsfile 示例。
environment { // credentials for other service, you can find it at: // Manager Jenkins -> Manger Credentials base_USER_CREDENTIALS = credentials('harbor1') DOCKER_USER_CREDENTIALS = credentials('harbor2') } stage ('Build Image') { steps { container('docker') { sh """#!/bin/bash set -xeu docker -v //配置正确的 hub 地址 docker login hub.xxxx.co -u '${env.DOCKER_USER_CREDENTIALS_USR}' -p '${env.DOCKER_USER_CREDENTIALS_PSW}' make image_dev //配置正确的 hub 地址 docker login hub.xxxx.co -u '${env.base_USER_CREDENTIALS_USR}' -p '${env.base_USER_CREDENTIALS_PSW}' make publish_dev """ } } }6. 总结
以上最小可以使用的 jenkinsfile 的每一个部分的详细介绍。最后将它们组合在一起,展示一个完整的:
pipeline { agent { kubernetes { yaml ''' metadata: labels: label-name: jenkins-demo spec: imagePullSecrets: - regcred containers: - name: jnlp resources: limits: cpu: 0.45 memory: 450Mi requests: cpu: 0.45 memory: 450Mi - name: streaming image: hub.xxxx.co/ubuntu:golang-1.16 //配置正确的 hub 地址 imagePullPolicy: Always command: - cat tty: true resources: limits: cpu: 1 memory: 1Gi requests: cpu: 1 memory: 1Gi - name: docker image: hub.xxxx.co/compiling:1.1.11-cache //配置正确的 hub 地址 imagePullPolicy: IfNotPresent command: - cat tty: true resources: limits: cpu: 1 memory: 1Gi requests: cpu: 1 memory: 1Gi securityContext: privileged: true env: - name: DOCKER_HOST value: tcp://localhost:2375 - name: dind image: docker:18.05-dind resources: limits: cpu: 0.5 memory: 550Mi requests: cpu: 0.5 memory: 500Mi securityContext: privileged: true args: - "--mtu=1450" volumeMounts: - name: dind-storage mountPath: /var/lib/docker volumes: - name: dind-storage emptyDir: {} ''' } } environment { // credentials for other service, you can find it at: // Manager Jenkins -> Manger Credentials base_USER_CREDENTIALS = credentials('harbor1') //配置正确的 hub 地址 DOCKER_USER_CREDENTIALS = credentials('harbor2') //配置正确的 hub 地址 BITBUCKET = 'bitbucket-ssh-access' } stages { stage('pulling code') { steps{ container('streaming') { buildName "#${env.BUILD_NUMBER}" git branch: "${env.branch}", credentialsId: "${env.BITBUCKET}", url: 'ssh://[email protected]/service.git' //配置正确的 hub 地址 } } } stage('excuting script') { steps { container('streaming') { sh """ export PATH="$PATH:/usr/lib/go-1.16/bin" export GOPROXY=https://mirrors.aliyun.com/goproxy/ make build """ } } } stage ('Build Image') { steps { container('docker') { sh """#!/bin/bash set -xeu docker -v //配置正确的 hub 地址 docker login hub.xxxx.co -u '${env.DOCKER_USER_CREDENTIALS_USR}' -p '${env.DOCKER_USER_CREDENTIALS_PSW}' make image_dev //配置正确的 hub 地址 docker login hub.xxxx.co -u '${env.base_USER_CREDENTIALS_USR}' -p '${env.base_USER_CREDENTIALS_PSW}' make publish_dev """ } } } } }7. 碎碎念
马上就是元旦了,希望大家都能万事胜意。
-
要在最快乐的年纪活的精彩且迷人。
-
愿听我碎碎念念的人,都可以陪我岁岁年年。
-
你的人生要自己去经历,所以是甜是苦,都不要辜负。
- Jenkins 内置环境变量
- 如何在 Docker 中使用 Docker
- GCP 发布 Kaniko:在非特权容器和 Kubernetes 中构建容器镜像的工具
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)