使用Oracle数据库、Helidon和Coherence构建Kubernetes容器,轻松又实用 — 第6部分:构建容器,享受部署的乐趣

2025/1/3 21:04:13

本文主要是介绍使用Oracle数据库、Helidon和Coherence构建Kubernetes容器,轻松又实用 — 第6部分:构建容器,享受部署的乐趣,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

现在我们的应用已经跑起来了,我们最终希望把它部署到Kubernetes集群上。但是在那之前,我们得先构建镜像。

咱们开始吧。

构建容器图像 — Coherence 图像

记得,这个待办事项应用包括三个部分:

前端和后端都是无状态的微服务,而Coherence则是有状态的。我们必须分别为它们构建容器镜像。我们先从构建Coherence的镜像开始。

但在构建镜像之前,我们必须改变配置Hibernate的模式。这是因为Hibernate配置文件包含了数据库的用户名称和密码,所以我们绝对不想将这些信息硬编码到镜像中。相反,在部署到Kubernetes时,我们最终希望使用Kubernetes Secret并将其挂载到pod的卷。至于钱包文件,我们希望使用Oracle Database Operator来为我们获取它,并将Hibernate配置文件的位置作为参数传递给程序。

首先,修改 coherence-cache-config.xml 并在 Hibernate CacheStore 的 init-param 中添加以下内容(除了 entityname 参数以外):

                        <cachestore-scheme>  
                            <class-scheme>  
                                <class-name>  
                                    com.oracle.coherence.hibernate.cachestore.HibernateCacheStore  
                                </class-name>  
                                <init-params>  
                                    <init-param>  
                                        <param-type>java.lang.String</param-type>  
                                        <param-value>{entityname}</param-value>  
                                    </init-param>  
                                    <init-param>  
                                        <param-name>java.lang.String</param-name>  
                                        <param-value>${coherence.hibernate.config hibernate.cfg.xml}</param-value>  
                                    </init-param>  
                                </init-params>  
                            </class-scheme>  
                        </cachestore-scheme>

我们现在可以将 coherence.hibernate.config 作为系统属性来使用,以设置 Hibernate 配置文件的位置,不管是本地运行还是构建容器镜像时。

接下来,创建一个Dockerfile用于构建Coherence镜像。

    # 第一阶段,构建应用程序
    FROM container-registry.oracle.com/java/jdk-no-fee-term:21 as build  

    # 安装 Maven
    WORKDIR /usr/share  
    RUN set -x && \  
        curl -O https://archive.apache.org/dist/maven/maven-3/3.8.4/binaries/apache-maven-3.8.4-bin.tar.gz && \  
        tar -xvf apache-maven-*-bin.tar.gz  && \  
        rm apache-maven-*-bin.tar.gz && \  
        mv apache-maven-* maven && \  
        ln -s /usr/share/maven/bin/mvn /bin/  

    WORKDIR /helidon  

    # 创建一个缓存本地仓库中'Maven World'的初始层。
    # 增量 Docker 构建在 pom.xml 更新之前会从这里开始。
    ADD coherence/pom.xml .  
    RUN mvn package -Dmaven.test.skip  

    # 进行 Maven 构建!
    # 增量 Docker 构建在你修改源代码时会从这里继续。
    ADD coherence coherence  
    RUN mvn -f coherence/pom.xml clean package -DskipTests  

    RUN echo "done!"  

    # 第二阶段,构建运行时镜像
    FROM container-registry.oracle.com/java/jdk-no-fee-term:21  
    WORKDIR /helidon  

    # 复制第一阶段构建的二进制文件
    COPY --from=build /helidon/coherence/target/coherence.jar ./  
    COPY --from=build /helidon/coherence/target/libs ./libs  

    HEALTHCHECK  --start-period=10s --interval=30s \  
        CMD ["java", \  
        "-cp", "/helidon/coherence.jar", \  
        "com.tangosol.util.HealthCheckClient", \  
        "http://127.0.0.1:6676/ready", \  
        "||", "exit", "1"]  

    # 设置环境变量
    # 默认使用 POF
    ENV COHERENCE_POF_ENABLED=true  

    ENV COHERENCE_SERIALIZER=pof  
    # 设置健康检查端口为固定值(与上面的命令相对应)
    ENV COHERENCE_HEALTH_HTTP_PORT=6676  
    # 启用 Coherence 指标
    ENV COHERENCE_METRICS_HTTP_ENABLED=true  
    # 将日志级别设置为调试
    ENV COHERENCE_LOG_LEVEL=9  

    CMD ["java", "-Dcoherence.grpc.server.port=1408", "-Dcoherence.hibernate.config=/hibernate/hibernate.cfg.xml", "-jar", "coherence.jar"]  

    EXPOSE 1408  

    EXPOSE 9612

我们现在可以动手构建和测试容器镜像了。

使用 `docker buildx build` 命令构建镜像,参数 `--no-cache` 表示不使用缓存,`--platform=linux/amd64` 表示目标平台为 Linux AMD64,`-t coherence` 指定镜像名称为 `coherence`,`-f docker/Dockerfile.coherence` 指定 Dockerfile 的路径。

我们现在就用刚才构建的容器来运行Coherence。

    # 导出 HIBERNATE_CFG_XML 和 WALLET 环境变量
    export HIBERNATE_CFG_XML=/path/to/hibernate.cfg.xml  
    export WALLET=/path/to/extracted/wallet  

    # 使用 Docker 运行容器,挂载所需文件路径并启动容器
    docker run --rm -it -v $HIBERNATE_CFG_XML:/hibernate/hibernate.cfg.xml -v $WALLET:/wallets/task_db coherence

我们现在可以看到Coherence开始启动了。

构建后端容器镜像

我们现在来构建后端容器镜像。回想一下,后端模块依赖于Coherence模块这一点。创建后端容器镜像的Dockerfile文件。

    # 第一阶段,构建应用  
    FROM container-registry.oracle.com/java/jdk-no-fee-term:21 as build  

    # 安装 Maven 模块构建工具  
    WORKDIR /usr/share  
    RUN set -x && \  
        curl -O https://archive.apache.org/dist/maven/maven-3/3.8.4/binaries/apache-maven-3.8.4-bin.tar.gz && \  
        tar -xvf apache-maven-*-bin.tar.gz  && \  
        rm apache-maven-*-bin.tar.gz && \  
        mv apache-maven-* maven && \  
        ln -s /usr/share/maven/bin/mvn /bin/  

    WORKDIR /helidon  

    ADD coherence coherence  
    RUN mvn -f coherence/pom.xml install -DskipTests  
    ADD backend backend  
    RUN mvn -f backend/pom.xml clean package -DskipTests  

    RUN echo "完成!"  

    # 第二阶段,构建运行时镜像环境  
    FROM container-registry.oracle.com/java/jdk-no-fee-term:21  
    WORKDIR /helidon  

    # 从第一阶段复制编译后的二进制文件  
    COPY --from=build /helidon/backend/target/backend.jar ./  
    COPY --from=build /helidon/backend/target/libs ./libs  

    设置环境变量 COHERENCE_CLUSTER=todo  

    CMD ["java", "-Dcoherence.pof.enabled=true", "-Dcoherence.hibernate.config=/hibernate/hibernate.cfg.xml", "-jar", "backend.jar"]  

    EXPOSE 8080

我们现在可以按照同样的方法来构建和测试这个图像了。

使用 Docker 构建一个名为 coherence 的镜像:

docker build -t coherence .  

运行并挂载指定目录的 Docker 容器:

docker run --rm -it -v $HIBERNATE_CFG_XML:/hibernate/hibernate.cfg.xml -v $WALLET:/wallets/task_db backend

请注意,我们使用了Hibernate配置文件和数据库凭证作为参数。这是因为我们希望在启动时将现有数据预载入缓存。

预加载数据(通过Coherence CacheLoader)

处理数据库的一致性涉及两个概念,

  • 一个 CacheStore,如我们上面提到的 HibernateCacheStore,它把数据写入数据库。
  • 一个 CacheLoader 使 Coherence 集群能够从数据库加载现有数据到缓存。
    import java.io.File;  
    import java.util.Collection;  
    导入 com.oracle.coherence.hibernate.cachestore.HibernateCacheLoader;  
    导入 org.hibernate.Session;  
    导入 org.hibernate.query.Query;
public class CachePreloader  
        extends HibernateCacheLoader {    // 初始化缓存预加载器
        public CachePreloader(String entity) {  
            super(entity, new File(System.getProperty("coherence.hibernate.config")));  
        }    
        public Collection<String> getAllKeys() {  
            ensureInitialized();  // 确保初始化
            Session session = openSession();  // 打开会话
            try {  
                Query<String> query = session.createQuery("SELECT e.id FROM " + getEntityName() + " e", String.class);  // 创建查询
                return query.list();  // 返回列表
            }  
            finally {  
                closeSession(session);  // 关闭会话
            }  
        }  
    }

并且添加一个方便的 REST API 以便调用它

    @GET  
    @Path("/preload")  
    @Produces(APPLICATION_JSON)  
    public Response preload() {  
        Collection<String> keys = new CachePreloader("todo.Task").getAllKeys();  
        String message = "预加载数据,找到键共=" + keys.size() + ".";  
        LOG.log(INFO, message);  
        svc.preloadTasks(keys);
返回 Response.ok(message + "\n").build();  

你现在可以通过调用这个预加载方法来提前加载数据:

```preload()


运行此命令来预加载后端数据
curl http://localhost:8080/api/backend/preload

如果你的数据库里已经有数据,如下所示:

正在预加载数据,找到的键值为11。

## 构建容器镜像文件 — 前端容器镜像

在开发的不同阶段,我们处于不同的时间点。有些开发者希望能够在本地进行开发和测试。最终我们希望能够测试整个系统。但在那之前,我们如何才能不用频繁修改代码和配置来进行测试呢?Helidon 提供了[配置文件](https://helidon.io/docs/v4/se/config/config-profiles),让你可以预设每个环境的配置。例如,在本地开发时,我们最初可能只想使用 jar 包和容器。创建一个名为 application-local 的文件,并设置如下配置:
services:  
  # 后端服务的端点地址
  backend.endpoint: "http://localhost:8080"
我们也可以为本地容器环境创建一个类似的。
services:  
  backend.endpoint: "http://host.docker.internal:8080"
对于 Kubernetes 来说:

服务:
后端端点: "http://backend:8080"

我们现在可以挑选要运行的配置。比如说我们要用本地配置。

运行带有特定配置的Java命令
java -Dconfig.profile=local -Xmx512m -Xms512m -jar target/frontend.jar

如果我们想本地运行容器呢?别担心,我们已经搞定了。
docker run --rm -it -v -e CONFIG_PROFILE='docker' $HIBERNATE_CFG_XML:/hibernate/hibernate.cfg.xml -v $WALLET:/wallets/task_db frontend
这里使用了 `docker` 命令来运行一个容器。命令中的 `-rm` 参数表示容器在停止后会被自动删除,`-it` 参数则为容器提供了交互式的终端。`-v` 参数用来挂载宿主机的文件或目录到容器内部,而 `-e` 参数设置环境变量 `CONFIG_PROFILE` 的值为 `'docker'`。最后,`$HIBERNATE_CFG_XML` 和 `$WALLET` 分别指向了宿主机上的文件路径,这些路径会被映射到容器内的指定路径中。`frontend` 则指定了要运行的镜像名称。

在我们准备在 Kubernetes 集群中运行时,只需将配置设置成环境变量,比如:
比如可以设置为环境变量。
kind: Deployment  
apiVersion: apps/v1  
metadata:  
  name: 前端  
  namespace: todo  
spec:  
  副本数: 1  
  选择器:  
    匹配标签:  
      app: 前端  
  模板:  
    metadata:  
      标签:  
        app: 前端  
        version: v1  
    spec:  
      容器:  
        - 名称: 前端  
          image: ocir.<region>.oci.oraclecloud.com/<tenancy_namespace>/todo/frontend:v3  
          环境变量:  
            - 名称: "CONFIG_PROFILE"  
              值: "k8s"  
          拉取策略: Always  
          端口:  
            - 容器端口: 7001  
      镜像拉取密钥:  
        - 名称: ocir-secret

一旦配置好基本设置,只需根据不同的环境调整这些设置的位置即可。

## 概述

在这篇文章中,我们简要但必要地讨论了如何在 Kubernetes 集群中构建容器镜像。我们探讨了如何安全地在各个开发阶段中包含 Hibernate 配置,以及如何根据 Helidon 的配置文件来调整配置。

希望你喜欢这篇文章,敬请期待下一期。

我想感谢我的同事 Tim Middleton、Sherwood Zern 和(罗曼·格雷库尔)Romain Grecourt,他们帮助了这篇文章的完成。


这篇关于使用Oracle数据库、Helidon和Coherence构建Kubernetes容器,轻松又实用 — 第6部分:构建容器,享受部署的乐趣的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程