笔者是一名Java服务端程序员,学习微服务后,在部署时发现过程复杂,且做的重复工作非常多,因此学习基本运维。目标是,使用Kubernetes和容器技术进行微服务编排和部署。
本文只讨论服务容器化,不涉及K8s和Jenkins相关内容。
在服务容器化时,一些参数必须动态传入,以适应不同的部署环境。变化的参数包括:
我的Java项目(Example)由多个微服务构成:如Example-core,Example-auth,Example-gateway等。以Example-auth这个微服务作为切入点,打包为Docker容器的代码为:
# 使用官方的OpenJDK 17作为基础镜像FROM openjdk:17# 镜像环境变量:# 开发环境:dev# 测试环境:test# 预发环境:staging# 生产环境:prod, 默认生产环境ARG ENVIRONMENT=prod# Jar包的版本,默认0.0.1-SNAPSHOTARG JAR_VERSION=0.0.1-SNAPSHOT# 注册中心服务地址ARG SERVER_NAME=www.nacos-server.cn# 维护者MAINTAINER xlxing@bupt.edu.cn# 拷贝文件到Docker容器中COPY target/auth-${JAR_VERSION}.jar /app/auth-${JAR_VERSION}.jar# 暴露服务端口EXPOSE 8999# 容器启动项ENTRYPOINT ["java", "-jar", "/app/auth-${JAR_VERSION}.jar", "--spring.profiles.active=${ENVIRONMENT}", "--spring.cloud.nacos.discovery.ip=${SERVER_NAME}"]
在构建容器时可以动态传入参数(jar包版本为1.1.0,环境是dev,服务发现地址www.my-auth.cn,构建的容器命名为myapp/example:auth-dev-1.1.0):
docker build --build-arg JAR_VERSION=1.1.0 ENVIRONMENT=dev SERVER_NAME=www.my-auth.cn -t myapp/example:auth-dev-1.1.0 .
该内容产生了以下两个具体问题:
在构建项目时,仍然需要手动传入项目版本,实际上该信息存在于项目中,如该微服务auth的pom.xml文件:
<artifactId>auth</artifactId> <version>0.0.1-SNAPSHOT</version> <name>auth</name> <description>权限微服务</description>
理想情况是:后端程序员来定义项目的版本,而流水线只需要依赖项目即可。
但是在当前情况下:当auth项目的version变更时,构建Docker镜像的指令也需要同步变化。该问题可以总结为,构建容器时如何从项目中获取JAR_VERSION?
docker build --build-arg JAR_VERSION=1.1.0 ENVIRONMENT=dev SERVER_NAME=www.my-auth.cn -t myapp/example:auth-dev-1.1.0 .
微服务启动时,将该服务注册到Nacos上,声明自己的服务地址。当部署到具体的服务器上时,该地址才被绑定,如auth服务可以部署在server-a上,也可以部署到server-b上。如何在运行时确定服务地址而不是构建时。
补充内容:
auth服务的配置文件
spring: application: name: auth # Nacos配置 cloud: nacos: server-addr: www.nacos-server.cn # 服务发现 discovery: cluster-name: BEIJING # 设置为非临时实例 ephemeral: true # 设置命名空间 namespace: e35500e1-2441-4001-b60f-3f7d55bxxxxx # 配置中心 config: file-extension: yaml # 文件后缀名 namespace: e35500e1-2441-4001-b60f-3f7d55bxxxxx group: DEFAULT_GROUPdubbo: # 将Dubbo注册到Nacos中,这样可供消费者直接使用 application: name: dubbo-auth protocol: name: dubbo port: -1 registry: address: nacos://www.nacos-server.cn?namespace=228df068-54b7-405e-9e32-72c759d79ed9 group: DEV_DUBBO_GROUP
其中涉及到很多配置相关的问题,缺乏一个系统性的文章探讨如何部署和运维。
docker run
时动态传入参数。ARG SERVER_NAME=www.nacos-server.cn
改为ENV SERVER_NAME=www.nacos-server.cn
对于你的问题,有几种可能的解决方案。首先,对于JAR_VERSION的动态获取,一种可能的方法是使用Maven的属性。你可以在pom.xml文件中定义一个属性,然后在构建Docker镜像时使用这个属性。例如:
在pom.xml中:
<project> ... <properties> <version>0.0.1-SNAPSHOT</version> </properties> ...</project>
然后在Dockerfile中:
FROM openjdk:17ARG JAR_VERSION=${version}...COPY target/auth-${JAR_VERSION}.jar /app/auth-${JAR_VERSION}.jar...
这样,当你在构建Docker镜像时,Maven会自动替换${version}为实际的版本号。
至于如何自动获取宿主机的SERVER_NAME,一种可能的方法是使用环境变量。你可以在部署时设置环境变量,然后在你的程序中读取这个环境变量。例如,你可以在Docker run时设置环境变量:
docker run -e SERVER_NAME=www.my-auth.cn -t myapp/example:auth-dev-1.1.0 .
然后在你的Java程序中读取这个环境变量:
String serverName = System.getenv("SERVER_NAME");
这样,你可以在部署时动态地设置服务器地址,而不需要修改Dockerfile或程序代码。
在开展实验之前,我们需要根据不同的平台提前安装相关依赖的软件包,具体需要的软件包如下: Rust 工具链 Rust 版本管理工具:rustup Rust 软件包管理工具:cargo Rust 编译器:rustc 等等 虚拟机软件:QEMU (版本至少支持 RISC-V 64) 具体安装的方法在不同平台上安装方式类似,但也有细微差别,后面会有具体说明。 安装 QEMU 根据不同平台,我们分为下面 3
我想部署我的微服务的几个实例,它们使用特定的端口,但使其可伸缩,并且不在任务定义/dockerfile中修复端口。我的微服务可以监听环境变量或命令行中提供的端口。
PWA 项目必须部署在 HTTPS 环境上才能够生效,主要是因为 Service Worker 只会在 HTTPS 环境下才能注册成功,我们不用担心在本地开发的时候 Service Worker 是否生效的问题,因为 Service Worker 在 localhost 和 127.0.0.1 的 host 下是能够注册成功的,这样可以确保我们在本地调试工作是能够顺利进行的。我们这里讲述的是如何部
我目前正在开发一个云备份解决方案,其中涉及到多达8个在spring-boot中开发的微服务,并使用mongo DB atlas作为持久层。 微服务包括Netflix ZUUL API网关和Netflix Eureka作为服务发现机制。微服务被要求彼此进行明显的对话。 对微服务进行了对接。到目前为止,我已经使用docker-compose文件将它们部署到EC2实例中,该文件列出了使用docker网络
我正在尝试开发一个Spring Cloud微服务,并使用Elastic Beanstalk部署到AWS cloud中。当我搜索部署选项时,我发现了Beanstalk的部署环境。我有一点困惑。我可以在不启动EC2机器的情况下使用Elastic Beanstalk部署我的微服务吗? 在这里,我只接近弹性豆茎服务。使用弹性Beanstalk部署微服务而不启动EC2是可能的吗? 我是AWS世界的初学者。