Java 开发人员和 DevOps 专业人员长期以来一直在努力实现企业 Java 应用程序部署的自动化。这些应用程序的复杂性通常意味着每次在 DEV/TEST 环境中部署应用程序时都必须重新配置应用程序依赖项和外部集成。
许多解决方案为应用程序部署宣传“一次建模,随处部署”的信息。然而实际上,总是存在一些复杂的问题,例如,很难在本地 vSphere 虚拟环境和 AWS 环境中重复使用应用程序模板。
然而,最近,Docker 容器普及了将应用程序组件打包到 Linux 容器中的想法,只要安装了 Docker 引擎,这些容器就可以完全相同地部署在任何 Linux 主机上。
不幸的是,容器化企业 Java 应用程序仍然是一个挑战,主要是因为现有的应用程序组合框架没有解决复杂的依赖关系、外部集成或自动扩展工作流的配置。此外,容器的短暂设计意味着开发人员必须启动新容器并在每次版本更新时重新创建复杂的依赖项和外部集成。
DCHQ 提供托管和本地版本,解决了所有这些挑战并通过先进的应用程序组合框架简化了企业 Java 应用程序的容器化,该框架使用跨图像环境变量绑定扩展 Docker Compose,可扩展的 BASH 脚本插件可以在请求时或配置后调用,以及应用程序集群以实现跨多个主机或区域的高可用性,并支持自动缩放。
供应应用程序后,用户可以监控正在运行的容器的 CPU、内存和 I/O,获取通知和警报,并执行第 2 天的操作,例如计划备份、使用 BASH 脚本插件的容器更新和扩展进出。此外,使用 Jenkins 促进持续交付的开箱即用工作流允许开发人员刷新正在运行的应用程序的 Java WAR 文件,而不会中断现有的依赖项和集成。
在这篇博客中,我们将介绍一个名为 Movie Store 的 Java 应用程序的端到端自动化,该应用程序部署在四个不同的容器化应用程序堆栈上:
- Nginx(用于负载平衡)、集群 Tomcat 和 MongoDB(作为数据库)
- Nginx(用于负载平衡)、集群 JBoss 和 MongoDB(作为数据库)
- Nginx(用于负载平衡)、集群 Jetty 和 MongoDB(作为数据库)
- Nginx(用于负载平衡)、集群 GlassFish 和 MongoDB(作为数据库)
同一个 Java WAR 文件将部署在四个不同的应用程序服务器上。 DCHQ 不仅实现了应用程序部署的自动化,而且还与 12 种不同的云集成,通过软件定义的网络自动配置和自动扩展集群。我们将涵盖:
- 构建可在任何地方运行的任何 Linux 主机上重复使用的应用程序模板
- 在任何云上配置和自动扩展底层基础设施(本博客中以 Rackspace 为例)
- 在 Rackspace 集群上部署基于 Java 的多层电影商店应用程序
- 监控正在运行的容器的 CPU、内存和 I/O
- 使用 Jenkins 启用持续交付工作流以在触发构建时更新正在运行的应用程序的 WAR 文件
- 扩展应用服务器集群以进行可扩展性测试
在 Tomcat、JBoss、Jetty 和 GlassFish 上为基于 Java 的电影商店应用程序构建应用程序模板
一旦登录到 DCHQ(托管的 DCHQ.io 或本地版本),用户可以导航到“管理”>“模板”,然后单击“+”按钮创建一个新的 Docker Compose 模板。
我们使用来自 Docker Hub 的官方镜像为同一个 Movie Store 应用程序创建了四个应用程序模板——但用于四个不同的应用程序服务器。
- 3 层 MovieStore(Nginx - Tomcat - Mongo)
- 3 层 MovieStore(Nginx-JBoss-Mongo)
- 3 层 MovieStore(Nginx - Jetty - Mongo)
- 3 层 MovieStore(Nginx - GlassFish - Mongo)
在所有四个模板中,您会注意到 Nginx 正在调用 BASH 脚本插件以动态(或在请求时)在 default.conf 文件中添加应用程序服务器的容器 IP。应用程序服务器(Tomcat、JBoss、Jetty 和 GlassFish)也调用 BASH 脚本插件从外部 URL 部署电影商店 Java WAR 文件 Tomcat、JBoss 和 Jetty 调用完全相同的插件——除了 WAR文件正在不同的目录中部署:
- Tomcat – dir=/usr/local/tomcat/webapps/ROOT.war
- JBoss – dir=/opt/jboss/wildfly/standalone/deployments/ROOT.war
- 码头 - dir=/var/lib/jetty/webapps/ROOT.war
GlassFish 正在调用另一个插件,该插件使用 asadmin 命令在默认服务器上部署应用程序。您会注意到 cluster_size 参数允许您指定要启动的容器数量(具有相同的应用程序依赖性)。主机参数允许您指定要用于容器部署的主机。这样,您可以确保跨不同主机(或区域)的应用程序服务器集群的高可用性,并且您可以遵守关联规则以确保数据库在单独的主机上运行,例如。以下是主机参数支持的值:
- host1、host2、host3 等——在数据中心(或集群)中随机选择一个主机进行容器部署
- <IP Address 1, IP Address 2, etc.> -- 允许用户指定用于容器部署的实际 IP 地址
- <Hostname 1, Hostname 2, etc.> -- 允许用户指定用于容器部署的实际主机名
- 通配符(例如“db-*”或“app-srv-*”)——指定在主机名中使用的通配符
此外,用户可以通过引用另一个图像的环境变量来创建跨图像环境变量绑定。在这种情况下,我们做了几个绑定——包括 mongo.host={{MongoDB|container_ip}}——其中数据库容器 IP 在请求时动态解析,用于确保应用程序服务器可以与数据库。以下是支持的环境变量值列表:
- {{字母数字 | 8}} – 创建一个随机的 8 字符字母数字字符串。这对于创建随机密码最有用。
- {{<图像名称> | ip}} – 允许您输入容器的主机 IP 地址作为环境变量的值。这对于允许中间件层与数据库建立连接最有用。
- {{<图像名称> | container_ip}} – 允许您输入容器的内部 IP 作为环境变量的值。这对于允许中间件层与数据库建立安全连接(不暴露数据库端口)最为有用。
- {{<图像名称> | port _<Port Number>}} – 允许您输入容器的端口号作为环境变量的值。这对于允许中间件层与数据库建立连接最有用。在这种情况下,指定的端口号需要是内部端口号——即不是分配给容器的外部端口。例如,{{PostgreSQL | port_5432}} 将被转换为允许中间件层与数据库建立连接的实际外部端口。
- {{<图像名称> | <Environment Variable Name>}} – 允许您将图像环境变量的值输入到另一个图像的环境变量中。这里的用例是无穷无尽的——因为大多数多层应用程序都具有跨图像依赖性。
在任何云上配置和自动扩展底层基础设施
保存应用程序后,用户可以注册云提供商以在 12 个不同的云端点上自动配置和自动扩展集群,包括 OpenStack、CloudStack、Amazon Web Services、Rackspace、Microsoft Azure、DigitalOcean、HP Public Cloud、 IBM SoftLayer、Google Compute Engine 等。首先,用户可以通过导航到 Manage > Repo & Cloud Provider 然后单击 + 按钮选择 Rackspace 来为 Rackspace(例如)注册一个 Cloud Provider。需要提供 Rackspace API 密钥——可以从 Rackspace 云控制面板的“帐户设置”部分检索。
然后,用户可以创建一个具有自动扩展策略的集群,以自动启动新的云服务器。这可以通过导航到“管理”>“集群”页面然后单击 + 按钮来完成。您可以选择基于容量的放置策略,然后将 Weave 作为网络层,以促进集群内多个主机之间安全、受密码保护的跨容器通信。此示例中的自动缩放策略将 VM(或云服务器)的最大数量设置为 10。
用户现在可以通过导航到“管理”>“裸机服务器和虚拟机”,然后单击“+”按钮选择 Rackspace,在新创建的集群上配置多个云服务器。选择云提供商后,用户可以选择所需的区域、大小和图像。可以在新的云服务器上打开端口(例如,Docker 为 32000-59000,Weave 为 6783,RabbitMQ 为 5672)。然后选择数据中心(或集群)并指定云服务器的数量。
在 Rackspace 集群上部署基于 Java 的多层电影商店应用程序
一旦配置了云服务器,用户就可以在新的云服务器上部署基于 Docker 的多层 Java 应用程序。这可以通过导航到自助服务库然后单击自定义来请求多层应用程序来完成。用户可以选择环境标签(如 DEV 或 QE)和在单击运行之前创建的 Rackspace 集群。
监控正在运行的容器的 CPU、内存和 I/O 利用率
应用程序启动并运行后,我们的开发人员会监控正在运行的容器的 CPU、内存和 I/O,以便在这些指标超过预定义阈值时收到警报。当我们的开发人员执行功能和负载测试时,这尤其有用。用户可以执行历史监控分析并将问题关联到容器更新或构建部署。这可以通过单击正在运行的应用程序的“操作”菜单,然后单击“监视”来完成。可以选择自定义日期范围来查看历史 CPU、内存和 I/O。
使用 Jenkins 启用持续交付工作流以在触发构建时更新正在运行的应用程序的 WAR 文件
对于希望通过重建包含应用程序代码的 Docker 映像并在每次应用程序更新时启动新容器来遵循“不可变”容器模型的开发人员,DCHQ 提供了一个自动构建功能,允许开发人员从 Dockerfiles 或包含以下内容的私人 GitHub 项目自动创建 Docker 映像Dockerfiles。但是,许多开发人员可能希望使用最新的 Java WAR 文件来更新正在运行的应用程序服务器容器。为此,DCHQ 允许开发人员使用 Jenkins 实现持续交付工作流。这可以通过单击正在运行的应用程序的 Actions 菜单然后选择 Continuous Delivery 来完成。用户可以选择一个已经在 DCHQ 注册的 Jenkins 实例,Jenkins 上将生成最新 WAR 文件的实际作业,然后选择一个 BASH 脚本插件来获取此构建并将其部署到正在运行的应用程序服务器上。保存此策略后,每当触发构建时,DCHQ 都会从 Jenkins 获取最新的 WAR 文件,并将其部署到正在运行的应用程序服务器上。因此,开发人员将始终在 DEV/TEST 环境中的运行容器上部署最新的 Java WAR 文件。
横向扩展 Tomcat 应用服务器集群
如果正在运行的应用程序变得资源受限,用户可以扩展应用程序以满足不断增加的负载。此外,用户可以安排在工作时间扩展,例如在周末安排扩展。要将 Tomcat 服务器集群从 2 个扩展到 3 个,用户可以单击正在运行的应用程序的 Actions 菜单,然后选择 Scale Out。然后用户可以指定集群的新大小,然后单击立即运行。然后我们使用 BASH 插件更新 Nginx 的 default.conf 文件,以便它知道添加的新应用程序服务器。还可以安排 BASH 脚本插件以适应用例,例如以定义的频率清理日志或更新配置。应用程序时间线可用于跟踪对应用程序所做的每个更改以进行审核和诊断。
横向扩展完成后,用户可以执行 BASH 插件来更新 Nginx 的 default.conf 文件,以便它知道添加的新应用程序服务器。还可以安排 BASH 脚本插件以适应用例,例如以定义的频率清理日志或更新配置。要在正在运行的容器上执行插件,用户可以单击正在运行的应用程序的操作菜单,然后选择插件。然后用户可以选择负载均衡器 (Nginx) 容器,搜索需要执行的插件,使用切换按钮启用容器重启。此插件的默认参数将动态解析所有正在运行的 Tomcat 服务器的容器 IP,并将它们添加为 default.conf 文件的一部分。
应用程序时间线可用于跟踪对应用程序所做的每个更改以进行审核和诊断。这可以从正在运行的应用程序页面底部的可扩展菜单中访问。
当容器或主机关闭或主机或容器的 CPU 和内存利用率超过定义的阈值时,警报和通知可用。
结论
容器化企业 Java 应用程序仍然是一个挑战,主要是因为现有的应用程序组合框架没有解决复杂的依赖关系、外部集成或配置后自动扩展工作流。此外,容器的短暂设计意味着开发人员必须启动新容器并在每次版本更新时重新创建复杂的依赖项和外部集成。
DCHQ 提供托管和本地版本,解决了所有这些挑战,并通过先进的应用程序组合框架简化了企业 Java 应用程序的容器化,该框架促进了跨图像环境变量绑定,可扩展的 BASH 脚本插件可以在请求时间或后置备,以及应用程序集群,以实现跨多个主机或区域的高可用性,并支持自动缩放。
在
http://DCHQ.io
上免费注册
访问开箱即用的多层 Java 应用程序模板(包括 Tomcat、JBoss、GlassFish 和 Jetty 上的 Movie Store 应用程序)以及应用程序生命周期管理功能,如监控、容器更新、扩展/扩展和持续交付。
作者
Amjad Afanah
是 DCHQ 的创始人。他在应用程序部署自动化和系统管理方面拥有丰富的经验。 DCHQ 是
500 Startups
的一部分。