Java 部署:K8s Deployment 部署 Spring Boot 应用

Java 部署:K8s Deployment 部署 Spring Boot 应用
在这里插入图片描述
👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕Java部署这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!

文章目录

Java 部署:K8s Deployment 部署 Spring Boot 应用 🚀

在现代云原生架构中,将 Java 应用部署到 Kubernetes(简称 K8s)已成为行业标准。Spring Boot 作为最流行的 Java 微服务框架之一,天然具备轻量、快速启动和内嵌容器等特性,非常适合与 Kubernetes 集成。本文将从零开始,手把手教你如何将一个 Spring Boot 应用打包为 Docker 镜像,并通过 Kubernetes Deployment 进行部署、扩缩容、健康检查和滚动更新。

无论你是刚接触 DevOps 的 Java 开发者,还是希望系统化梳理 K8s 部署流程的工程师,本文都将为你提供实用、可落地的完整指南。我们将涵盖以下核心内容:

  • 构建一个简单的 Spring Boot 应用
  • 使用 Dockerfile 打包应用镜像
  • 编写 Kubernetes Deployment 和 Service 配置
  • 配置就绪(Readiness)与存活(Liveness)探针
  • 实现滚动更新与回滚策略
  • 使用 ConfigMap 和 Secret 管理配置
  • 通过 Ingress 暴露服务
  • 监控与日志最佳实践

准备好了吗?让我们开启这段云原生之旅!☁️


1. 创建一个简单的 Spring Boot 应用 💻

首先,我们需要一个可运行的 Spring Boot 应用。为了演示,我们创建一个极简的 REST API 服务,它提供两个端点:

  • /api/hello:返回 “Hello from Spring Boot on Kubernetes!”
  • /actuator/health:健康检查端点(由 Spring Boot Actuator 提供)

1.1 项目结构

使用 Spring Initializr 快速生成项目,选择以下依赖:

  • Spring Web
  • Spring Boot Actuator

生成的 pom.xml 如下:

<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.0</version><relativePath/></parent><groupId>com.example</groupId><artifactId>k8s-springboot-demo</artifactId><version>1.0.0</version><name>k8s-springboot-demo</name><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

1.2 编写控制器

创建一个简单的控制器类:

// src/main/java/com/example/k8sdemo/controller/HelloController.javapackagecom.example.k8sdemo.controller;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassHelloController{@GetMapping("/api/hello")publicStringsayHello(){return"Hello from Spring Boot on Kubernetes! 🌈";}}

1.3 配置 Actuator

为了让 Kubernetes 能够进行健康检查,我们需要暴露 /actuator/health 端点。在 application.yml 中添加:

# src/main/resources/application.ymlserver:port:8080management:endpoints:web:exposure:include: health,info endpoint:health:show-details: always 

此时,应用启动后可通过以下 URL 访问:

  • http://localhost:8080/api/hello
  • http://localhost:8080/actuator/health

1.4 本地测试

运行应用:

./mvnw spring-boot:run 

访问 http://localhost:8080/api/hello,应看到:

Hello from Spring Boot on Kubernetes! 🌈 

访问 http://localhost:8080/actuator/health,应返回:

{"status":"UP"}

✅ 本地验证通过!


2. 构建 Docker 镜像 🐳

Kubernetes 运行的是容器,因此我们需要将 Spring Boot 应用打包成 Docker 镜像。

2.1 编写 Dockerfile

在项目根目录创建 Dockerfile

# 使用官方 OpenJDK 17 镜像作为基础 FROM openjdk:17-jdk-slim # 设置工作目录 WORKDIR /app # 复制构建好的 JAR 文件 COPY target/k8s-springboot-demo-1.0.0.jar app.jar # 暴露端口 EXPOSE 8080 # 启动应用 ENTRYPOINT ["java", "-jar", "app.jar"] 
💡 优化建议:生产环境中可考虑使用多阶段构建(multi-stage build)或 JLink 减小镜像体积,但本例以简洁为主。

2.2 构建 JAR 和镜像

先构建 JAR:

./mvnw clean package -DskipTests 

然后构建 Docker 镜像:

docker build -t k8s-springboot-demo:1.0.0 .

验证镜像是否构建成功:

docker images |grep k8s-springboot-demo 

2.3 本地运行容器测试

docker run -p 8080:8080 k8s-springboot-demo:1.0.0 

再次访问 http://localhost:8080/api/hello,确认容器内应用正常运行。

✅ 注意:如果你使用的是远程 Docker daemon(如 Docker Desktop for Mac/Windows),确保网络可访问。

3. Kubernetes 基础概念回顾 🧠

在正式编写 YAML 之前,简要回顾几个关键概念:

  • Pod:K8s 最小调度单元,包含一个或多个容器。
  • Deployment:声明式地管理 Pod 副本,支持滚动更新、回滚、扩缩容。
  • Service:为一组 Pod 提供稳定的网络入口(ClusterIP、NodePort、LoadBalancer)。
  • ConfigMap / Secret:用于解耦配置与代码,分别存储非敏感和敏感数据。
  • Ingress:管理外部 HTTP/HTTPS 流量进入集群的规则(需 Ingress Controller 支持)。

我们的目标是:

  1. 通过 Deployment 启动 3 个 Pod 副本
  2. 通过 Service 暴露内部服务
  3. 通过 Ingress 暴露到公网(可选)
  4. 配置健康探针确保高可用

4. 编写 Kubernetes Deployment 配置 📄

4.1 deployment.yaml

创建 deployment.yaml

apiVersion: apps/v1 kind: Deployment metadata:name: springboot-app labels:app: springboot-app spec:replicas:3selector:matchLabels:app: springboot-app template:metadata:labels:app: springboot-app spec:containers:-name: springboot-container image: k8s-springboot-demo:1.0.0 ports:-containerPort:8080env:-name: JAVA_OPTS value:"-Xmx512m -Xms256m"resources:requests:memory:"256Mi"cpu:"100m"limits:memory:"512Mi"cpu:"500m"
⚠️ 注意:上述 image: k8s-springboot-demo:1.0.0 是本地镜像。在真实集群中,你需要将镜像推送到镜像仓库(如 Docker Hub、Harbor、ECR 等),并使用完整路径,例如 your-registry/k8s-springboot-demo:1.0.0

4.2 service.yaml

创建 service.yaml,将 Pod 暴露为 ClusterIP 服务:

apiVersion: v1 kind: Service metadata:name: springboot-service labels:app: springboot-app spec:type: ClusterIP selector:app: springboot-app ports:-protocol: TCP port:80targetPort:8080

这样,集群内其他服务可通过 http://springboot-service 访问该应用。

4.3 应用配置到集群

假设你已有一个运行中的 Kubernetes 集群(如 Minikube、Kind、EKS、AKS 等),执行:

kubectl apply -f deployment.yaml kubectl apply -f service.yaml 

查看状态:

kubectl get pods kubectl get deployments kubectl get services 

你应该看到 3 个 Running 状态的 Pod。


5. 配置健康探针:Liveness 与 Readiness 🩺

Kubernetes 通过探针(Probes)判断容器是否健康。两种关键探针:

  • Liveness Probe:判断容器是否“活着”。失败则重启容器。
  • Readiness Probe:判断容器是否“准备好”接收流量。失败则从 Service 后端移除。

Spring Boot Actuator 提供了 /actuator/health,非常适合做探针端点。

5.1 更新 deployment.yaml

在容器配置中添加探针:

# 在 containers 下添加livenessProbe:httpGet:path: /actuator/health port:8080initialDelaySeconds:20periodSeconds:10timeoutSeconds:5failureThreshold:3readinessProbe:httpGet:path: /actuator/health port:8080initialDelaySeconds:10periodSeconds:5timeoutSeconds:3failureThreshold:2

完整容器部分如下:

containers:-name: springboot-container image: k8s-springboot-demo:1.0.0 ports:-containerPort:8080env:-name: JAVA_OPTS value:"-Xmx512m -Xms256m"resources:requests:memory:"256Mi"cpu:"100m"limits:memory:"512Mi"cpu:"500m"livenessProbe:httpGet:path: /actuator/health port:8080initialDelaySeconds:20periodSeconds:10timeoutSeconds:5failureThreshold:3readinessProbe:httpGet:path: /actuator/health port:8080initialDelaySeconds:10periodSeconds:5timeoutSeconds:3failureThreshold:2
📌 参数说明initialDelaySeconds:容器启动后等待多久开始探测periodSeconds:探测间隔failureThreshold:连续失败多少次才判定为失败

重新应用配置:

kubectl apply -f deployment.yaml 

Kubernetes 将自动滚动更新 Pod,新 Pod 会启用探针。


6. 滚动更新与版本管理 🔄

Kubernetes Deployment 支持无缝滚动更新。只需修改镜像版本,K8s 会逐步替换旧 Pod。

6.1 修改应用并发布 v1.1.0

假设我们修改 HelloController

@GetMapping("/api/hello")publicStringsayHello(){return"Hello from Spring Boot v1.1.0 on Kubernetes! 🚀";}

重新构建 JAR 和镜像:

./mvnw clean package -DskipTests docker build -t k8s-springboot-demo:1.1.0 .

6.2 更新 Deployment 镜像

有两种方式:

方式一:直接编辑 YAML

deployment.yaml 中的镜像改为 k8s-springboot-demo:1.1.0,然后:

kubectl apply -f deployment.yaml 
方式二:使用 kubectl set image
kubectl set image deployment/springboot-app springboot-container=k8s-springboot-demo:1.1.0 

6.3 查看滚动更新过程

kubectl rollout status deployment/springboot-app 

输出类似:

Waiting for deployment "springboot-app" rollout to finish: 1 out of 3 new replicas have been updated... Waiting for deployment "springboot-app" rollout to finish: 2 out of 3 new replicas have been updated... deployment "springboot-app" successfully rolled out 

Kubernetes 默认采用 滚动更新策略(RollingUpdate),确保服务不中断。

6.4 回滚到上一版本

如果新版本有问题,可快速回滚:

kubectl rollout undo deployment/springboot-app 

查看历史版本:

kubectl rollout history deployment/springboot-app 
🔄 滚动更新策略细节
默认 maxUnavailable: 25%, maxSurge: 25%,即最多 25% Pod 不可用,最多超出期望副本数 25%。可在 Deployment 中显式配置。

7. 使用 ConfigMap 和 Secret 管理配置 🔐

硬编码配置是反模式。K8s 提供 ConfigMap(非敏感)和 Secret(敏感)来管理配置。

7.1 使用 ConfigMap 配置应用

假设我们想通过环境变量设置欢迎语:

@RestControllerpublicclassHelloController{@Value("${app.message:Hello from Spring Boot!}")privateString message;@GetMapping("/api/hello")publicStringsayHello(){return message +" 🌈";}}

application.yml 中引用:

app:message: ${APP_MESSAGE:Default Message}

7.2 创建 ConfigMap

创建 configmap.yaml

apiVersion: v1 kind: ConfigMap metadata:name: springboot-config data:APP_MESSAGE:"Welcome to Kubernetes with ConfigMap! 🎉"

应用:

kubectl apply -f configmap.yaml 

7.3 在 Deployment 中引用 ConfigMap

更新 deployment.yaml 的容器部分:

env:-name: JAVA_OPTS value:"-Xmx512m -Xms256m"-name: APP_MESSAGE valueFrom:configMapKeyRef:name: springboot-config key: APP_MESSAGE 

重新部署后,访问 /api/hello 将显示新消息。

7.4 使用 Secret 管理敏感信息

例如数据库密码:

# 创建 Secret(Base64 编码)echo -n 'mysecretpassword'| base64 # 输出: bXlzZWNyZXRwYXNzd29yZAo=# 创建 secret.yaml
apiVersion: v1 kind: Secret metadata:name: db-secret type: Opaque data:DB_PASSWORD: bXlzZWNyZXRwYXNzd29yZAo= 

在 Deployment 中引用:

env:-name: DB_PASSWORD valueFrom:secretKeyRef:name: db-secret key: DB_PASSWORD 
🔒 安全提示:Secret 仅提供基本编码,不加密。生产环境应结合 Vault、KMS 或 Sealed Secrets 使用。

8. 通过 Ingress 暴露服务到公网 🌐

Service 的 ClusterIP 仅限集群内访问。若需从外部访问,可使用 Ingress。

8.1 安装 Ingress Controller

不同平台安装方式不同。以 Minikube 为例:

minikube addons enable ingress 

对于云厂商(如 AWS EKS),通常使用 ALB Ingress Controller;GKE 使用 GCE Ingress。

8.2 创建 Ingress 规则

创建 ingress.yaml

apiVersion: networking.k8s.io/v1 kind: Ingress metadata:name: springboot-ingress annotations:nginx.ingress.kubernetes.io/rewrite-target: / spec:ingressClassName: nginx # 根据你的 Ingress Controller 调整rules:-host: springboot.example.com http:paths:-path: / pathType: Prefix backend:service:name: springboot-service port:number:80
🌐 注意host 字段需解析到你的集群入口 IP。本地测试可修改 /etc/hosts
# 获取 Ingress IP kubectl get ingress # 假设 IP 为 192.168.49.2echo"192.168.49.2 springboot.example.com"|sudotee -a /etc/hosts 

然后访问 http://springboot.example.com/api/hello

8.3 HTTPS 支持(可选)

可通过 cert-manager 自动申请 Let’s Encrypt 证书。参考 cert-manager 官方文档


9. 应用架构与流量流向图 🗺️

为了更直观理解组件关系,我们使用 Mermaid 绘制架构图:

HTTP/HTTPS

External User

Ingress Controller

Ingress Rule
springboot.example.com

Service: springboot-service

Pod 1

Pod 2

Pod 3

ConfigMap/Secret

该图展示了:

  • 外部用户通过域名访问 Ingress Controller
  • Ingress 根据规则路由到 Service
  • Service 负载均衡到多个 Pod
  • Pod 从 ConfigMap/Secret 获取配置

10. 日志与监控最佳实践 📊

可观测性是云原生应用的核心。

10.1 日志收集

Spring Boot 默认输出日志到 stdout/stderr,K8s 会自动收集。可通过以下命令查看:

kubectl logs -l app=springboot-app --tail=100

生产环境建议集成:

  • EFK Stack(Elasticsearch + Fluentd + Kibana)
  • Loki + Promtail + Grafana

10.2 指标监控

Spring Boot Actuator 提供 /actuator/metrics,可暴露给 Prometheus。

添加 Micrometer 依赖:

<dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId></dependency>

暴露 Prometheus 端点:

management:endpoints:web:exposure:include: health,info,metrics,prometheus 

然后配置 Prometheus 抓取该端点。

10.3 分布式追踪

集成 OpenTelemetry 或 Spring Cloud Sleuth,实现跨服务追踪。


11. 常见问题与调试技巧 🛠️

11.1 Pod 一直处于 Pending 状态

  • 检查资源请求是否超过节点容量:kubectl describe pod <pod-name>
  • 检查是否有污点(Taint)或亲和性(Affinity)限制

11.2 应用启动失败

  • 查看日志:kubectl logs <pod-name>
  • 检查探针是否过早失败(调整 initialDelaySeconds

11.3 无法访问服务

  • 检查 Service Selector 是否匹配 Pod Labels
  • 检查 Ingress Host 是否解析正确
  • 使用 kubectl port-forward 临时调试:
kubectl port-forward svc/springboot-service 8080:80 

然后访问 http://localhost:8080


12. 总结与进阶方向 🎯

通过本文,你已经掌握了:

✅ 构建 Spring Boot 应用
✅ 打包 Docker 镜像
✅ 编写 K8s Deployment/Service
✅ 配置健康探针
✅ 实现滚动更新与回滚
✅ 使用 ConfigMap/Secret
✅ 通过 Ingress 暴露服务
✅ 基础可观测性

但这只是起点。下一步可探索:

  • Helm Chart:将应用打包为 Helm Chart,实现版本化部署
  • GitOps:使用 Argo CD 或 Flux 实现声明式持续交付
  • Service Mesh:集成 Istio 或 Linkerd 实现高级流量管理
  • Serverless:尝试 Knative 将 Spring Boot 转为事件驱动

Kubernetes 生态庞大而强大,但核心思想始终是:声明式、自动化、弹性、可观测。掌握这些原则,你就能在云原生世界游刃有余。

🌟 延伸阅读Kubernetes 官方文档Spring Boot on Kubernetes 官方指南Docker 官方最佳实践

愿你的 Java 应用在 Kubernetes 上稳定、高效、优雅地运行!🎉


🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨

Read more

一款数据库SQL防火墙:可以拦截99.99%,可以阻止恶意SQL

一款数据库SQL防火墙:可以拦截99.99%,可以阻止恶意SQL

文章目录 * 一、SQL注入:那个偷偷溜进房子的"不速之客" * 二、三种模式,给数据库装上"智能门禁系统" * 三、又快又准又简单,这才是理想中的安全防护 * 1. 99.99%的拦截准确率,近乎"零误报" * 2. 性能损耗低于6%,业务无感 * 3. 两步配置,小白也能轻松上手 * 四、从党政到能源,为什么他们都选择了金仓? 在数字化转型的浪潮中,数据已成为企业的核心资产。然而,SQL注入攻击如同潜伏在阴影中的"不速之客",时刻威胁着数据库的安全。即使开发团队严守预编译、输入过滤等防线,遗留代码、第三方组件的漏洞或人为疏忽仍可能给攻击者可乘之机。难道只能被动挨打、疲于补漏吗?金仓数据库(KingbaseES)内置的SQL防火墙,

By Ne0inhk
联邦学习架构深度分析:支持多家医院协作训练AI模型方案分析

联邦学习架构深度分析:支持多家医院协作训练AI模型方案分析

引言 随着人工智能技术在医疗领域的广泛应用,医疗机构面临着如何在保护患者隐私的同时,高效利用分散在各医疗机构的医疗数据进行模型训练的挑战。传统的集中式数据共享方法不仅面临隐私泄露风险,还涉及复杂的法律合规问题。在这一背景下,"数据不动模型动"的联邦学习架构应运而生,为医疗机构提供了在不共享原始数据的前提下协同训练AI模型的新范式。 联邦学习(Federated Learning)是一种分布式机器学习范式,允许多个参与方在不直接交换原始数据的情况下,通过交换加密的模型参数或特征表示,共同训练一个高性能的全局模型。这种"数据不动模型动"的方式完美解决了医疗数据隐私保护与有效利用之间的矛盾,正逐渐成为医疗AI协作的基础设施级解决方案。 本报告将深入剖析"数据不动模型动"的联邦学习架构,从技术架构、隐私机制、医疗场景适配性、性能优化及实施挑战五个维度进行深度分析,探讨其如何支持多家医院协作训练AI模型,同时确保敏感医疗数据的安全与隐私。 核心架构:分层协同与动态聚合 联邦学习系统通常采用三层拓扑结构实现医院间的高效协作,这种分层设计显著降低通信延迟,避免单点故障,符合医疗机构的

By Ne0inhk
OpenClaw Gateway 安装失败:systemctl --user is-enabled unavailable 排查与解决(完整踩坑记录)

OpenClaw Gateway 安装失败:systemctl --user is-enabled unavailable 排查与解决(完整踩坑记录)

说明:仅供学习使用,请勿用于非法用途,若有侵权,请联系博主删除 作者:zhu6201976 最近在安装 OpenClaw Gateway 时,遇到了一个比较奇怪的错误: systemctl is-enabled unavailable Command failed: systemctl --user is-enabled openclaw-gateway.service 看起来只是一个简单的 systemd 错误,但实际上背后涉及: * systemd user service * Node.js / nvm 环境 * PATH 环境变量 * CLI daemon 启动方式 这篇文章记录了 完整的排查过程 + 最终解决方案。 一、运行环境 我的环境如下: Window11 + WSL2 Ubuntu 24.04.4

By Ne0inhk
Java 中间件:MinIO 文件上传(分片上传 + 预签名 URL)

Java 中间件:MinIO 文件上传(分片上传 + 预签名 URL)

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Java中间件这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获! 文章目录 * Java 中间件:MinIO 文件上传(分片上传 + 预签名 URL) * 为什么选择 MinIO? * 分片上传 vs 普通上传 * 普通上传(Simple Upload) * 分片上传(Multipart Upload) * 预签名 URL:安全的前端直传机制 * 整体架构设计 * 环境准备 * 1. 启动 MinIO 服务 * 2. 创建 Bucket * 3. Java 项目依赖 * 核心代码实现 * 1. MinIO 客户端配置 * 2.

By Ne0inhk