如何使用构建包来构建 Java 容器

如何使用构建包来构建 Java 容器

您是否仍然编写冗长的 Dockerfile 来描述构建容器映像所需的每个步骤?然后,构建包来拯救你!开发人员只需向他们提供应用程序,构建包发挥其魔力,并将其变成一个功能齐全的容器,准备部署在任何云上。

但魔术究竟是如何发生的呢?如果生成的容器性能不符合业务需求,该怎么办?

本文将深入探讨构建包的幕后情况,了解它们的运行方式,并提供有关优化默认设置以达到更好的性能结果的提示。

什么是构建包?

构建包将应用程序源代码转换为可运行的生产就绪容器映像。构建包为开发人员节省了时间和精力,因为无需配置映像并通过 Dockerfile 手动管理依赖项。

Heroku是2011年第一家开发构建包的公司。从那时起,许多其他公司(Cloud Foundry,Google等)都采用了这一概念。2018 年,Heroku 与 Pivotal 合作创建了云原生构建包项目,该项目涵盖了容器映像的现代标准和规范,例如 OCI 格式。该项目是云原生计算基金会(CNCF)的一部分。

我们将在本文中使用的Paketo构建包是一个由Cloud Foundry支持并由VMware赞助的开源项目。它实现了云原生构建包规范,并支持最流行的语言,包括Java。使用 Paketo 构建包生成的容器可以在任何云上运行。

构建包的工作原理

构建包分两个阶段运行:检测和构建。

  1. 检测阶段

在检测阶段,构建包会分析源代码,寻找是否应将其应用于应用程序的指标。换句话说,根据源代码测试一组构建包,并选择第一组被认为适合代码来构建应用程序。在构建包检测到必要的指标后,它会返回创建映像所需的协定,并进入构建阶段。

  1. 构建阶段

在构建阶段,构建包转换代码库,满足之前编写的合同要求。它提供构建时和运行时环境,下载必要的依赖项,根据需要编译代码,并设置入口点和启动脚本。

建设者

生成器是构建容器映像所需的组件组合:

  • 构建包,一组可执行文件,用于分析代码并提供构建和运行应用程序的计划;
  • 堆栈由两个映像组成:构建映像和运行映像。生成映像提供构建环境(执行构建包的容器化环境),运行映像在运行时为应用程序映像提供环境;
  • 生命周期管理构建包执行,并将生成的工件组装到最终映像中。

因此,一个构建器可以自动检测和构建不同的应用程序。

构建包提供了多种 JVM — 如何选择?

Paketo buildpacks 默认使用 Liberica JVM。Liberica是一个基于HotSpot的Java运行时,由OpenJDK的主要贡献者支持,并由Spring推荐。它为所有LTS版本(8,11,17)和当前版本以及Liberica Native Image Kit(NIK)提供JDK和JRE,这是一个基于GraalVM的实用程序,用于将基于JVM的应用程序转换为本机映像并加速启动。当您需要避免在 AWS 中冷启动时,本机映像非常有用。

但是构建包支持多个Java发行版,可以使用这些发行版代替默认的JVM:

  • 收养
  • 阿里巴巴龙井
  • 亚马逊科雷托
  • 祖鲁祖鲁
  • 贝尔软件利比里亚(默认)
  • Eclipse OpenJ9
  • 格拉尔虚拟机
  • 甲骨文 JDK
  • 微软OpenJDK
  • 树液机

如果要切换 JVM,则必须记住几个细微差别:

  • Alibaba Dragonwell,Amazon Corretto,GraalVM,Oracle JDK和Microsoft OpenJDK仅提供JDK。生成的容器将是基于 JRE 的容器的两倍;
  • Adoptium 为 Java 8 和 11 提供 JDK 和 JRE,仅为 Java 16+ 提供 JDK;
  • Oracle JDK 仅提供 Java 17。

另一个重要的考虑因素是:构建包有助于和加速部署,但是如果您对容器性能不满意或寻求改进基本KPI(吞吐量,延迟或内存消耗),则必须自己调整JVM。有关更多详细信息,请参阅下面的配置 JVM 部分。

例如,基于OpenJ9 JVM的Eclipse OpenJ9在某些情况下可能表现出比HotSpot更好的性能,因为HotSpot带有默认设置,并且OpenJ9已经调整。添加一些简单的参数将为您提供与热点相同或更出色的性能。

如何使用Paketo构建包

让我们使用 Paketo 构建包构建一个 Java 容器。

首先,确保 Docker 已启动并运行。如果没有,请按照这些说明为您的系统安装 Docker 桌面。

下一步是安装 pack CLI,这是一个由云原生构建包维护的命令行界面,可用于处理构建包。按照指南完成适用于您的平台的安装(支持 macOS、Linux 和 Windows)。包是几个可用的工具之一。例如,Spring Boot 开发人员可以研究 Spring Boot Maven 插件或 Spring Boot Gradle 插件。

我们将使用 Paketo 示例应用程序,因此运行以下命令:

git clone  && cd samples

Alternatively, utilize your own demo app.

Make Paketo Base builder the default builder:

pack config default-builder paketobuildpacks/builder:base

To build an image from source with Maven, run

pack build samples/java \\

 --path java/maven --env BP_JVM_VERSION=17

Java example images should return {"status":"UP"} from the actuator health endpoint:

docker run --rm --tty --publish 8080:8080 samples/java

curl -s  | jq .

It is also possible to build an image from a compiled artifact. The following archive formats are supported: executable JAR, WAR, or distribution ZIP.

To compile an executable JAR and build an image using pack, run

cd java/maven

./mvnw package

pack build samples/java \\

   --path ./target/demo-0.0.1-SNAPSHOT.jar

提取软件物料清单

软件供应链由用于开发和运行应用程序的众多库、工具和流程组成。通常很难跟踪软件产品中所有软件组件的来源,这增加了嵌套漏洞的风险。软件物料清单 (SBOM) 列出了用于构建软件项目的所有库依赖项。它类似于传统的物料清单,它总结了制造产品所需的原材料、零件、组件和确切数量。

SBOM 使开发人员能够监控软件组件的版本,及时集成安全补丁,并将易受攻击的库拒之门外。

构建包还使开发人员能够查看其映像的 SBOM。运行以下命令,为之前构建的示例/java 映像提取 SBOM:

pack sbom download samples/java --output-dir /tmp/samples-java-sbom

之后,您可以浏览该文件夹。SBOM 以 JSON 格式呈现。若要列出文件夹中的所有 .json 文件,请运行以下命令:

find /tmp/samples-java-sbom -name "*.json"

/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_executable-jar/sbom.cdx.json

/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_executable-jar/sbom.syft.json

/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_spring-boot/helper/sbom.syft.json

/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_spring-boot/spring-cloud-bindings/sbom.syft.json

/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_bellsoft-liberica/jre/sbom.syft.json

/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_bellsoft-liberica/helper/sbom.syft.json

/tmp/samples-java-sbom/layers/sbom/launch/sbom.legacy.json

/tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_ca-certificates/helper/sbom.syft.json

现在,您可以使用任何文本编辑器打开文件。例如,如果您安装了Visual Studio Code,请运行以下命令:

code /tmp/samples-java-sbom/layers/sbom/launch/paketo-buildpacks_bellsoft-liberica/jre/sbom.syft.json

您将获得以下输出:

{

   "Artifacts": [

       {

           "ID": "1f2d01eeb13b5894",

           "Name": "BellSoft Liberica JRE",

           "Version": "17.0.6",

           "Type": "UnknownPackage",

           "FoundBy": "libpak",

           "Locations": [

               {

                   "Path": "buildpack.toml"

               }

           ],

           "Licenses": [

               "GPL-2.0 WITH Classpath-exception-2.0"

           ],

           "Language": "",

           "CPEs": [

               "cpe:2.3:a:oracle:jre:17.0.6:*:*:*:*:*:*:*"

           ],

           "PURL": "pkg:generic/[email protected]?arch=amd64"

       }

   ],

   "Source": {

       "Type": "directory",

       "Target": "/layers/paketo-buildpacks_bellsoft-liberica/jre"

   },

   "Descriptor": {

       "Name": "syft",

       "Version": "0.32.0"

   },

   "Schema": {

       "Version": "1.1.0",

       "URL": ""

   }

}

配置 JVM

BellSoft Liberica Buildpack 提供了构建包中支持的 Java 版本的最新补丁更新。默认情况下,构建包使用最新的 LTS 版本。如果要使用其他 Java 版本,请使用 BP_JVM_VERSION 环境变量。例如,BP_JVM_VERSION=11 将安装最新版本的 Liberica JDK 和 JRE 11。

此外,您还可以更改 JDK 类型。构建包在构建时使用 JDK,在运行时使用 JRE。指定 BP_JVM_TYPE=JDK 选项将强制构建包在运行时使用 JDK。

BP_JVM_JLINK_ENABLED选项使用 Java 9+ 运行 jlink 工具,从而删除自定义 JRE。

如果将 Java 应用程序部署到应用程序服务器,则构建包默认使用 Apache Tomcat。您可以选择其他服务器(TomEE 或 Open Liberty)。例如,运行以下命令切换到 TomEE:

pack build samples/war -e BP_JAVA_APP_SERVER=tomee

您可以使用JAVA_TOOL_OPTIONS环境变量在运行时配置 JVM。例如,您可以配置垃圾回收、线程数、内存限制等,以达到满足特定需求的最佳性能:

docker run --rm --tty \\

  --env JAVA_TOOL_OPTIONS='-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=40' \\

  --env BPL_JVM_THREAD_COUNT=100 \\

  samples/java

结论

如您所见,构建包是出色的自动化工具,可以节省开发人员的时间。但如果你明智地使用它们会有所帮助,否则你就有可能把一只猫放在麻袋里。我们的一般建议是定义 KPI 并相应地调整 JVM 设置。

如果您对生成的图像的大小不满意,该怎么办?毕竟,无法更改构建包使用的基本操作系统映像。一种选择是迁移到本机映像以优化资源消耗。另一种选择是手动构建容器并切换到较小的操作系统映像,例如Alpine或Alpaquita Linux。后者支持两种libc实现(优化的musl和glibc),并具有许多性能和安全性增强功能。

你可能感兴趣的:(java,云原生,分布式)