容器化部署
1、Docker
1.1、什么是容器
容器的英文是container,其实container还有集装箱的意思
容器是一种操作系统虚拟机化技术,用于打包应用程序及其依赖项,并在隔离环境中运行它们。
物理机到容器的技术演进:
- 物理机
- 一个或多个应用部署在同一台机器上
- 一个应用在部署之前需要先安装各种依赖环境,然后进行应用的部署
问题:
- 资源利用率低:传统的CPU、内存利用率都在15%左右
- 成本高:集群部署,需要多台物理机,每台物理机购买成本较高
- 不隔离:多个应用之间不隔离,共用CPU、内存等硬件资源,相互影响
- 有限的可伸缩性:迁移和扩展困难(都需要新的物理机,扩展新的物理机都需要安装各种依赖环境)
- 虚拟机
- 一台物理机安装多个虚拟机(VM),一个虚拟机部署一个或多个应用
虚拟机将计算机的资源虚拟化为一个或多个较小的单个计算机,然后在其上部署操作系统,接着在这些操作系统上部署运行相应的应用程序
虚拟机技术其实是通过软件的手段来虚拟硬件的一种技术,从而达到和物理机一样的体验。
虚拟化技术就是在操作系统上多加了一个虚拟化层(
Hypervisor
),可以将物理机的CPU、内存、硬盘等资源进行虚拟化,再通过虚拟化出来的空间上安装操作系统 比如,我们可以将一台32核CPU、64G内存、500G磁盘的物理机进行虚拟化,可以创建8台4核CPU、8G内存的虚拟机。这些机器提供给不同的应用去部署,如此极大提供了资源利用率。常见的虚拟化技术如VMWare,VirtualBox等
缺点:
-
- 虚拟机本身占用大量的资源,8G内存的虚拟机,应用可用的只有7G或更少
- 虚拟机硬件需要初始化,其本身也是一个操作系统,启动较为耗时
- 容器化
- 一台物理机安装多个容器实例(container),一个容器跑一个或多个应用
与虚拟化整个计算机相比,容器则采用不同的方式——直接虚拟化操作系统
容器化是一种将虚拟化带到操作系统级别的虚拟化。虚拟化为硬件带来了抽象,而容器化为操作系统带来了抽象。
容器内的应用程序进程直接运行在宿主机(真实物理机)的内核上,各个容器相互独立直接运行于未经虚拟化的宿主机硬件上,同时各个容器也没有自己的内核
虚拟机最终虚拟出了一台完整的计算机系统,其拥有底层的物理硬件、操作系统和应用程序执行的完整环境,都对硬件资源造成了一定的消耗,比较重量化
与虚拟机通过操作系统实现隔离不同,容器技术只隔离应用程序的运行时环境但容器之间可以共享同一个操作系统(这里的运行时环境指的是程序运行依赖的必要的操作系统包、应用程序及配置,通常不包含完整的操作系统)
也就是说容器是对进程的隔离,对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。每个容器对宿主机资源的访问都会被严格限制,其中包括:CPU、内存、磁盘、网络带宽等等
容器的好处:
- 更加的轻量级且占用的资源更少,与操作系统相比,容器体积小
- 资源利用率高:容器之间可以共享资源,最大化资源的利用率
- 运行速度快:直接运行于宿主系统内核,容器里面的应用就是底层系统的一个进程,所以启动容器相当于直接运行本机的一个进程,而不是一个完整并臃肿的操作系统,自然就快很多
虚拟机和容器的区别?
1)速度:虚拟机启动时间比容器长的多,因为虚拟机硬件需要初始化,其本身也是一个操作系统,启动较为耗时;而容器是直接运行于宿主系统内核,容器里面的应用就是底层系统的一个进程,所以启动容器相当于直接运行本机的一个进程,而不是一个完整并臃肿的操作系统,自然就快很多;
2)资源:虚拟机最终是虚拟出了一台完整的计算机系统,其拥有底层的物理硬件、操作系统和应用程序执行的完整环境,都对硬件资源造成了一定的消耗,比较重量化,即使虚拟机不处理用户请求,虚拟机本身也会消耗内存,能应用可用资源就偏少;而容器更加轻量级且占用资源更少,容器之间可以共享资源,最大化资源的利用率;
3)安全性和隔离性:虚拟机是保持独立和相互隔离的;而容器只隔离应用程序的运行时环境但容器之间可以共享同一个操作系统,它是对进程的隔离;
4)可移植性和应用程序共享:虚拟机需要复制整个操作系统、主机内核、系统库、配置文件和任何必要的文件目录,在共享或转移时面临挑战;而容器镜像比虚拟机小得多,它们更容易转移,并节省主机文件系统的空间
Docker是容器化技术的一种实现,使用Docker可以尽可能轻松地创建和使用容器,是目前最流行的容器解决方案
1.2、什么是Docker
Docker是一个开源的应用容器引擎,基于Go语言开发。
Docker 是在Linux 容器里运行应用的开源工具,是一种轻量级的“虚拟机”
Docker 的容器技术可以在一台主机上轻松为任何应用创建一个轻量级的,可移植的,自给自足的容器
Docker 的Logo设计为蓝色鲸鱼,拖着许多集装箱,鲸鱼可以看作为宿主机,集装箱可以理解为相互隔离的容器,每个集装箱中都包含自己的应用程序
Docker的思想来自于集装箱, 是一个以容器的形式将应用程序及其所有依赖项打包在一起的平台。它使用容器使应用程序的创建、部署和运行变得更加容易。Docker 在容器内绑定应用程序及其依赖项。容器允许开发人员将应用程序及其所需的所有部分(例如库和其他依赖项)打包在一起,然后将其作为一个包发送出去。
Docker的主要目标是"Build,Ship and Run any App,Angwhere",构建,运输,处处运行
1.3、Docker基本概念
- 镜像(Image):Docker镜像(Image),就相当于是一个root文件系统。比如官方镜像ubuntu:16.04就包含了完整的一套Ubuntu16.04最小系统的root文件系统
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行的实体。容器可以被创建、启动、停止、删除、暂停等
- 仓库(Repository):用来保存镜像,集中存放镜像的地方。最大的公开仓库是 Docker Hub:https://hub.docker.com,存放了数量庞大的镜像供用户下载
理解镜像和容器:
容器从容器镜像中创建,其中包含了系统、应用程序和容器环境。
容器镜像和创建特定容器模板一样,同一镜像可用于生成任意数量的运行中的容器。
这与类和实例在面向对象编程中的工作方式类似:一个单独的类可以用于创建任何数量的实例,一个单独的容器镜像也可以用于创建任何数量的容器。这类比喻也适用于继承方面,因为容器镜像可以作为其他自定义容器镜像的父级。用户可以从外部资源下载预先构建的容器,也可以根据需要构建自定义镜像
1.4、Kubernetes
简称k8s,k和s之间有8个字母
k8s是一个开源的容器集群管理系统,可以实现容器集群的自动化部署、自动扩缩容、维护等功能
尽管Docker为容器化的应用程序提供了开放标准,但随着容器越来越多出现了一系列新问题:
- 如何协调和调度这些容器?
- 如何在升级应用程序时不会中断服务?
- 如何监视应用程序的运行状况?
- 如何批量重新启动容器里的程序?
Kubernetes中文为舵手,container除了容器还有集装箱的意思,Kubernetes 也就借着这个寓意,希望成为运送集装箱的一个轮船,来帮助我们管理这些集装箱,也就是管理这些容器
Matrix容器平台,云原生时代的一站式DevOps平台,其容器管理模块基于k8s开发。
在了解容器部署之前先介绍下CI/CD
2、CI/CD
2.1、什么是CI/CD
在软件工程中,CI/CD 或 CICD 通常指的是持续集成(Continuous Integration)和持续交付(Continuous Delivery)或持续部署(Continuous Deploy)的组合实践。
CI/CD 可简单理解为自动化执行应用程序的构建、测试和部署
2.2、GitLab CI/CD
GitLab CI/CD是 GitLab 的一部分,可用于所有持续方法(持续集成、交付和部署)。使用 GitLab CI/CD,您可以测试、构建和发布您的软件,而无需第三方应用程序或集成
2.2.1、GitLab CI/CD工作流程
代码的提交/合并自动触发CI/CD管道的执行
2.2.2、GitLab CI/CD 配置
CI/CD管道的配置文件为 .gitlab-ci.yml , 位于项目根目录下。
配置示例:
stages:
- appstore-upgrade-package-prd
- appstore-upgrade-build-image-prd
# 自定义变量配置,实际项目中建议配置在项目GitLab-->Setting-->CI/CD-->Variables中
variables:
MICR_PROJECT: appstore # 项目名/工程名
REPO_NAMESPACE: appstore # MICR容器镜像平台的命名空间,其中保存镜像仓库,建议与
REPO_PASS: xxx
REPO_SERVER: xxx.cn
REPO_USER: yangyongjie
# 电视应用商店升级模块生产环境打包
appstore-upgrade-package-prd:
stage: appstore-upgrade-package-prd
image:
name: cr.d.xiaomi.net/containercloud/ubuntu-openjdk1.8-maven3.5:latest
script:
- mvn clean package -P prd -Dmaven.test.skip=true
artifacts:
paths:
- appstore-upgrade/target/appstore-upgrade-*.jar
after_script:
- echo "appstore-upgrade-package-prd completed"
only:
refs:
- master
changes:
- appstore-config/**/*
- appstore-common/**/*
- appstore-upgrade/**/*
- .gitlab-ci.yml
- pom.xml
# 电视应用商店升级模块生产环境镜像构建
appstore-upgrade-build-image-prd:
stage: appstore-upgrade-build-image-prd
image:
name: cr.d.xiaomi.net/containercloud/kaniko-executor-xiaomi:release
entrypoint: [ "" ]
script: # kanio Docker镜像构建工具
- APPSTORE_UPGRADE_IMAGE=$REPO_SERVER/$REPO_NAMESPACE/appstore-upgrade:prd-$CI_COMMIT_SHORT_SHA
- echo "{\"auths\":{\"$REPO_SERVER\":{\"username\":\"$REPO_USER\",\"password\":\"$REPO_PASS\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/appstore-upgrade/Dockerfile --destination $APPSTORE_UPGRADE_IMAGE --validate-image
after_script:
- echo "appstore-upgrade-build-image-prd completed"
only:
refs:
- master
changes:
- appstore-config/**/*
- appstore-common/**/*
- appstore-upgrade/**/*
- .gitlab-ci.yml
- pom.xml
retry: 2
配置说明:
- stages
- 用于定义包括作业(job)组的阶段。在作业中使用stage以将作业配置为在特定阶段运行
- stages定义了作业的执行顺序,下一阶段的作业在上一阶段的作业成功完成后运行
- variables
- 自定义CI/CD作业所需的变量
- 出了自定义变量外,还有预定义的CI/CD变量
-
CI_PROJECT_DIR:当前项目目录
-
CI_COMMIT_SHA:构建项目的提交修订号
-
CI_COMMIT_SHORT_SHA:CI_COMMIT_SHA的前8个字符
-
- 配置作业(job)的关键词
- stage:定义作业所属阶段
- image:指定作业运行的 Docker 镜像,CI/CD作业在此镜像中运行
- name:作业运行所在的 Docker 镜像的名称
- script:由运行程序执行的 Shell 脚本
- artifacts:artifacts,构件,job执行成功后保存到文件和目录列表,job作业完成后,构件将发送到GitLab,默认情况下,后期阶段的作业会自动下载早期阶段作业创建的所有构件
- path:路径是相对于项目目录 ($CI_PROJECT_DIR) 的,不能直接链接到项目目录之外
- after_script:定义在每个作业之后运行的命令数组,包括失败的作业
- only:控制何时执行job作业
- refs:分支名称
- changes:哪些文件有变动
.gitlab-ci.yml详细配置说明:https://docs.gitlab.com/ee/ci/yaml/index.html#default
预定义变量说明:https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
3、部署
打包、构建镜像、推送镜像
3.1、创建并配置.gitlab-ci.yml文件
在项目的根目录下创建 .gitlab-ci.yml文件,配置应用的自动化打包,构建镜像(引用Dockerfile来构建镜像),推送镜像到镜像仓库
3.2、构建镜像
在项目根目录或者部署模块根目录新建Dockerfile文件
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明
Docker使用Dockerfile来自动化构建镜像
Dockfile配置示例:
#指定了运行容器的镜像并把生成程序文件拷贝到镜像根目录用以运行
FROM xxx/openjdk:8-jre-alpine
ENV TZ "Asia/Shanghai"
COPY appstore-upgrade/target/appstore-upgrade-*.jar /opt/appstore-upgrade.jar
WORKDIR /opt
CMD ["java", "-jar", "appstore-upgrade.jar"]
Dockerfile配置说明:
-
FROM:使用的基础镜像源
-
RUN:用于执行后面跟着的命令行命令
-
注意:Dockerfile的指令每执行一次都会在docker上新建一层。所以过多无意义的层,会造成镜像膨胀过大。因此 RUN 后面有多个命令的话,以&&符号连接命令,这样执行后,只会创建一层镜像。
-
RUN命令有两种格式:
-
shell格式:RUN <命令行命令>
-
exec格式:RUN ["可执行文件", "参数1", "参数2"]
-
-
-
COPY:复制指令,从上下文路径中复制文件或目录到容器指定路径
-
上下文路径:是指docker在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令在得知这个路径后,会将路径下的所有内容打包。默认的上下文目录是Dockerfile所在的目录
-
-
CMD:类似RUN指令,但二者运行的时间点不同:
-
RUN是在docker build,CMD在docker run时运行
-
作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖
-
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效
-
ENV:设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量
-
WORKDIR:为 Dockerfile 中任何 RUN、CMD、ENTRYPOINT、COPY 和 ADD 指令设置工作目录,如果未指定,则默认工作目录为 /
Dockerfile详细配置说明:https://docs.docker.com/engine/reference/builder/
3.3、推送镜像
推送镜像到镜像仓库,在.gitlab-ci.yml中配置在镜像构建完成之后推送到镜像仓库中
END.