微服务(Orchestration)架构 - 开发流水线与 DevOps 工具集
课程地址:18微服务orchestration架构—开发流水线与-devops-工具集
一、DevOps(开发与运维 – Development and Operations)
一个软件从零开始到最终交付,大概包括以下几个阶段:规划、编码、构建、测试、发布、部署和维护。一般由软件开发程序员、软件测试程序员,软件运维程序员这三种程序员来负责这个过程。
软件交付模型依次有瀑布模型、敏捷开发模型和DevOps模型。
瀑布模型
瀑布模型是最早期的软件交付模型,就是等一个阶段所有工作完成之后,再进入下一个阶段。软件开发流程如下:
- 软件开发工程师花费很长时间编写项目代码。
- QA(质量保障)团队对项目代码进行测试。
- 运维团队负责部署项目的最终发布版。
以上这三个阶段,即开发,测试,部署。
但是,项目不可能是单向运作的。客户也是有需求的。产品也是会有问题的,需要改进的。随着时间推移,用户对系统的需求不断增加,与此同时,给的时间周期却越来越少。在这个情况下,笨重迟缓的瀑布式开发已经不合时宜了。于是就发展出新的软件交付模型——“敏捷开发(Agile Development)”。
敏捷开发
敏捷开发能应对快速变化需求。每次开发一个部分就进行测试,然后再进行下一轮开发。通过重复交替进行开发和测试,可以帮助更快地发现问题,产品被更快地交付到用户手中,团队可以更快地得到用户的反馈,从而进行更快地响应。
而且,DevOps小步快跑的形式带来的版本变化是比较小的,风险会更小。即使出现问题,修复起来也会相对容易一些。
虽然敏捷开发大幅提升了软件开发的效率和版本更新的速度,但是它的效果仅限于开发环节。运维的部署部分还是没有参与其中。
DevOps
DevOps由Development和Operations组合而得,它强调了开发团队和运维团队的沟通合作,通过自动化流程来使得软件构建、测试、部署的整个过程更加快速、频繁和可靠。如下图所示,DevOps打破了开发团队与运维团队之间的高墙,使二者可以更高效地合作。
注意开发到运维中间其实还有测试环节,所以DevOps实际上包含了三个部分:开发、测试和运维。
快速的部署的好处是可以更快地发现软件的问题,更快地将产品交付到用户手中,更快地获得用户反馈,从而帮助团队进行更快地更新迭代。而且,DevOps小步快跑的形式使得每次版本改动较小,即使出现问题也比较容易解决。
在DevOps的流程下,运维人员会在项目开发期间就介入到开发过程中,了解开发人员使用的系统架构和技术路线,从而制定适当的运维方案。而开发人员也会在运维的初期参与到系统部署中,并提供系统部署的优化建议。
下图可见DevOps贯穿了软件全生命周期,而不仅限于开发阶段。
DevOps与虚拟化、容器、微服务
微服务就是将一个提供多种服务整体产品进行拆分,拆成各自提供不同服务的多个个体。微服务架构下,不同的工程师可以对各自负责的模块进行处理,例如开发、测试、部署、迭代。
虚拟化就是一种敏捷的云计算服务。它从硬件上,将一个系统“划分”为多个系统,系统之间相互隔离,为微服务提供便利。
容器不是划分为不同的操作系统,而是在操作系统上划分为不同的“运行环境”(Container),占用资源更少,部署速度更快。
虚拟化和容器,其实为DevOps提供了很好的前提条件。开发环境和部署环境都可以更好地隔离了,减小了相互之间的影响。
二、什么是 CI/CD 流水线?
有两个词经常会伴随着DevOps出现,那就是CI和CD。CI是Continuous Integration(持续集成),而CD对应Continuous Delivery(持续交付)或Continuous Deployment(持续部署)。三者关系如下图所示:
参考持续集成、持续交付、持续部署(CI/CD)简介 给产品经理讲讲,什么是持续交付和 DevOps 敏捷开发、持续集成/交付(CI/CD)、DevOps学习笔记
持续集成(CI – Continuous Integration)
在传统软件开发过程中,代码集成一般是在项目结束阶段一次性将所有开发人员的代码整合起来,这个整合过程花费大量时间和人力。而在持续集成(CI)方式下,代码集成每天都在发生,每次只需要花费几分钟的时间。
不同的开发人员各自编写自己负责部分的代码,然后上传到源代码库中合并, CI 服务器负责构建软件并测试是否能正常运行,将测试结果反馈给开发人员。
集成的代码即使通过了测试、能够成功的工作,也仍然不能直接投产,因为它还没有在类似生产环境中测试和验证以表明能够工作。
持续交付(CD – Continuous Delivery )
持续交付是在持续集成的基础上,将集成后的代码部署到更贴近真实运行的环境中去进行进一步的测试。具体来说,持续集成部分只完成了简单的单元测试,而持续交付部分可以把代码部署到与数据库相连的Staging环境中做进一步的测试。
我们可以从每个环境的测试中获得新的反馈,如果出现了错误,我们可以更容易的理解问题到底在哪里,并且及时进行修改。如果代码通过测试,则可以继续手动部署到真实的生产环境中。
持续交付中,不一定会把软件的改动都部署到产品环境中,它指的是任何的代码改动都可以在任何时候实施部署。这里强调的是:
- 手动部署。
- 有部署的能力,但不一定部署。
持续部署(CD – Continuous Deployment)
持续部署则是在持续交付的基础上,自动化把代码部署到生产环境的这个过程。
这里强调的是:
- 部署过程是自动的。
- 每个改动都会部署到生产环境中。
三、工具
代码管理(SCM):GitHub、GitLab、SubVersion
构建工具:Ant、Gradle、maven
持续集成(CI):Travis、Jenkins、Drone
容器:Docker、LXC、第三方厂商如AWS
编排:Core、Kubernetes、Apache Mesos
服务注册与发现:etcd、Zookeeper、
日志管理:ELK、Logentries
应用服务器:Tomcat、JBoss
Web服务器:Apache、Nginx、IIS
关系型数据库:Oracle、MySQL
NoSQL数据库:redis、mongoDB
工具、CI/CD、DevOps的关系:通过技术工具链完成持续集成CI、持续交付CD、用户反馈和代码更新迭代的整合,实现DevOps。
根据实际需要,选择合适的工具组合起来构建CI/CD流水线
- Docker + Gogs + Jenkins + MYSQL + Nginx
- Docker + GitLab + Drone + Nginx
- …
借这个机会,我查看了一些我比较感兴趣的工具的基础知识和原理,总结了一下3个比较热门的工具(Git、Docker、Kubernetes)的笔记:
1、Git、GitHub、GitLab
Git
Git 是一个版本控制系统。
在早期没有版本控制系统的时候,程序员一般在项目目录下这样命名项目:project_v1、project_v1.1、project_v2等,通过加后缀的方式记录项目的不同版本,一般还需要额外写一个说明文件,记录此版本项目新增、修改,删除等操作。(我的本科毕设版本控制就是这么做的,简直不堪回首)
而在有了版本控制系统Git之后,就不需要再手动保存历史版本以及写版本更迭说明文件了,只要把每次的改动都提交到Git上,我们就可以随时回溯到某个历史版本去。
早期的版本控制系统比如SVN是集中式的,由一个服务器集中管理和保存项目的所有版本文件,而协作开发的所有人都通过客户端连接到这台服务器,拉取最新的项目文件或者提交代码更新,原理如下图所示:
集中式版本控制系统的一个最大的缺点就是每个开发人员必须联网才能拉取或者提交代码,而如果使用分布式版本控制系统Git,则每次客户端从服务器爬取的不只是最新的代码文件,而是把整个代码仓库完整地拉取下来,相当于每个人的本地工作目录下都有一个完整的代码版本库,即便在网络环境比较差的情况下也不用担心,因为版本库就在本地,原理如下图所示:
GitHub vs GitLab
GitHub 和 GitLab 都是基于Git的版本控制系统
- GitHub是最火的开源项目托管平台,同时提供公共仓库和私有仓库,但私有仓库收费。
- GitLab在很大程度上GitLab是仿照GitHub来做的,但它的公共仓库和私有仓库都免费,且GitLab可以部署到自己的服务器上,数据库等一切信息都掌握在自己手上,适合团队内部协作开发,是企业端Git仓库的首选。
简单来说,GitHub的功能GitLab都有,而且GitLab私有仓库还免费,按道理来说应该是GitLab更优越的,但目前GitHub还是最火的开源项目托管平台,主要是GitHub先发优势,大多数开源项目都在GitHub上,大家习惯放到GitHub上,而且GitLab配置更复杂。所以总的来说,开源项目倾向于选择GitHub,企业项目倾向于选择GitLab。
2、Docker
Docker 是目前最流行的 Linux 容器方案。Docker 将应用程序本体以及该程序运行所需的依赖环境,打包在了一个镜像文件之中。只要运行这个镜像文件,就会生成一个虚拟容器,程序可以在这个虚拟容器里正常运行。
镜像(image)
镜像文件类似压缩包,它将一系列文件按照一定的格式制作成单一的文件,以方便用户上传、下载和使用,比如操作系统、游戏就经常用镜像的形式流通。在以前,一般会将系统制作成一个镜像,这样就可以把镜像拿到别的机器上运行、还原出一个一模一样的系统出来。
仓库(repository)
仓库是用户集中存放镜像文件的地方,仓库注册服务器(Registry)上存放着许多仓库,每个仓库中又存放着多个镜像,通过标签(tag)来区分不同的镜像。目前,最大的公开仓库是 Docker Hub,用户可以从Docker Hub上拉取镜像到本地使用。
容器( Container)
Docker 使用容器来运行应用。容器是镜像的运行实例。它可以被启动、开始、停止、删除。每个容器相互隔离的、互不干扰。可以使用docker ps 查看运行中的容器信息。
虚拟机(Virtual Machine)
容器直接在linux系统上运行,并与其他容器共享主机的内核,它作为一个独立的进程运行,占用很少的系统资源。
虚拟机以完整的操作系统的形式运行,通过虚拟机管理程序对主机资源进行访问,相比容器,虚拟机占用了更多的系统资源。
虚拟机和容器的架构图对比:
总结
理清楚上面几个概念的关系,就能理解容器是什么。
使用Docker的大致流程:从仓库(DockerHub)拉取(pull)一个镜像,执行Docker的run方法运行镜像,得到一个容器运行实例,用户在容器里执行各种操作。修改完毕后,用户可以使用Docker的commit方法或者编写Dockerfile文件,将这个容器打包成镜像。然后使用Docker的login、push等命令将这个镜像推送(push)到仓库上。其他用户就可以拉取该镜像去生成容器,进而运行其中的应用程序了。
更具体的笔记我总结在Docker基础知识和使用示例中。
3、Kubernetes
Kubernetes 用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Docker这个新兴的容器化技术当前已经被很多公司所采用,其从单机走向集群已成为必然,而云计算的蓬勃发展正在加速这一进程。Kubernetes作为当前唯一被业界广泛认可和看好的Docker分布式系统解决方案,地位越来越重要。
使用Kubernetes就是在全面拥抱微服务架构。微服务架构的核心是将一个巨大的单体应用分解为很多小的互相连接的微服务,一个微服务背后可能有多个实例副本在支撑,副本的数量可能会虽社系统的负荷变化而进行调整,内嵌的负载均衡器在这里发挥了重要作用。
微服务架构使得每个服务都可以由专门的开发团队开发,开发者可以自由选择开发技术,这对于大规模团队来说很有价值,另外每个微服务独立开发、升级、扩展,因此系统具备很高的稳定性和快速迭代进化能力。谷歌、亚马逊等大厂也都采用了微服务架构,此次谷歌更是将微服务架构的基础设施直接打包到Kubernetes解决方案中,让我们有机会直接应用微服务架构解决复杂业务的架构问题。
Kubernetes组件
Pod是Kubernetes最小的调度单元,Pod是一组容器的集合,这些容器共享IPC,Network和UTS,也就是这些容器相互之间可以共享进程信息,网络信息和主机信息。这一组容器相互之间可以通过Localhost互访。
Pod有时也称为实例(或者服务实例)。 当我们说一个服务存在2个实例时,也就是说这个服务有两个Pod。
Kubernetes提供了一些管理Pod的组件,比如有DaemonSet、ReplicaSet、StatefulSet、Job等, 这些组件适用于不同的场景。
这只是最基础的内容,Kubernetes当然还有更多的内容,这里不多写,具体可以按照十分钟了解Kubernetes中提到的知识点去查。
四、使用Jenkins、Docker构建CI/CD流水线
到目前为止,我们已经了解了 CI/CD 流水线及其工作原理,还有相关的一些工具。接下来我们将介绍如何使用 Jenkins 构建CI/CD流水线,并自动化整个过程。
参考使用Jenkins+docker 部署springboot项目
我们的目标是要将软件开发生命周期的整个过程都自动化,即从开发人员向代码库中提交代码开始,到将此代码投入生产环境中使用为止,全部自动化完成。
这个案例是使用码云+jenkins+docker来部署springboot项目
- 码云:基于Git的代码托管和研发协作平台,是一个供开发人员提交代码的仓库。
- Jenkins :持续集成、交付、部署(软件/代码的编译、打包、部署)的基于web界面的平台,可安装各种插件处理任何类型的构建或持续集成。
- docker:保证开发环境和生产环境一致,方便部署。
开始构建CI/CD流水线
1、springboot项目
首先写一个最简单的只有响应"hello spring boot"的springboot项目,编写Dockerfile:
#FROM openjdk:8-jdk-alpine #基与jdk1.8
FROM hub.c.163.com/dwyane/openjdk:8
VOLUME /tmp #挂载容器的位置, 容易找到
ADD docker-springboot-1.0-SNAPSHOT.jar app.jar #宿主机器的jar文件 移动到 容器的jar文件
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
#容器执行的命令
上传到码云上此项目的git地址上
2、安装和配置Jenkins
安装
- Jenkins是基于Java语言开发的,所以需要先安装JDK〔Java development kit〕Java开发组件。
- 这里通过tomcat来启动Jenkins,因此先安装tomcat。
- 到官网https://jenkins.io/download/ 下载Jenkins的war包,war包需要配置Tomcat服务器才能运行访问,因此复制war包到tomcat的webapps目录下,启动tomcat
解锁
打开Jenkins后会提示解锁Jenkins,复制 /Users/Shared/Jenkins/Home/secrets/initialAdminPassword
文件内容到页面的Administrator password
栏中
$ cat /Users/Shared/Jenkins/Home/secrets/initialAdminPassword
设置用户
普通的设置用户名、密码之类的
安装默认插件
然后提示安装插件,选择默认的安装,等待安装完成。
全局配置
点击 >系统设置>全局工具配置,配置maven、JDK、Docker、git的路径
3、使用Jenkins部署项目到docker
事先安装好docker。
在jenkins页面新建自由风格的软件项目
。
在源码管理
中,添加git仓库和用户名、密码配置,并且选择代码分支(这里是master)
在构建
步骤中,添加2个步骤
- 1.
顶级maven
选择maven版本(上面的全局配置中配的maven),添加maven打包命令
clean install -Dmaven.test.skip=true
- 2.
执行shell
添加shell:
mvn docker:build #构建docker镜像
echo "当前docker 镜像:"
docker images | grep dockerspringboot
echo "启动容器----->"
docker run -p 8080:8080 -d dockerspringboot
echo "启动服务成功!"
4、执行构建并启动服务
上面配置完成后,到Jenkins的Web主页,选择配置好的项目,菜单中点击立即构建
,看到左边菜单里有执行的进度条,点进去后可以看到执行日志,如果启动服务成功,则可以到浏览器访问localhost:8080
5、改造shell脚本
如果下次构建该项目的时候,docker镜像和服务已存在,需要先删除镜像和服务
# 先删除之前的容器
echo "remobe old container"
docker ps -a | grep dockerspringboot | awk '{print $1}'| xargs docker rm -f
# 删除之前的镜像
echo "romove old image"
docker rmi dockerspringboot
# 构建镜像
mvn docker:build
# 打印当前镜像
echo "current docker images"
docker images | grep dockerspringboot
# 启动容器
echo "start container"
docker run -p 8001:8001 -d dockerspringboot
# 打印当前容器
echo "current container"
docker ps -a | grep dockerspringboot
echo "star service success!"