本地开发最佳实践:Java、Docker、Kubernetes



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

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

我缺少的:

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

遗憾的是,Skafold这个我很乐意使用的工具无法与Java一起使用。Java开发人员是否正在使用另一种工具来使其本地部署速度极快,并与DUCK语言(py,js)竞争?

您可以使用docker-maven插件直接从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图像

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

  • 就像@Ortomala Lokni提到的那样,使用docker-maven-plugin从您的专业构建中构建直接的docker映像
  • 您可以使用https://github.com/fabric8io/fabric8-maven-plugin直接推送到kubernetes集群
  • 如果您的集群托管在云中,那么您的构建机器应该能够访问k8s API服务器。为此,您可能需要使用SSH隧道和堡垒,这取决于您的云k8集群的API服务器是否公开可用
  • 看看本地k8s测试集群的minikube,即使是最新版本的桌面docker现在也内置了一个简单的k8s服务器
  • 还没有使用过Skafold,但对文档的基本了解表明,它也应该适用于您,因为它接管了监视代码、启动docker构建和部署到k8s的基本功能。这些函数在不同语言中保持不变。已经说过,上面两个插件将构建docker镜像和部署到k8s集成到您的maven工作流中

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

此外,热部署也适用于Java,即使在eclipse之类的情况下,比如说,使用基于spring引导的微服务,您也可以使用spring开发工具进行实时重新加载和自动重启。然而,我不知道有什么能帮助你处理docker容器的实时更改,我想请你回避它,docker容器应该是不可变的。

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

首先,docker在kubernetes集群上的构建和部署是软件供应链的两个完全不同的阶段,让我们将它们作为单独的论述

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

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

b) 把config和感兴趣的微服务放在一起,用提交哈希标记新构建的映像,并在管道的末尾kubectl应用env.yaml&amp;kubectl set image myregistry.com/myimage:${commitHash}(只需确保标记为"最新",并在部署规范中包含最新标记,这有助于在删除和应用配置后重建当前情况)

c) 使用舵图进行部署。它与前面的类似,但您可以利用依赖关系管理和部署模板化的所有优势

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

  2. 您需要在笔记本电脑上的微服务之间进行一些调试/集成。我并不反对这种做法,但必须以速度对生产力不那么重要的频率进行。但如果你想这样做,你可以用docker compose构建一个"笔记本电脑"或"开发"环境,从注册表中提取你的依赖项(以再现当前的"在线"情况),然后用自己的配置构建你的微服务。另一种方法是使用端口转发k8s功能来假装pod与您的本地机器连接,从而暴露出一个众所周知的端口,但如果存在许多依赖关系,这将是一个令人头疼的问题。第三种方法是使用以下工具https://www.telepresence.io/它承诺在本地运行一个pod,并在两个方向上使用一对代理连接到集群

最新更新