毕业设计:基于Jenkins与Docker容器化技术的全栈自动化CI/CD平台设计与实现
摘要
随着软件开发的复杂性和迭代速度不断提升,持续集成和持续部署(CI/CD)已成为现代软件开发不可或缺的一部分。本文设计并实现了一个基于Jenkins与Docker容器化技术的全栈自动化CI/CD平台。该平台利用Jenkins的强大任务调度和自动化构建能力,结合Docker的容器化技术,实现了代码的自动化构建、测试、部署和监控。通过实际项目应用验证,该平台能够显著提高软件开发的效率和质量,缩短交付周期,降低运维成本。本文详细阐述了平台的设计思路、关键技术实现及实际应用效果,为相关领域的实践提供了参考。
关键词: Jenkins, Docker, CI/CD, 容器化, 自动化部署
Abstract
As the complexity and iteration speed of software development continue to increase, Continuous Integration and Continuous Deployment (CI/CD) have become indispensable components of modern software development. This paper designs and implements a full-stack automated CI/CD platform based on Jenkins and Docker containerization technology. The platform leverages Jenkins’ powerful task scheduling and automated build capabilities, combined with Docker’s containerization technology, to achieve automated building, testing, deployment, and monitoring of code. Through practical project application validation, the platform can significantly improve the efficiency and quality of software development, shorten the delivery cycle, and reduce operational costs. This paper elaborates on the design思路, key technology implementation, and practical application effects of the platform, providing a reference for practices in related fields.
Keywords: Jenkins, Docker, CI/CD, Containerization, Automated Deployment
第一章 绪论
1.1 选题背景及意义
随着软件开发复杂性的不断攀升,持续集成(CI)和持续交付/部署(CD)已然成为提升开发效率与软件质量的关键手段。Jenkins作为一款广受欢迎的开源自动化服务器,具备强大的CI/CD流程支持能力。与此同时,Docker容器化技术的兴起,为应用部署带来了轻量级且高度灵活的虚拟化解决方案,极大地提升了部署效率。
在此背景下,引入Kubernetes(k8s)这一先进的容器编排平台,将进一步优化CI/CD流程。Kubernetes不仅能够高效管理Docker容器,还提供了强大的集群管理、服务发现、负载均衡等功能,确保应用在复杂环境中的稳定运行。
结合Jenkins、Docker与Kubernetes,构建一个高效的全栈自动化CI/CD平台,不仅能够实现代码的快速迭代与高质量交付,还能有效应对大规模、高复杂度的应用部署需求。这一平台的搭建,对于提升软件开发流程的自动化水平、缩短产品上市时间、增强系统稳定性和可扩展性具有重要意义,是现代软件开发不可或缺的一环。
1.2 国内外现状
目前国内众多企业和研究机构已广泛采用CI/CD技术来提升软件开发效率。例如,阿里巴巴、腾讯等大型互联网公司在其内部开发流程中大量使用Jenkins进行自动化构建和测试。中小企业也开始引入CI/CD流程,但应用深度和广度仍有待提升,部分企业仍停留在基础的自动化构建阶段,缺乏系统化的测试策略、持续部署的实践以及全面的监控和反馈机制。
Docker作为确保环境一致性的强力工具在国内的开发者社区中得到了广泛应用,极大地减少了“在我机器上能跑”的问题。一些初创公司和技术团队也在积极探索Docker在微服务架构中的应用。
随着容器化技术的广泛应用,容器数量的激增使得管理问题日益凸显。传统的容器编排工具如Docker Compose,在应对弹性扩容、负载均衡等方面显得力不从心。在此背景下,Kubernetes作为先进的容器编排平台,在国内逐渐受到广泛关注和重视。华为、百度等头部企业已在其云服务平台中集成Kubernetes,提供高效、智能的容器管理服务。与此同时,一些国内企业也开始积极探索将Jenkins、Docker与Kubernetes相结合,构建全栈自动化CI/CD平台,尽管目前应用案例相对较少,但已展现出显著的潜力和价值。
国外在CI/CD领域的研究和应用起步较早,已形成较为成熟的技术体系和实践标准。GitHub、GitLab等平台提供了集成的CI/CD功能,广泛应用于开源项目和企业开发中。大型企业如Google、Facebook等,早已将CI/CD纳入其标准开发流程,积累了丰富的实践经验。许多国外企业,如Netflix、Spotify等,通过Docker和Kubernetes实现了高度自动化的应用部署和管理。
1.3 主要研究内容
本文在深入研究了传统的CI/CD原理后,设计并实现了一套基于Jenkins与Docker容器化技术的全栈CI/CD解决方案,使用Jenkins作为集成服务器,全自动的完成从开发到落地部署到Kubernetes集群中,确保生产环境中业务的稳定运行。本系统将CI/CD拆分为了四层,分别是:
(1)源码管理层:使用Git作为版本控制系统,管理项目的源代码。负责代码的版本控制、分支管理和代码审查,确保代码的版本一致性和可追溯性。
(2)构建测试层:利用Jenkins的构建任务和多种测试框架(如JUnit、Selenium等),负责代码的自动化构建和测试。包括代码编译、单元测试、集成测试等,确保代码质量符合预期。
(3)镜像管理层:使用Docker进行容器镜像的构建和管理,将构建好的应用打包成Docker镜像,并存储到Harbor私有镜像仓库。确保镜像的安全性和可复用性。
(4)部署编排层:通过单机部署或采用Kubernetes进行容器的部署和编排,负责将Docker镜像部署到Kubernetes集群中,进行服务的编排、负载均衡和弹性伸缩,确保应用在生产环境中的高可用性和稳定性。
1.4 系统创新点
高效自动化:通过分层设计和工具集成,实现了从代码提交到生产部署的全流程自动化,显著提升了开发效率。
环境一致性:利用Docker和Kubernetes,确保了开发、测试和生产环境的一致性,减少了环境差异导致的隐患。
高可用性:通过Kubernetes的负载均衡和弹性伸缩功能,相比传统的单机部署确保了应用的高可用性和稳定性。
滚动迭代:通过Kubernetes的Deployment组件可以实现用户无感知的滚动更新,并且支持回滚,提升用户体验。
1.5 论文主要结构
本文主要工作如下:
第一章序列:介绍选题背景及意义、国内外现状分析、系统创新点以及论文主要结构。
第二章 相关理论及技术选型
2.1 持续集成与持续部署
CI/CD 作为 DevOps 和敏捷开发的关键技术,通过自动化流程和紧密协作,帮助企业实现快速、高效、高质量的软件开发和交付。
2.1.1 持续集成 (CI)
持续集成(CI)是软件开发过程中的一种实践,旨在通过自动且频繁地将代码更改集成到共享源代码存储库中,来提高代码质量和开发效率。其主要特点包括:
自动化构建和测试:每次代码提交都会触发自动化构建和测试流程,确保新代码与现有代码库的兼容性,并及早发现潜在问题。
频繁集成:开发人员将代码更改频繁地集成到主分支,通常每天多次,从而减少集成过程中的冲突和风险。
代码质量监控:通过代码静态分析、单元测试等手段,持续监控代码质量,并及时反馈给开发人员。
CI 的优势在于:
及早发现并修复错误:自动化测试可以快速发现代码中的问题,并及时修复,避免问题累积。
提高代码质量:频繁的集成和测试有助于提高代码的整体质量和稳定性。
加快开发速度:自动化流程减少了手动操作,提高了开发效率。
2.1.2 持续交付/部署 (CD)
持续交付/部署(CD)是 CI 的延伸,涵盖了代码更改的集成、测试、交付和部署等环节。它分为两个阶段:
持续交付(Continuous Delivery):将经过测试的代码更改自动部署到测试环境和/或预生产环境,但不会自动部署到生产环境。人工干预是必要的,以确保最终部署的稳定性和安全性。
持续部署(Continuous Deployment):在持续交付的基础上,进一步自动化部署流程,将经过测试的代码更改自动部署到生产环境,无需人工干预。
CD 的优势在于:
缩短发布周期:自动化部署流程加快了软件发布的速度,使新功能更快地交付给用户。
降低发布风险:频繁且小规模的发布降低了每次发布的风险,更容易定位和解决问题。
提高用户体验:快速迭代和持续反馈有助于及时响应用户需求,提升用户体验。
2.2 Jenkins
2.2.1 Jenkins简介
Jenkins 是一款广泛使用的开源自动化服务器,旨在帮助开发团队实现持续集成(CI)和持续交付/部署(CD)。它的核心功能是自动化构建、测试和部署流程。通过 Jenkins,开发团队可以快速发现代码中的问题,缩短开发周期,提升代码质量,减少人工干预。Jenkins 提供了丰富的插件系统,能够集成多种工具和技术栈,并支持不同的构建和部署环境,能够为开发团队提供灵活且可扩展的自动化解决方案。
2.2.2 Jenkins核心架构
Jenkins的架构采用了主从(Master-Slave)模式,这种分布式架构不仅提高了系统的可扩展性和灵活性,还确保了构建任务的高效执行。Jenkins的架构主要由以下几个核心组件组成:
(1)Master节点
Jenkins Master是Jenkins架构中的核心组件,负责协调和管理构建任务的执行。它接收用户的操作请求,如创建任务、触发构建等,并将这些请求分发到相应的Jenkins Slave上执行。同时,Jenkins Master还负责存储所有的配置信息和构建历史记录,供用户查询和分析。
- 任务管理:Jenkins Master负责管理和调度所有的构建任务。用户可以在Jenkins Master上创建和配置任务,指定构建脚本、构建参数和触发器等信息。
- 节点管理:Jenkins Master可以管理多个Jenkins Slave(或称节点),并将构建任务分配到不同的节点上执行。这种分布式构建模式可以有效利用计算资源,提高构建效率。
- 插件管理:Jenkins Master提供了丰富的插件支持,用户可以根据需要安装和配置各种插件,以扩展Jenkins的功能。这些插件涵盖了构建工具、测试框架、源代码管理工具等多个方面。
(2)Slave节点
Jenkins Slave是Jenkins架构中的工作节点,负责执行Jenkins Master分配的构建任务。每个Slave节点可以是一个独立的计算机、虚拟机或Docker容器,具体取决于团队的部署策略。Slave节点根据Master节点的指令执行构建脚本,完成代码的编译、测试和打包等任务。
- 构建执行:Slave节点接收来自Master节点的构建任务,并根据任务要求执行相应的构建脚本。在构建过程中,Slave节点会下载源代码、编译代码、运行测试等,最终生成可部署的软件包。
- 资源隔离:由于每个Slave节点可以独立运行在不同的操作系统和硬件环境中,因此可以实现构建资源的有效隔离。这有助于避免不同项目之间的资源冲突和相互干扰。
(3)Jenkins插件
Jenkins插件是扩展Jenkins功能的重要组件。这些插件提供了丰富的功能和集成支持,如版本控制系统集成、构建工具集成、测试框架集成等。用户可以根据项目的具体需求选择合适的插件进行安装和配置,以满足项目的持续集成和持续交付需求。
- 构建工具插件:如Maven插件、Gradle插件等,用于集成构建工具,实现自动化构建和依赖管理。
- 测试框架插件:如JUnit插件、TestNG插件等,用于集成测试框架,支持测试报告的生成和分析。
- 源代码管理插件:如Git插件、SVN插件等,用于集成版本控制系统,实现代码的自动拉取和更新。
2.3 Git源码管理
2.3.1 Git简介
Git是一种分布式版本控制系统,由Linux内核创始人Linus Torvalds于2005年开发。其诞生源于对当时版本控制系统的不满,特别是集中式版本控制系统(如CVS和SVN)在速度、安全性和灵活性方面的不足。Git的设计初衷是为了高效地管理Linux内核这样的大型项目,并支持全球范围内的协作开发。
2.3.2 Git的核心概念
Git将所管理的项目有三大分区,分别是工作区、暂存区、版本库。对应着三种状态:已修改(modified)、已提交(committed)和已暂存(staged)。工作区是开发者直接进行编辑的区域,即各种IDE开发软件对代码进行的操作,暂存区是开发者暂时提交的代码,版本库即本地代码库,由于Git分布式的特性,每个人都会在本地存储一份完整的代码库,尽管另一个丢失了数据,也很容易进行找回。另外为了方便开发者的提交,还引入了远程代码库,在本文中即Gitea服务器,用来托管团队成员项目的代码。
2.3.3 Gitea简介
Gitea 是一个开源的、基于Go语言编写的轻量级 Git 服务器,旨在为用户提供一个简洁、易用且高效的代码管理平台。它作为 GitHub 和 GitLab 的轻量级替代品,特别适合小型和中型团队进行代码托管和版本控制。Gitea 具有跨平台、易于安装和维护的特点,支持多种数据库后端,并提供丰富的功能,如代码仓库管理、问题跟踪、Wiki支持以及Pull Request等。本文将使用Gitea作为CI/CD中的源码管理层的主要工具进行测试。
2.4 Docker容器化技术
2.4.1 Docker简介
Docker 是一款开源的容器化平台,用于开发、运输和运行应用程序。它通过将应用及其所有依赖项打包成一个容器,保证应用在不同环境中具有一致的运效果。与传统的虚拟化技术不同,Docker 容器通过共享宿主操作系统的内核来减少资源开销,从而提供更高的效率和更快的启动时间。
2.4.2 传统虚拟机与Docker的对比
传统的虚拟机通过在物理硬件上模拟完整的操作系统环境,每个虚拟机都需要独立的操作系统和资源,导致资源占用高、启动时间长,且管理复杂。相比之下,Docker采用容器化技术,直接在宿主机操作系统上运行应用,共享宿主机的内核,从而大幅减少了资源消耗和启动时间。Docker容器轻量级且易于迁移,能够实现快速部署和弹性扩展,更适合微服务架构和持续集成/持续部署(CI/CD)流程。此外,Docker的标准化和自动化特性简化了应用管理和运维工作,提升了开发效率和系统稳定性,在资源效率和灵活性方面更具优势。
2.4.3 Docker主要组件
(1)镜像
docker镜像类似于虚拟机镜像,可以将其理解为一个只读模板。除了提供容器运行时所需的程序、库、资源、配置等文件外,docker镜像还包含了一些为运行时准备的一些配置参数。镜像是创建docker容器的基础,它可以通过版本管理和增量的文件系统,如Docker Hub。
(2)容器
容器是从镜像创建的应用运行实例,可以将其启动、开始、停止、删除,但是所有的容器是相互隔离的,互不可见的,这就提供了一个实体机可以安装多个容器,且很轻量级相对于虚拟机。镜像本身是只读的,容器从镜像启动的时候,docker会在镜像的最上层创建一个可写层,镜像本身保持不变。
(3)仓库
docker仓库(repository)类似于代码库,是docker集中存放镜像的场所。实际上,注册服务器是存放仓库的地方,其上往往存放着很多仓库。每个仓库集中存放某一类镜像,往往包括多个镜像文件,通过不同的标签(tag)来进行区分。
2.5 Harbor
2.5.1 Harbor简介
Harbor 是一个开源的企业级 Docker 镜像仓库,旨在为企业提供高效、安全的容器镜像管理。它是基于 CNCF 的核心项目之一,不仅支持 Docker 镜像存储,还具备镜像扫描、访问控制、权限管理等高级功能。Harbor 允许团队集中管理和存储镜像,同时支持镜像的版本控制与生命周期管理,从而帮助企业实现更好的 DevOps 流程和安全性控制。
2.5.2 Harbor核心组件
其中harbor-core 作为核心服务,负责用户认证、项目管理和 API 接口等核心逻辑;harbor-jobservice 处理异步任务如镜像复制和垃圾回收;proxy 充当反向代理,增强安全性和负载均衡;harbor-portal 提供 Web 界面,方便用户操作;registry 和 registryctl 负责镜像的存储与管理;trivy_adapter 集成 Trivy 进行镜像安全扫描;chartmuseum 支持 Helm Charts 的存储与管理。
2.6 Kubernetes
2.6.1 Kubernetes简介
Kubernetes(K8s)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用。它通过管理多个容器实例的生命周期,确保应用的高可用性和可靠性。Kubernetes 将容器组织为 Pod,通过 Deployment 管理应用的扩展和更新。它通过 Services 提供统一的访问接口,并且能够自动处理容器的故障恢复和资源分配。Kubernetes 使得分布式应用的部署变得更加简便,适用于大规模容器化应用的管理。
2.6.2 Kubernetes核心架构
2.7 其他相关技术
Maven:Maven是Java项目中广泛使用的构建工具,支持项目构建、依赖管理和项目信息管理。它提供标准化的构建生命周期,便于自动化集成和项目管理。Maven拥有丰富的插件生态系统,可以轻松集成各种构建和测试工具,从而提高开发效率和项目质量。
Spring Boot:Spring Boot是一个基于Spring框架的轻量级开发框架,旨在简化Spring应用的初始搭建和开发过程。它通过提供一系列默认配置和自动化功能,使开发者能够快速构建生产级别的Spring应用。Spring Boot支持嵌入式服务器,简化了部署流程,广泛应用于微服务架构和现代Java开发。
Vue:Vue.js是一个用于构建用户界面的渐进式JavaScript框架。它以简洁易用著称,支持双向数据绑定和组件化开发,能够高效地构建单页面应用(SPA)。Vue.js具有轻量级、灵活性和高性能的特点,广泛应用于前端开发,特别是在快速迭代和响应式设计的需求中。
第三章 需求分析
3.1 功能需求
持续集成与持续交付/部署(CI/CD):支持多种编程语言和构建工具(如 Maven、Gradle、NPM 等),实现从代码提交到应用部署的全自动化流程,快速、稳定地将功能推向生产环境,缩短开发周期。
自动化测试:集成单元测试、集成测试和功能测试,自动执行并生成详细的测试报告。支持测试结果的实时通知,帮助团队快速发现并修复问题,确保代码质量。
容器化部署:自动构建 Docker 镜像,确保开发、测试、生产环境的一致性。支持使用容器编排工具(如 Kubernetes)进行自动化部署与管理,简化多环境部署流程。
弹性伸缩:平台应具备自动弹性伸缩能力,根据负载情况动态调整资源(如计算、存储等),以保证系统性能和资源的高效利用。能够应对不同工作负载的变化,确保在高峰时段和压力情况下的稳定运行。
监控与通知:实时监控构建、测试和部署状态,自动识别异常并通知相关人员。确保团队能快速响应并处理问题,保证流程高效运转。
3.2 非功能需求
可扩展性:平台应具备良好的扩展性,能够适应不同规模的项目和团队需求。支持插件机制,方便集成新的工具、服务和功能,以应对未来业务的发展和变化。
安全性:确保代码、敏感信息和数据的安全存储与传输。提供完善的权限管理和访问控制机制,保障不同用户的操作权限,防止未经授权的访问和操作。
稳定性与可靠性:平台需具备高可用性,确保在高负载和故障情况下的持续运行。自动化流程应具备稳定性和容错能力,最大限度减少人工干预,保证流程的高效执行。
易用性:提供直观、友好的用户界面和操作体验,简化平台的使用。通过清晰的功能布局和易懂的操作流程,确保用户能够快速上手和高效完成任务。
第四章 系统设计
4.1 总体架构设计
本文介绍的平台是基于B/S架构设计,并且使用Jenkins作为CI/CD的核心调度工具,业务每个组件都是基于Docker容器以确保良好的可移植性。源代码作为CI/CD的起点,使用Git进行代码版本控制。在收到开发人员的提交代码请求后,Git仓库会向Jenkins发送一个webhook请求,然后通过构建服务器进行编译容器,将编译好的容器上传至Harbor私有镜像仓库,可以选择自动部署至开发、测试、预生产环境,或者手动发布至生产环境,例如单机部署或使用Kubernetes进行容器编排和部署。
4.2 分层架构设计
本文介绍的平台将CI/CD流程拆分为四个层级:源码管理层、构建测试层、镜像管理层和部署编排层。源码管理层负责代码的版本控制、存储和管理,确保代码的完整性和可追溯性。构建测试层自动化构建和测试代码,确保代码质量和功能的正确性。镜像管理层管理和存储构建生成的镜像,确保镜像的安全性和可复用性。部署编排层自动化部署和编排应用,确保应用的稳定运行和高可用性。下面将依次介绍这四个层次,以及技术选型的原因。
4.2.1 源码管理层
源码管理层作为CI/CD流程的起点,主要负责代码的版本控制、存储和管理,确保代码的完整性和可追溯性。该层支持Git、SVN等版本控制系统,记录每次代码提交的详细信息,包括提交者、时间和变更内容。分支管理功能支持创建、合并和删除分支,并提供分支对比和冲突解决工具。代码审查集成同行评审工具,支持自动化代码风格检查和静态分析。权限与访问控制基于角色的访问控制,支持细粒度的权限设置。备份与恢复机制定期自动备份代码仓库,提供灾难恢复功能。
技术选型上,采用Git作为版本控制系统,开源项目Gitea作为代码托管平台。Gitea类似于 GitHub、Bitbucket 和 GitLab,是一种轻量级、自托管、一体化的软件开发服务。包括 Git 托管、代码审查、团队协作、包注册和 CI/CD。它提供了一个Web界面,后端处理请求并提供API接口,存储使用文件系统或对象存储服务,数据库支持SQLite3 、MySQL、PostgreSQL等,具有良好的兼容性。
4.3.2 构建测试层
构建测试层负责自动化构建和测试代码,确保代码质量和功能的正确性。该层通过Jenkins调度构建服务器,将代码构建成容器镜像,并进行一系列的测试验证。Jenkins作为核心的CI工具,配置了自动化构建流程,触发构建任务后将代码打包成Docker镜像。构建服务器上安装有Docker等容器化工具,能够高效地完成镜像构建任务。构建完成后,容器镜像会被推送到临时的测试环境中进行单元测试和集成测试。单元测试使用JUnit、pytest等测试框架,确保代码模块的功能正确性。集成测试则通过Selenium、Cypress等工具,验证各个模块之间的协同工作情况。测试过程中生成的报告会自动汇总,提供详细的测试结果和分析,帮助开发团队快速定位问题。技术选型上,采用Jenkins作为CI工具,Docker进行容器化构建,JUnit/pytest进行单元测试,Selenium/Cypress进行集成测试。架构设计上,包括Jenkins服务器、构建服务器、测试环境和报告生成服务,确保构建和测试流程的自动化和高效性。通过这种方式,构建测试层不仅提升了代码的质量,还为后续的镜像管理和部署编排奠定了坚实的基础。
4.3.3 镜像管理层
镜像管理层负责管理和存储构建生成的镜像,确保镜像的安全性和可复用性。该层使用Docker技术自动构建应用镜像,并将这些镜像存储在Harbor镜像仓库中。Harbor提供了丰富的镜像管理功能,包括镜像的版本控制、访问权限设置和镜像标签管理。镜像安全扫描集成Clair或Trivy等工具,能够检测镜像中的安全漏洞,确保镜像的安全性。版本管理功能允许管理和查询镜像的不同版本,支持回滚到历史版本。镜像分发机制确保镜像能够高效地分发到不同的部署环境。技术选型上,采用Docker进行镜像构建,Harbor作为镜像仓库,Clair/Trivy进行安全扫描。架构设计上,包括镜像构建服务、Harbor镜像仓库和镜像分发服务,确保镜像的存储、管理和分发流程高效、安全且可靠。通过这些功能和设计,镜像管理层为后续的部署编排层提供了稳定的基础,保障了应用部署的一致性和安全性。
4.3.4 部署编排层
部署编排层负责自动化部署和编排应用,确保应用的稳定运行和高可用性。该层支持将应用部署到开发环境、测试环境和生产环境,既可以基于Docker进行单机部署,也可以使用Kubernetes进行集群部署。对于单机部署,通过Docker Compose或直接使用Docker命令,将构建好的容器镜像部署到指定的服务器上,适用于小型项目或开发测试阶段。对于生产环境或需要高可用性的场景,则采用Kubernetes进行部署,利用其强大的编排能力,实现应用的自动扩展、负载均衡和故障恢复。
部署服务通过Jenkins或其他CI/CD工具触发,自动拉取最新的容器镜像,并根据配置文件进行部署。环境管理功能确保不同环境之间的配置隔离和一致性,避免环境差异导致的问题。编排管理通过Kubernetes的YAML文件定义应用部署的详细配置,包括服务、副本集、持久化存储等。监控与告警系统实时监控应用和基础设施的状态,一旦发现异常情况,立即发送告警通知,确保问题能够及时处理。日志管理则通过ELK Stack等工具,集中收集、存储和分析应用日志,提供全面的日志查询和审计功能。
技术选型上,使用Docker进行单机部署,Kubernetes进行集群部署,Jenkins触发自动化部署流程,Prometheus和Grafana进行监控,ELK Stack进行日志管理。架构设计上,包括部署服务、Kubernetes集群、监控服务和日志服务,确保部署和编排流程的自动化、高效性和可靠性。通过灵活的部署策略和强大的编排能力,部署编排层为应用的持续交付和稳定运行提供了坚实的保障。
第五章 系统实现
在这一章中,我们将介绍平台在实际系统中的安装和部署过程。本文的系统使用个人免费版的VMware Workstation Pro 17.5.2来创建虚拟机环境,为各个模块的实现提供基础设施支持。
5.1 CI/CD调度器Jenkins
5.1.1 Jenkins的安装部署
Jenkins的安装直接在虚拟机本机进行,配置好Java环境后从阿里云镜像下载jenkins的rpm包进行安装:
1
dnf install https://mirrors.aliyun.com/jenkins/redhat-stable/jenkins-2.479.1-1.1.noarch.rpm -y
在部署成功后我们访问http://10.1.1.202进入系统查看:
Jenkins拥有非常丰富的插件生态,需要先为Jenkins集成必备的插件如Git、SSH Build Agents、Outbound WebHook for build events等。
5.1.2 Jenkins的配置
在传统开发到生产部署流程中,开发人员首先提交代码,并在本地进行编译和初步测试。测试通过后,应用被传递给测试团队进行测试。一旦测试团队确认无误,应用即进入预生产或直接生产环境,从而完成一次版本迭代。
为了自动化上述流程,本系统在Jenkins中设计了以下任务:
(1)构建开发镜像:从源代码构建开发镜像。
(2)部署至开发环境:为便于开发人员直接在构建服务器上进行初步测试。
(3)推送开发镜像到仓库:若开发人员初步测试通过,自动将镜像推送至镜像仓库。
(4)部署至测试环境:将开发人员初步测试通过的镜像部署测试环境,进而由测试人员进行测试。
(5)部署至生产环境:将测试团队测试通过的镜像部署至预生产或生产环境。
通过这一自动化流程,我们高效地完成了一次版本迭代。
5.2 各层实现
以下是各个层级的具体实现步骤。
5.2.1 源码管理层
在源码管理方面,我们选择了分布式版本控制系统Git。相比传统的集中式版本控制系统如SVN,Git支持分布式协作,每个开发者都拥有完整的代码仓库副本,即使离线或中央仓库损坏,也很方便进行修复,极大地提升了开发效率和灵活性。并且Git的分支管理功能非常强大,可以轻松创建、合并和删除分支,使得并行开发和多版本管理变得简单高效。Git还采用SHA-1算法进行数据校验,确保了代码的完整性和安全性。得益于Git广泛的社区支持和丰富的第三方工具集成,其能够更好地适应各种开发场景和需求。
本文采用开源项目Gitea作为代码仓库,安装Gitea的虚拟机配置如下:
名称 | 参数 |
---|---|
CPU | 2核 |
内存 | 2G |
操作系统 | RockyLinux9 X64 |
带宽 | 1Gbps |
IP地址 | 10.1.1.201 |
Gitea的安装部署采用官方操作手册中提供的docker安装方法,编写dokcer-compose文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
networks:
gitea:
external: false
services:
server:
image: docker.io/gitea/gitea:1.23.1
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__webhook__ALLOWED_HOST_LIST=10.1.1.0/24
- GITEA__webhook__SKIP_TLS_VERIFY=true
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "80:3000"
- "222:22"
在目录下使用docker-compose up -d命令即可启动服务,docker-compose文件中指定了Gitea版本为1.23.1,以及为容器映射了主机目录 ./gitea到容器中的 /data以实现数据的持久化。这里用作演示所以使用的是默认的sqlite,在生产环境中我们可以配置MySQL或PostgreSQL数据库,以获得更好的性能。
在部署成功后我们访问http://10.1.1.201进入系统查看:
源码管理层通过Webhook与集成服务器(如Jenkins)进行高效通信。在项目的设置选项卡中,选择“Web钩子”并添加一个新的Webhook。目标URL应填写为Jenkins服务器的地址,格式如下:http://10.1.1.201:80/jenkins/generic-webhook-trigger/invoke?token=back-end
。为确保自动化构建流程的顺畅,需在Jenkins中启用触发构建功能。安装Generic Webhook Trigger插件后,项目设置中将新增一个触发器选项。在此处填写特定的token,以便区分不同的项目。当开发团队完成代码提交后,Gitea服务器会自动向Jenkins发送HTTP请求,触发相应的构建任务,从而实现无缝的自动化构建流程。
5.2.2 构建测试层
构建测试层为多台不同操作系统例如Linux、Windows、MacOS的服务器,用于适应不同的编译环境, 本文所介绍的系统是基于Docker进行构建,得益于Docker强大的兼容性,所以采用资源占用较少的Linux操作系统。Linux虚拟机的配置如下:
名称 | 参数 |
---|---|
CPU | 2核 |
内存 | 2G |
操作系统 | RockyLinux9 X64 |
带宽 | 1Gbps |
IP地址 | 10.1.1.202 |
JDK版本 | 21.0.5 |
在构建测试层中,编译服务器作为Jenkins的slave节点,接受Jenkins的调度管理。通过SSH进行通讯,该服务器能够识别slave节点的特性,并根据这些特性智能分配调度任务。例如,对于需要较多内存的npm项目,系统会优先分配到内存资源充足的slave节点;而对于需要较高带宽的maven项目,则会选择带宽条件较好的节点进行任务执行。这种智能调度机制有效提升了构建效率和资源利用率。
在构建测试层中,采用Docker环境进行镜像构建具有显著优势。相比在服务器上逐一安装Maven、Node.js、Java等构建工具进行本地构建,使用Docker可以显著简化流程并提升效率。具体而言,每个服务都可以独立构建为Docker镜像,无需在物理机上安装任何额外的构建工具,仅需部署Docker环境即可。通过在Dockerfile中引用相应的基础镜像进行构建,并利用Docker的分阶段构建特性,应用程序在构建完成后可以运行于全新的基础镜像之上,从而大幅缩减容器镜像的体积,优化存储和部署效率。例如,在本示例项目的后端服务镜像构建中,使用了openjdk:8作为构建阶段的基础镜像。在安装完所需的Maven依赖后,编译生成的jar包会被传递到最终镜像中。随后,使用一个干净的openjdk:8作为运行时的基础镜像,从而大幅减少了镜像大小。
5.2.3 镜像管理层
本文所阐述的系统的核心优势在于采用容器镜像作为基础单元。相较于传统方法,不同平台和语言环境下的执行包往往存在差异,导致管理过程复杂繁琐。然而,通过将所有必需元素集成至容器镜像,我们能够实现高效便捷的管理。此外,Docker的分层(layer)机制有效减少了存储冗余,即便经历多次版本迭代,系统所占用的存储空间仍能保持精简。
在镜像管理层,我们采用了开源项目Harbor。通过使用官方提供的安装程序进行配置和安装,完成后会在目录下自动生成一个docker-compose.yml
文件。借助该文件,后续可通过docker-compose
命令对由Harbor编排的容器进行高效管理。以下是进入主页面后的界面展示:
在软件开发过程中,通常会经历四个主要阶段:开发阶段、测试阶段和生产阶段。与之相对应,容器镜像也分为四个版本:开发镜像、测试镜像和生产镜像。
开发镜像:主要用于开发团队内部自测,通常不存储在镜像仓库中,以保持开发环境的灵活性和便捷性。
测试镜像:当软件进入测试阶段后,相应的容器镜像会被存储在镜像仓库中,便于测试团队进行系统测试和验证。
生产镜像:若测试顺利通过,只需为测试镜像添加一个新的标签,即可指定版本并发布到生产环境,确保部署的稳定性和一致性。
这种分阶段的镜像管理策略,有助于提高软件开发的效率和安全性。
5.2.4 部署编排层
部署编排层负责将构建好的容器镜像部署到目标环境中,并进行相应的配置和管理。本系统采用Kubernetes作为容器编排平台,利用其强大的自动化部署、扩展和管理能力,实现高效、可靠的容器化应用部署。
Kubernetes集群由一个主节点(Master)和多个工作节点(Node)组成。主节点负责管理和控制整个集群,工作节点则负责运行容器应用。
主节点配置:
名称 | 参数 |
---|---|
CPU | 4核 |
内存 | 8G |
操作系统 | RockyLinux9 X64 |
带宽 | 1Gbps |
IP地址 | 10.1.1.203 |
Kubernetes | v1.28.0 |
工作节点配置:
名称 | 参数 |
---|---|
CPU | 2核 |
内存 | 4G |
操作系统 | RockyLinux9 X64 |
带宽 | 1Gbps |
IP地址 | 10.1.1.204/205 |
Kubernetes | v1.28.0 |
Master和Slave节点都需要做一些系统优化以确保集群的正常工作,如安装必要的工具包、永久关闭SELinux和Swap、开放防火墙端口、开启网络转发、安装CRI-O作为容器运行时,最后安装kubeadm、kubelet和kubectl等组件。
Master节点上还需要并进行初始化,初始化之后会生成一个token和加入集群的命令,后续Slave就可以使用这个命令加入集群。
第六章 系统测试
为了验证本文所设计的全栈自动化CI/CD平台的实际效果,我们选择了一个典型的前后端分离项目进行测试。该项目前端采用Vue.js框架,后端采用Spring Boot框架,数据存储使用Redis和MySQL。通过模拟实际开发流程,我们将测试平台的自动化构建、测试、部署和监控等功能,并评估其效率和稳定性。
6.1 测试环境搭建
测试环境包括以下组件:
- 代码仓库:使用Gitea搭建私有代码仓库,用于存储项目代码。
- CI/CD平台:使用Jenkins搭建CI/CD平台,负责自动化构建、测试和部署流程。
- 镜像仓库:使用Harbor搭建私有镜像仓库,用于存储Docker镜像。
- 容器编排平台:使用Kubernetes搭建容器编排平台,用于自动化部署和管理容器应用。
- 测试环境:使用虚拟机搭建测试环境,包括开发环境、测试环境和生产环境。
6.2 测试流程
测试流程如下:
- 代码提交:开发人员将代码提交到Gitea代码仓库。
- 触发构建:Gitea代码仓库通过Webhook通知Jenkins触发构建任务。
- 自动化构建:Jenkins拉取代码,并使用Docker进行自动化构建,生成Docker镜像。
- 自动化测试:Jenkins执行自动化测试,包括单元测试、集成测试和功能测试。
- 镜像推送:Jenkins将构建成功的Docker镜像推送到Harbor镜像仓库。
- 自动化部署:Jenkins使用Kubernetes进行自动化部署,将Docker镜像部署到测试环境。
- 测试验证:测试人员在测试环境中进行功能测试和性能测试。
- 发布上线:测试通过后,将Docker镜像部署到生产环境。
6.3 测试结果
通过测试,我们发现该平台能够有效地实现自动化构建、测试、部署和监控等功能,并取得了以下成果:
- 提高开发效率:自动化流程减少了人工操作,缩短了开发周期,提高了开发效率。
- 保证代码质量:自动化测试能够及时发现代码中的问题,保证了代码质量。
- 简化部署流程:自动化部署简化了部署流程,降低了部署风险。
- 提高系统稳定性:Kubernetes的容器编排功能保证了应用的高可用性和稳定性。
6.4 测试结论
测试结果表明,本文所设计的全栈自动化CI/CD平台能够有效地提高软件开发效率和质量,缩短交付周期,降低运维成本。该平台具有以下优势:
- 高效自动化:通过分层设计和工具集成,实现了从代码提交到生产部署的全流程自动化。
- 环境一致性:利用Docker和Kubernetes,确保了开发、测试和生产环境的一致性。
- 高可用性:通过Kubernetes的负载均衡和弹性伸缩功能,确保了应用的高可用性和稳定性。
- 滚动迭代:通过Kubernetes的Deployment组件可以实现用户无感知的滚动更新,并支持回滚,提升用户体验。
第七章 总结优化
7.1 总结
本文设计并实现了一个基于Jenkins与Docker容器化技术的全栈自动化CI/CD平台。该平台通过整合Git、Jenkins、Docker、Harbor和Kubernetes等工具,实现了代码的自动化构建、测试、部署和监控,有效提高了软件开发效率和质量,缩短了交付周期,降低了运维成本。
平台的核心优势在于:
- 高效自动化: 通过分层设计和工具集成,实现了从代码提交到生产部署的全流程自动化,显著提升了开发效率。
- 环境一致性: 利用Docker和Kubernetes,确保了开发、测试和生产环境的一致性,减少了环境差异导致的隐患。
- 高可用性: 通过Kubernetes的负载均衡和弹性伸缩功能,相比传统的单机部署确保了应用的高可用性和稳定性。
- 滚动迭代: 通过Kubernetes的Deployment组件可以实现用户无感知的滚动更新,并且支持回滚,提升用户体验。
7.2 优化方向
尽管该平台已经取得了显著的成果,但仍有一些方面可以进一步优化:
- 增强安全性: 可以引入更严格的安全机制,例如代码审计、镜像安全扫描和访问控制,以保护代码和镜像的安全。
- 提高可扩展性: 可以考虑使用更灵活的架构,例如微服务架构,以提高平台的可扩展性和可维护性。
- 优化资源利用率: 可以通过资源调度和监控,优化资源利用率,降低成本。
- 引入人工智能: 可以利用人工智能技术,例如机器学习,来预测和解决潜在的问题,进一步提高平台的智能化水平。
7.3 未来展望
随着云计算和人工智能技术的不断发展,CI/CD平台将会变得更加智能化和自动化。未来,CI/CD平台可能会具备以下功能:
- 智能代码审查: 利用人工智能技术,自动识别代码中的潜在问题,并提供修复建议。
- 自动化测试: 利用人工智能技术,自动生成测试用例,并执行测试。
- 智能部署: 利用人工智能技术,根据负载情况,自动调整资源,并进行智能部署。
- 预测性维护: 利用人工智能技术,预测系统故障,并进行预防性维护。
总之,CI/CD平台将会在软件开发中扮演越来越重要的角色,帮助开发团队更快、更好地交付高质量的软件产品。
第八章 致谢
第九章 附录
Kubernetes初始化脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#!/bin/bash
# 配置主机名和hosts
config_hostname() {
echo "正在配置主机名..."
read -p "请输入master节点IP (默认: 10.1.1.200): " MASTER_IP
MASTER_IP=${MASTER_IP:-10.1.1.200}
hostnamectl set-hostname master
cat >> /etc/hosts << EOF
$MASTER_IP master
10.1.1.201 node1
10.1.1.202 node2
10.1.1.203 node3
EOF
}
# 系统配置
system_config() {
echo "正在配置系统..."
# 关闭SELinux
sed -i 's/.*SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
setenforce 0
# 关闭swap
swapoff -a
sed -i 's/.*swap.*/#&/' /etc/fstab
# 配置防火墙
firewall-cmd --permanent --add-port=6443/tcp
firewall-cmd --permanent --add-port=2379-2380/tcp
firewall-cmd --permanent --add-port=10250/tcp
firewall-cmd --permanent --add-port=10251/tcp
firewall-cmd --permanent --add-port=10259/tcp
firewall-cmd --permanent --add-port=10257/tcp
firewall-cmd --reload
# 网络配置
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
modprobe br_netfilter
modprobe overlay
sysctl -p /etc/sysctl.d/k8s.conf
}
# 安装CRI-O
install_crio() {
echo "正在安装CRI-O..."
cat > /etc/yum.repos.d/cri-o.repo << EOF
[cri-o]
name=CRI-O
baseurl=https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/rpm/repodata/repomd.xml.key
EOF
dnf install cri-o -y
systemctl enable crio
systemctl start crio
}
# 安装Kubernetes
install_kubernetes() {
echo "正在安装Kubernetes组件..."
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/repodata/repomd.xml.key
EOF
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet
systemctl start kubelet
}
# 初始化集群
init_cluster() {
echo "正在初始化Kubernetes集群..."
# 初始化集群
kubeadm init --kubernetes-version=1.28.15 \
--apiserver-advertise-address=10.1.1.200 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--ignore-preflight-errors=Swap \
--cri-socket=unix:///var/run/crio/crio.sock | tee kubeadm-init.log
# 配置kubectl
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
# 安装Flannel网络插件
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
# 获取join命令并存储到变量中
export JOIN_CMD=$(kubeadm token create --print-join-command)
echo "集群初始化完成!"
echo "使用以下命令查看节点状态:"
echo "kubectl get nodes"
}
# 配置node节点
config_nodes() {
echo "正在配置node节点..."
read -p "请输入node节点数量(1-3): " NODE_COUNT
read -p "请输入node节点密码: " NODE_PASS
for i in $(seq 1 $NODE_COUNT)
do
NODE_IP="10.1.1.20$i"
echo "正在配置 node$i ($NODE_IP)..."
yum install -y sshpass
# 使用sshpass进行免密配置
sshpass -p "$NODE_PASS" ssh-copy-id -o StrictHostKeyChecking=no root@$NODE_IP
# 远程执行node节点配置
sshpass -p "$NODE_PASS" ssh -o StrictHostKeyChecking=no root@$NODE_IP "bash -s" << ENDSSH
# 设置主机名
hostnamectl set-hostname "node${i}"
# 配置hosts
cat >> /etc/hosts << EOF
10.1.1.200 master
10.1.1.201 node1
10.1.1.202 node2
10.1.1.203 node3
EOF
# 系统配置
sed -i 's/.*SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
setenforce 0
swapoff -a
sed -i 's/.*swap.*/#&/' /etc/fstab
# 配置防火墙
firewall-cmd --permanent --add-port=179/tcp
firewall-cmd --permanent --add-port=10250/tcp
firewall-cmd --permanent --add-port=30000-32767/tcp
firewall-cmd --permanent --add-port=4789/udp
firewall-cmd --reload
# 网络配置
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
modprobe br_netfilter
modprobe overlay
sysctl -p /etc/sysctl.d/k8s.conf
# 安装CRI-O
cat > /etc/yum.repos.d/cri-o.repo << EOF
[cri-o]
name=CRI-O
baseurl=https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/rpm/repodata/repomd.xml.key
EOF
dnf install cri-o -y
systemctl enable crio
systemctl start crio
# 安装Kubernetes
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/repodata/repomd.xml.key
EOF
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet
systemctl start kubelet
# 执行join命令
$JOIN_CMD
ENDSSH
done
}
# 重置集群
reset_cluster() {
echo "正在重置Kubernetes集群..."
# 重置所有节点
read -p "请输入node节点数量(1-3): " NODE_COUNT
read -p "请输入node节点密码: " NODE_PASS
# 首先重置worker节点
for i in $(seq 1 $NODE_COUNT)
do
NODE_IP="10.1.1.20$i"
echo "正在重置 node$i ($NODE_IP)..."
sshpass -p "$NODE_PASS" ssh -o StrictHostKeyChecking=no root@$NODE_IP "kubeadm reset -f"
sshpass -p "$NODE_PASS" ssh -o StrictHostKeyChecking=no root@$NODE_IP "rm -rf /etc/cni/net.d"
sshpass -p "$NODE_PASS" ssh -o StrictHostKeyChecking=no root@$NODE_IP "ipvsadm --clear"
done
# 重置master节点
kubeadm reset -f
rm -rf $HOME/.kube
rm -rf /etc/cni/net.d
ipvsadm --clear
echo "集群重置完成!"
}
# 修改show_menu函数
show_menu() {
echo "========== K8s Master节点配置脚本 =========="
echo "0. 执行所有配置"
echo "1. 配置主机名和hosts"
echo "2. 系统配置(SELinux/swap/防火墙)"
echo "3. 安装CRI-O环境"
echo "4. 安装Kubernetes组件"
echo "5. 初始化集群"
echo "6. 配置node节点"
echo "7. 重置集群"
echo "q. 退出"
echo "请输入选项 [0-7]: "
}
# 修改主程序的case语句
while true; do
show_menu
read choice
case $choice in
0)
config_hostname
system_config
install_crio
install_kubernetes
init_cluster
config_nodes
break
;;
1) config_hostname ;;
2) system_config ;;
3) install_crio ;;
4) install_kubernetes ;;
5) init_cluster ;;
6) config_nodes ;;
7) reset_cluster ;;
q|Q) exit 0 ;;
*) echo "无效选项,请重新选择" ;;
esac
done