CICD 流水线文档
git代码管理
jenkins
docker或者k8s集群
对于CICD本身的理解:
CI 与 CD 离不开jenkins这一组件,CI的过程即是通过Jenkins将代码从git拉取,构建,制作镜像交给测试人员
可以实现持续的集成,自动构建,测试
CD通过Jenkins将已经测试好的发行版本,拉取 构建 制作为镜像交给运维人员去部署
持续交付:交付给运维人员手动部署
持续部署:自动化部署
我的流程大致是这样的:
GitLab (代码仓库)
↓
Jenkins (CI/CD 服务器)
↓
Docker 镜像构建
↓
目标服务器部署
Git,Github,Gitlab的区别
Git是一个开源的分布式版本控制系统。用于处理或小或大的项目
Github是基于git的在线代码托管服务。Gitlab也是,只是由不同人开发
部署git服务
准备一台机器 内存最好10G起步
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
| #使用docker安装gitlab,国内大部分加速地址都没了,代理docker的网络来拉取镜像,网上有文档 #首先创建好数据卷存放的目录 在usr/local/创建docker目录 在docker目录中创建gitlab_docker #进入gitlab_docker目录,编写docker-compose.yml(去找模板) services: gitlab: image: 'gitlab/gitlab-ce:latest' container_name: gitlab restart: always environment: GITLAB_OMNIBUS_CONFIG: | external_url 'http://192.168.100.121:8929' gitlab_rails['gitlab_shell_ssh_port'] = 2224 ports: - '8929:8929' - '2224:2224' volumes: - './config:/etc/gitlab' - './logs:/var/log/gitlab' - './data:/var/opt/gitlab'
docker pull gitlab/gitlab-ce:latest #等待拉取完成
docker-compose up -d # 启动服务
docker-compose logs -f #查看日志来确认启动成功 如果遇到权限问题 给data加权限
|
浏览器访问服务的映射端口,默认的管理员密码在输出日志中可以查看。
部署Jenkins
也准备一台内存较大的机器,通过docker部署Jenkins
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #首先创建好数据卷存放的目录 在usr/local/创建docker目录 在docker目录中创建jenkins_docker #编写docker-compose文件 services: jenkins: image: jenkins/jenkins:lts container_name: jenkins ports: - "8080:8080" - "50000:50000" volumes: - ./data/:/var/jenkins_home/ - /var/run/docker.sock:/var/run/docker.sock # 重要:允许容器内使用 Docker - /etc/docker/daemon.json:/etc/docker/daemon.json #同时使用宿主机的daemon.json中的配置 user: root
|
***关键配置说明:***
- 挂载 Docker socket (/var/run/docker.sock) 使 Jenkins 容器可以使用宿主机 Docker(用以构建镜像)
主要就是将宿主机的某些目录映射到容器内部 和端口映射一个道理
- 设置 user: root 获取必要权限
在Jenkins容器内安装docker客户端
1 2 3 4 5 6 7 8 9 10
| # 进入 Jenkins 容器 docker exec -it jenkins bash
# 安装 Docker 客户端 apt-get update apt-get install -y docker.io
# 验证安装 docker --version docker ps
|
省略了maven的部署(主要应用于java项目)
对Jenkins进行配置
1. 首次登录和初始化
1.1 获取初始管理员密码
Jenkins 首次启动后,需要获取初始管理员密码:
方法1:在容器内查看
1
| docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
|
方法2:在宿主机查看
1 2
| cd /usr/local/docker/jenkins_docker cat data/secrets/initialAdminPassword
|
1.2 完成初始化向导
- 访问 Jenkins:
http://192.168.100.122:8080
- 输入初始管理员密码
- 选择 安装推荐的插件 或 选择插件来安装
- 等待插件安装完成
- 创建管理员账户(或使用默认的 admin 账户)
2. 安装必要插件
2.1 必须安装的插件
- Pipeline - Pipeline 支持(通常已包含在推荐插件中)
- Git - Git 版本控制支持
- Docker Pipeline - Docker 流水线支持(可选)
2.2 安装插件步骤
- Jenkins → 系统管理 → 插件管理
- 点击 可选插件 标签
- 搜索需要的插件
- 勾选插件,点击 Install without restart 或 Download now and install after restart
- 等待安装完成
2.3 如果插件安装失败
问题:插件版本不兼容
- 确保 Jenkins 版本足够新(推荐 2.440+ LTS)
- 检查插件要求的 Jenkins 最低版本
问题:插件下载失败
- 配置 Jenkins 使用国内镜像源(见下方配置)
3. 配置 Jenkins 更新中心镜像源
3.1 修改更新中心配置
- Jenkins → 系统管理 → 插件管理 → 高级
- 找到 更新站点 部分
- 将默认 URL 替换为国内镜像:
清华大学镜像:
1
| https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
|
或者直接修改配置文件:
在 Jenkins 容器内或宿主机上:
1 2 3 4 5
| docker exec -it jenkins bash
vi /var/jenkins_home/hudson.model.UpdateCenter.xml
|
修改为:
1 2 3 4 5 6 7
| <?xml version='1.1' encoding='UTF-8'?> <sites> <site> <id>default</id> <url>https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json</url> </site> </sites>
|
- 重启 Jenkins:
4. 配置系统设置
4.1 系统配置
- Jenkins → 系统管理 → 系统配置
- 重要配置项:
- Jenkins URL:
http://192.168.100.122:8080
- 执行者数量: 根据服务器性能设置(建议 2-4)
- 工作空间目录: 默认即可
4.2 全局工具配置
Jenkins → 系统管理 → 全局工具配置
Git 配置:
- Name:
Default
- Path to Git executable: 通常自动检测,或填写
/usr/bin/git
Docker 配置(如果使用 Docker 工具):
- Name:
Docker
- Docker installation: 选择 Install automatically 或指定路径
5. 配置凭据管理
5.1 添加 GitLab 凭据
- Jenkins → 系统管理 → 凭据管理 → 系统 → 全局凭据 → 添加凭据
- 配置 GitLab 凭据:
- Kind: Username with password
- Scope: Global
- Username:
Administrator(或 root)
- Password: GitLab 密码
- ID:
gitlab-admin(记住这个 ID,Pipeline 中会用到)
- Description:
GitLab Administrator Account
- 点击 确定
5.2 添加 SSH 凭据(可选)
如果需要 SSH 方式连接服务器:
- 添加凭据
- 配置:
- Kind: SSH Username with private key
- Username:
root
- Private Key: 选择 Enter directly,粘贴私钥内容
- ID:
target-server-ssh
- Description:
Target Server SSH Key
进行cicd的操作:
1. 创建 Pipeline 任务
- 在 Jenkins 中点击 新建任务
- 输入任务名称:
mytest-pipeline
- 选择 流水线(Pipeline)
- 点击 确定
2. 配置源码管理
在 Pipeline 配置中:
- Definition: 选择 Pipeline script(或 Pipeline script from SCM)
- 如果使用 SCM,配置:
- SCM: Git
- Repository URL:
http://192.168.100.121:8929/root/mytest.git
- Credentials: 选择 GitLab 凭据
- Branches to build:
*/master
3. 配置 Git 凭据
- Jenkins → 系统管理 → 凭据管理 → 系统 → 全局凭据 → 添加凭据
- 配置:
- Kind: Username with password
- Username:
Administrator 或 root
- Password: GitLab 密码
- ID:
gitlab-admin
- Description:
GitLab Administrator
4. 配置 SSH 免密登录
4.1 在 Jenkins 容器内生成 SSH 密钥
1 2 3 4
| docker exec -it jenkins bash ssh-keygen -t rsa -b 4096
cat ~/.ssh/id_rsa.pub
|
4.2 将公钥添加到目标服务器
在目标服务器上执行:
1 2 3 4
| mkdir -p ~/.ssh chmod 700 ~/.ssh echo "Jenkins的公钥内容" >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys
|
4.3 测试 SSH 连接
1 2 3
| ssh root@192.168.100.122
|
为了能够编写以及维护 需要学习shell脚本编写和pipeline的一些语法
以下是一个简单流程的pipeline脚本示例:
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
| pipeline { agent any environment { TARGET_SERVER = '192.168.100.122' TARGET_USER = 'root' TARGET_PATH = '/opt/mytest' IMAGE_NAME = 'mytest:latest' GIT_URL = 'http://192.168.100.121:8929/root/mytest.git' } stages { stage('拉取代码') { steps { script { sh ''' echo "========== 拉取代码 ==========" if [ -d ".git" ]; then echo "Git 仓库已存在,更新代码..." git pull origin master else echo "克隆代码仓库..." git clone ${GIT_URL} . fi echo "代码拉取完成" ''' } } } stage('构建 Docker 镜像') { steps { script { sh ''' echo "========== 开始构建 Docker 镜像 ==========" docker build -t ${IMAGE_NAME} . if [ $? -ne 0 ]; then echo "Docker 镜像构建失败!" exit 1 fi echo "========== 保存镜像文件 ==========" docker save ${IMAGE_NAME} -o mytest.tar ls -lh mytest.tar ''' } } } stage('推送到目标服务器') { steps { script { sh ''' echo "========== 推送到目标服务器 ==========" # 创建目录 ssh -o StrictHostKeyChecking=no ${TARGET_USER}@${TARGET_SERVER} "mkdir -p ${TARGET_PATH} && chmod 755 ${TARGET_PATH}" # 推送文件 scp -o StrictHostKeyChecking=no mytest.tar ${TARGET_USER}@${TARGET_SERVER}:${TARGET_PATH}/ if [ $? -ne 0 ]; then echo "文件推送失败!" exit 1 fi echo "========== 在目标服务器上部署 ==========" # 使用 8081:8080 端口映射,避免与 Jenkins 的 8080 冲突 ssh -o StrictHostKeyChecking=no ${TARGET_USER}@${TARGET_SERVER} "cd ${TARGET_PATH} && docker load -i mytest.tar && docker stop mytest 2>/dev/null || true && docker rm mytest 2>/dev/null || true && docker run -d --name mytest -p 8081:8080 --restart unless-stopped mytest:latest" if [ $? -eq 0 ]; then echo "========== 部署成功! ==========" echo "Jenkins: http://${TARGET_SERVER}:8080" echo "应用已部署到: http://${TARGET_SERVER}:8081" else echo "========== 部署失败! ==========" exit 1 fi ''' } } } } post { always { cleanWs() } success { echo '构建成功!' } failure { echo '构建失败!' } } }
|
以下是脚本的详解:
它的核心功能是实现一个简单的 CI/CD(持续集成/持续部署) 流程:从 Git 拉取代码 -> 在 Jenkins 节点构建 Docker 镜像 -> 将镜像打包成文件 -> 拷贝到另一台应用服务器 -> 在应用服务器上重新部署运行。
1. 头部定义与环境变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| pipeline { agent any environment { TARGET_SERVER = '192.168.100.122' TARGET_USER = 'root' TARGET_PATH = '/opt/mytest' IMAGE_NAME = 'mytest:latest' GIT_URL = 'http://192.168.100.121:8929/root/mytest.git' } }
|
2. 第一阶段:拉取代码 (Pull Code)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| stage('拉取代码') { steps { script { sh ''' # 1. 检查当前目录下是否已经有 .git 隐藏目录 if [ -d ".git" ]; then echo "Git 仓库已存在,更新代码..." # 如果有,说明以前跑过任务,只需要增量更新 (git pull) git pull origin master else echo "克隆代码仓库..." # 如果没有,说明是第一次跑,需要全量下载 (git clone) git clone ${GIT_URL} . fi ''' } } }
|
3. 第二阶段:构建 Docker 镜像 (Build)
这一步是在 Jenkins 所在的机器 上执行的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| stage('构建 Docker 镜像') { steps { script { sh ''' # 1. 执行 Docker 构建,利用当前目录下的 Dockerfile docker build -t ${IMAGE_NAME} . # 2. $? 是 Linux 上一个命令的退出码。0 代表成功,非 0 代表失败。 # 这是一个很好的错误处理习惯:构建失败立即退出,不往后跑。 if [ $? -ne 0 ]; then ... exit 1; fi # 3. 核心步骤:将镜像保存为 tar 包 docker save ${IMAGE_NAME} -o mytest.tar ''' } } }
|
- 为什么用
docker save?
- 标准做法通常是
docker push 推送到 Harbor 私有仓库。
- 但这个脚本采用了 “离线传输” 模式:把它打包成
mytest.tar 文件。这样做的好处是不需要搭建 Docker 仓库,坏处是文件传输(scp)比镜像层同步(pull)要慢且占带宽。
. 第三阶段:推送到目标服务器 (Deploy)
这一步是最复杂的,涉及跨服务器操作(从 Jenkins 机器 -> 122 应用服务器)。
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
| stage('推送到目标服务器') { steps { script { sh ''' # 1. 远程创建目录 # -o StrictHostKeyChecking=no:这是关键参数! # 作用:跳过 SSH 第一次连接时的 "Are you sure...? (yes/no)" 确认提示,否则自动化脚本会卡死。 ssh -o StrictHostKeyChecking=no ${TARGET_USER}@${TARGET_SERVER} "mkdir -p ${TARGET_PATH} && chmod 755 ${TARGET_PATH}" # 2. 将构建好的 tar 包发送过去 (SCP) scp -o StrictHostKeyChecking=no mytest.tar ${TARGET_USER}@${TARGET_SERVER}:${TARGET_PATH}/ # 3. 远程执行部署命令(长指令解析) ssh ... "cd ${TARGET_PATH} && \ # 加载镜像文件到目标机的 Docker docker load -i mytest.tar && \ # 停止旧容器。注意后面的 "|| true" # 含义:如果容器原本不存在,stop 会报错,但加了 || true 后,即使报错也强行视为成功。 # 这样防止第一次部署时因为没有旧容器而导致流水线中断。 docker stop mytest 2>/dev/null || true && \ # 删除旧容器,逻辑同上 docker rm mytest 2>/dev/null || true && \ # 启动新容器 # -d: 后台运行 # -p 8081:8080: 宿主机8081映射到容器8080 # --restart unless-stopped: 如果服务器重启,容器也会自动重启 docker run -d --name mytest -p 8081:8080 --restart unless-stopped mytest:latest" ''' } } }
|
5. 结束处理 (Post)
1 2 3 4 5 6 7 8 9
| post { always { cleanWs() } success { echo '构建成功!' } failure { echo '构建失败!' } }
|
总结
这个 Pipeline 的核心流程是:
- 代码:Git 拉取。
- 产物:构建镜像 -> 打包成
.tar 文件。
- 传输:通过
scp 将打包好的大文件传给目标机。
- 运行:目标机 SSH 远程执行
docker load -> docker run。
注意事项:
要让这个脚本跑通,前提是 Jenkins 服务器必须配置了到目标服务器(192.168.100.122)的 SSH 免密登录(即把 Jenkins 的公钥放到了目标机的 authorized_keys 里),否则脚本会在 SSH/SCP 那一步因需要输入密码而失败。
接下来搭建私有仓库改变镜像的传输模式。