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

9
我正在尝试找出在本地环境或开发代码时使用Java在Docker容器中部署Kubernetes的最佳实践。理想情况下,Java开发人员应该能够像Python/JavaScript开发人员一样快速移动,但是我很难达到这个速度(甚至接近都很困难)。
目前,我有一个手动部署的k8's集群。我的Java Spring项目在运行手动构建命令(mvn clean install)后由Maven构建,然后我运行一个脚本制作镜像,之后我运行一个脚本运行Minikube(如果它还没有运行),最后我必须应用部署清单文件(将容器启动到Pod中)。
我缺少的内容:
  1. 所有这些都是手动完成的(在代码构建后自动构建镜像并使用新镜像更新k8s的过程中存在明显的自动化空间)。
  2. 构建是手动指定的(Python在保存代码时重新启动。据我所知,Java世界中没有热重载)。
  3. 我还没有看到本地开发环境和云托管k8's集群之间的集成。理想情况下,开发人员会在本地测试,直到准备好部署到云端。当他们准备好时,点击一个按钮,让集群从远程注册表读取,可以获取docker镜像更改并重新加载。

遗憾的是,Skaffold 这个工具无法原生地与Java一起使用。 有没有其他工具是Java开发人员正在使用的,使他们的本地部署速度超快,与鸭子语言(py、js)竞争?


2
如果我没记错,Jib已经合并到Skaffold中了,所以你可能需要重新考虑一下。此外,我们在https://kubernetes.io/blog/2018/05/01/developing-on-kubernetes/上写了一些东西,也许会有所帮助... - Michael Hausenblas
3个回答

2
你可以通过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有其难以解决的限制。我在这里绘制了其中一个痛点: https://stackoverflow.com/questions/52378551/micro-services-with-docker-compose-same-container-multiple-projects此外,我喜欢在本地和云中运行相同的编排。这种模式使我能够以相同的方式理解所有内容(无论本地/云状态如何),并有效地测试部署策略,然后再呈现给人们。 - Chad Van De Hey
Spotify的docker-maven-plugin我认为已经不再维护了。我使用Spotify的dockerfile-maven-plugin和fabric8 docker maven插件,指向我的minikube的docker实例,这样在开发过程中就不必推送到注册表了。这为我节省了大量时间。 - Bal Chua

1

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

  • 像@Ortomala Lokni提到的那样,使用docker-maven-plugin从maven构建直接构建Docker镜像。
  • 您可以使用https://github.com/fabric8io/fabric8-maven-plugin 直接推送到Kubernetes集群。
  • 如果您的集群托管在云中,则构建机器应该能够访问k8s API服务器。为此,您可能需要使用SSH隧道和Bastions,具体取决于您的云k8s集群的API服务器是否公开可用。
  • 查看minikube以获取本地k8s测试集群,即使是最新版本的桌面Docker现在也内置了一个简单的k8s服务器。
  • 虽然我没有使用过Skaffold,但基本上看文档表明它也适用于您,因为它接管了观察您的代码、启动Docker构建和部署到k8s的基本功能。这些功能在不同语言之间保持不变。话虽如此,上述两个插件将构建Docker镜像和部署到k8s整合到了您的maven工作流程中。
你提到Python和JS很快,但请注意,即使对于这些语言,基本步骤也是相同的:构建Docker镜像,推送到仓库,更新K8s部署。
此外,Java也可以进行热部署,即使在像Eclipse这样的IDE中,使用基于Spring Boot的微服务可以使用spring-dev-tools进行实时重载和自动重启。但是,我不知道是否有任何工具可以帮助您处理Docker容器的实时更改,因为Docker容器应该是不可变的,请尽量避免这样做。

0

很抱歉,如果我来晚了,我会尽力为未来的读者或者也许是你回答。

首先,Docker 构建和 Kubernetes 集群部署是您软件供应链的两个完全不同的阶段,让我们将它们作为不同的话题。

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

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

b) 将配置文件与相关的微服务放在一起,使用提交哈希标记新构建的镜像,并在管道的末尾执行 kubectl apply env.yaml && kubectl set image myregistry.com/myimage:${commitHash}(确保也将其标记为“latest”,并在部署规范中包含最新标记,这有助于在删除和应用配置后重建当前情况)

c) 使用 Helm Charts 进行部署。它类似于前面的步骤,但您可以利用依赖管理和部署模板化的所有优势。

  • 热重载在进行TDD开发时很好用,但是当代码即将交付时就没有用了。对于使用node/python微服务,你也不会使用它,因为一旦你的代码被容器化,你应该用AK47射击每个试图触碰它的开发人员。真正重要的是自动化你的集成/交付/部署。在我的团队中,我们只需要打开并接受一个PR,魔法就会发生。

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


  • 网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接