将Java 应用容器化改造并迁移到Kubernetes 平台

简介:
为了能够适应容器云平台的管理模式和管理理念,应用系统需要完成容器化的改造过程。对于新开发的应用,建议直接基于微服务架构进行容器化的应用开发;对于已经运行多年的传统应用系统,也应该逐步将其改造成能够部署到容器云平台上的容器化应用。本文针对传统的Java 应用,对如何将应用进行容器化改造和迁移到Kubernetes 平台上进行说明。

要将传统Java 应用改造迁移到Kubernetes 平台上运行,通常要经过以下几个步骤。

(1)进行应用代码改造,要考虑配置文件、多实例部署下的分布式架构问题,并对程序代码和架构做出相应的改造。

(2)进行容器化改造,选择合适的基础镜像并打包生成新的应用镜像,使得应用能以容器方式部署、运行。

(3)进行Kubernetes 建模与部署,采用合适的Kubernetes 资源对象建模Java 应用,最终发布到Kubernetes 平台上实现应用的自动化运维。

接下来以一个传统的Java 应用改造迁移过程为例,来说明上述步骤中的细节。

1 Java 应用的容器化改造迁移

我们的目标是搭建一个简单的学员分数管理系统(Study Application),应用界面与架构如下图。
520865ab970006ffcecbc67368d83d225bccfbcd
Study Application 是一个典型的J2EE 系统,为了方便理解,并没有采用额外的框架技术,而是采用了MySQL 数据库,将JSP 作为Web 页面,并通过JDBC 进行数据库操作,整个系统以标准方式部署在Tomcat 的webapp 目录下。

下图所示是Study Application的目录结构与说明。
a30354db78ba7c7b8e8d1c1eed611fca76a0ddcb
下面是在index.jsp 中访问数据库的关键代码, 数据库连接的配置信息被放在jdbc.properties 属性文件中,便于在不同的环境下修改:

01124bdcd985184e8ba37e09e6fa8430eaee2f57

   Class.forName("com.mysql.jdbc.Driver");
    java.util.Properties pps = new java.util.Properties();
    pps.load(new java.io.FileInputStream("jdbc.properties"));
    String ip=pps.getProperty("mysql_ip");
    String user=pps.getProperty("user");
    String password=pps.getProperty("password");
    System.out.println("Connecting to database...");
    conn =
java.sql.DriverManager.getConnection("jdbc:mysql://"+ip+":3306"+"?useUnicode=true&characterEncoding=UTF-8", user,password)
        stmt = conn.createStatement();
        String sql = "show databases like 'HPE_APP'";
        rs =stmt.executeQuery(sql);

我们知道,应用在以容器化运行以后,是不建议进入容器里修改配置文件的(在多实例情况下很难保持配置文件同步更新),因此,需要修改从jdbc.properties 属性文件中获取数据库连接的以上代码,根据容器环境的要求,将其改为从环境变量中获取,改造后的代码如下:
3ec70a5c597ea153852e79c8723bfc6f45659111

    String ip=System.getenv("mysql_ip");
    String user=System.getenv("user");
    String password=System.getenv("password");

改造后的代码基本达到了容器化的要求,但对于一个完整的应用来说,由于还存在用户Session 会话保持的问题,因此还需要实现分布式的Session 会话机制,才能做到多实例部署,此时可以考虑采用Spring Session 框架来改造、升级我们的单体应用。对于大部分RESTful 服务,由于不需要会话保持功能,因此可以直接多副本部署,多个实例可以同时提供服务。

2 Java 应用的容器镜像构建

接下来,我们需要将自己的Java 应用打包为Docker 镜像,以容器方式启动并提供服务。在打包镜像时,需要注意以下几个关键问题。

(1)需要注意基础镜像的选择问题。选择基础镜像的两个原则:标准化与精简化。尽可能选择Docker 官方发布的基础镜像,这些基础镜像通常符合标准化与精简化这两个目标。比如,它们都有Dockerfile 源文件,我们可以获知此镜像是如何制作的,并可以在此基础上实现诸如软件版本、性能优化、日志及安全等方面的特殊定制,然后打包为公司级别的内部标准镜像,供各个项目使用。

(2)需要注意业务进程的启动方式。与在物理机上将自己的程序放到后台运行的方式不同,在容器化时,我们需要将自己的业务进程放到前台运行。这样一来,当业务进程由于某种原因而停止时,容器也随之销毁,我们就能及时观察到这种严重故障,并做出相应的行动来恢复系统。目前有一些系统在容器化的过程中采用了supervisord 这样的工具,将业务的主进程和辅助进程放到后台启动,并交给supervisord 监管,这种做法虽然在一定程度上也能实现自动重启故障进程的目标,但它将问题隐藏得更深,即使业务进程由于特殊故障始终无法重启成功,运维人员也发现不了问题,因此不建议采用这种方式启动业务进程。

(3)需要注意程序的日志输出问题。在物理机上运行业务进程时,我们通常会把程序日志输出到指定的文件中,以便更好地排查故障。但在容器化以后,我们需要改变这种做法,将程序的日志直接输出在容器的屏幕上(或者说控制台Console 上),此时Docker 会将这些输出日志存放到容器之外的特定文件中,第三方的日志收集工具(例如Elasticsearch)就可以方便采集这些日志并实现集中化的日志搜索和分析功能。此外,Docker 也提供了统一的log 命令来查看容器的日志,这推进了系统运维的标准化。Java 中常用的Log4j 及Slf4j日志框架都支持把日志输出到控制台的配置方式,在打包应用时,需要对日志的配置文件做出相应的修改。

(4)需要注意文件操作的问题。当业务进程运行在物理机上时,它看到的文件系统就是物理机的文件系统;但当业务进程运行在容器中时,它所访问的文件系统就是一种特殊的、被隔离的、分层模式的虚拟文件系统,在这种情况下,频繁进行I/O 操作的性能比较低。为了解决这个问题,容器可以使用Volume 将频繁进行操作的目录映射到容器外部(通常是物理机上);同时,Volume 也是容器与外部交换文件的重要工具,因此在制作镜像和运行容器时,需要考虑Volume 映射的问题,对于在程序运行过程中产生的大量临时文件和被频繁读写的文件,或者在需要跟外界交换文件时,可以选择挂载Volume。

下图是Study Application 打包镜像的示意图及对应的Dockerfile 源码。
1aa2d23012bffc92b70a95236770db6444a9b9dd
Study Application 的镜像继承了tomcat:9-alpine 这个官方的基础镜像,这个镜像基于Alpine Linux,如果对比一下,我们会发现,基于alpine 的镜像不到5MB,而基于Ubuntu或CentOS 的镜像都在100MB 以上。此外,从Study Application 的Dockerfile 来看,制作Java 类型应用的Docker 镜像是很方便的一件事,通常只需几行代码。

3 在Kubernetes 上建模与部署

在应用容器化后,就可以在Kubernetes 上建模与部署了,在建模的过程中,我们需要考虑一些关键问题,这些问题及其答案如下。

(1)将业务进程建模为Pod 还是RC?

对于这个问题,最重要的判断依据是该进程提供的是有状态服务还是无状态服务。对于无状态服务,比如大多数REST 接口的服务,通常是可以在任意节点上启动并提供服务的,例如我们这里的Web 应用程序就符合无状态服务。但对于有状态服务,比如MySQL服务,我们通常不能这么做,因为它依赖本地存储的数据库文件。对于有状态服务,我们通常只能将业务进程建模为Pod,这是因为RC 控制的Pod 实例可以从一台节点飘到另一台节点上,如果我们能够通过共享存储解决Pod 的状态问题,则也可以把某些有状态服务的进程建模为RC,这种做法与StatefulSet 很类似。

(2)我们是否需要在Pod 的基础上,继续建模对应的Service?

这主要取决于此Pod 是否会被其他业务进程(或终端用户)所访问,对于不会被其他业务进程所访问的Pod,我们无须建模对应的Service。实际上,在一个分布式系统中,大多数进程都会被建模为Service 并对应一个微服务,如果某个服务还需要被终端用户访问,则往往还需要“导出”外网访问地址,比如NodePort 端口。对于无须外部访问的Service,还可以考虑建模为Headless Service,在这种情况下,该Service 不会分配一个虚拟的ClusterIP,通信效率更高。

(3)是否需要考虑应用的数据存储问题?

如果只是本机存储,则可以直接使用Kubernetes Volume 资源对象;如果希望有远程存储功能,则可以考虑使用PV(Persistent Volume)。这样一来,不管Pod 被调度到哪台机器,都可以继续访问原来的存储数据。如果希望系统自动管理共享存储的空间,则可以考虑建模对应的StorageClass。

(4)是否需要考虑应用的配置问题?

我们知道,在几乎所有应用开发中,都会涉及配置文件的管理问题,比如StudyApplication 中的数据库配置信息,常见的互联网应用还有缓存中间件、消息队列、全文检索等一系列中间件的配置文件。而在分布式情况下,发布在多个节点上的Pod 副本都需要访问同一份配置文件,这也加大了配置管理的难度,为此业内的一些大公司专门开发了自己的一套配置管理中心,如360 的Qcon、百度的Disconf 等,但这些解决方案都比较复杂而且有侵入性。Kubernetes 则提供了无侵入的更简单的方案,这就是ConfigMap,我们可以把任意数量的配置文件放入ConfigMap 中,实现集中化管理,然后通过环境变量的方式将配置数据传递到Pod 里,或者通过Volume 方式挂载到Pod 内。

在Study Application 中,Web 应用在Kubernetes 上的建模如图6-4 所示。我们通过定义一个RC 来控制Web 的Pod 实例,数据库连接信息则通过环境变量传递到Pod 里,然后定义一个Service,并且通过NodePort 方式暴露到集群外供用户访问,即可完成这个Java应用的容器化改造工作。

本文选自 《Kubernetes权威指南:企业级容器云实战》一书,电子工业出版社9月出版。本书通过全新的视角,针对容器云领域现下的热点和技术难点,给出了基于Kubernetes的企业级容器云落地指南,为企业传统IT转型和业务上云提供助力。

95d720cb4419ef3bace850f2c0259918e92b2851
图书详情:https://item.jd.com/12420042.html
相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
4月前
|
人工智能 算法 Java
Java与AI驱动区块链:构建智能合约与去中心化AI应用
区块链技术和人工智能的融合正在开创去中心化智能应用的新纪元。本文深入探讨如何使用Java构建AI驱动的区块链应用,涵盖智能合约开发、去中心化AI模型训练与推理、数据隐私保护以及通证经济激励等核心主题。我们将完整展示从区块链基础集成、智能合约编写、AI模型上链到去中心化应用(DApp)开发的全流程,为构建下一代可信、透明的智能去中心化系统提供完整技术方案。
373 3
|
6月前
|
运维 监控 数据可视化
小白也能部署应用,3个免费的容器化部署工具测评
本文对比了三款容器化部署工具:Docker Compose、Portainer 和 Websoft9。Docker Compose 适合开发者编排多容器应用,Portainer 提供图形化管理界面,而 Websoft9 则面向中小企业和非技术人员,提供一键部署与全流程运维支持,真正实现“开箱即用”。三款工具各有定位,Websoft9 更贴近大众用户需求。
小白也能部署应用,3个免费的容器化部署工具测评
|
6月前
|
存储 数据采集 搜索推荐
Java 大视界 -- Java 大数据在智慧文旅旅游景区游客情感分析与服务改进中的应用实践(226)
本篇文章探讨了 Java 大数据在智慧文旅景区中的创新应用,重点分析了如何通过数据采集、情感分析与可视化等技术,挖掘游客情感需求,进而优化景区服务。文章结合实际案例,展示了 Java 在数据处理与智能推荐等方面的强大能力,为文旅行业的智慧化升级提供了可行路径。
Java 大视界 -- Java 大数据在智慧文旅旅游景区游客情感分析与服务改进中的应用实践(226)
|
6月前
|
机器学习/深度学习 数据采集 数据可视化
Java 大视界 -- 基于 Java 的大数据可视化在城市空气质量监测与污染溯源中的应用(216)
本文探讨Java大数据可视化在城市空气质量监测与污染溯源中的创新应用,结合多源数据采集、实时分析与GIS技术,助力环保决策,提升城市空气质量管理水平。
Java 大视界 -- 基于 Java 的大数据可视化在城市空气质量监测与污染溯源中的应用(216)
|
6月前
|
存储 监控 数据可视化
Java 大视界 -- 基于 Java 的大数据可视化在企业生产运营监控与决策支持中的应用(228)
本文探讨了基于 Java 的大数据可视化技术在企业生产运营监控与决策支持中的关键应用。面对数据爆炸、信息孤岛和实时性不足等挑战,Java 通过高效数据采集、清洗与可视化引擎,助力企业构建实时监控与智能决策系统,显著提升运营效率与竞争力。
|
6月前
|
Java 大数据 数据处理
Java 大视界 -- 基于 Java 的大数据实时数据处理在工业互联网设备协同制造中的应用与挑战(222)
本文探讨了基于 Java 的大数据实时数据处理在工业互联网设备协同制造中的应用与挑战。文章分析了传统制造模式的局限性,介绍了工业互联网带来的机遇,并结合实际案例展示了 Java 在多源数据采集、实时处理及设备协同优化中的关键技术应用。同时,也深入讨论了数据安全、技术架构等挑战及应对策略。
|
6月前
|
数据采集 搜索推荐 Java
Java 大视界 -- Java 大数据在智能教育虚拟学习环境构建与用户体验优化中的应用(221)
本文探讨 Java 大数据在智能教育虚拟学习环境中的应用,涵盖多源数据采集、个性化推荐、实时互动优化等核心技术,结合实际案例分析其在提升学习体验与教学质量中的成效,并展望未来发展方向与技术挑战。
|
4月前
|
监控 Kubernetes 安全
还没搞懂Docker? Docker容器技术实战指南 ! 从入门到企业级应用 !
蒋星熠Jaxonic,技术探索者,以代码为笔,在二进制星河中书写极客诗篇。专注Docker与容器化实践,分享从入门到企业级应用的深度经验,助力开发者乘风破浪,驶向云原生新世界。
还没搞懂Docker? Docker容器技术实战指南 ! 从入门到企业级应用 !
|
4月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
291 8
|
5月前
|
人工智能 Java API
Java与大模型集成实战:构建智能Java应用的新范式
随着大型语言模型(LLM)的API化,将其强大的自然语言处理能力集成到现有Java应用中已成为提升应用智能水平的关键路径。本文旨在为Java开发者提供一份实用的集成指南。我们将深入探讨如何使用Spring Boot 3框架,通过HTTP客户端与OpenAI GPT(或兼容API)进行高效、安全的交互。内容涵盖项目依赖配置、异步非阻塞的API调用、请求与响应的结构化处理、异常管理以及一些面向生产环境的最佳实践,并附带完整的代码示例,助您快速将AI能力融入Java生态。
869 12

相关产品

  • 容器服务Kubernetes版
  • 推荐镜像

    更多