1. 方案概述
本手册基于云容器引擎实践所编写,用于指导您已有应用的容器化改造。
1.1. 什么是容器
容器是一种轻量级的Linux虚拟化技术,它可以将应用程序及其依赖项打包到一个隔离的环境中,使得应用程序可以在不同的Linux系统上快速部署和运行。
云容器引擎是中国电信天翼云推出的一款容器服务,旨在为企业提供安全、可靠、高效的容器化应用托管服务。它基于Kubernetes技术,支持多种应用部署方式,可实现快速的应用开发和部署,帮助企业提升业务创新速度。
1.2. 为什么需要使用容器
· 隔离性 :容器可以提供独立的运行环境,隔离应用程序与主机操作系统的其他部分,减少潜在的冲突和风险。
· 可移植性 :容器化应用程序可以在任何支持容器技术的平台上运行,实现快速部署和迁移。
· 资源优化 :容器可以高效地使用系统资源,避免资源浪费,使得在云端和数据中心更有效地运行和管理应用。
· 快速部署 :通过容器,可以快速打包和部署应用程序,简化部署过程,提高开发效率。
· 持续集成和持续部署 :容器是实现CI/CD(持续集成/持续部署)流程的关键组件,支持快速迭代和自动化部署。
· 安全性增强 :容器技术提供了一定的安全隔离,减少潜在的安全风险,例如减少恶意软件的攻击面。
· 标准化 :容器技术使得应用程序的部署和管理更加标准化,降低了运维的复杂性。
· 易于管理 :容器管理工具如Docker和Kubernetes提供了强大的管理能力,使得容器的生命周期管理变得简单。
1.3. 企业应用容器化改造方式
企业应用容器化改造主要有以下三种方式:
· Docker容器化 Docker是一种开源的应用容器引擎,它通过容器技术将应用及其依赖打包成一个可移植、标准化的组件——容器镜像。企业在进行Docker容器化改造时,可以将单体应用或微服务模块封装到Docker容器中运行,实现环境的一致性、资源的隔离与高效利用。
· Kubernetes集群化 Kubernetes(简称k8s)是Google开发的开源容器编排系统,用于自动化部署、扩展和管理容器化应用程序。企业应用在经过Docker容器化之后,可以通过Kubernetes进行集群化改造,实现跨主机的容器调度、负载均衡、自动伸缩、故障恢复等功能,从而构建高可用、弹性的分布式应用平台。
· Serverless容器改造 Serverless架构更进一步地抽象了底层基础设施,让开发者无需关心服务器管理和运维。当有请求触发时,平台会自动创建并运行容器来处理业务逻辑。这种方式适用于处理短生命周期、间歇性且对响应时间敏感的任务。
这些方式都有各自的优缺点,具体采用哪种方式需要根据企业的实际情况和应用需求进行评估和选择。同时,进行企业应用容器化改造还需要注意数据安全、网络配置、监控运维等方面的问题,确保改造后的应用能够稳定、安全地运行。
这三种方式的优缺点如下表:
应用容器化改造方式 | 优点 | 缺点 |
---|---|---|
方式一:Docker容器化 | ·环境一致性好·资源利用率高·部署与扩展便捷 | ·安全性需要额外加强·运维复杂度相对增加 |
方式二:Kubernetes集群化 | ·自动化运维能力强·微服务支持完善·弹性伸缩能力出色 | ·学习曲线陡峭·初期投入成本较大 |
方式三:Serverless容器改造 | ·无需关心底层资源管理·成本节省明显(按需付费) | ·冷启动延迟问题·对于长期运行的服务或者对执行环境有特殊要求的应用,Serverless架构可能不是最佳选择 |
注意Docker容器化是Kubernetes集群化和Serverless容器化的基础,三者都会用到Docker容器化的技术。本教程以“Docker容器化”为主,将单体的企业ERP系统做整体的容器化改造,最后包含一部分将容器部署在云容器引擎中的内容。
2. 资源与成本规划
本文提供的成本预估费用仅供参考,资源的实际费用以天翼云管理控制台显示为准。
完成本实践所需的资源如下:
资源 | 资源说明 | 数量 | 费用(元) |
---|---|---|---|
弹性云主机CT-ECS | ·CT-ECS虚拟机规格:4核8G,Ubuntu 16.04操作系统。·绑定弹性IP规格:按带宽计费,5Mbit/s。·建议选择按需计费 | 1 | 0.95元/小时 |
云容器引擎CCSE | ·CCSE集群版本:v1.25.6。·虚拟机节点规格:4核8G或以上规格。·建议选择按需计费 | 1 | 5.92元/小时 |
3. 实施步骤
3.1. 整体应用容器化改造
本教程将以“整体应用容器化改造”为具体示例,全程协助您将正在虚拟机上运行的ERP企业管理系统顺利实现容器化改造,并最终将其优雅地部署至容器服务环境中。
您无需对现有的任何代码或架构进行调整,仅需将整个应用系统封装构建为容器镜像,就可以将其轻松部署至云容器引擎之内。
3.1.1. 本例应用简介
本案例中的“企业管理解决方案”由A企业自主研发,该应用旨在服务于各类第三方企业客户。这些客户仅需专注于应用的使用,而相关的维护工作则全程由A企业负责承担。
当第三方企业需要接入并使用这款应用时,需要在其内部环境配置一套独立的运行架构,包括Tomcat应用服务器和MongoDB数据库系统。值得注意的是,用于存储各第三方企业专属数据的MySQL数据库将由A企业提供,并进行统一管理和维护。
如上图,这款应用基于标准的Tomcat运行环境,后端则与MongoDB和MySQL数据库实现了深度集成。对于此类应用,在初步阶段可选择不进行架构拆分,而将整体应用整合构建为单一容器镜像,即将Tomcat应用与MongoDB一同封装在同一个镜像之中。这样一来,当其他企业需要部署或更新该应用时,即可通过便捷地使用此预配置的镜像来一次性完成部署或升级操作。
注意将Tomcat应用和MongoDB整合到一个Docker镜像中并不是最佳实践,因为它们通常各自作为独立的服务运行,并且这样可以更好地利用容器化的优势,如服务隔离、资源管理和扩展性。
3.1.2. 本例应用容器化改造价值
在本实例中,对传统虚机部署的企业管理应用进行容器化改造所体现的价值尤为显著。原系统采用虚拟机方式进行部署时,面临着一系列挑战:
· 部署成本 :在以前的模式下,每为一个新客户部署一套独立系统时,必须分配并配置一台全新的虚拟机,导致部署成本高昂。
· 升级效率 :当需要对软件版本进行升级时,运维人员需逐个登录各个虚拟机进行手动更新,这一过程耗时费力且容易出现人为错误,整体升级效率较低。
通过实施容器化部署策略后,以上问题可以得到显著的改进与优化:
· 成本节约 :容器化极大地降低了部署成本,借助容器服务实现多租户隔离,在同一台物理或虚拟服务器上可以运行多个相互隔离的容器环境,使得给不同企业部署系统所需的成本至少降低50%以上。
· 快速升级 :升级流程得到大幅简化和加速,现在只需替换容器镜像版本即可实现在秒级内的无缝升级,而且云容器引擎支持滚动升级机制,能够在升级过程中确保业务连续性不受影响。
· 运维便捷性 :传统的运维工作量大大减少,不再需要针对每个客户单独维护一台虚拟机。在容器化环境中,企业的运维重点转向了应用本身,自动化运维工具和技术得以广泛应用,显著降低了随着客户数量增长而攀升的运维成本,使得团队能更专注于业务开发与创新。
3.2. 改造流程
整体应用容器化改造时,一般需要执行如下流程。
3.3. 分析应用
分析应用的主要目的是为了确保成功地将应用程序转换为容器化的部署形式,并在容器环境中稳定、高效地运行。这一过程包括但不限于以下方面:
类别
子类
说明
运行环境
依赖性管理
应用所依赖的库、框架以及服务版本需明确,并确保这些依赖可以在容器镜像中正确打包,避免因环境差异导致运行失败。
本例中,ERP应用tomcat类型的web应用,依赖tomcat和jre 8环境。mangoDB是c++程序,主要依赖C库
操作系统兼容性
分析应用在何种操作系统上运行最稳定或有官方支持,选择合适的容器基础镜像
本例是对于操作系统没有强需求,可以选择基于alpine系统的openjdk官方基础镜像
部署形态
配置项管理
梳理应用的配置文件、环境变量等,保证相关配置既能灵活调整以适应各种场景需求,又能保持安全性与易管理性。
本例中mysql的信息通过环境变量注入。
资源需求
确定应用所需的CPU、内存、磁盘空间和网络带宽等资源,以便为容器设置合适的资源限制与配额。
本例中不需要针对相关资源进行特殊配置
网络配置
考虑应用的网络模型、端口映射、域名解析、服务发现的需求,确保容器化后能够正常进行内外部通信。
本例中ERP应用与mangoDB打包在一起,两者的网络请求可以使用localhost方式,并将配置信息固定在代码中。
ERP有外面依赖mysql,需要确定mysql的访问路径。本例中通过环境变量的方式将mysql访问信息注入到容器中,需要如下环境变量:
url=jdbc:mysql://服务器地址/数据库名称 #数据库连接URL
username=**** #数据库登录用户名
password=**** #数据库登录密码
存储需求
评估应用的数据持久化需求,包括容量、性能、是否需要迁移、是否需要分布式存储等。
本例中不需要存储配置
日志与监控
预先规划如何将应用的日志输出到容器外,并集成到集中式日志系统。同时,确定如何实现对容器内应用性能的实时监控。
本例中使用云容器引擎提供的监控中心和日志中心。
健康检查与故障恢复
定义应用健康检查机制,确保容器启动后应用服务已就绪,并能够在异常状态下自动重启或替换容器实例。
本例中不需要相关配置
3.4. 准备应用容器化开发环境
应用容器化的开发环境需要准备以下内容:
基础操作系统环境 :
· 通常选择Linux作为宿主机操作系统,因为它对Docker等容器技术提供了更好的支持。可以是Ubuntu、CentOS、CTyunOS等。本例中使用Ubuntu。
容器运行时环境 :
· 安装和配置容器运行时,如Docker或containerd,来下载、制作、运行容器镜像。本例中使用Docker,它对容器镜像相关功能有更为完整的支持。
其它相关依赖软件:
· 如文件编辑软件、应用开发调试软件、下载工具等。本例中不讨论这一部分。
· 容器镜像中需要包含的相关软件,如应用的可执行程序、war包等。本例中主要是应用的war包
本例中使用弹性云主机作为开发环境,可以在创建云主机时选择Ubuntu系统。所以安装操作系统的步骤不再介绍。本节点主要包含以下内容:
3.4.1. 安装Docker
在Ubuntu系统上安装Docker是一个相对直接的过程,以下将详细阐述每一步骤:
第一步:更新系统软件包
首先确保你的Ubuntu系统是最新的,打开终端并运行以下命令来更新系统的软件包列表及其版本:
sudo apt update
sudo apt upgrade
第二步:设置存储库和安装依赖
为了能够从官方的Docker仓库中安装Docker,我们需要添加Docker的GPG密钥,并将Docker的存储库添加到Ubuntu的软件源列表中。执行以下命令:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
第三步:再次更新软件包列表
由于我们刚刚添加了新的软件源,现在需要重新更新软件包列表以包含Docker的安装信息:
sudo apt update
第四步:安装Docker Engine
接下来,使用apt包管理器安装Docker Engine。执行如下命令:
sudo apt install docker-ce docker-ce-cli containerd.io
第五步:验证Docker安装是否成功
安装完成后,可以运行docker命令检查Docker服务是否正常启动以及版本信息:
sudo docker run hello-world
如果一切顺利,此命令将会下载一个测试镜像并在容器中运行它,输出一条欢迎消息。
3.4.2. 选择基础镜像及版本
本例中,ERP应用tomcat类型的web应用,依赖tomcat和jre 8环境。mangoDB是c++程序,主要依赖C库。针对这些特点,我们选择openjdk:8-jdk-alpine作为应用容器化的基础镜像。它有以下优点:
· 更小的镜像体积 : Alpine Linux 是一个极简的 Linux 发行版,其内核小巧,基础系统包仅占用极少量的空间。因此,基于 Alpine 构建的 openjdk:8-jdk-alpine 镜像比基于 CentOS 或 Ubuntu 的镜像要小得多,这在容器化部署场景中尤其重要,因为更小的镜像意味着更快的下载速度、更高效的存储利用以及更快的应用启动时间。
· 安全性和稳定性 : 尽管体积小巧,Alpine Linux 仍提供了稳定的环境,并且由于其软件包管理系统 APK 的严格控制,能够保证软件依赖关系清晰、版本更新及时。OpenJDK 在 Alpine 上的构建经过了精心配置和优化,确保在最小化环境中提供稳定运行的基础,而且Alpine系统的软件源中包含本例中的mangoDB,使得我们可以安装mangoDB,不需要再手动下载mangoDB安装包。
· 精简的安全性考量 : Alpine 使用了musl libc替代glibc作为C标准库,这对于某些专注于安全性的环境来说是一个优点,因为它缩小了攻击面。然而,这也可能导致与一些依赖glibc的程序存在兼容性问题,但在纯Java应用中这种影响较小。
· 易于维护和升级 : Docker官方提供的OpenJDK镜像是经过专门设计和测试的,当有新的安全补丁或性能改进时,可以更容易地通过更新镜像版本来获取最新特性及修复问题,减少了手动安装和管理Java开发工具包的复杂度。
可以通过以下命令下载基础镜像到本地
sudo docker pull openjdk:8-jdk-alpine
3.4.3. 准备工作目录
制作容器镜像时,Docker命令会将指定目录中的内容全部导入缓存,为了提高速度,并且为了后续维护方便,创建一个目录作为工作目录,将相关软件包、配置文件等都放在一起。本例以erp-demo.war指代客户的应用。具体命令如下:
sudo mkdir ~/erp-demo #创建目录
sudo mv erp-demo.war ~/erp-demo #将应用war包放入工作目录,注意war包的实际路径
cd ~/erp-demo
3.5. 编写开机运行脚本
entrypoint脚本是容器运行的入口,它有以下作用:
· 定制化启动流程 : entrypoint脚本允许开发者定义一个自定义的启动命令序列,确保每次容器启动时都会按照预期执行一系列操作。这可以是运行服务前必要的环境准备、参数检查、配置加载等步骤。
· 控制可执行程序的行为 : 通过设置entrypoint,可以精确控制哪个命令或脚本作为容器启动后的主进程,并且可以接收传入的CMD参数来调整其行为。这意味着即便用户在docker run命令中提供额外的参数,这些参数也会被整合到entrypoint脚本中处理,从而增强了对容器内应用程序执行逻辑的控制。
· 标准化和重用性 : 如果应用有多个启动场景或需要不同的启动选项,entrypoint脚本可以集中管理这些逻辑,使得每个容器实例遵循相同的启动标准。这样,无论何时何地创建新容器,都能确保一致性和兼容性。
· 简化运维 : 在维护阶段,当需要添加新的初始化任务或更改现有任务的顺序时,只需更新entrypoint脚本即可,无需修改镜像中的其他部分或者重新构建镜像。
本例中,tomcat应用与mangoDB打包在同一个容器中,需要同时运行这两个软件。我们编写entrypoint脚本如下:
#!/bin/sh
mongodb --dbpath $MONGO_DATA_DIR --logpath $MONGO_LOG_DIR &
sleep 10 # 确保MongoDB启动后再启动Tomcat
exec /opt/tomcat/latest/bin/catalina.sh run
将该文件命名为start.sh,并保存在工作目录中。
3.6. 编写Dockerfile文件
Dockerfile 是一个文本文件,它包含了用于自动化构建Docker镜像的一系列指令。开发者通过编写Dockerfile来定义镜像的内容、结构以及构建过程。在执行 docker build 命令时,Docker引擎会根据Dockerfile中的指令自动生成一个新的Docker镜像。
每个Dockerfile包含一系列命令,包括但不限于:
· FROM: 定义基础镜像。
· RUN: 在新创建的镜像内部执行命令,通常用来安装软件包或设置环境。
· COPY: 将宿主机上的文件和目录复制到镜像内部。
· ADD: 类似于 COPY,但可以自动解压tar文件并从URL获取资源。
· WORKDIR: 设置镜像内工作目录。
· ENV: 设置环境变量。
· CMD 或 ENTRYPOINT: 指定容器启动时运行的应用程序及其参数。
· EXPOSE: 指明容器需要对外开放哪些端口。
· VOLUME: 创建可以在多个容器之间共享或持久化数据的存储区域。
当Docker按照Dockerfile进行构建时,每一行指令都会生成一个新的镜像层,并提交至镜像堆栈中,从而形成最终的镜像。这样做的好处是可以实现高效的增量构建和分层存储,同时使得镜像构建过程可重现且易于维护。
使用Dockerfile不仅可以简化应用部署流程,还能确保团队成员间以及不同开发和生产环境之间的一致性。
编写Dockerfile直接影响生成的容器镜像的大小、启动速度等,编写时可以参考:Dockerfile高效编写指引
本例中Dockerfile内容如下:
# 基于一个包含了Java环境的基础镜像
FROM openjdk:8-jdk-alpine AS builder
# 安装MongoDB
RUN apk add --no-cache mongodb
# 设置MongoDB的数据存储路径
ENV MONGO_DATA_DIR=/data/db \
MONGO_LOG_DIR=/var/log/mongodb 1011# 创建数据目录并赋予适当权限
RUN mkdir -p "$MONGO_DATA_DIR" "$MONGO_LOG_DIR" && \
chown -R mongodb:mongodb "$MONGO_DATA_DIR" "$MONGO_LOG_DIR"
# 下载并解压Tomcat
ENV TOMCAT_VERSION=9.0.85
WORKDIR /opt/
ADD https://downloads.apache.org/tomcat/tomcat-9/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz .
RUN tar -xzf apache-tomcat-*.tar.gz && \
rm apache-tomcat-*.tar.gz && \
ln -s /opt/apache-tomcat-${TOMCAT_VERSION} /opt/tomcat/latest
# 添加你的应用程序war包(假设已放在当前目录)
COPY erp-demo.war /opt/tomcat/latest/webapps/
# 设置启动脚本以启动MongoDB然后启动Tomcat
COPY start.sh /start.sh
RUN chmod +x /start.sh
# 使用非root用户运行Tomcat
USER mongodb
# 设置容器启动时执行的命令
CMD ["/start.sh"]
将该文件命名为Dockerfile并保存到工作目录
3.7. 制作并上传镜像
在工作目录运行如下命令可以完成容器镜像的制作:
sudo docker build -t erp-demo .
注意最后的“.”是必须的
这个过程中,Docker会逐行解析Dockerfile中的指令,并根据这些指令构建一个新的镜像层。每个指令都会生成一个新的镜像层,从而形成最终的自定义Docker镜像。
命令运行完成后可以通过下面的命名查看容器镜像
sudo docker images | grep erp-demo
3.7.1. 容器镜像服务CRS
天翼云容器镜像服务CRS是一种支持容器镜像全生命周期管理的服务,提供简单易用、安全可靠的镜像管理功能,帮助用户快速部署容器化服务。产品相关介绍可以参阅:产品介绍
用户可以将制作好的容器镜像上传到容器镜像服务,方便后续部署容器。容器镜像的上传方法参阅:使用企业版实例推送和拉取镜像
3.8. 创建容器工作负载
在创建好容器镜像后,可以在开发环境对其进行简单的验证。
首先确保环境中已有正常运行中的mysql,并将与其相关的信息保存在文档里,方便在运行容器时以环境变量的方式将这些信息注入,文件内容如下:
MYSQL_URL=jdbc:mysql://服务器地址/数据库名称 #数据库连接URLMYSQL_USERNAME=**** #数据库登录用户名MYSQL_PASSWORD=**** #数据库登录密码
请将文件中的“服务器地址”、“数据库名称”、用户名和登陆密码更改为实际环境中的信息。将该文件命名为envs并保存。
在与envs文件同级的目录下运行以下命名启动容器:
sudo docker run -d --env-file envs erp-demo
上面的命令会以守护进程的方式运行erp-demo镜像中的程序,并将envs文件中的内容以环境变量的方式注入容器。容器首先会启动start.sh脚本,这个脚本先后启动了mongoDB和tomcat应用。tomcat应用会通过环境变量获得MYSQL的相关信息并建立连接。
容器正常启动后,可以通过下面的命令查看运行中的容器
sudo docker ps
其它Docker命令行的使用方法请参阅官方文档
3.8.1. 云容器引擎CCSE
天翼云容器引擎CCSE为用户提供了高度可扩展的、高性能的Kubernetes集群、一站式容器服务。具体产品介绍请参阅:产品介绍
下面将介绍如何将erp-demo容器部署在CCSE中。
首先需要创建一个用户集群,具体过程请参阅:创建一个应用集群
在集群准备好后,就可以将erp-demo部署在CCSE中了,具体流程请参阅:创建一个无状态工作负载
Erp-demo部署在CCSE后,可以通过Ingress路由将应用发布。关于Ingress相关信息,请参阅:Ingress