AI心情日记后端迁移K8s部署全流程

打印 上一主题 下一主题

主题 945|帖子 945|积分 2835

一、项目背景与目标

今天想将本地以java -jar运行的Spring Boot应用(AI心情日记后端)迁移至Kubernetes集群,实现容器化部署和康健管理,趁便再次回顾一下k8s的操作细节。
因为我引入了springAI组件,这个组件需要springboot版本在3.2以上,jdk要17 以上,在部署的过程中遇到了一些问题。

二、引入康健检查模块(Spring Boot Actuator)

1. 添加Maven依赖(pom.xml)

  1. <!-- 引入Spring Boot Actuator实现健康检查 -->
  2. <dependency>
  3.     <groupId>org.springframework.boot</groupId>
  4.     <artifactId>spring-boot-starter-actuator</artifactId>
  5. </dependency>
复制代码

三、容器化:Dockerfile配置

  1. # 使用轻量级 OpenJDK 19
  2. FROM openjdk:19
  3. # 设置工作目录(避免容器内路径冲突)
  4. WORKDIR /app
  5. # 复制编译好的 JAR 文件到容器
  6. COPY target/ai-0.0.1-SNAPSHOT.jar app.jar
  7. # 启动命令(可添加 JVM 参数优化性能)
  8. ENTRYPOINT ["java", "-jar", "app.jar"]
复制代码

四、Kubernetes资源配置

1. Deployment配置(deployment.yaml)

  1. # 指定 API 版本(不同资源类型对应不同 API 版本)
  2. apiVersion: apps/v1
  3. # 定义资源类型为 Deployment(副本控制器)
  4. kind: Deployment
  5. # 元数据部分(定义资源标识)
  6. metadata:
  7.   # Deployment 对象名称(集群内唯一)
  8.   name: ai-app
  9.   # 标签系统(可用于其他资源关联筛选)
  10.   labels:
  11.     app: ai-app
  12. # 部署规格(核心配置部分)
  13. spec:
  14.   # 期望的 Pod 副本数量(此处设置为 1,生产环境建议至少 2)
  15.   replicas: 1
  16.   # 标签选择器(告诉 Deployment 如何找到要管理的 Pod)
  17.   selector:
  18.     matchLabels:
  19.       # 必须与 template.metadata.labels 完全匹配
  20.       app: ai-app
  21.   # Pod 模板(定义具体 Pod 的配置)
  22.   template:
  23.     metadata:
  24.       labels:
  25.         # Pod 标签(必须与 selector.matchLabels 一致)
  26.         app: ai-app
  27.     # Pod 规格(定义容器细节)
  28.     spec:
  29.       containers:
  30.         - name: ai-container  # 容器名称(同一 Pod 内多个容器需唯一)
  31.           # 镜像地址(需与 docker build 时设置的名称一致)
  32.           image: xiajing/ai-service:v1.1
  33.           # 容器端口声明(仅文档作用,实际暴露需配合 Service)
  34.           ports:
  35.             - containerPort: 8100  # 此处存在错误,应与应用实际端口一致(见下方说明)
  36.           # 资源配额管理(关键配置)
  37.           resources:
  38.             # 请求资源(调度依据,节点必须满足才能运行)
  39.             requests:
  40.               cpu: "1"    # 0.5 核(500m,即 500 毫核)
  41.               memory: "1Gi"  # 512MB(二进制单位,1Mi=1024^2 bytes)
  42.             # 资源上限(防止容器耗尽节点资源)
  43.             limits:
  44.               cpu: "2"      # 最多使用 1 核
  45.               memory: "2Gi" # 最多使用 1GB(二进制单位)
  46.           # 存活探针(失败则重启容器)
  47.           livenessProbe:
  48.             httpGet:  # 使用 HTTP GET 请求检测
  49.               path: /actuator/health/liveness  # 健康检查路径(需应用实现该接口)
  50.               port: 8100  # 必须与 containerPort 一致,应为 8100
  51.             initialDelaySeconds: 30  # 容器启动后 30 秒开始探测
  52.             periodSeconds: 10        # 每 10 秒检测一次
  53.             timeoutSeconds: 5        # 超时时间(默认 1 秒)
  54.             failureThreshold: 3      # 连续失败 3 次标记为不健康
  55.           # 就绪探针(通过后才接收流量)
  56.           readinessProbe:
  57.             httpGet:
  58.               path: /actuator/health/readiness
  59.               port: 8100  # 同上错误,应改为 8100
复制代码
2. Service配置(service.yaml)

  1. # 指定 API 版本(Service 使用 core/v1)
  2. apiVersion: v1
  3. # 定义资源类型为 Service
  4. kind: Service
  5. # 元数据部分
  6. metadata:
  7.   # Service 名称(集群内唯一标识)
  8.   name: ai-service
  9. # Service 规格(核心配置)
  10. spec:
  11.   # 标签选择器(选择要代理的 Pod)
  12.   selector:
  13.     # 必须与 Deployment 中 Pod 的标签完全匹配
  14.     app: ai-app  # 需与 Deployment 的标签一致(原配置中是 app: ai-app)
  15.   # 端口映射规则
  16.   ports:
  17.     - protocol: TCP      # 协议类型(支持 TCP/UDP/SCTP)
  18.       port: 8101           # Service 对外暴露的端口(集群内访问用)
  19.       targetPort: 8100   # Pod 容器的实际端口(必须与容器端口一致)
  20.       nodePort: 31000
  21.   # Service 类型(决定如何暴露服务)
  22.   type: NodePort         # 可选值:ClusterIP(默认)、NodePort、LoadBalancer
复制代码

五、执行部署脚本

  1. # 1. 构建并推送镜像
  2. docker build -t your-registry/diary-backend:1.0 .  # 构建镜像
  3. docker push your-registry/diary-backend:1.0        # 推送到镜像仓库
  4. # 2. 部署到Kubernetes
  5. kubectl apply -f deployment.yaml  # 创建Deployment
  6. kubectl apply -f service.yaml      # 创建Service
  7. # 3. 验证部署状态
  8. kubectl get pods -o wide          # 查看Pod状态和所在节点
  9. kubectl get svc diary-service    # 获取Service的NodePort端口
复制代码

六、验证服务状态

  1. # 1. 检查Pod是否就绪
  2. kubectl get pods -l app=diary-backend
  3. # 预期输出:READY 1/1,STATUS Running
  4. # 2. 查看健康检查日志
  5. kubectl logs <pod-name> | grep 'actuator/health'
  6. # 预期输出:200 OK
  7. # 3. 访问服务接口(通过NodePort)
  8. curl http://<节点IP>:31000/api/diary
  9. # 预期输出:JSON格式的日记数据
复制代码

七、问题与办理:JDK版本升级

1. 错误现象

部署后Pod状态为CrashLoopBackOff,日志报错:
  1. Caused by: java.lang.NullPointerException:
  2.   Cannot invoke "jdk.internal.platform.CgroupInfo.getMountPoint()"
复制代码
2. 原因分析



  • JDK 17的局限性:jdk.internal.platform模块在部分镜像(如slim)中缺失。
  • 容器环境兼容性:Kubernetes Cgroup v2与JDK 17的兼容性问题。
3. 办理方案



  • 升级JDK到19:使用完整镜像openjdk:19-jdk。
  • 更新Dockerfile
    1. FROM openjdk:19   # 运行阶段JDK 19
    复制代码
  • 验证修复
    1. kubectl rollout restart deployment/diary-backend  # 触发重建Pod
    2. kubectl get pods -w  # 观察新Pod状态
    复制代码

八、总结

通过本流程,我已实现:

  • 康健检查集成:通过Actuator实现存活/停当探针。
  • 容器化优化:多阶段构建减少镜像体积至200MB以下。
  • K8s生产级配置:资源限制、滚动更新战略、服务暴露。
  • 版本问题办理:升级JDK 19彻底修复Cgroup兼容性问题。
最终结果:AI心情日记后端稳定运行于Kubernetes集群,可通过http://<节点IP>:31000访问,后面如果有流量增加可以自动弹性伸缩。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户国营

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表