【问题标题】:Local Development Best Practices: Java, Docker, Kubernetes本地开发最佳实践:Java、Docker、Kubernetes
【发布时间】:2019-03-14 12:59:24
【问题描述】:

我正在尝试找出在使用 Kubernetes 在本地环境中或在开发代码时部署的 Docker 容器中使用 Java 的最终最佳实践。在理想状态下,Java 开发人员应该能够像 python/javascript 开发人员一样快速移动,但我很难匹配速度(甚至接近)。

目前,我有一个工作的、手动部署的 k8 集群。我的 Java Spring 项目是在手动运行构建命令(mvn clean install)之后由 maven 构建的,然后我运行一个脚本来制作图像,之后我运行一个脚本来运行 minkube(如果它尚未运行),最后我必须apply 一个部署清单文件(它将容器启动到 pod 中)。

我错过了什么:

  1. 所有这些都是手动完成的(在构建代码后自动构建映像并使用新映像更新 k8s 的过程有明显的空间)。
  2. 手动指定构建(python 在代码保存时重新启动。据我所知,在 java 世界中没有热重新加载)。
  3. 我还没有看到本地开发环境和云托管 k8 集群之间的集成。理想情况下,开发人员会在本地进行测试,直到他们准备好部署到云端。当它们准备就绪时,单击一个按钮并从远程注册表读取一个集群,该集群可以获取 docker 映像更改并重新加载,这将是非常棒的。

很遗憾,Skaffold,我很高兴使用的工具不适用于 Java。 Java 开发人员是否正在使用另一种工具来使他们的本地部署变得超级快速并与 DUCK 语言(py、js)竞争?

【问题讨论】:

标签: java docker kubernetes


【解决方案1】:

您可以使用 docker-maven-plugin 直接从 maven 构建 docker 映像。添加到您的pom.xml

<build>
  <plugins>
    ...
    <plugin>
      <groupId>com.spotify</groupId>
      <artifactId>docker-maven-plugin</artifactId>
      <version>VERSION GOES HERE</version>
      <configuration>
        <imageName>example</imageName>
        <dockerDirectory>docker</dockerDirectory>
        <resources>
           <resource>
             <targetPath>/</targetPath>
             <directory>${project.build.directory}</directory>
             <include>${project.build.finalName}.jar</include>
           </resource>
        </resources>
      </configuration>
    </plugin>
    ...
  </plugins>
</build>

我不确切地知道您的用例,但在您的开发机器中部署 k8 的集群可能是矫枉过正。你可以用Docker compose测试你的docker镜像

【讨论】:

  • 我同意 docker-compose 在本地运行当然更方便。话虽如此,docker-compose 有其难以解决的局限性。我在这里描绘了一个痛点:stackoverflow.com/questions/52378551/… 此外,我喜欢在本地运行与在云中运行相同的编排。这种模式让我能够以相同的方式理解一切(无论本地/云状态如何),并在部署策略出现在人们面前之前对其进行有效测试。
  • 我相信 Spotify 的 docker-maven-plugin 不再维护。我使用 Spotify 的 dockerfile-maven-plugin 和 fabric8 docker maven 插件指向我的 minikube 的 docker 实例,所以我不必在开发过程中推送到注册表。节省了我很多。
【解决方案2】:

我对您的开发工作流程的看法:

  • 就像 @Ortomala Lokni 提到的那样,使用 docker-maven-plugin 从您的 maven 构建中直接构建 docker 映像。
  • 您可以使用https://github.com/fabric8io/fabric8-maven-plugin 直接推送到kubernetes 集群。
  • 如果您的集群托管在云端,您的构建机器应该能够访问 k8s API 服务器。为此,您可能需要使用 SSH 隧道和Bastions,具体取决于您的云 k8s 集群的 API 服务器是否公开可用。
  • 查看 minikube 的本地 k8s 测试集群,even latest versions of docker for desktop 现在内置了一个简单的 k8s 服务器。
  • 没有使用过 Skaffold,但对文档的基本了解表明它也应该适用于您,因为它接管了监视代码、启动 docker 构建和部署到 k8s 的基本功能。这些功能在不同语言中保持不变。话虽如此,以上两个插件将构建 docker 镜像和部署到 k8s 集成到您的 maven 工作流程中。

您提到 python/js 速度很快,但请注意,即使是这些语言,基本步骤也保持不变,构建 docker 映像、推送到存储库、更新 k8s 部署。

热部署也适用于 Java,即使在 Eclipse 等基于 Spring Boot 的微服务中,您也可以使用 spring-dev-tools 进行实时重新加载和自动重启。 但是,我不知道有什么可以帮助您处理对 docker 容器的实时更改,我会要求您避开它,docker 容器应该是不可变的。

【讨论】:

    【解决方案3】:

    对不起,如果我迟到了,我会尽力为未来的读者提供答案,或者也许仍然给你!

    首先,docker build 和 deploy on kubernetes cluster 是你的软件供应链的两个完全不同的阶段,让我们把它们作为单独的话语来保存

    1. 构建过程应该已经自动化:如果您需要手动运行 mvn clean install,这意味着您正在失去 Docker 的优势之一:构建可重复、不可变的软件包,可以在任何地方交付。只需将 RUN mvn clean install 添加到您的 Dockerfile 中(是的,您之前需要将 maven 放入您的镜像中,但是周围有一些基础镜像可以为您完成这项工作)。现在你应该设置一个 CI 服务器,在每次存储库签入时构建和推送图像(我故意跳过任何质量门和管道工作流,它们由你来自动化)。部署也可以由 CI 服务器管理,主要有两种方法

    a) 创建一个包含所有 k8s 清单的配置存储库,并在每次推送时从您的 CI 服务器运行 kubectl apply

    b) 将配置与感兴趣的微服务一起放置,用提交哈希标记新构建的图像,并在管道结束时 kubectl apply env.yaml && kubectl set image myregistry.com/myimage:${commitHash }(请务必标记为“最新”并在您的部署规范中包含最新的标签,这有助于在删除并应用配置后重建当前情况)

    c) 使用 helm 图表进行部署。它与上一个类似,但您可以利用依赖管理和部署模板化的所有优势

    1. 热重载在您进行 tdd 开发时很好,但在代码即将交付时无用,无论是使用 node/python 微服务,您都不会使用它,因为一旦您的代码被容器化,您应该使用 AK47每个试图触及它的开发人员。这里真正重要的是自动化您的集成/交付/部署。在我的团队中,我们只需要打开并接受 PR,奇迹就会发生

    2. 您需要在笔记本电脑上的微服务之间进行一些调试/集成。我不会阻止这种做法,但必须以速度对生产力不那么重要的频率进行操作。但是如果你想这样做,你可以用 docker compose 构建一个“laptop”或“dev”环境,从注册表中提取你的依赖项(重现当前“在线”情况),然后用它自己构建你的微服务配置。另一种方法是使用 k8s 的端口转发功能来假装一个 pod 与您的本地机器连接,暴露一个众所周知的端口,但是如果有很多依赖项,那就很头疼了。第三种方法是使用像 https://www.telepresence.io/ 这样的工具,它承诺在本地运行一个 Pod,并通过一对代理双向连接到集群

    【讨论】:

      猜你喜欢
      • 2018-10-21
      • 2011-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-08
      相关资源
      最近更新 更多