38.DevOps之基于Jenkins实现的CI与CD

文章目录

    • 一 DevOps 简介
      • 1.1 什么是 DevOps
      • 1.2 为什么要推广 DevOps?
      • 1.3 传统技术团队
      • 1.4 DevOps 技术团队
      • 1.5 什么是持续集成(CI-Continuous integration)
      • 1.6 什么是持续部署(CD-continuous deployment)
      • 1.7 什么是持续交付(Continuous Delivery)
      • 1.8 常见的部署方式
      • 1.9 常见的持续集成开源工具
        • 1.9.1 CVS(Concurrent Version System)
        • 1.9.2 SVN(Subversion)--集中式版本控制系统
        • 1.9.3 Gitlib—分布式版本控制系统:
      • 1.10 版本控制系统分类
        • 1.10.1 集中式版本控制系统
        • 1.10.2 分布式版本控制系统
    • 二 Gitlab 部署与使用
      • 2.1 下载并部署 gitlab
        • 2.1.1 Ubuntu 系统环境准备
          • 2.1.1.1 配置 ubuntu 远程连接
          • 2.1.1.2 配置 ubuntu 网卡和主机名
          • 2.1.1.3 配置 ubuntu 仓库
        • 2.1.2 Centos 系统环境在准备
        • 2.1.3 gitlab 安装及使用
          • 2.1.3.1 gitlab 配置使用
          • 2.1.3.2 初始化服务
          • 2.1.3.3 常用命令
          • 2.1.3.4 验证 gitlab 启动完成
          • 2.1.3.5 验证端口及状态
          • 2.1.3.6 登录 gitlab web 界面
          • 2.1.3.7 登录 gitlab
          • 2.1.3.8 默认首页
          • 2.1.3.9 关闭账号注册
          • 2.1.3.10 验证是否还有注册选项
          • 2.1.3.11 创建 git 账户
          • 2.1.3.12 重新设置密码
          • 2.1.3.13 创建组
          • 2.1.3.14 使用管理员创建项目
          • 2.1.3.15 将用户添加到组
          • 2.1.3.16 创建一个测试页面
          • 2.1.3.17 git 客户端测试 clone 项目
          • 2.1.3.18 git web 端验证数据
          • 2.1.3.19 gitlab 使用
            • 2.1.3.19.1 数据保存方式
            • 2.1.3.19.2 常用 git 命令
            • 2.1.3.19.3 git 缓存区与工作区等概念
          • 2.1.3.20 gitlab 数据备份恢复
            • 2.1.3.20.1 停止 gitlab 数据服务
            • 2.1.3.20.2 手动备份数据
            • 2.1.3.20.3 查看要恢复的文件
            • 2.1.3.20.4 执行恢复
            • 2.1.3.20.5 启动服务
          • 2.1.3.21 gitlab 汉化
            • 2.1.3.21.1 下载语言包替换
            • 2.1.3.21.2 通过源码汉化
      • 2.2 常见的代码部署方式
        • 2.2.1 蓝绿部署
        • 2.2.2 金丝雀发布
        • 2.2.3 滚动发布
        • 2.2.4 A/B 测试
    • 三 部署 web 服务器环境
      • 3.1 java 环境
      • 3.2 准备 tomcat 启动脚本
      • 3.3 web 部署
      • 3.4 配置 tomcat 配置文件
      • 3.5 启动 tomcat
      • 3.6 确认各 web 服务器访问正常
      • 3.7 部署 keepalived
      • 3.8 部署 haproxy 
      • 3.9 测试访问
      • 3.10 验证 HAProxy 统计页面
      • 3.11 验证 haproxy 代理 web 服务器
    • 四 Jenkins 部署与基础配置
      • 4.1 配置 java 环境并部署 jenkins
        • 4.1.1 java 环境配置
        • 4.1.2 启动 Jenkins:
          • 4.1.2.1 通过 jar 包直接启动 jenkins
          • 4.1.2.2 rpm 包安装 jenkins 配置
        • 4.1.3 Jenkins 启动过程
        • 4.1.4 访问 jenkins 页面
        • 4.1.5 选择安装 jenkins 插件
        • 4.1.6 插件安装过程中
        • 4.1.7 创建 jenkins 管理员
        • 4.1.8 配置 jenkins URL
        • 4.1.9 配置完成并登陆 jenkins
        • 4.1.10 登陆 jenkins 界面
        • 4.1.11 jenkins 插件管理及安装
          • 4.1.11.1 插件安装目录
          • 4.1.11.2 安装插件
        • 4.1.12 配置 jenkins 权限管理
          • 4.1.12.1 安装插件
          • 4.1.12.2 创建新用户
          • 4.1.12.3 更改认证方式
          • 4.1.12.4 创建角色
          • 4.1.12.5 添加角色
          • 4.1.12.6 对角色分配权限
          • 4.1.12.7 将用户关联到角色
          • 4.1.12.8 测试普通用户登录
        • 4.1.13 jenkins 邮箱配置
          • 4.1.13.1 生成 QQ 邮箱登录授权码
          • 4.1.13.2 配置 jenkins 管理员邮箱
          • 4.1.13.3 发件配置
          • 4.1.13.4 测试发送邮件
      • 4.2 基于 ssh key 拉取代码
        • 4.2.1 添加 ssh key
        • 4.2.2 添加 ssh key
        • 4.2.3 创建 ssh key
        • 4.2.4 测试 ssh key
      • 4.3 配置 jenkins 到 gitlab 非交互拉取代码
        • 4.3.1 jenkins 服务器添加证书
        • 4.3.2 jenkins 创建 project
        • 4.3.3 配置 git 项目地址和用户
        • 4.3.4 测试构建项目
          • 4.3.4.1 点击立即构建
          • 4.3.4.2 验证构建结果
          • 4.3.4.3 服务器验证数据
          • 4.3.4.4 将代码部署至后端服务器
      • 4.4 构建触发器(钩子)
        • 4.4.1 gitlab 新建 develop 分支
        • 4.4.2 gitlab 定义分支名称并创建
        • 4.4.3 jenkins 安装插件
        • 4.4.4 jenkins 修改登录认证方式
        • 4.4.5 jenkins 新建 develop job
        • 4.4.6 jenkins 构建 shell 命令
        • 4.4.7 jenkins 配置构建触发器
        • 4.4.8 jenkins 验证分支 job 配置文件
        • 4.4.9 curl 命令测试触发并验证远程触发构建
        • 4.4.10 jenkins 验证 job 是否自动构建
        • 4.4.11 gitlab 配置 webhook
        • 4.4.12 测试钩子可用性
        • 4.4.13 jenkins 执行 shell 命令
        • 4.4.12 gitlab 开发分支 develop 测试提交代码
        • 4.4.13 jenkins 验证 develop job 自动构建
      • 4.5 构建后项目关联
        • 4.5.1 配置构建后操作
        • 4.5.2 验证构建后操作
      • 4.6 jenkins 分布式
        • 4.6.1 配置 slave 节点 java 环境
        • 4.6.2 添加 slave 节点
        • 4.6.3 添加 slave 认证凭据
        • 4.6.4. slave 节点最终信息
        • 4.6.5 jenkins slave 创建日志
        • 4.6.6 如果 slave 没有 java 环境则报错如下
        • 4.6.7 验证 slave web 状态
        • 4.6.8 验证 slave 进程状态
      • 4.7 pipline
        • 4.7.1 pipline 语法
        • 4.7.2 pipline 优势
        • 4.7.3 pipline job 测试
          • 4.7.3.1 创建 pipline job
          • 4.7.3.2 测试简单 pipline job 运行
          • 4.7.3.3 执行 pipline job
          • 4.7.3.4 自动生成拉取代码的 pipline 脚本
          • 4.7.3.5 更改 pipline job
          • 4.7.3.6 执行 jenkins job
          • 4.7.3.7 验证 git clone 日志
          • 4.7.3.8 jenkins 服务器验证 clone 代码数据
          • 4.7.3.9 pipline 中执 shell 命令打包代码
          • 4.7.3.10 pipline 部署示例
          • 4.7.3.11 执行并验证 pipline job
          • 4.7.3.12 指定 node 节点 运行 job
          • 4.7.3.13 验证 slave 执行构建
          • 4.7.3.14 验证 web 服务器代码版本
      • 4.8 视图
        • 4.8.1 安装 build pipeline 插件
        • 4.8.2 创建新的视图
        • 4.8.3 创建 pipline 视图
          • 4.8.3.1 定义视图配置信息
          • 4.8.3.2 web 显示界面
        • 4.8.4 列表视图
          • 4.8.4.1 定义视图名称
          • 4.8.4.2 选择任务
          • 4.8.4.3 最终状态
      • 4.5 我的视图
        • 4.5.1 创建我的视图
        • 4.5.2 最终状态
    • 五 代码质量测试
      • 5.1 代码测试工具 SonarQube 简介
      • 5.2 基础环境依赖
        • 5.2.1 数据库环境依赖
        • 5.2.2 java 环境依赖
        • 5.2.3 系统及内核参数
        • 5.2.4 硬件依赖
      • 5.3 部署 SonarQube
        • 5.3.1 MySQL 数据库及 SonarQube 6.7.X 部署
          • 5.3.1.1 安装 MySQL
          • 5.3.1.2 测试 sonar 账户连接 mysql
          • 5.3.1.3 解压 sonarqube 并配置文件
          • 5.3.1.4 启动 sonarqube
          • 5.3.1.5 登录到 web 界面
          • 5.3.1.6 安装中文支持
            • 5.3.1.6.1 查看本地已安装插件
            • 5.6.1.3.2 安装中文语言插件
            • 5.6.1.3.3 重启 sonarquebe
          • 5.3.1.7 安装其他插件
        • 5.3.2 PostgreSQL 及 SonarQube 7.9.X 部署
          • 5.3.2.1 安装 JDK 11
          • 5.3.2.1 部署 PostgreSQL 服务器
          • 5.3.2.2 配置 postgrepsql
          • 5.3.2.2 部署 7.9.X SonarQube
          • 5.3.2.3 验证 SonarQube
          • 5.3.2.4 访问 SonarQube web 界面
          • 5.3.2.5 安装中文插件
      • 5.4 jenkins 服务器部署扫描器 sonar-scanner
        • 5.4.1 部署 sonar-scanner
        • 5.4.2 准备测试代码
        • 5.4.3 在源代码目录执行扫描
        • 5.4.4 sonarquebe we 界面验证扫描结果
      • 5.5 jenkins 执行代码扫描
        • 5.5.1 jenkins 安装 SonarQube 插件
        • 5.5.2 添加 sonarquebe URL
        • 5.5.3 让 jenkins 添加 Sonarscanner 扫描器
          • 5.5.3.1 手动指定绝对路径
          • 5.5.3.2 自动安装
        • 5.4.6 配置扫描
        • 5.4.7 配置项目进行扫描
        • 5.4.8 构建项目并测试 sonar-scanner 是否生效
        • 5.4.9 查看项目的构建历史
    • 六 实战案例
      • 6.1 创建项目
      • 6.2 添加部署 key
      • 6.3 确认 key
      • 6.4 Shell 脚本
      • 6.5 验证 ssh
      • 6.6 配置 jenkins 用户 sudu 权限
      • 6.7 测试执行命令
      • 6.8 web 服务器免密码登录
      • 6.9 gitlab 提交代码
      • 6.10 项目关联
      • 6.11 定义视图
      • 6.12 执行构建
      • 6.13 代码自动构建
      • 6.14 自动构建插件
      • 6.15 Token
      • 6.16 触发器
      • 6.17 gitlab 触发
      • 6.18 测试 gitlab 触发
      • 6.2 HAProxy
      • 6.21 haproxy 动态增减服务器

一 DevOps 简介

https://www.bagevent.com/event/6243820?bag_track=bagevent #Gdevops2020
https://www.bagevent.com/event/DevOpsDays-SH #DevOpsDays 2019

DevOps 是 Development 和 Operations 的组合,也就是开发和运维的简写。
DevOps 是针对企业中的研发人员、运维人员和测试人员的工作理念,是他们在应用开发、 代码部署和质量测试等整条生命周期中协作和沟通的最佳实践, DevOps 强调整个组织的合作以及交付和基础设施变更的自动化、从而实现持续集成(开发)、持续部署(运维)和持续交付。

38.DevOps之基于Jenkins实现的CI与CD_第1张图片

DevOps 四大平台:代码托管(gitlab/svn)、项目管理(jira)、运维平台(腾讯蓝鲸/开源平
台)、持续交付(Jenkins/gitlab)

1.1 什么是 DevOps

38.DevOps之基于Jenkins实现的CI与CD_第2张图片

1.2 为什么要推广 DevOps?

DevOps 强调团队协作、 相互协助、持续发展,然而传统的模式是开发人员只顾开发程序,运维只负责基础环境管理和代码部署及监控等, 其并不是为了一个共同的目标而共同实现最终的目的, 而 DevOps 则实现团队作战,即无论是开发、运维还是测试,都为了最终的代码发布、 持续部署和业务稳定而付出各自的努力, 从而实现产品设计、开发、 测试和部署的良性循环, 实现产品的最终持续交付。

1.3 传统技术团队

38.DevOps之基于Jenkins实现的CI与CD_第3张图片

1.4 DevOps 技术团队

38.DevOps之基于Jenkins实现的CI与CD_第4张图片

1.5 什么是持续集成(CI-Continuous integration)

持续集成是指多名开发者在开发不同功能代码的过程当中,可以频繁的将代码行合并到一起并切相互不影响工作。

1.6 什么是持续部署(CD-continuous deployment)

是基于某种工具或平台实现代码自动化的构建、测试和部署到线上环境以实现交付高质量的产品,持续部署在某种程度上代表了一个开发团队的更新迭代速率。

1.7 什么是持续交付(Continuous Delivery)

持续交付是在持续部署的基础之上, 将产品交付到线上环境, 因此持续交付是产品值的一种交付, 是产品价值的一种盈利的实现。

38.DevOps之基于Jenkins实现的CI与CD_第5张图片

上图说明:一堆软件的结合

计划阶段用JIRA做项目管理,用git来做代码仓库,构建工具使用Maven和Ant较多,测试阶段用Selenium,持续集成用Jenkins,部署使用Saltstack或者Ansible、scp(比较慢)、rsync;运营阶段使用elastic,监控使用Zabbix或者Prometheus

1.8 常见的部署方式

开发自己上传–最原始的方案
开发给运维手动上传–运维自己手动部署
运维使用脚本复制–半自动化
结合 web 界面一键部署–自动化

1.9 常见的持续集成开源工具

在公司的服务器安装某种程序,该程序用于按照特定格式和方式记录和保存公司多名开发人员不定期提交的源代码,且后期可以按照某种标记Tag及方式对用户提交的数据进行还原。

1.9.1 CVS(Concurrent Version System)

早期的集中式版本控制系统,现已基本淘汰
会出现数据提交后不完整的情况

1.9.2 SVN(Subversion)–集中式版本控制系统

2000 年开始开发,目标就是替代 CVS 集中式管理,依赖于网络,一台服务器集中管理目前依然有部分公司在使用

1.9.3 Gitlib—分布式版本控制系统:

Linus 在 1991 年创建了开源的 Linux 内核,从此 Linux 便不断快速发展, 不过 Linux 的壮大是离不开全世界的开发者的参与,这么多人在世界各地为 Linux 编写代码,那Linux 内核的代码是如何管理的呢?事实是,在 2002 年以前,世界各地的志愿者把源代码文件通过 diff 的方式发给 Linus,然后由 Linus 本人通过手工方式合并代码!你也许会想,为什么 Linus 不把 Linux 代码放到版本控制系统里呢?不是有 CVS、 SVN 这些免费的版本控制系统吗?因为 Linus 坚定地反对 CVS 和 SVN,这些集中式的版本控制系统不但速度慢,且必须联网才能使用, 但是也有一些商用的版本控制系统,虽然比CVS、 SVN 好用,但那是付费的,和 Linux 的开源精神不符,不过,到了 2002 年, Linux系统已经发展了十年了,代码库之大让 Linus 很难继续通过手工方式管理了,社区的弟兄们也对这种方式表达了强烈不满,于是 Linus 选择了一个商业的版本控制系统BitKeeper, BitKeeper 的东家 BitMover 公司出于人道主义精神,授权 Linux 社区免费使用这个版本控制系统,但是安定团结的大好局面在 2005 年就被打破了,原因是 Linux社区牛人聚集,不免沾染了一些梁山好汉的江湖习气, 开发 Samba 的 Andrew 试图破解 BitKeeper 的协议(这么干的其实也不只他一个),被 BitMover 公司发现了(监控工作做得不错!),于是 BitMover 公司怒了,要收回 Linux 社区的免费使用权,这时候其实 Linus 可以向 BitMover 公司道个歉,保证以后严格管教弟兄们, 但这是不可能的, 而且实际情况是 Linus 自己花了两周时间自己用 C 写了一个分布式版本控制系统,这就是 Git!一个月之内, Linux 内核的源码已经由 Git 管理了!牛是怎么定义的呢?大家可以体会一下,然后 Git 迅速成为最流行的分布式版本控制系统,尤其是 2008 年,GitHub 网站上线了,它为开源项目免费提供 Git 存储,无数开源项目开始迁移至 GitHub,包括 jQuery, PHP, Ruby 等等。

  • git–linus开源的一个分布式版本控制系统
  • github–是基于git的一个免费提供代码的仓库的网站
  • gitlab–是一个软件,在公司安装后可以实现代码本地提交和版本管理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D5FX8XBU-1626502809246)(C:\Users\cui\Desktop\课程截图\38.DevOps之基于Jenkins实现的CI与CD_图片\gettyimages-532505754.jpg)]

gitlab 企业版

38.DevOps之基于Jenkins实现的CI与CD_第6张图片

1.10 版本控制系统分类

1.10.1 集中式版本控制系统

任何的提交和回滚都依赖于连接服务器 SVN 服务器是单点

38.DevOps之基于Jenkins实现的CI与CD_第7张图片

1.10.2 分布式版本控制系统

Git 在每个用户都有一个完整的服务器,然后在有一个中央服务器,用户可以先将代码提交到本地,没有网络也可以先提交到本地,然后在有网络的时候再提交到中央服务器,这样就大大方便了开发者的代码提交和回滚,而相比 CVS 和 SVN 都是集中式的版本控制系统,工作的时候需要先从中央服务器获取最新的代码,改完之后需要提交,如果是一个比较大的文件则需要足够快的网络才能快速提交完成,而使用分布式的版本控制系统,每个用户都是一个完整的版本库,即使没有中央服务器也可以提交代码或者回滚,最终再把改好的代码提交至中央服务器进行合并即可。

38.DevOps之基于Jenkins实现的CI与CD_第8张图片

二 Gitlab 部署与使用

https://about.gitlab.com/install/ # Gitlab 服务的安装文档
https://docs.gitlab.com/ce/install/requirements.html #安装环境要求

存储:8*600G=4.8T%50=2T 10K 15K 或固态

cpu:8c 16C

内存:16G 32G

38.DevOps之基于Jenkins实现的CI与CD_第9张图片

2.1 下载并部署 gitlab

gitlab使用,group user和project配置

  • users:账号,开发人员
  • project:某个仓库,针对某个服务
  • group:就是一个项目的统称,一个group会包含好多project,一个project会被授权给一个或多个user权限
  • clone–》编辑–》add–》commit–》push
  • git reset --hard HEAD^^

2.1.1 Ubuntu 系统环境准备

2.1.1.1 配置 ubuntu 远程连接
jack@ubuntu:~$ sudo su - root
[sudo] password for jack:
root@ubuntu:~# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
root@ubuntu:~# vim /etc/ssh/sshd_config
http/https/ssh/git
PermitRootLogin yes
PasswordAuthentication yes
2.1.1.2 配置 ubuntu 网卡和主机名
root@ubuntu:~# cat /etc/netplan/01-netcfg.yaml
# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: no
      addresses: [192.168.8.2/21]
      gateway4: 192.168.15.254
      nameservers:
        addresses: [192.168.15.254]

root@ubuntu:~# cat /etc/hostname
jenkins.example.com
root@ubuntu:~# reboot
2.1.1.3 配置 ubuntu 仓库
root@ubuntu:~#vim /etc/apt/sources.list
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe
multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

root@jenkins:~# apt update
root@jenkins:~# apt install iproute2 ntpdate tcpdump telnet traceroute nfs-kernel-server nfs-common lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev ntpdate tcpdump telnet traceroute gcc openssh-server lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev ntpdate tcpdump telnet traceroute iotop unzip zip ipmitool

2.1.2 Centos 系统环境在准备

最小化服务器安装,配置如下

# yum install vim gcc gcc-c++ wget net-tools lrzsz iotop lsof iotop bash-completion -y
# yum install curl policycoreutils openssh-server openssh-clients postfix -y
# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
# systemctl disable firewalld
# sed -i '/SELINUX/s/enforcing/disabled/' /etc/sysconfig/selinux
# hostnamectl set-hostname gitlab.example.com
# reboot

2.1.3 gitlab 安装及使用

安装包下载地址 https://packages.gitlab.com/gitlab/gitlab-ce
rpm 包国内下载地址 https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/
ubuntu 国内下载地址 https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu/pool/

V11.11.8 linux38

[root@gitlab src]#dpkg -i gitlab-ce_13.1.10-ce.0_amd64.deb
2.1.3.1 gitlab 配置使用
#公司里推荐使用域名
[root@gitlab ~]#grep "^[a-Z]" /etc/gitlab/gitlab.rb
external_url 'http://10.0.78.101'

encpnupnpbongcbi
#可选邮件通知设置
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "[email protected]"
gitlab_rails['smtp_password'] = "ooejgzgofwzdihdh"
gitlab_rails['smtp_domain'] = "qq.com"
gitlab_rails['smtp_authentication'] = :login
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
gitlab_rails['gitlab_email_from'] = "[email protected]"
user["git_user_email"] = "[email protected]"
2.1.3.2 初始化服务

执行配置并启动服务

# gitlab-ctl reconfigure #修改完配置文件要执行此操作

38.DevOps之基于Jenkins实现的CI与CD_第10张图片

#gitlab 相关的目录有哪些

/etc/gitlab #配置文件目录
/run/gitlab #运行 pid 目录
/opt/gitlab #安装目录
/var/opt/gitlab #数据目录
/var/log/gitlab #日志目录
2.1.3.3 常用命令

# gitlab-rails #用于启动控制台进行特殊操作,比如修改管理员密码、打开数据库控制
台( gitlab-rails dbconsole)等

root@gitlab:~# gitlab-rails dbconsole
psql (9.6.11)
Type "help" for help.
gitlabhq_production=>
# gitlab-rails --help

# gitlab-psql #数据库命令行

root@s1:~# gitlab-psql
psql (9.6.11)
Type "help" for help.
gitlabhq_production=# \db
List of tablespaces
Name | Owner | Location
------------+-------------+----------
pg_default | gitlab-psql |
pg_global | gitlab-psql |
(2 rows)

# gitlab-rake #数据备份恢复等数据操作
# gitlab-ctl #客户端命令行操作行
# gitlab-ctl stop #停止 gitlab
# gitlab-ctl start #启动 gitlab
# gitlab-ctl restar #重启 gitlab
# gitlab-ctl status #查看组件运行状态
# gitlab-ctl tail nginx #查看某个组件的日志

38.DevOps之基于Jenkins实现的CI与CD_第11张图片

2.1.3.4 验证 gitlab 启动完成

38.DevOps之基于Jenkins实现的CI与CD_第12张图片

2.1.3.5 验证端口及状态

80 端口是在初始化 gitlib 的时候启动的,因此如果之前的有程序占用会导致初始化失败或无法访问!

38.DevOps之基于Jenkins实现的CI与CD_第13张图片

2.1.3.6 登录 gitlab web 界面

http://x.x.x.x/
登录 web 页面并设置密码,最少 8 位

38.DevOps之基于Jenkins实现的CI与CD_第14张图片

2.1.3.7 登录 gitlab

登录,默认用户为 root

38.DevOps之基于Jenkins实现的CI与CD_第15张图片

2.1.3.8 默认首页

38.DevOps之基于Jenkins实现的CI与CD_第16张图片

2.1.3.9 关闭账号注册

默认情况下可以直接注册账号,因此一般都关闭此功能,由运维工程师来创建,防止恶意注册

38.DevOps之基于Jenkins实现的CI与CD_第17张图片

取消账户注册功能之后点 save

38.DevOps之基于Jenkins实现的CI与CD_第18张图片

2.1.3.10 验证是否还有注册选项

38.DevOps之基于Jenkins实现的CI与CD_第19张图片

2.1.3.11 创建 git 账户

38.DevOps之基于Jenkins实现的CI与CD_第20张图片

38.DevOps之基于Jenkins实现的CI与CD_第21张图片

image-20200915143502379

再创建一个tangtang

38.DevOps之基于Jenkins实现的CI与CD_第22张图片

2.1.3.12 重新设置密码

第一次使用新账号登录要设置密码

38.DevOps之基于Jenkins实现的CI与CD_第23张图片

通过邮件重置用户密码

38.DevOps之基于Jenkins实现的CI与CD_第24张图片

设置密码

38.DevOps之基于Jenkins实现的CI与CD_第25张图片

2.1.3.13 创建组

使用管理员 root 创建组,一个组里面可以有多个项目分支,可以将开发添加到组里面进行设置权限,不同的组就是公司不同的开发项目或者服务模块,不同的组添加不同的开发即可实现对开发设置权限的管理。

38.DevOps之基于Jenkins实现的CI与CD_第26张图片

2.1.3.14 使用管理员创建项目

38.DevOps之基于Jenkins实现的CI与CD_第27张图片

使用管理员创建项目

38.DevOps之基于Jenkins实现的CI与CD_第28张图片

创建后的项目效果

38.DevOps之基于Jenkins实现的CI与CD_第29张图片

2.1.3.15 将用户添加到组

https://docs.gitlab.com/ee/user/permissions.html (更多权限)

38.DevOps之基于Jenkins实现的CI与CD_第30张图片

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gBHQeTc6-1626502809342)(C:\Users\cui\Desktop\课程截图\38.DevOps 之基于 Jenkins 实现的 CI 与 CD_图片\image-20200915160057525.png)]

38.DevOps之基于Jenkins实现的CI与CD_第31张图片

38.DevOps之基于Jenkins实现的CI与CD_第32张图片

2.1.3.16 创建一个测试页面

找到项目界面

38.DevOps之基于Jenkins实现的CI与CD_第33张图片

38.DevOps之基于Jenkins实现的CI与CD_第34张图片

添加一个页面

38.DevOps之基于Jenkins实现的CI与CD_第35张图片

2.1.3.17 git 客户端测试 clone 项目
[root@web3 opt]#git clone http://10.0.78.101/magedu/web1.git
Cloning into 'web1'...
Username for 'http://10.0.78.101': qinghe
Password for 'http://[email protected]': 
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
[root@web3 opt]#cat web1/index.html 
<h2>magedu web1 version11111111111111111</h2>

编辑文件并测试提交

[root@web3 opt]#vim web1/index.html
[root@web3 opt]#cat web1/index.html
<h2>magedu web1 version11111111111111111</h2>
<h2>magedu web2 version22222222222222222</h2>
[root@web3 opt]#cd web1/
[root@web3 web1]#git add index.html
[root@web3 web1]#git commit -m "v2"
[master f428c8e] v2
 Committer: root <[email protected]>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:

    git config --global --edit

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 1 file changed, 2 insertions(+), 1 deletion(-)
[root@web3 web1]#git push
Username for 'http://10.0.78.101': qinghe
Password for 'http://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 276 bytes | 276.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To http://10.0.78.101/magedu/web1.git
   13ede10..f428c8e  master -> master
2.1.3.18 git web 端验证数据

38.DevOps之基于Jenkins实现的CI与CD_第36张图片

2.1.3.19 gitlab 使用
2.1.3.19.1 数据保存方式

SVN 与 CVS:
每次提交的文件都单独保存, 即按照文件的提交时间区分不同的版本, 保存至不同的逻辑存储区域,后期恢复的时候直接基于之前版本恢复。

38.DevOps之基于Jenkins实现的CI与CD_第37张图片

Gitlab:
Gitlab 与 SVN 的数据保存方式不一样, gitlab 虽然也会在内部对数据进行逻辑划分保存,但是当后期提交的数据如果和之前提交过的数据没有变化,其就直接快照之前的文件,而不是在将文件重新上传一份在保存一遍,这样既节省了空间又加快了代码提交速度。

38.DevOps之基于Jenkins实现的CI与CD_第38张图片

2.1.3.19.2 常用 git 命令

使用 git 命令下载代码与提交代码等操作。

38.DevOps之基于Jenkins实现的CI与CD_第39张图片

上图说明:

工作区指的就是Windows上的一个目录(上面例子的web1目录),add之后是放在了暂存区,再用commit命令提交到本地工作区(本机仓库,没有网也可以提交),一旦提交到本地仓库就会产生一个tag信息(标记,代码恢复时使用),最后再push到git仓库(上图少了一步),这样别的开发才能拿到你写的代码

git config --global user.name "name" #设置全局用户名,并不一定是真实的,但一定要有,最好写真实的
git config --global user.email [email protected] #设置全局邮箱,同上
git config --global --list  #列出用户全局设置
git add index.html / . 		#添加指定文件、 目录或当前目录下所有数据到暂存区
git commit -m "11" 			#提交文件到工作区
git status 					#查看工作区的状态
git push 					#提交代码到服务器
git pull 					#获取代码到本地
git log 					#查看操作日志,里面会有commit标记(回滚时使用的),非常重要!!!
vim .gitignore 				#定义忽略文件上传至 gitlab
#以下是运维相关
git reset --hard HEAD^^ 	#git 版本回滚, HEAD 为当前版本,加一个^为上一个, ^^为上上一个版本;必须是在不影响用户访问的前提下再进行代码部署
git reflog # 				#获取每次提交的 ID,可以使用--hard 根据提交的 ID 进行版本回退
git reset --hard 5ae4b06 	#回退到指定 id 的版本,前八位即可
#git branch 				#查看当前所处的分支
#git checkout -b develop 	#创建并切换到一个新分支 
#git checkout develop 		#切换分支
2.1.3.19.3 git 缓存区与工作区等概念

工作区: clone 的代码或者开发自己编写的代码文件所在的目录, 通常是代码所在的一个服务的目录名称。
暂存区: 用于存储在工作区中对代码进行修改后的文件所保存的地方, 使用 git add 添加。
本地仓库: 用于提交存储在工作区和暂存区中改过的文件地方,使用 git commit 提交。
远程仓库: 多个开发共同协作提交代码的仓库,即 gitlab 服务器。

38.DevOps之基于Jenkins实现的CI与CD_第40张图片

2.1.3.20 gitlab 数据备份恢复
2.1.3.20.1 停止 gitlab 数据服务
[root@gitlab ~]#gitlab-ctl stop unicorn
[root@gitlab ~]#gitlab-ctl stop sidekiq
ok: down: sidekiq: 0s, normally up
2.1.3.20.2 手动备份数据
[root@gitlab ~]#gitlab-rake gitlab:backup:create #在任意目录即可备份当前 gitlab 数据
[root@gitlab ~]#gitlab-ctl start #备份完成后启动 gitlab
2.1.3.20.3 查看要恢复的文件
/var/opt/gitlab/backups/ # Gitlab 数据备份目录, 需要使用命令备份的
/var/opt/gitlab/nginx/conf #nginx 配置文件
/etc/gitlab/gitlab.rb #gitlab 配置文件
/etc/gitlab/gitlab-secrets.json #key 文件

[root@gitlab ~]#ll /var/opt/gitlab/backups/
total 392
drwx------  2 git  root   4096 Sep 15 21:36 ./
drwxr-xr-x 21 root root   4096 Sep 14 20:56 ../
-rw-------  1 git  git  194560 Sep 15 21:33 1600176792_2020_09_15_13.1.10_gitlab_backup.tar
-rw-------  1 git  git  194560 Sep 15 21:36 1600176968_2020_09_15_13.1.10_gitlab_backup.tar
#1600176968是时间戳,从1970年开始计算的,以秒为单位,这样备份的文件就不会重名
#13.1.10是gitlab的版本号
2.1.3.20.4 执行恢复

删除一些数据,测试能否恢复

[root@gitlab ~]#gitlab-ctl stop unicorn
[root@gitlab ~]#gitlab-ctl stop sidekiq #恢复数据之前停止服务
root@s1:~# gitlab-rake gitlab:backup:restore BACKUP=备份文件名

#以下为实验示例
[root@gitlab ~]#gitlab-rake gitlab:backup:restore BACKUP=1600176968_2020_09_15_13.1.10

确认恢复数据

38.DevOps之基于Jenkins实现的CI与CD_第41张图片

2.1.3.20.5 启动服务
[root@gitlab ~]#gitlab-ctl start sidekiq
ok: run: sidekiq: (pid 57185) 0s
[root@gitlab ~]#gitlab-ctl start unicorn
2.1.3.21 gitlab 汉化

虽然不推荐,但是有需求, 基于第三方开发爱好者实现

2.1.3.21.1 下载语言包替换

通过指定版本的语言包汉化
https://gitlab.com/xhang/gitlab/-/archive/v12.3.5-zh/gitlab-v12.3.5-zh.tar.gz
https://gitlab.com/xhang/gitlab/-/archive/v11.11.5-zh/gitlab-v11.11.5-zh.tar
https://gitlab.com/xhang/gitlab/-/archive/v11.9.8-zh/gitlab-v11.9.8-zh.tar
https://gitlab.com/xhang/gitlab

38.DevOps之基于Jenkins实现的CI与CD_第42张图片

首次安装 gitlab 步骤
# vim /etc/gitlab/gitlab.rb #修改配置
# gitlab-ctl reconfigure
已经安装 gitlab 步骤
# gitlab-ctl stop
# tar xvf gitlab-vX.Y.Z-zh.tar
# cp -rp /opt/gitlab/embedded/service/gitlab-rails /opt/gitlab-rails.bak #备份源文件
# cp -rf gitlab-vX.Y.Z-zh/* /opt/gitlab/embedded/service/gitlab-rails/ #替换文件
# gitlab-ctl reconfigure
# gitlab-ctl start

Web 界面更改语言:
右上角的账户下拉框选 Settings 然后左侧 Preferences 设置项,然后语言选择中文

38.DevOps之基于Jenkins实现的CI与CD_第43张图片

保存后刷新界面

2.1.3.21.2 通过源码汉化

https://gitlab.com/xhang/gitlab #汉化包地址
# gitlab-ctl stop
# git clone https://gitlab.com/xhang/gitlab.git
# head -1 /opt/gitlab/version-manifest.txt #查看当前 gitlab 版本
# cd gitlab
# git diff v11.9.8 v11.9.8-zh
# git diff v12.3.5 v12.3.5-zh
# git diff v11.9.8 v11.9.8-zh > /root/v11.9.8-zh.diff
# gitlab-ctl stop
# patch -f -d /opt/gitlab/embedded/service/gitlab-rails -p1 < /root/v11.9.8-zh.diff
# gitlab-ctl reconfigure
# gitlab-ctl start
v11.11.8 汉化效果

38.DevOps之基于Jenkins实现的CI与CD_第44张图片

v.12.2.8 汉化效果

38.DevOps之基于Jenkins实现的CI与CD_第45张图片

V12.3.5 汉化效果:

38.DevOps之基于Jenkins实现的CI与CD_第46张图片

2.2 常见的代码部署方式

2.2.1 蓝绿部署

蓝绿部署指的是不停老版本代码(不影响上一个版本访问), 而是在另外一套环境部署新版本然后进行测试,测试通过后将用户流量切到新版本, 其特点为业务无中断,升级风险相对较小。需要大量服务器的支撑

具体过程
1、 当前版本业务正常访问(V1)
2、 在另外一套环境部署新代码(V2),代码可能是增加了功能或者是修复了某些 bug
3、 测试通过之后将用户请求流量切到新版本环境
4、 观察一段时间,如有异常直接切换旧版本
5、 下次升级, 将旧版本升级到新版本(V3)

蓝绿部署适用的场景:
1、不停止老版本,额外部署一套新版本,等测试发现新版本 OK 后,删除老版本。
2、蓝绿发布是一种用于升级与更新的发布策略,部署的最小维度是容器,而发布的最小维度是应用。
3、蓝绿发布对于增量升级有比较好的支持,但是对于涉及数据表结构变更等等不可逆转的升级,并不完全合适用蓝绿发布来实现,需要结合一些业务的逻辑以及数据迁移与回滚的策略才可以完全满足需求。

38.DevOps之基于Jenkins实现的CI与CD_第47张图片

2.2.2 金丝雀发布

38.DevOps之基于Jenkins实现的CI与CD_第48张图片

38.DevOps之基于Jenkins实现的CI与CD_第49张图片

非常适合于中小企业

金丝雀发布也叫灰度发布, 是指在黑与白之间,能够平滑过渡的一种发布方式, 灰度发布是增量发布的一种类型,灰度发布是在原有版本可用的情况下,同时部署一个新版本应用作为“金丝雀” (小白鼠),测试新版本的性能和表现,以保障整体系统稳定的情况
下,尽早发现、调整问题。

“金丝雀”的由来 17 世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感。空气中哪怕有极其微量的瓦斯,金丝雀也会停止歌唱;而当瓦斯含量超过一定限度时,虽然鲁钝的人类毫无察觉,金丝雀却早已毒发身亡。当时在采矿设备相对简陋的条件下,工人们每次下井都会带上一只金丝雀作为“瓦斯检测指标”,以便在危险状况下紧急撤离。

金丝雀发布、灰度发布步骤组成:
1、准备好部署各个阶段的工件,包括 构建工件,测试脚本,配置文件和部署清单文件。
2、从负载均衡列表中移除掉“金丝雀”服务器。
3、升级“金丝雀”应用(排掉原有流量并进行部署)。
4、对应用进行自动化测试。
5、将“金丝雀”服务器重新添加到负载均衡列表中(连通性和健康检查)。
6、如果“金丝雀”在线使用测试成功,升级剩余的其他服务器。(否则就回滚)
灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。

灰度发布/金丝雀部署适用的场景:
1、不停止老版本,额外搞一套新版本,不同版本应用共存。
2、灰度发布中,常常按照用户设置路由权重,例如 90%的用户维持使用老版本, 10%的用户尝鲜新版本。
3、经常与 A/B 测试一起使用,用于测试选择多种方案。

下图中,左下方的少部分用户就被当作“金丝雀”来用于测试新上线的1.1版本。如果新版本出现问题,“金丝雀”们会报警,但不会影响其他用户业务的正常运行

38.DevOps之基于Jenkins实现的CI与CD_第50张图片

逐步推送示例:

38.DevOps之基于Jenkins实现的CI与CD_第51张图片

2.2.3 滚动发布

38.DevOps之基于Jenkins实现的CI与CD_第52张图片

滚动发布,一般是取出一个或者多个服务器停止服务,执行更新,并重新将其投入使用。周而复始,直到集群中所有的实例都更新成新版本。

2.2.4 A/B 测试

A/B 测试也是同时运行两个 APP 环境,但是蓝绿部署完全是两码事, A/B 测试是用来测试应用功能表现的方法,例如可用性、受欢迎程度、可见性等等,蓝绿部署的目的是安全稳定地发布新版本应用,并在必要时回滚, 即蓝绿部署是一套正式环境环境在线, 而A/B 测试是两套正式环境在线。

38.DevOps之基于Jenkins实现的CI与CD_第53张图片

三 部署 web 服务器环境

38.DevOps之基于Jenkins实现的CI与CD_第54张图片

3.1 java 环境

各 web 服务器准备 tomcat 运行环境

# useradd www -u 2000
# mkdir /apps && cd /apps
[root@web1 src]#tar xvf jdk-8u261-linux-x64.tar.gz
[root@web1 jdk1.8.0_261]#ln -sv /usr/local/src/jdk1.8.0_261/ /usr/local/jdk
# vim/etc/profile
export HISTTIMEFORMAT="%F %T `whoami` "
export export LANG="en_US.utf-8"
export JAVA_HOME=/apps/jdk
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
# source /etc/profile && java -version
[root@web1 apps]#tar xvf apache-tomcat-8.5.57.tar.gz
[root@web1 apps]#ln -sv /apps/apache-tomcat-8.5.57 /apps/tomcat
#方便以后做升级

3.2 准备 tomcat 启动脚本

# cp /root/tomcat /etc/init.d/

3.3 web 部署

部署 web 服务器并确认各 web 服务器访问正常

# groupadd -g 2020 magedu && useradd -m -g magedu -u 2020 -s /bin/bash magedu
# 创建web 账户
# useradd www -u 2019 #centos 创建web 启动账户
# mkdir /data/tomcat/tomcat_appdir -p #保存 web 压缩包
# mkdir /data/tomcat/tomcat_webdir #保存解压后的 web 目录
# mkdir /data/tomcat/tomcat_webapps #tomcat app 加载目录,在 server.xml 定义
# mkdir /data/tomcat/tomcat_webdir/myapp #Java 代码目录
# echo SERVER_IP > /data/tomcat/tomcat_webdir/myapp/index.html

3.4 配置 tomcat 配置文件

[root@web1 ~]#vim /apps/tomcat/conf/server.xml
<Host name="localhost"  appBase="/data/tomcat/tomcat_webapps"  unpackWARs="false" autoDeploy="false">

3.5 启动 tomcat

#修改权限,切换到普通用户magedu
[root@web1 ~]#chown magedu.magedu /apps/tomcat /apps/apache-tomcat-8.5.57 /data/tomcat/ -R
[root@web1 ~]#su - magedu
magedu@web1:~$/etc/init.d/tomcat start

3.6 确认各 web 服务器访问正常

image-20200916105250593

image-20200916105205879

3.7 部署 keepalived

编译过程如下

# yum install libnfnetlink-devel libnfnetlink ipvsadm libnl libnl-devel libnl3 libnl3-devel lm_sensors-libs net-snmp-agent-libs net-snmp-libs open server openssh-clients openssl openssldevel automake iproute
# cd keepalived-2.0.7 && ./configure --prefix=/usr/local/keepalived --disable-fwmark
# make && amke install
# # mkdir /usr/local/keepalived/etc/sysconfig – p && cp keepalived/etc/init.d/keepalived.rh.init /usr/local/keepalived/etc/sysconfig/keepalived
# cp keepalived/keepalived.service /usr/lib/systemd/system/
# mkdir /usr/local/keepalived/sbin && cp bin/keepalived /usr/local/keepalived/sbin/keepalived
# mkdir /etc/keepalived
# vim /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 80
priority 100
advert_int 1
unicast_src_ip 192.168.7.103
unicast_peer {
192.167.7.104
}
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.7.100 dev eth0 label eth0:0
} 
}

yum安装如下:

[root@jenkins-slave1 ~]#apt install keepalived -y
[root@jenkins-slave1 ~]#cp /usr/share/doc/keepalived/samples/keepalived.conf.vrrp /etc/keepalived/keepalived.conf

[root@jenkins-slave1 ~]#cat /etc/keepalived/keepalived.conf 
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    garp_master_delay 10
    smtp_alert
    virtual_router_id 90
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.78.188 dev eth0 label eth0:1
    }
}

#backup的级别调低一点,降为80
[root@jenkins-slave2 ~]#vim /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    garp_master_delay 10
    smtp_alert
    virtual_router_id 90
    priority 80
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.78.188 dev eth0 label eth0:1
    }
}

[root@jenkins-slave1 ~]#systemctl restart keepalived.service 
[root@jenkins-slave1 ~]#systemctl enable keepalived.service

#最好验证keepalived的可用性,把优先级高的先停了,看看地址会不会飘过去,再开启,看会不会抢占回去

3.8 部署 haproxy 

# tar xvf haproxy-1.8.13.tar.gz
# cd haproxy-1.8.13
# make ARCH=x86_64 TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy
# make install PREFIX=/usr/local/haproxy
# vim /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
#支持多配置文件读取,类似于从侧面是实现配置文件的 include 功能。
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf -p /run/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
# mkdir /etc/haproxy

3.9 测试访问

测试 haproxy 反向代理 web 服务器
编辑本机 hosts 文件,将 myapp.web.com 解析到对应的 IP 负载 IP

C:\Windows\System32\drivers\etc\hosts
192.168.7.100 myapp.web.com

记录 HAProxy 访问日志

vim/etc/rsyslog.conf
14 # Provides UDP syslog reception
15 $ModLoad imudp #去掉注释
16 $UDPServerRun 514 #去掉注释
18 # Provides TCP syslog reception
19 $ModLoad imtcp #去掉注释
20 $InputTCPServerRun 514 #去掉注释
93 local3.* /var/log/haproxy.log

systemctl restart rsyslog

log 127.0.0.1 local3 info #global 部分
listen web_port
bind 0.0.0.0:80
mode http
log global
option httplog
server 192.168.7.103 192.168.7.103:8080 check inter 3000 fall 2 rise 5
server 192.168.7.104 192.168.7.104:8080 check inter 3000 fall 2 rise 5

重启 rsyslog 和 haproxy 服务,验证/var/log/haproxy.log 可以记录日志

38.DevOps之基于Jenkins实现的CI与CD_第55张图片

[root@jenkins-slave2 src]#vim /etc/sysctl.conf
net.ipv4.ip_nonlocal_bind = 1
[root@jenkins-slave2 src]#sysctl -p
net.ipv4.ip_nonlocal_bind = 1

[root@jenkins-slave2 src]#ss -ntl |grep 80
LISTEN   0         128             10.0.78.188:80               0.0.0.0:*

#此时再去访问vip,就能转发到两个web服务器上去

3.10 验证 HAProxy 统计页面

http://myapp.web.com:9009/haproxy-status

38.DevOps之基于Jenkins实现的CI与CD_第56张图片

做一次域名解析:

38.DevOps之基于Jenkins实现的CI与CD_第57张图片

3.11 验证 haproxy 代理 web 服务器

http://myapp.web.com/myapp/

image-20200916145222606

image-20200916145235166

四 Jenkins 部署与基础配置

https://jenkins.io/zh/

4.1 配置 java 环境并部署 jenkins

4.1.1 java 环境配置

root@jenkins:/usr/local/src# tar xvf jdk-8u192-linux-x64.tar.gz
root@jenkins:/usr/local/src# ln -sv /usr/local/src/jdk1.8.0_192/ /usr/local/jdk
root@jenkins:/usr/local/src# ln -sv /usr/local/jdk/bin/java /usr/bin/ #java 命令软连接

root@jenkins:/usr/local/src# vim /etc/profile
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar

root@jenkins:/usr/local/src# source /etc/profile
root@jenkins:/usr/local/src# java -version
java version "1.8.0_192"
Java(TM) SE Runtime Environment (build 1.8.0_192-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)

apt安装过程如下:

[root@jenkins-master ~]#apt install -y openjdk-8-jdk
[root@jenkins-master ~]#java -version
openjdk version "1.8.0_265"
OpenJDK Runtime Environment (build 1.8.0_265-8u265-b01-0ubuntu2~18.04-b01)
OpenJDK 64-Bit Server VM (build 25.265-b01, mixed mode)
[root@jenkins-master ~]#apt install daemon
[root@jenkins-master ~]#dpkg -i jenkins_2.235.5_all.deb

4.1.2 启动 Jenkins:

https://mirrors.tuna.tsinghua.edu.cn/jenkins/debian-stable/ #ubuntu 安装包下载

4.1.2.1 通过 jar 包直接启动 jenkins
# java \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=12345 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname="192.168.8.2 " \
-jar jenkins-2.138.3.war &
4.1.2.2 rpm 包安装 jenkins 配置
[root@s1 ~]# grep -v "#" /etc/sysconfig/jenkins | grep -v "^$"
JENKINS_HOME="/var/lib/jenkins"
JENKINS_JAVA_CMD=""
JENKINS_USER="jenkins"
JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=12345 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname="192.168.7.101" \
"

JENKINS_PORT="8080"
JENKINS_LISTEN_ADDRESS=""
JENKINS_HTTPS_PORT=""
JENKINS_HTTPS_KEYSTORE=""
JENKINS_HTTPS_KEYSTORE_PASSWORD=""
JENKINS_HTTPS_LISTEN_ADDRESS=""
JENKINS_DEBUG_LEVEL="5"
JENKINS_ENABLE_ACCESS_LOG="no"
JENKINS_HANDLER_MAX="100"
JENKINS_HANDLER_IDLE="20"
JENKINS_ARGS=""

可选启动参数

JENKINS_JAVA_OPTIONS="--server -Xms1g -Xmx1g -Xss512k -Xmn1g
-XX:CMSInitiatingOccupancyFraction=65
-XX:+UseFastAccessorMethods
-XX:+AggressiveOpts -XX:+UseBiasedLocking
-XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10
-XX:NewSize=2048M -XX:MaxNewSize=2048M -XX:NewRatio=2
-XX:PermSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5
-XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled -Djava.awt.headless=true
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=12345
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname="192.168.7.102"

4.1.3 Jenkins 启动过程

38.DevOps之基于Jenkins实现的CI与CD_第58张图片

4.1.4 访问 jenkins 页面

38.DevOps之基于Jenkins实现的CI与CD_第59张图片

4.1.5 选择安装 jenkins 插件

解决插件安装慢的解决方式,通过 Nginx 进行 rewrite 或者反向代理,如下

127.0.0.1 updates.jenkins-ci.org

location /download/plugins {
  proxy_set_header Host mirrors.tuna.tsinghua.edu.cn;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  rewrite /download/plugins(.*) /jenkins/plugins/$1 break;
  proxy_pass http://mirrors.tuna.tsinghua.edu.cn;
}

38.DevOps之基于Jenkins实现的CI与CD_第60张图片

如果现实 jenkins 已离线,将以下文件中的更新检查地址改成国内清华大学地址, 然后
重启 jenkins 即可 https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

# cat /var/lib/jenkins/hudson.model.UpdateCenter.xml
<?xml version='1.1' encoding='UTF-8'?>
<sites>
  <site>
    <id>default</id>
    <url>https://updates.jenkins.io/update-center.json</url>
  </site>

4.1.6 插件安装过程中

http://updates.jenkins-ci.org/download/plugins/ #插件下载地址
插件安装过程中。。, 如果因为某种原因导致有有安装失败的插件, 没有关系,可以后期再单独安装

38.DevOps之基于Jenkins实现的CI与CD_第61张图片

4.1.7 创建 jenkins 管理员

38.DevOps之基于Jenkins实现的CI与CD_第62张图片

4.1.8 配置 jenkins URL

38.DevOps之基于Jenkins实现的CI与CD_第63张图片

4.1.9 配置完成并登陆 jenkins

38.DevOps之基于Jenkins实现的CI与CD_第64张图片

38.DevOps之基于Jenkins实现的CI与CD_第65张图片

4.1.10 登陆 jenkins 界面

38.DevOps之基于Jenkins实现的CI与CD_第66张图片

4.1.11 jenkins 插件管理及安装

4.1.11.1 插件安装目录

插件下载地址 http://updates.jenkins-ci.org/download/plugins/

38.DevOps之基于Jenkins实现的CI与CD_第67张图片

4.1.11.2 安装插件

搜索需要 gitlab 的插件并安装

gitlab 和 Blue Ocean

38.DevOps之基于Jenkins实现的CI与CD_第68张图片

38.DevOps之基于Jenkins实现的CI与CD_第69张图片

4.1.12 配置 jenkins 权限管理

基于角色的权限管理,先创建角色和用户, 给角色授权,然后把用户管理到角色。

4.1.12.1 安装插件

Role-based #基于角色的认证策略

38.DevOps之基于Jenkins实现的CI与CD_第70张图片

4.1.12.2 创建新用户

Jenkins—系统管理—管理用户

38.DevOps之基于Jenkins实现的CI与CD_第71张图片

38.DevOps之基于Jenkins实现的CI与CD_第72张图片

4.1.12.3 更改认证方式

Jenkins—系统管理—全局安全配置
默认创建的用户登录后可以做任何操作,取决于默认的认证授权方式。

38.DevOps之基于Jenkins实现的CI与CD_第73张图片

4.1.12.4 创建角色

Jenkins—系统管理–Manage and Assign Roles(管理和分配角色)

38.DevOps之基于Jenkins实现的CI与CD_第74张图片

4.1.12.5 添加角色

38.DevOps之基于Jenkins实现的CI与CD_第75张图片

4.1.12.6 对角色分配权限

38.DevOps之基于Jenkins实现的CI与CD_第76张图片

38.DevOps之基于Jenkins实现的CI与CD_第77张图片

修改权限

image-20200916183155876

38.DevOps之基于Jenkins实现的CI与CD_第78张图片

4.1.12.7 将用户关联到角色

38.DevOps之基于Jenkins实现的CI与CD_第79张图片

4.1.12.8 测试普通用户登录

38.DevOps之基于Jenkins实现的CI与CD_第80张图片

登录成功之的界面,没有系统管理权限,只能执行被授权过的 job且没有了管理员权限。

38.DevOps之基于Jenkins实现的CI与CD_第81张图片

4.1.13 jenkins 邮箱配置

4.1.13.1 生成 QQ 邮箱登录授权码
4.1.13.2 配置 jenkins 管理员邮箱

Jenkins—系统管理—系统设置

image-20200916212202174

4.1.13.3 发件配置

38.DevOps之基于Jenkins实现的CI与CD_第82张图片

4.1.13.4 测试发送邮件

38.DevOps之基于Jenkins实现的CI与CD_第83张图片

4.2 基于 ssh key 拉取代码

4.2.1 添加 ssh key

38.DevOps之基于Jenkins实现的CI与CD_第84张图片

[root@jenkins-master ~]#ssh-keygen
[root@jenkins-master ~]#ll /root/.ssh/
total 20
drwx------ 2 root root 4096 Sep 16 22:30 ./
drwx------ 5 root root 4096 Sep 16 22:30 ../
-rw------- 1 root root 1679 Sep 16 22:30 id_rsa
-rw-r--r-- 1 root root  415 Sep 16 22:30 id_rsa.pub
-rw-r--r-- 1 root root  222 Sep 16 22:30 known_hosts

#查看公钥
[root@jenkins-master ~]#cat /root/.ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGo6lz3IRWvzWTWpDo+Cy3Y24UvYWQC1xM3ypcofbaN4F1SRa4x0BvVhMZdCoNtixC5ePEC7oXhJBQ4FbBhnZadVkzAZ7GfXl2sjGd7pjh0acycvg8yB72W97CTsYGsuv24hS0EKwWxb8VJNSdzZt6a2lRoFRQmOf45a1LxPka7zoPy8nurNOxuep9rhX3NrQAFNAVYh4rhaX7Bx4RW/NqSXpxdpjJLQuMns5LkSvVbDJqfqINuU94BUnkECO6fWmlRgrT+kbYlaAtZGjRgwgPSaa2r0BIiEMTo8O3UkBuo5v26H7AZML8pojlHftBeDBYx1Oj5VkNULMJW7DbykIX [email protected]

4.2.2 添加 ssh key

38.DevOps之基于Jenkins实现的CI与CD_第85张图片

4.2.3 创建 ssh key

ssh key 只用于免认证获取代码

38.DevOps之基于Jenkins实现的CI与CD_第86张图片

4.2.4 测试 ssh key

测试可以不使用用户名密码后直接获取代码,仅用于代码部署,不能用于提交

38.DevOps之基于Jenkins实现的CI与CD_第87张图片

4.3 配置 jenkins 到 gitlab 非交互拉取代码

4.3.1 jenkins 服务器添加证书

Jenkins-凭据-jenkins—全局凭据—添加凭据

38.DevOps之基于Jenkins实现的CI与CD_第88张图片

4.3.2 jenkins 创建 project

38.DevOps之基于Jenkins实现的CI与CD_第89张图片

4.3.3 配置 git 项目地址和用户

添加完成的证书没有报错表示认证通过

38.DevOps之基于Jenkins实现的CI与CD_第90张图片

4.3.4 测试构建项目

4.3.4.1 点击立即构建

38.DevOps之基于Jenkins实现的CI与CD_第91张图片

4.3.4.2 验证构建结果

38.DevOps之基于Jenkins实现的CI与CD_第92张图片

4.3.4.3 服务器验证数据

38.DevOps之基于Jenkins实现的CI与CD_第93张图片

4.3.4.4 将代码部署至后端服务器

先做好key验证:

[root@jenkins-master ~]#ssh-copy-id [email protected]
[root@jenkins-master ~]#ssh-copy-id [email protected]
#验证
[root@jenkins-master ~]#ssh [email protected]
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-117-generic x86_64)
magedu@web2:~$

构建执行 shell, 脚本内容:

cd /var/lib/jenkins/workspace/linux36-job1/
tar czvf code.tar.gz index.html
scp code.tar.gz [email protected]:/data/tomcat/tomcat_appdir/
scp code.tar.gz [email protected]:/data/tomcat/tomcat_appdir/

ssh [email protected] "/etc/init.d/tomcat stop && rm -rf
/data/tomcat/tomcat_webdir/myapp/* && cd /data/tomcat/tomcat_appdir && tar
xvf code.tar.gz -C /data/tomcat/tomcat_webdir/myapp/"

ssh [email protected] "/etc/init.d/tomcat stop && rm -rf
/data/tomcat/tomcat_webdir/myapp/* && cd /data/tomcat/tomcat_appdir && tar xvf
code.tar.gz -C /data/tomcat/tomcat_webdir/myapp/"

ssh [email protected] "/etc/init.d/tomcat start"
ssh [email protected] "/etc/init.d/tomcat start"

第一次构建之后

38.DevOps之基于Jenkins实现的CI与CD_第94张图片

升级一次代码在进行构建

[root@jenkins-master opt]#git clone http://10.0.78.101/magedu/web1.git
Cloning into 'web1'...
Username for 'http://10.0.78.101': tangtang
Password for 'http://[email protected]': 
remote: Enumerating objects: 15, done.
remote: Counting objects: 100% (15/15), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 15 (delta 3), reused 15 (delta 3), pack-reused 0
Unpacking objects: 100% (15/15), done.

[root@jenkins-master opt]#vim web1/index.html
<h2>magedu web1 version11111111111111111</h2>
<h2>magedu web1 version22222222222222222</h2>
<h2>magedu web1 version33333333333333333</h2>
<h2>magedu web1 version44444444444444444</h2>
<h2>magedu web1 version55555555555555555</h2>
<h2>magedu web1 version66666666666666666</h2>

#代码修改后进行提交
[root@jenkins-master web1]#git add .
[root@jenkins-master web1]#git commit -m "v6"	``
[master 79f9525] v6
 Committer: root <[email protected]>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:

    git config --global --edit

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 1 file changed, 5 insertions(+), 4 deletions(-)

[root@jenkins-master web1]#git push
Username for 'http://10.0.78.101': root
Password for 'http://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 297 bytes | 297.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To http://10.0.78.101/magedu/web1.git
   87d5dd4..79f9525  master -> master

脚本不建议放在Jenkins中,不太安全也不太直观,很多人进来之后都可以改;建议放在Jenkins服务器上,单独创建一个目录,如下:

[root@jenkins-master opt]#mkdir /data/scripts -p
[root@jenkins-master opt]#cd /data/scripts
#每个项目再单独创建一个目录
[root@jenkins-master scripts]#mkdir qinghe
[root@jenkins-master scripts]#cd qinghe/
[root@jenkins-master qinghe]#vim web-deploy.sh
[root@jenkins-master qinghe]#cat web-deploy.sh
#!/bin/bash
cd /var/lib/jenkins/workspace/qinghe-job1
tar czvf web1.tar.gz ./*

scp web1.tar.gz [email protected]:/data/tomcat/tomcat_appdir/
scp web1.tar.gz [email protected]:/data/tomcat/tomcat_appdir/

ssh [email protected] "/etc/init.d/tomcat stop && rm -rf /data/tomcat/tomcat_webapps/web1/* && cd /data/tomcat/tomcat_appdir/ && tar xvf web1.tar.gz -C /data/tomcat/tomcat_webapps/web1/"
ssh [email protected] "/etc/init.d/tomcat stop && rm -rf /data/tomcat/tomcat_webapps/web1/* && cd /data/tomcat/tomcat_appdir/ && tar xvf web1.tar.gz -C /data/tomcat/tomcat_webapps/web1/"

ssh [email protected] "/etc/init.d/tomcat start"
ssh [email protected] "/etc/init.d/tomcat start"

[root@jenkins-master qinghe]#chmod +x web-deploy.sh
[root@jenkins-master qinghe]#ll /data/scripts/qinghe/web-deploy.sh
-rwxr-xr-x 1 root root 684 Sep 16 23:53 /data/scripts/qinghe/web-deploy.sh*

image-20200916234817549

再一次构建之后:

38.DevOps之基于Jenkins实现的CI与CD_第95张图片

4.4 构建触发器(钩子)

构建触发器(webhook), 有的人称为钩子, 实际上是一个 HTTP 回调,其用于在开发人员向 gitlab 提交代码后能够触发 jenkins 自动执行代码构建操作。

以下为新建一个开发分支, 只有在开发人员向开发(develop)分支提交代码的时候才会触发代码构建, 而向主分支提交的代码不会自动构建, 需要运维人员手动部署代码到生产环境。(一般是在凌晨,不影响用户访问)

38.DevOps之基于Jenkins实现的CI与CD_第96张图片

由开发先把代码提交到开发分支,再把开发分支的代码部署到测试环境

此实验翻车,原因可能是gitlab版本太旧,Jenkins版本太新

38.DevOps之基于Jenkins实现的CI与CD_第97张图片

4.4.1 gitlab 新建 develop 分支

38.DevOps之基于Jenkins实现的CI与CD_第98张图片

4.4.2 gitlab 定义分支名称并创建

38.DevOps之基于Jenkins实现的CI与CD_第99张图片

4.4.3 jenkins 安装插件

#系统管理-管理插件-可选插件-Gitlab Hook 和 Gitlab Authentication

注意事项:
https://jenkins.io/security/advisory/2018-05-09/#SECURITY-263

  • 在 jenkins 系统管理–全局安全设置,认证改为登录用户可以做任何事情
  • 取消跨站请求伪造保护的勾选项
  • Gitlab Hook Plugin 以纯文本形式存储和显示 GitLab API 令牌

38.DevOps之基于Jenkins实现的CI与CD_第100张图片

4.4.4 jenkins 修改登录认证方式

系统管理—全局安全设置–授权策略

38.DevOps之基于Jenkins实现的CI与CD_第101张图片

以下为旧版本需要的操作,本次实验中并没有此项

38.DevOps之基于Jenkins实现的CI与CD_第102张图片

保存以上配置

4.4.5 jenkins 新建 develop job

38.DevOps之基于Jenkins实现的CI与CD_第103张图片

4.4.6 jenkins 构建 shell 命令

构建命令为简单的测试命令,比如输出当前的账户信息

38.DevOps之基于Jenkins实现的CI与CD_第104张图片

4.4.7 jenkins 配置构建触发器

生产 token 认证

[root@jenkins-master ~]#openssl rand -hex 12
d082dbd1b373e4eb5e2b9ae7

38.DevOps之基于Jenkins实现的CI与CD_第105张图片

4.4.8 jenkins 验证分支 job 配置文件

[root@jenkins-master ~]#vim /var/lib/jenkins/jobs/qinghe-job1/config.xml

38.DevOps之基于Jenkins实现的CI与CD_第106张图片

4.4.9 curl 命令测试触发并验证远程触发构建

  • 使用浏览器直接访问 URL 地址
  • 使用 curl 命令访问 URL
root@jenkins-master:~# curl http://10.0.78.102:8080/job/qinghe-job1/build?token=d082dbd1b373e4eb5e2b9ae7

4.4.10 jenkins 验证 job 是否自动构建

38.DevOps之基于Jenkins实现的CI与CD_第107张图片

4.4.11 gitlab 配置 webhook

Admin area—groups/project—System Hooks

38.DevOps之基于Jenkins实现的CI与CD_第108张图片

4.4.12 测试钩子可用性

38.DevOps之基于Jenkins实现的CI与CD_第109张图片

执行结果 (老师视频翻车

image-20200922100200605

4.4.13 jenkins 执行 shell 命令

将开发分支的执行 shell 命令更改为正式脚本

cd /var/lib/jenkins/workspace/linux36-job1-develop
tar czvf code.tar.gz index.html
scp code.tar.gz [email protected]:/data/tomcat/tomcat_appdir/
scp code.tar.gz [email protected]:/data/tomcat/tomcat_appdir/

ssh [email protected] "/etc/init.d/tomcat stop && rm -rf
/data/tomcat/tomcat_webdir/myapp/* && cd /data/tomcat/tomcat_appdir && tar
xvf code.tar.gz -C /data/tomcat/tomcat_webdir/myapp/"

ssh [email protected] "/etc/init.d/tomcat stop && rm -rf
/data/tomcat/tomcat_webdir/myapp/* && cd /data/tomcat/tomcat_appdir && tar xvf
code.tar.gz -C /data/tomcat/tomcat_webdir/myapp/"

ssh [email protected] "/etc/init.d/tomcat start"
ssh [email protected] "/etc/init.d/tomcat start"

4.4.12 gitlab 开发分支 develop 测试提交代码

root@gitlab:/opt# git clone -b develop http://192.168.7.101/linux36/web1.git
root@gitlab:/opt# cd web1/
root@gitlab:/opt/web1# vim index.html
root@gitlab:/opt/web1# git add index.html
root@gitlab:/opt/web1# git commit -m "v7"
root@gitlab:/opt/web1# git push
Username for 'http://192.168.7.101': user1
Password for 'http://[email protected]':
Counting objects: 3, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 291 bytes | 291.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote:
remote: To create a merge request for develop, visit:
remote:
http://192.168.7.101/linux36/web1/merge_requests/new?merge_request%5Bsource_
branch%5D=develop
remote:
To http://192.168.7.101/linux36/web1.git
9432b30..5110a70 develop -> develop

4.4.13 jenkins 验证 develop job 自动构建

38.DevOps之基于Jenkins实现的CI与CD_第110张图片

4.5 构建后项目关联

38.DevOps之基于Jenkins实现的CI与CD_第111张图片

用于多个 job 相互关联,需要串行执行多个 job 的场景, 可以通过安装插件 Parameterized Trigger 触发执行其他 project。用的并不多

38.DevOps之基于Jenkins实现的CI与CD_第112张图片

构建完成后触发另外一个 project

38.DevOps之基于Jenkins实现的CI与CD_第113张图片

38.DevOps之基于Jenkins实现的CI与CD_第114张图片

4.5.1 配置构建后操作

38.DevOps之基于Jenkins实现的CI与CD_第115张图片

4.5.2 验证构建后操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MVpOpOHo-1626502810064)(C:\Users\cui\Desktop\课程截图\38.DevOps之基于Jenkins实现的CI与CD_图片\image-20200922103722162.png)]

4.6 jenkins 分布式

在众多 Job 的场景下,单台 jenkins master 同时执行代码 clone、编译、 打包及构建,其性能可能会出现瓶颈从而会影响代码部署效率,影响 jenkins 官方提供了 jenkins 分布式构建, 将众多 job 分散运行到不同的 jenkins slave 节点, 大幅提高并行 job 的处理能力。

38.DevOps之基于Jenkins实现的CI与CD_第116张图片

4.6.1 配置 slave 节点 java 环境

Slave 服务器创建工作目录, 如果 slave 需要执行编译 job,则也需要配置 java 环境并且安装 git、 svn、 maven 等与 master 相同的基础运行环境,另外也要创建与 master 相同的数据目录,因为脚本中调用的路径只有相对一 master 的一个路径,此路径在master 与各 node 节点必须保持一致。

# mkdir -p /var/lib/jenkins #创建数据目录
# jenkins home location
JENKINS_HOME=/var/lib/$NAME #工作目录配置与 master 保持一致

# vim /etc/profile
export HISTTIMEFORMAT="%F %T `whoami` "
export export LANG="en_US.utf-8"
export JAVA_HOME=/usr/local/jdk
export
CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin

4.6.2 添加 slave 节点

Jenkins—系统管理—节点管理—新建节点
添加 slave 节点

38.DevOps之基于Jenkins实现的CI与CD_第117张图片

部分 jenkins slave 信息

38.DevOps之基于Jenkins实现的CI与CD_第118张图片

或者选择不校验证书(推荐)

38.DevOps之基于Jenkins实现的CI与CD_第119张图片

4.6.3 添加 slave 认证凭据

38.DevOps之基于Jenkins实现的CI与CD_第120张图片

4.6.4. slave 节点最终信息

38.DevOps之基于Jenkins实现的CI与CD_第121张图片

4.6.5 jenkins slave 创建日志

38.DevOps之基于Jenkins实现的CI与CD_第122张图片

4.6.6 如果 slave 没有 java 环境则报错如下

38.DevOps之基于Jenkins实现的CI与CD_第123张图片

4.6.7 验证 slave web 状态

正常状态

38.DevOps之基于Jenkins实现的CI与CD_第124张图片

时间不同步状态

38.DevOps之基于Jenkins实现的CI与CD_第125张图片

4.6.8 验证 slave 进程状态

38.DevOps之基于Jenkins实现的CI与CD_第126张图片

4.7 pipline

官方介绍; https://jenkins.io/2.0/ #jenkins 2.X 管官方介绍

https://jenkins.io/zh/doc/book/pipeline/ #官方 pipline 示例

pipline 是帮助 Jenkins 实现 CI 到 CD 转变的重要角色,是运行在 jenkins 2.X 版本的核心插件,简单来说 Pipline 就是一套运行于 Jenkins 上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂发布流程, 从而实现单个任务很难实现的复杂流程编排和任务可视化, Pipeline 的实现方式是一套Groovy DSL,任何发布流程都可以表述为一段 Groovy 脚本。

38.DevOps之基于Jenkins实现的CI与CD_第127张图片

基本流程:

  1. Clone 代码
  2. 代码质量测试
  3. 编译或打包
  4. 代码分发
  5. 服务器下线
  6. 停止web服务
  7. 代码替换
  8. 启动web服务
  9. web服务测试
  10. 添加到负载均衡

4.7.1 pipline 语法

Stage:阶段,一个 pipline 可以划分为若干个 stage,每个 stage 都是一个操作步骤,比如 clone 代码、代码编译、 代码测试和代码部署, 阶段是一个逻辑分组, 可以跨多个 node 执行。
Node:节点,每个 node 都是一个 jenkins 节点,可以是 jenkins master 也可以是 jenkins agent, node 是执行 step 的具体服务器。
Step:步骤, step 是 jenkins pipline 最基本的操作单元, 从在服务器创建目录到构建容器镜像,由各类 Jenkins 插件提供实现, 一个 stage 中可以有多个 step, 例如 sh “make”

4.7.2 pipline 优势

可持续性 jenkins 的重启或者中断后不影响已经执行的 Pipline Job
支持暂停 pipline 可以选择停止并等待人工输入或批准后再继续执行。
可扩展 通过 groovy 的编程更容易的扩展插件。
并行执行 通过 groovy 脚本可以实现 step, stage 间的并行执行,和更复杂的相互依赖关系。

4.7.3 pipline job 测试

4.7.3.1 创建 pipline job

38.DevOps之基于Jenkins实现的CI与CD_第128张图片

4.7.3.2 测试简单 pipline job 运行
Pipeline 测试命令: 
node {
    stage("clone 代码"){
      echo "代码 clone"
    }
    stage("代码构建"){
      echo "代码构建"
    }
    stage("代码测试"){
      echo "代码测试"
    }
    stage("代码部署"){
      echo "代码部署"
    }
}

Jenkins Web 界面配置

38.DevOps之基于Jenkins实现的CI与CD_第129张图片

4.7.3.3 执行 pipline job

38.DevOps之基于Jenkins实现的CI与CD_第130张图片

4.7.3.4 自动生成拉取代码的 pipline 脚本

点击 流水线语法 跳转至生成脚本 URL

38.DevOps之基于Jenkins实现的CI与CD_第131张图片

生成流水线脚本

38.DevOps之基于Jenkins实现的CI与CD_第132张图片

4.7.3.5 更改 pipline job
node {
    stage("clone 代码"){
        //sh "cd /data/git/linux41/ && rm -rf web1 && git clone -b master [email protected]:magedu/web1.git"
        //sh "cd /data/git/linux41/ && rm -rf web1"
        sh "cd /var/lib/jenkins/workspace/qinghe-pipline-job1 && rm -rf ./*"
        git credentialsId: '04bed6a5-7277-4599-b485-9e0773a19d59', url: '[email protected]:magedu/web1.git'
    }
    stage("代码构建"){
        echo "代码构建"
    }
    stage("代码测试"){
        echo "代码测试"
    }
    stage("代码部署"){
        echo "代码部署"
    }
}
4.7.3.6 执行 jenkins job

38.DevOps之基于Jenkins实现的CI与CD_第133张图片

4.7.3.7 验证 git clone 日志

38.DevOps之基于Jenkins实现的CI与CD_第134张图片

4.7.3.8 jenkins 服务器验证 clone 代码数据

38.DevOps之基于Jenkins实现的CI与CD_第135张图片

4.7.3.9 pipline 中执 shell 命令打包代码
node {
    stage("clone 代码"){
        sh "cd /var/lib/jenkins/workspace/qinghe-pipline-job1 && rm -rf ./*"
        git credentialsId: '04bed6a5-7277-4599-b485-9e0773a19d59', url: '[email protected]:magedu/web1.git'
    }
    stage("代码构建"){
        sh 'cd /var/lib/jenkins/workspace/qinghe-pipline-job1 && tar czvf web1.tar.gz ./*'
    }
    stage("代码测试"){
        echo "代码测试"
    }
    stage("代码部署"){
        echo "代码部署"
    }
}
4.7.3.10 pipline 部署示例
node {
    stage("clone 代码"){
        sh "cd /var/lib/jenkins/workspace/qinghe-pipline-job1 && rm -rf ./*"
        git credentialsId: '04bed6a5-7277-4599-b485-9e0773a19d59', url: '[email protected]:magedu/web1.git'
    }
    stage("代码构建"){
        sh 'cd /var/lib/jenkins/workspace/qinghe-pipline-job1 && tar czvf web1.tar.gz ./*'
    }
    stage("代码复制"){
        sh 'cd /var/lib/jenkins/workspace/qinghe-pipline-job1 && scp web1.tar.gz [email protected]:/data/tomcat/tomcat_appdir/'
        sh 'cd /var/lib/jenkins/workspace/qinghe-pipline-job1 && scp web1.tar.gz [email protected]:/data/tomcat/tomcat_appdir/'
    }
    stage("停止 tomcat 服务"){
        sh 'ssh  [email protected] "/etc/init.d/tomcat stop"'
        sh 'ssh  [email protected] "/etc/init.d/tomcat stop"'
        echo "web服务停止完成,即将开始代码替换"
    }
    stage("代码部署"){
        sh 'ssh  [email protected] "rm -rf /data/tomcat/tomcat_webapps/web1/* && cd /data/tomcat/tomcat_appdir/ && tar xvf web1.tar.gz -C /data/tomcat/tomcat_webapps/web1/"'
        sh 'ssh  [email protected] "rm -rf /data/tomcat/tomcat_webapps/web1/* && cd /data/tomcat/tomcat_appdir/ && tar xvf web1.tar.gz -C /data/tomcat/tomcat_webapps/web1/"'
    }
    stage("启动 tomcat 服务"){
        sh 'ssh  [email protected] "/etc/init.d/tomcat start"'
        sh 'ssh  [email protected] "/etc/init.d/tomcat start"'
    }
}
4.7.3.11 执行并验证 pipline job

在 gitlab 提交代码, 执行 pipline job 并验证代码是否最终部署到了 web 服务器。

38.DevOps之基于Jenkins实现的CI与CD_第136张图片

38.DevOps之基于Jenkins实现的CI与CD_第137张图片

4.7.3.12 指定 node 节点 运行 job

node 节点需要安装 git 命令

jenkins node1:

# apt-get install git -y

jenkins node2 :

# apt-get install git -y

node 节点需要打通与 web server 免密钥登录

jenkins node1:

[root@jenkins-slave1 ~]#ssh-keygen
[root@jenkins-slave1 ~]#ssh-copy-id [email protected]
[root@jenkins-slave1 ~]#ssh-copy-id [email protected]

jenkins node2

[root@jenkins-slave2 ~]#ssh-keygen
[root@jenkins-slave2 ~]#ssh-copy-id [email protected]
[root@jenkins-slave2 ~]#ssh-copy-id [email protected]

jenkins pipeline 代码 :

node("Jenkins-node1"){
    stage("clone 代码"){
        sh "cd /var/lib/jenkins/workspace/qinghe-pipline-job1 && rm -rf ./*"
        git credentialsId: '04bed6a5-7277-4599-b485-9e0773a19d59', url: '[email protected]:magedu/web1.git'
    }
    stage("代码构建"){
        sh 'cd /var/lib/jenkins/workspace/qinghe-pipline-job1 && tar czvf web1.tar.gz ./*'
    }
    stage("代码复制"){
        sh 'cd /var/lib/jenkins/workspace/qinghe-pipline-job1 && scp web1.tar.gz [email protected]:/data/tomcat/tomcat_appdir/'
        sh 'cd /var/lib/jenkins/workspace/qinghe-pipline-job1 && scp web1.tar.gz [email protected]:/data/tomcat/tomcat_appdir/'
    }
    stage("停止 tomcat 服务"){
        sh 'ssh  [email protected] "/etc/init.d/tomcat stop"'
        sh 'ssh  [email protected] "/etc/init.d/tomcat stop"'
        echo "web服务停止完成,即将开始代码替换"
    }
    stage("代码部署"){
        sh 'ssh  [email protected] "rm -rf /data/tomcat/tomcat_webapps/web1/* && cd /data/tomcat/tomcat_appdir/ && tar xvf web1.tar.gz -C /data/tomcat/tomcat_webapps/web1/"'
        sh 'ssh  [email protected] "rm -rf /data/tomcat/tomcat_webapps/web1/* && cd /data/tomcat/tomcat_appdir/ && tar xvf web1.tar.gz -C /data/tomcat/tomcat_webapps/web1/"'
    }
    stage("启动 tomcat 服务"){
        sh 'ssh  [email protected] "/etc/init.d/tomcat start"'
        sh 'ssh  [email protected] "/etc/init.d/tomcat start"'
    }
}
4.7.3.13 验证 slave 执行构建

38.DevOps之基于Jenkins实现的CI与CD_第138张图片

38.DevOps之基于Jenkins实现的CI与CD_第139张图片

4.7.3.14 验证 web 服务器代码版本

Gitlab 重新提交代码并测试代码部署

38.DevOps之基于Jenkins实现的CI与CD_第140张图片

4.8 视图

视图可用于归档 job 进行分组显示, 比如将一个业务的视图放在一个视图显示, 安装完成 build pipeline 插件之后将会有一个+号用于创建视图。

38.DevOps之基于Jenkins实现的CI与CD_第141张图片

4.8.1 安装 build pipeline 插件

38.DevOps之基于Jenkins实现的CI与CD_第142张图片

插件安装完成

38.DevOps之基于Jenkins实现的CI与CD_第143张图片

4.8.2 创建新的视图

38.DevOps之基于Jenkins实现的CI与CD_第144张图片

4.8.3 创建 pipline 视图

38.DevOps之基于Jenkins实现的CI与CD_第145张图片

4.8.3.1 定义视图配置信息

38.DevOps之基于Jenkins实现的CI与CD_第146张图片

4.8.3.2 web 显示界面

38.DevOps之基于Jenkins实现的CI与CD_第147张图片

4.8.4 列表视图

列表视图使用场景比较多, 用于将一个业务的 job 保存至一个列表视图进行分类管理,即不同业务的 job 放在不同的列表视图中。

列表视图是对众多 job 推荐使用的分类功能。

4.8.4.1 定义视图名称

38.DevOps之基于Jenkins实现的CI与CD_第148张图片

4.8.4.2 选择任务

38.DevOps之基于Jenkins实现的CI与CD_第149张图片

4.8.4.3 最终状态

38.DevOps之基于Jenkins实现的CI与CD_第150张图片

4.5 我的视图

我的视图会显示当前账户有权限访问的 job,因此需要提前划分好权限。用的较少

4.5.1 创建我的视图

创建后点保存,就会直接看到当前账户有权限的 job。

38.DevOps之基于Jenkins实现的CI与CD_第151张图片

4.5.2 最终状态

image-20200922113835046

五 代码质量测试

官方网站:http://www.sonarqube.org/

SonarQube 是一个用于代码质量管理的开放平台,通过插件机制, SonarQube可以集成不同的测试工具,代码分析工具,以及持续集成工具,例如 Hudson/Jenkins 等。

下载地址:https://www.sonarqube.org/downloads/

七个维度检测代码质量

  • 复杂度分布: 代码复杂度过高将难以理解
  • 重复代码:程序中包含大量复制、粘贴的代码而导致代码臃肿, sonar 可以展示源码中重复严重的地方
  • 单元测试统计:统计并展示单元测试覆盖率,开发或测试可以清楚测试代码的覆盖情况
  • 代码规则检查:检查代码是否符合规范
  • 注释率:若代码注释过少,特别是人员变动后,其他人接手比较难接手;若过多,又不利于阅读
  • 潜在的:Bug 检测潜在的 bug
  • 结构与设计:找出循环,展示包与包、类与类之间的依赖、检查程序之间耦合度

38.DevOps之基于Jenkins实现的CI与CD_第152张图片

5.1 代码测试工具 SonarQube 简介

7.9.x 版本不再支持 MySQL
https://docs.sonarqube.org/latest/setup/upgrade-notes/

MySQL No Longer Supported
SonarQube no longer supports MySQL. To migrate from MySQL to a supported database, see the
free MySQL Migrator tool.

38.DevOps之基于Jenkins实现的CI与CD_第153张图片

下载官方安装文件

38.DevOps之基于Jenkins实现的CI与CD_第154张图片

5.2 基础环境依赖

5.2.1 数据库环境依赖

https://docs.sonarqube.org/6.7/Requirements.html

SonarQube 6.7.X LTS 版本要求数据库要使用 MySQ 5.6 及以上版本,不支持 5.5 及更早的版
本, 7.9.X LTS 版本不再使用 MySQL。

image-20200926231709092

5.2.2 java 环境依赖

6.7.X 需要使用 Oracle JRE8

38.DevOps之基于Jenkins实现的CI与CD_第155张图片

7.9.X 需要使用

38.DevOps之基于Jenkins实现的CI与CD_第156张图片

5.2.3 系统及内核参数

[root@sonarqube ~]#groupadd -g 2020 sonarqube
[root@sonarqube ~]#useradd -r -m -s /bin/bash -g 2020 -u 2020 sonarqube  #使用普通账户启动 sonarqube
[root@sonarqube ~]#vim /etc/sysctl.conf 
vm.max_map_count=262144
fs.file-max=65536
[root@sonarqube ~]#sysctl -p

[root@sonarqube ~]#vim /etc/security/limits.conf
sonarqube - nofile 65536
sonarqube - nproc 2048

38.DevOps之基于Jenkins实现的CI与CD_第157张图片

5.2.4 硬件依赖

CPU/内存/磁盘

5.3 部署 SonarQube

5.3.1 MySQL 数据库及 SonarQube 6.7.X 部署

5.3.1.1 安装 MySQL
root@s4:~# apt-get install mysql-server mysql-client
root@s4:~# vim /etc/mysql/mysql.conf.d/mysqld.cnf #配置文件路径
root@s4:~# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.26-0ubuntu0.18.04.1 (Ubuntu)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

#创建数据库默认编码 utf-8 并授权
mysql> create database sonar default character set utf8 collate utf8_general_ci;
Query OK, 1 row affected (0.00 sec)
mysql> GRANT ALL PRIVILEGES ON sonar.* TO 'sonar'@'%' IDENTIFIED BY
'123456';
Query OK, 0 rows affected, 1 warning (0.00 sec)
5.3.1.2 测试 sonar 账户连接 mysql
root@s4:~# mysql -usonar -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.26-0ubuntu0.18.04.1 (Ubuntu)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema || sonar |
+--------------------+
2 rows in set (0.00 sec)
5.3.1.3 解压 sonarqube 并配置文件

sonar 依赖于 java 环境,而且 java 版本必须是 1.8 版本或更高,否则 sonar 启动失败
6.7.X 版本的 sonar 需要调用 elasticsearch, 而且默认需要使用普通用户启动

root@s4:~# cd /usr/local/src/
root@s4:/usr/local/src# unzip sonarqube-6.7.7.zip
root@s4:/usr/local/src# ln -sv /usr/local/src/sonarqube-6.7.7 /usr/local/sonarqube
'/usr/local/sonarqube' -> '/usr/local/src/sonarqube-6.7.7'

root@s4:/usr/local/src# chown sonarqube.sonarqube /usr/local/src/sonarqube-6.7.7
/usr/local/sonarqube -R #更改目录权限属主和属组为 sonarqube

root@s4:/usr/local/src# cd /usr/local/sonarqube
root@s4:/usr/local/sonarqube# ll #验证权限属主和属组都为 sonarqube

root@s4:/usr/local/sonarqube# su – sonarqube # 切换为 sonarqube 账户
sonarqube@s4:~$ cd /usr/local/sonarqube
sonarqube@s4:/usr/local/sonarqube$ vim conf/sonar.properties

sonarqube@s4:/usr/local/sonarqube$ grep "^[a-Z]" conf/sonar.properties
sonar.jdbc.username=sonar
sonar.jdbc.password=123456
sonar.jdbc.url=jdbc:mysql://127.0.0.1:3306/sonar?useUnicode=true&characterEncoding
=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
sonar.web.host=0.0.0.0
sonar.web.port=9000
5.3.1.4 启动 sonarqube

sonarqube@s4:/usr/local/sonarqube$ ./bin/linux-x86-64/sonar.sh start
Starting SonarQube…
Started SonarQube.

验证日志

38.DevOps之基于Jenkins实现的CI与CD_第158张图片

5.3.1.5 登录到 web 界面

点击有上角 login 登录,默认用户名密码都是 admin

38.DevOps之基于Jenkins实现的CI与CD_第159张图片

5.3.1.6 安装中文支持
5.3.1.6.1 查看本地已安装插件
#插件本地路径安装中文插件 
sonarqube@s4:~$ ll /usr/local/sonarqube/extensions/plugins/
total 40476
drwxr-xr-x 2 sonarqube sonarqube 4096 Jul 22 18:06 ./
drwxr-xr-x 5 sonarqube sonarqube 4096 Jul 22 18:07 ../
-rw-r--r-- 1 sonarqube sonarqube 92 Apr 16 15:39 README.txt
-rw-r--r-- 1 sonarqube sonarqube 2703958 Apr 15 18:38 sonar-csharp-plugin-6.5.0.3866.jar
-rw-r--r-- 1 sonarqube sonarqube 1618672 Apr 15 18:38 sonar-flex-plugin-2.3.jar
-rw-r--r-- 1 sonarqube sonarqube 6759535 Apr 15 18:38 sonar-java-plugin-4.15.0.12310.jar
-rw-r--r-- 1 sonarqube sonarqube 3355702 Apr 15 18:38 sonar-javascript-plugin-
3.2.0.5506.jar
-rw-r--r-- 1 sonarqube sonarqube 3022870 Apr 15 18:38 sonar-php-plugin-2.11.0.2485.jar
-rw-r--r-- 1 sonarqube sonarqube 4024311 Apr 15 18:38 sonar-python-plugin-1.8.0.1496.jar
-rw-r--r-- 1 sonarqube sonarqube 3625962 Apr 15 18:38 sonar-scm-git-plugin-1.3.0.869.jar
-rw-r--r-- 1 sonarqube sonarqube 6680471 Apr 15 18:38 sonar-scm-svn-plugin-1.6.0.860.jar
-rw-r--r-- 1 sonarqube sonarqube 2250667 Apr 15 18:38 sonar-typescript-plugin-
1.1.0.1079.jar
-rw-r--r-- 1 sonarqube sonarqube 7368250 Apr 15 18:38 sonar-xml-plugin-1.4.3.1027.jar
5.6.1.3.2 安装中文语言插件

administration- Marketplace,在后面的搜索框搜索插件 chinese,然后点 install 安装
或 在 插 件 目 录 /usr/local/sonarqube/extensions/plugins/ 执 行以下命令
# wget https://github.com/SonarQubeCommunity/sonar-l10nzh/releases/download/sonar-l10n-zh-plugin-1.11/sonar-l10n-zh-plugin-1.11.jar

38.DevOps之基于Jenkins实现的CI与CD_第160张图片

5.6.1.3.3 重启 sonarquebe

Web 界面安装完成插件后或者在插件目录下载插件后需要重启 sonarquebe 服务生效 :

sonarqube@s4:~$ /usr/local/sonarqube/bin/linux-x86-64/sonar.sh restart
Stopping SonarQube...
Waiting for SonarQube to exit...
Stopped SonarQube.
Starting SonarQube...
Started SonarQube.

或者在 web 界面重启

image-20210717111458384

5.3.1.7 安装其他插件

Sonarquebe 对代码的扫描都基于插件实现,因此要安装要扫描的开发语言插件
Php
Java
Python
内存不足的截图

38.DevOps之基于Jenkins实现的CI与CD_第161张图片

5.3.2 PostgreSQL 及 SonarQube 7.9.X 部署

5.3.2.1 安装 JDK 11
[root@sonarqube ~]#apt-cache madison openjdk-11-jdk
openjdk-11-jdk | 11.0.8+10-0ubuntu1~18.04.1 | http://mirrors.huaweicloud.com/ubuntu bionic-security/main amd64 Packages
openjdk-11-jdk | 11.0.8+10-0ubuntu1~18.04.1 | http://mirrors.huaweicloud.com/ubuntu bionic-updates/main amd64 Packages
openjdk-11-jdk | 10.0.1+10-3ubuntu1 | http://mirrors.huaweicloud.com/ubuntu bionic/main amd64 Packages
openjdk-lts | 10.0.1+10-3ubuntu1 | http://mirrors.huaweicloud.com/ubuntu bionic/main Sources
openjdk-lts | 11.0.8+10-0ubuntu1~18.04.1 | http://mirrors.huaweicloud.com/ubuntu bionic-security/main Sources
openjdk-lts | 11.0.8+10-0ubuntu1~18.04.1 | http://mirrors.huaweicloud.com/ubuntu bionic-updates/main Sources
[root@sonarqube ~]#apt install -y openjdk-11-jdk
[root@sonarqube ~]#java -version
openjdk version "11.0.8" 2020-07-14
OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu118.04.1)
OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu118.04.1, mixed mode, sharing)
5.3.2.1 部署 PostgreSQL 服务器
[root@sonarqube ~]#apt-cache madison postgresql
postgresql | 10+190ubuntu0.1 | http://mirrors.huaweicloud.com/ubuntu bionic-security/main amd64 Packages
postgresql | 10+190ubuntu0.1 | http://mirrors.huaweicloud.com/ubuntu bionic-updates/main amd64 Packages
postgresql |     10+190 | http://mirrors.huaweicloud.com/ubuntu bionic/main amd64 Packages
postgresql-common |        190 | http://mirrors.huaweicloud.com/ubuntu bionic/main Sources
postgresql-common | 190ubuntu0.1 | http://mirrors.huaweicloud.com/ubuntu bionic-security/main Sources
postgresql-common | 190ubuntu0.1 | http://mirrors.huaweicloud.com/ubuntu bionic-updates/main Sources
[root@sonarqube ~]#apt install postgresql -y
5.3.2.2 配置 postgrepsql

切换到 postgres 操作, PostgresSQL 安装后会自动创建 postgres 用户且没有密码。

root@sonarqube-server:~# su - postgres
postgres@sonarqube-server:~$登录 postgresql 数据库:
postgres@sonarqube-server:~$ psql -U postgres
psql (10.12 (Ubuntu 10.12-0ubuntu0.18.04.1))
Type "help" for help.
创建数据库并进行授权普通用户访问:
postgres=# CREATE DATABASE sonar; #创建数据库
CREATE DATABASE
postgres=# CREATE USER sonar WITH ENCRYPTED PASSWORD '123456'; #创建用户
CREATE ROLE
postgres=# GRANT ALL PRIVILEGES ON DATABASE sonar TO sonar; #授权用户
GRANT
postgres=# ALTER DATABASE sonar OWNER TO sonar; #执行变更
ALTER DATABASE
postgres=# \q
#修改监听地址
[postgres@sonarqube ~]$vim /etc/postgresql/10/main/postgresql.conf
59 listen_addresses = '*'
#开启远程访问
root@sonarqube-server:~# vim /etc/postgresql/10/main/pg_hba.conf
85:local all postgres peer
90:local all all peer
92:host all all 0.0.0.0/0 md594:host all all ::1/128 md5
97:local replication all peer
98:host replication all 127.0.0.1/32 md5
99:host replication all ::1/128 md5
root@sonarqube-server:~# systemctl restart postgresql
5.3.2.2 部署 7.9.X SonarQube
[root@sonarqube ~]#mkdir /apps
[root@sonarqube ~]#cd /apps
[root@sonarqube apps]#unzip sonarqube-7.9.4.zip
[root@sonarqube apps]#ln -sv /apps/sonarqube-7.9.4 /apps/sonarqube
'/apps/sonarqube' -> '/apps/sonarqube-7.9.4'
[root@sonarqube sonarqube]#chown sonarqube.sonarqube /apps/sonarqube* -R
[root@sonarqube sonarqube]#su - sonarqube
sonarqube@sonarqube:~$ cd /apps/sonarqube
sonarqube@sonarqube:/apps/sonarqube$ vim conf/sonar.properties
sonar.jdbc.username=sonar
sonar.jdbc.password=123456
sonar.jdbc.url=jdbc:postgresql://10.0.78.108/sonar
\#sonar.jdbc.url=jdbc:postgresql://172.31.0.106/sonarqube?currentSchema=my_schema

sonarqube@sonarqube:/apps/sonarqube$ ./bin/linux-x86-64/sonar.sh --help
Usage: ./bin/linux-x86-64/sonar.sh { console | start | stop | force-stop | restart | status | dump }

sonarqube@sonarqube:/apps/sonarqube$ ./bin/linux-x86-64/sonar.sh start
Starting SonarQube...
Started SonarQube.

sonarqube@sonarqube:/apps/sonarqube$ tail logs/* -f

38.DevOps之基于Jenkins实现的CI与CD_第162张图片

5.3.2.3 验证 SonarQube

38.DevOps之基于Jenkins实现的CI与CD_第163张图片

[root@sonarqube ~]#cat /etc/systemd/system/sonarqube.service
[Unit]
Description=SonarQube service
After=syslog.target network.target

[Service]
Type=simple
User=sonarqube
Group=sonarqube
PermissionsStartOnly=true
ExecStart=/usr/bin/nohup /usr/bin/java -Xms32m -Xmx32m -Djava.net.preferIPv4Stack=true -jar /apps/sonarqube-7.9.4/lib/sonar-application-7.9.4.jar
StandardOutput=syslog
LimitNOFILE=65536
LimitNPROC=8192
TimeoutStartSec=5
Restart=always

[Install]
WantedBy=multi-user.target

[root@sonarqube ~]#systemctl daemon-reload 
[root@sonarqube ~]#systemctl start sonarqube.service
5.3.2.4 访问 SonarQube web 界面

登录账户名和密码默认都是 admin

38.DevOps之基于Jenkins实现的CI与CD_第164张图片

5.3.2.5 安装中文插件

38.DevOps之基于Jenkins实现的CI与CD_第165张图片

38.DevOps之基于Jenkins实现的CI与CD_第166张图片

5.4 jenkins 服务器部署扫描器 sonar-scanner

下载地址 https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/
官方文档 https://docs.sonarqube.org/latest/analysis/scan/sonarscanner/

5.4.1 部署 sonar-scanner

sonarqube 通过调用扫描器 sonar-scanner 进行代码质量分析,即扫描器的具体工作就是扫描代码

root@jenkins-master:~# cd /apps
[root@jenkins-master apps]#unzip sonar-scanner-cli-4.3.0.2102-linux.zip
[root@jenkins-master apps]#ln -sv /apps/sonar-scanner-4.3.0.2102-linux/ /apps/sonar-scanner
'/apps/sonar-scanner' -> '/apps/sonar-scanner-4.3.0.2102-linux/'
[root@jenkins-master apps]#vim sonar-scanner/conf/sonar-scanner.properties
#----- Default SonarQube server
sonar.host.url=http://10.0.78.108:9000
#----- Default source code encoding
sonar.sourceEncoding=UTF-8

5.4.2 准备测试代码

# unzip sonar-examples-master.zip
# cd sonar-examples-master/
# cd projects/languages/php/php-sonar-runner
# pwd
/usr/local/src/sonar-examples-master/projects/languages/php/php-sonar-runner
# ll
total 24
drwxr-xr-x 3 root root 4096 Jul 25 2016 ./
drwxr-xr-x 4 root root 4096 Jul 25 2016 ../
-rw-r--r-- 1 root root 453 Jul 25 2016 README.md
-rw-r--r-- 1 root root 331 Jul 25 2016 sonar-project.properties
drwxr-xr-x 2 root root 4096 Jul 25 2016 src/
-rw-r--r-- 1 root root 272 Jul 25 2016 validation.txt
# cat sonar-project.properties 以下为默认生成的配置文件
# Required metadata
sonar.projectKey=org.sonarqube:php-simple-sq-scanner #自定义项目 key
sonar.projectName=PHP :: Simple Project :: SonarQube Scanner #项目名称, 会显示在web
sonar.projectVersion=1.0 #项目版本
# Comma-separated paths to directories with sources (required)
sonar.sources=src #源代码目录
# Language
sonar.language=php #代码语言类型
# Encoding of the source files
sonar.sourceEncoding=UTF-8 #编码格式

#最终配置
# Required metadata
sonar.projectKey=qinghe-web1-key
sonar.projectName=qinghe-web1-name
sonar.projectVersion=0.1

# Comma-separated paths to directories with sources (required)
sonar.sources=src

# Language
sonar.language=py

# Encoding of the source files
sonar.sourceEncoding=UTF-8

5.4.3 在源代码目录执行扫描

#手动在当前项目代码目录执行扫描,以下是扫描过程的提示信息,扫描的配置文件
sonar-project.propertie 每个项目都要有

# pwd
/usr/local/src/sonar-examples-master/projects/languages/php/php-sonar-runner
# /usr/local/sonar-scanner/bin/sonar-scanner

38.DevOps之基于Jenkins实现的CI与CD_第167张图片

5.4.4 sonarquebe we 界面验证扫描结果

38.DevOps之基于Jenkins实现的CI与CD_第168张图片

5.5 jenkins 执行代码扫描

5.5.1 jenkins 安装 SonarQube 插件

安装插件 SonarQube Scanner,然后配置 SonarQube server, 系统管理-系统设置。

38.DevOps之基于Jenkins实现的CI与CD_第169张图片

5.5.2 添加 sonarquebe URL

Jenkins—系统管理—系统设置–SonarQube servers

38.DevOps之基于Jenkins实现的CI与CD_第170张图片

5.5.3 让 jenkins 添加 Sonarscanner 扫描器

添加扫描器
Jenkins–系统管理-全局工具配置

5.5.3.1 手动指定绝对路径

/apps/sonar-scanner-4.3.0.2102-linux/

38.DevOps之基于Jenkins实现的CI与CD_第171张图片

5.5.3.2 自动安装

38.DevOps之基于Jenkins实现的CI与CD_第172张图片

5.4.6 配置扫描

选择自己的项目( linuxNN-job1-develop) -构建-execute sonarqube scanner,将配置文件的
内容修改成如下格式填写完成后点保存

sonar.projectKey=qinghe-web1-key
sonar.projectName=qinghe-web1-name
sonar.projectVersion=0.1
sonar.sources=src
sonar.language=py
sonar.sourceEncoding=UTF-8

5.4.7 配置项目进行扫描

38.DevOps之基于Jenkins实现的CI与CD_第173张图片

5.4.8 构建项目并测试 sonar-scanner 是否生效

点击项目的立即构建,下图是执行成功的信息 
Started by user jenkinsadmin
Building on master in workspace /var/lib/jenkins/workspace/linux36-job1-develop
[WS-CLEANUP] Deleting project workspace...
[WS-CLEANUP] Deferred wipeout is used...
[WS-CLEANUP] Done
using credential 0e23c215-2853-4bdf-9198-481f28ac0e1b
Cloning the remote Git repository
Cloning repository [email protected]:linux36/web1.git
\> git init /var/lib/jenkins/workspace/linux36-job1-develop # timeout=10
Fetching upstream changes from [email protected]:linux36/web1.git
\> git --version # timeout=10
using GIT_SSH to set credentials
\> git fetch --tags --progress [email protected]:linux36/web1.git +refs/heads/*:refs/remotes/origin/*
\> git config remote.origin.url [email protected]:linux36/web1.git # timeout=10
\> git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
\> git config remote.origin.url [email protected]:linux36/web1.git # timeout=10
Fetching upstream changes from [email protected]:linux36/web1.git
using GIT_SSH to set credentials
\> git fetch --tags --progress [email protected]:linux36/web1.git +refs/heads/*:refs/remotes/origin/*
\> git rev-parse refs/remotes/origin/develop^{commit} # timeout=10
\> git rev-parse refs/remotes/origin/origin/develop^{commit} # timeout=10
Checking out Revision 5110a701d0490d6aa2232ad40f8a245b23c52b5f (refs/remotes/origin/develop)
\> git config core.sparsecheckout # timeout=10
\> git checkout -f 5110a701d0490d6aa2232ad40f8a245b23c52b5f
Commit message: "v7"
\> git rev-list --no-walk 5110a701d0490d6aa2232ad40f8a245b23c52b5f # timeout=10
[linux36-job1-develop] $ /usr/local/src/sonar-scanner-4.0.0.1744-linux/bin/sonar-scanner -
Dsonar.host.url=http://192.168.7.104:9000 -Dsonar.language=php -Dsonar.projectName=job1-
develop -Dsonar.projectVersion=1.0 -Dsonar.sourceEncoding=UTF-8 -Dsonar.projectKey=job1-develop -
Dsonar.sources=./ -Dsonar.projectBaseDir=/var/lib/jenkins/workspace/linux36-job1-develop
INFO: Scanner configuration file: /usr/local/src/sonar-scanner-4.0.0.1744-linux/conf/sonarscanner.properties
INFO: Project root configuration file: NONE
INFO: SonarQube Scanner 4.0.0.1744
INFO: Java 11.0.3 AdoptOpenJDK (64-bit)
INFO: Linux 4.15.0-20-generic amd64
INFO: User cache: /root/.sonar/cache
INFO: SonarQube server 6.7.7
INFO: Default locale: "en_US", source code encoding: "UTF-8"
INFO: Publish mode
INFO: Load global settings
INFO: Load global settings (done) | time=69ms
INFO: Server id: 577C9AC7-AWwZJiIb-_VXsQd7E0lh
INFO: User cache: /root/.sonar/cache
INFO: Load plugins index
INFO: Load plugins index (done) | time=57ms
INFO: Plugin [l10nzh] defines 'l10nen' as base plugin. This metadata can be removed from manifest of
l10n plugins since version 5.2.
INFO: Process project properties
INFO: Load project repositories
INFO: Load project repositories (done) | time=92ms
INFO: Load quality profiles
INFO: Load quality profiles (done) | time=39ms
INFO: Load active rules
INFO: Load active rules (done) | time=913ms
INFO: Load metrics repository
INFO: Load metrics repository (done) | time=36ms
INFO: Project key: job1-develop
INFO: ------------- Scan job1-develop
INFO: Load server rules
INFO: Load server rules (done) | time=83ms
INFO: Base dir: /var/lib/jenkins/workspace/linux36-job1-develop
INFO: Working dir: /var/lib/jenkins/workspace/linux36-job1-develop/.scannerwork
INFO: Source paths: .
INFO: Source encoding: UTF-8, default locale: en_US
INFO: Language is forced to php
INFO: Index files
WARN: File '/var/lib/jenkins/workspace/linux36-job1-develop/index.html' is ignored because it doesn't
belong to the forced language 'php'
INFO: 0 files indexed
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by net.sf.cglib.core.ReflectUtils$1
(file:/root/.sonar/cache/3c43ca34b48e025530485308ddac54a2/sonar-javascript-plugin-
3.2.0.5506.jar) to method
java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of net.sf.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
INFO: Sensor SonarJavaXmlFileSensor [java]
INFO: Sensor SonarJavaXmlFileSensor [java] (done) | time=0ms
INFO: Sensor Analyzer for "php.ini" files [php]
INFO: Sensor Analyzer for "php.ini" files [php] (done) | time=16ms
INFO: Sensor Zero Coverage Sensor
INFO: Sensor Zero Coverage Sensor (done) | time=0ms
INFO: Sensor CPD Block Indexer
INFO: Sensor CPD Block Indexer (done) | time=0ms
INFO: Calculating CPD for 0 files
INFO: CPD calculation finished
INFO: Analysis report generated in 186ms, dir size=22 KB
INFO: Analysis reports compressed in 19ms, zip size=5 KB
INFO: Analysis report uploaded in 42ms
INFO: ANALYSIS SUCCESSFUL, you can browse http://192.168.7.104:9000/dashboard/index/job1-
develop
INFO: Note that you will be able to access the updated dashboard once the server has processed the
submitted analysis report
INFO: More about the report processing at
http://192.168.7.104:9000/api/ce/task?id=AWwZi39XBenn7N3kRArM
INFO: Task total time: 4.319 s
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 6.714s
INFO: Final Memory: 7M/24M
INFO: ------------------------------------------------------------------------
[linux36-job1-develop] $ /bin/sh -xe /tmp/jenkins5134965889873889449.sh
\+ cd /var/lib/jenkins/workspace/linux36-job1-develop
\+ tar czvf code.tar.gz index.html
index.html
\+ scp code.tar.gz [email protected]:/data/tomcat/tomcat_appdir/
\+ scp code.tar.gz [email protected]:/data/tomcat/tomcat_appdir/
\+ ssh [email protected] /etc/init.d/tomcat stop && rm -rf /data/tomcat/tomcat_webdir/myapp/*
&& cd /data/tomcat/tomcat_appdir && tar xvf code.tar.gz -C /data/tomcat/tomcat_webdir/myapp/
正在判断服务状态,请稍等 3 秒钟!
3

5.4.9 查看项目的构建历史

38.DevOps之基于Jenkins实现的CI与CD_第174张图片

六 实战案例

将代码部署到 web 服务器

6.1 创建项目

新建一个项目叫 test-deploy 用于代码发布,上一个项目 testdemo 可用于代码 测试,当测试阶段出现问题的时候也不会立即进行发布,只有当测试通过之后才执行发布的项目
即可

如何将代码发布到 web 服务器?
可以通过执行命令或脚本的方式进行代码发布,在各 web 服务器包括Jenkins 服务器创建一个 www 用户,保持 id 一致,用于启动 web 服务并进行代码发布
# useradd www
# echo “123456” | passwd --stdin www
# su -www
$ ssh-keygen

6.2 添加部署 key

添加 Jenkins 服务器 www 用户的公钥到 git 服务器项目当中

image-20210717112100645

6.3 确认 key

确认 www 用户的 key 可以拉取代码

38.DevOps之基于Jenkins实现的CI与CD_第175张图片

6.4 Shell 脚本

关于权限
一般使用非 root 用户启动 web 服务及完成代码发布,默认 Jenkins 运行使用的是 Jenkins 用户,因此需要赋予 Jenkins 用户一定的权限,另外发布的脚本可以在本机也可以不在 本机,需要使用 Jenkins 用户 ssh到发布服务器执行 shell 脚本。

将脚本放在/home/www 用户家目录, git 代码也放在家目录,因此需要jenkins 服务器 远程到代码发布服务器执行远程命令,需要做免登陆认证,将 jenkins 服务器 root 和

www 用 户 的 公 钥 放 在 代 码 部 署 服 务 器 的 www 用 户 家 目录.ss/authorized_keys 文件中
# su -www

$ vim/home/www/.ssh/authorized_keys

• $ chmod 600 authorized_keys

image-20210717112205215

6.5 验证 ssh

在 root 用户和 www 用户下 ssh 到本机的 www 用户,确认可以免密码登录,以 便让部署服务器将用户的 key 添加到 know_keys,否则报错 Hostkey verification failed

38.DevOps之基于Jenkins实现的CI与CD_第176张图片

6.6 配置 jenkins 用户 sudu 权限

假如 jenkins 使用普通用户 jenkins 或其他普通用户启动,则要授予 sudo 权限, root 不
需要设置。

# vim/etc/sudoers
56 #Defaults requiretty #不需要 tty
99jenkinsALL=(ALL) NOPASSWD: /usr/bin/ssh #不需要使用密码即可执行 ssh

脚本内容:

$ cd /home/www/
$ vim deploy.sh
\#!/bin/bash
echo $USER
cd /home/www/myweb1
git pull
scp -r ./* [email protected]:/apps/tomcat/webapps/myapp
scp -r ./* [email protected]:/apps/tomcat/webapps/myapp

6.7 测试执行命令

#在 test-deploy 项目的构建步骤调用,项目-配置-构建 

38.DevOps之基于Jenkins实现的CI与CD_第177张图片

执行结果

38.DevOps之基于Jenkins实现的CI与CD_第178张图片

6.8 web 服务器免密码登录

复制 www 用户公钥到各 web 服务器的 www 用户
$ssh-copy-id [email protected]
$ssh-copy-id [email protected]

38.DevOps之基于Jenkins实现的CI与CD_第179张图片

6.9 gitlab 提交代码

在另外一台服务器编辑代码后重新提交
# git clone http://192.168.10.130/web/myweb1.git
# echo “xxx” >> index.html
# git addindex.html
# git commitindex.html
# gitpush
在 jenkins 执行项目构建
构建项目之前要在 www 用下的 xxx 项目里面进行 git pull 命令。否则第一次更新提示输入yes 会导致部署失败
再次提交代码
构建结果

38.DevOps之基于Jenkins实现的CI与CD_第180张图片

访问负载测试

38.DevOps之基于Jenkins实现的CI与CD_第181张图片

6.10 项目关联

代码测试的项目执行成功之后自动调用代码发布的项目完成代码部署安装 Parameterized 插件, 系统管理-管理插件-可选插件,搜索Parameterized, 如果插件在线安装不成功可以下载插件到此目录,然后把属主属组改成Jenkins在重启Jenkins服务即可完成安装

image-20210717112454042

配置项目 test-demo 的构建后操作, demo 构建完成后自动构建

38.DevOps之基于Jenkins实现的CI与CD_第182张图片

demp-deploy 项目

38.DevOps之基于Jenkins实现的CI与CD_第183张图片

38.DevOps之基于Jenkins实现的CI与CD_第184张图片

添加构建后操作

6.11 定义视图

安装 pipeline 插

image-20210717112615427

添加视图

image-20210717112634024

38.DevOps之基于Jenkins实现的CI与CD_第185张图片

配置视图

38.DevOps之基于Jenkins实现的CI与CD_第186张图片

6.12 执行构建

38.DevOps之基于Jenkins实现的CI与CD_第187张图片

6.13 代码自动构建

GitLab 触发 jenkins 构建项目

目的为在公司的测试环境当中一旦开发向 gitlab 仓库提交成功代码, gitlab 通知jenkins 进行构建项目、代码质量测试然后部署至测试环境,注意这只是测试环境,而生产环境依然需要手动部署代码

6.14 自动构建插件

安装 Gitlab Hook Plugin 插件
# 系 统 管 理 - 管 理 插 件 - 可 选 插 件 -Gitlab Hook Plugin 和 Build
AuthorizationTokenRoot
Plugin

image-20210717112817449

6.15 Token

# openssl rand -hex 12
 f7d0ead5398bd808ee139067

6.16 触发器

测试成功

38.DevOps之基于Jenkins实现的CI与CD_第188张图片

6.17 gitlab 触发

# 插 件 使 用 介 绍 , https://wiki.jenkinsci.org/display/JENKINS/Build+Token+Root+Plugin
\

#选择项目-设置-webhooks
http://192.168.10.131:8080/buildByToken/build?job=testdemo&token=f7d0ead5398bd808ee139067

格式如下
http://X.X.X.X:8080/buildByToken/build?job=项目名&token=随机数
保存后进行测试

38.DevOps之基于Jenkins实现的CI与CD_第189张图片

6.18 测试 gitlab 触发

在另一台向 git 服务器提交代码,验证是否可以自动部署
# echo “ccc” >>index.html
# git addindex.html
# git commit -m"ccc“
# git push
验证是否自动构建

38.DevOps之基于Jenkins实现的CI与CD_第190张图片

6.2 HAProxy

实现在 haproxy 动态增减服务器

6.21 haproxy 动态增减服务器

在 Jenkins 服务器复制 www 用户的公钥到 haproxy 服务器

$ ssh-copy-id [email protected]
# ssh-copy-id [email protected]
Haproxy 服务器编辑# vim /etc/sudoers 必须要 tty
# vim/etc/sudoers
root ALL=(ALL) ALL
jenkinsALL=(ALL) NOPASSWD: /usr/bin/ssh
www ALL=(ALL) ALL
测试 www 和 root 用户的 ssh 功能

验证:

38.DevOps之基于Jenkins实现的CI与CD_第191张图片

开启功能

# vim/etc/haproxy/haproxy.cfg
stats socket /usr/local/haproxy/stats mode 600 level admin
安装命令并测试
yum install socat
#echo "help"| socat stdio /usr/local/haproxy/stats
# echo "show info"| socat stdio /usr/local/haproxy/stats
#echo "show stat"| socat stdio /usr/local/haproxy/stats
# echo "disable server myapp_host/web2"|socat stdio /usr/local/haproxy/stats

38.DevOps之基于Jenkins实现的CI与CD_第192张图片

分组是为了在代码分批次上线的时候对后端服务器的一种筛选方法:

38.DevOps之基于Jenkins实现的CI与CD_第193张图片

编写 shell 脚本实现自动化部署与回 滚

你可能感兴趣的:(jenkins,ci/cd)