尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Spring Boot部署Kubernetes实战:镜像构建、探针配置与滚动发布

发布时间:2026/9/24 19:27:41

资讯中心
01
ARTICLE

Spring Boot部署Kubernetes实战:镜像构建、探针配置与滚动发布

Spring Boot部署Kubernetes实战:镜像构建、探针配置与滚动发布
最近团队在折腾把Spring Boot服务迁到Kubernetes上的事前前后后踩了不少坑也总结出一些能直接抄作业的套路。很多人一上来就找一堆YAML模板往上一贴结果要么Pod起不来要么流量一上来就内存爆掉还有的连探针都没配服务挂在半死状态自己都不知道。这篇把我从零部署Spring Boot项目的完整思路、文件怎么写、为什么这么写、出现了问题怎么查原原本本理一遍顺便把企业项目里最常问的那几个点也交代清楚。适合谁看正在从单体部署往容器化迁移的Java后端刚把应用打成镜像但不太清楚Kubernetes里怎么编排的以及在测试环境能用docker run跑通、到K8s上却总出幺蛾子的同学。我不打算做概念宣讲Kubernetes和Spring Boot的基本概念默认你已经有数直接讲实操。1. 部署前的准备镜像构建与容器化细节1.1 Spring Boot应用镜像的构建思路很多人把镜像构建当成“写一个Dockerfile把jar丢进去”这么简单但在Kubernetes里跑和本地docker run有几个本质区别一是Pod会被调度到不同节点镜像体积直接决定拉取时间二是容器进程被K8s直接托管1号进程是否优雅处理SIGTERM会直接影响滚动发布三是JVM对容器CPU和内存的感知如果不正确性能会跑偏。基础镜像我建议优先用Eclipse Temurin的JRE版本而不是JDK完整版。一个只有几十MB的JRE基础镜像配合多阶段构建最终镜像能控制在200MB以内传统胖Jar方式可能上500MB。如果你们的Spring Boot版本已经到3.x推荐直接上eclipse-temurin:17-jre-alpine或21-jre-alpine这类基于Alpine的镜像Alpine的musl libc已经能正常跑JVM而且镜像非常小唯一的坑是如果你们用了一些依赖native库的中间件比如某些OCR、图像处理库可能得换成ubuntu-jammy基础镜像否则运行时会缺动态库报错。多阶段构建是最推荐的方式理由不只是“减小体积”。它可以彻底把构建环境和运行环境隔离保证宿主机上不残留Maven仓库、编译临时文件之类的垃圾另外在Docker缓存策略上也更友好。.dockerignore文件别忘了加把.git、target、*.iml、IDE配置都排除掉不然每改一行代码构建上下文都会把几百MB的代码和缓存推给Docker daemon。1.2 JVM在容器里的内存和CPU配置这里是我见过最多人踩坑的地方也是线上事故高发区。JVM默认的堆大小是物理内存的1/4但容器里看到的是宿主机内存而不是cgroup限制这就导致一个极其常见的现象你在Deployment里写了limits: memory: 512Mi结果JVM直接把堆开到宿主机几个G最后容器被OOM Killer杀掉Pod无限重启。解决办法很简单显式指定-XX:MaxRAMPercentage75.0这类比例参数或者直接用-Xmx限制堆大小。我个人的习惯是堆内存不超过容器内存的70%再留一些给元空间、线程栈、JIT编译等。比如容器限制512Mi堆就写-Xmx384m预留大概25%左右的非堆开销。JDK 8u191和JDK 11默认开启了UseContainerSupport但开启了不代表你就能不管因为默认值依然按宿主机内存算还是得手动设置。另一个值得说的点是对容器CPU的限制。默认JVM会检测宿主机CPU核心数来设置GC线程和ForkJoinPool如果你limit了2核但宿主机是32核JVM会创建大量的GC线程造成无谓的上下文切换。加一句-XX:ActiveProcessorCount2就能解决也可以搭配容器限核配置。# 多阶段构建示例 FROM maven:3.9-eclipse-temurin-17 AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline -B COPY src ./src RUN mvn clean package -DskipTests FROM eclipse-temurin:17-jre-alpine RUN addgroup -S app adduser -S app -G app WORKDIR /app COPY --frombuild /app/target/*.jar app.jar USER app ENV JAVA_OPTS-XX:MaxRAMPercentage75.0 -XX:ActiveProcessorCount2 ENV TZAsia/Shanghai EXPOSE 8080 ENTRYPOINT [sh, -c, java $JAVA_OPTS -jar app.jar]这里的adduser非root用户很重要别用默认的root跑服务。一方面这是容器安全基线另一方面一些K8s集群开了Pod Security Admission之后root用户直接会被拦截。还有把时区在镜像层就设好TZAsia/Shanghai不然应用里数据库连接、日志时间戳会差8个小时排查问题的时候焦虑加倍。1.3 优雅停机与Spring Boot的配合Kubernetes在滚动更新或Pod删除时会给容器主进程发送SIGTERM信号然后等待terminationGracePeriodSeconds指定的时间默认30秒超时后强制SIGKILL。Spring Boot默认会注册JVM ShutdownHook但问题在于Spring Boot的关闭默认是立刻销毁Bean不等待正在处理的请求结束。想要优雅停机需要在application.yml里开启server: shutdown: graceful spring: lifecycle: timeout-per-shutdown-phase: 20sshutdown: graceful让Spring Boot在收到SIGTERM后停止接收新请求并等待存量请求处理完再销毁容器。timeout-per-shutdown-phase控制等待上限这个值建议比K8s的terminationGracePeriodSeconds小一点保证你有足够时间让Spring完成收尾。说到Java 21的虚拟线程如果你的服务是Spring Boot 3.5搭配虚拟线程部署上多注意一下虚拟线程适合IO密集型场景但容器里线程资源已经由K8s在管理很多人在Pod里配上几百个平台线程照样没事虚拟线程的优势主要在应用内并发模型更轻量跟K8s本身没有直接冲突。不过有一点要注意如果你在代码里用了ThreadLocal、synchronized或者一些没适配虚拟线程的库改造成本会很明显部署阶段的JVM参数反而不需要特殊处理。2. 核心资源编排从Deployment到Service2.1 Deployment设计副本数、滚动更新与探针Deployment是Kubernetes里最基础的负载资源它负责维持Pod副本数在期望状态。Spring Boot应用无状态天然适合Deployment管理。需要重点说的是滚动更新策略和探针的配合这是保证发布不中断流量的根本。一个生产可用的副本数可以设为3但更重要的是更新策略strategy: type: RollingUpdate rollingUpdate: maxSurge: 25% maxUnavailable: 0maxUnavailable: 0意味着滚动过程中任何时候都不允许可用Pod少于期望副本数代价是更新时先起一个额外Pod再杀掉旧的maxSurge: 25%控制最多超过期望副本数的比例。这套组合在Spring Boot启动较慢的场景下非常重要因为如果maxUnavailable不是0滚动一开始就会先停掉一个Pod而新Pod可能还在拉镜像、等Java启动流量窗口会变窄。很多公司在测试环境不敏感一到生产发布就报警大概率就是这个参数没配对。探针是K8s健康检查的关键。Spring Boot项目直接集成Actuatorspring: boot: admin: context-path: /hello # 注意这和下面没关系只是示例 management: endpoints: web: exposure: include: health,info,metrics endpoint: health: probes: enabled: true health: livenessstate: enabled: true readinessstate: enabled: true开启probes.enabled: true后/actuator/health会暴露liveness和readiness两个子状态。K8s里配两组探针livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 20 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 3这里有几个关键点要解释清楚。liveness探针失败会重启容器readiness探针失败会从Service Endpoints中摘除流量。区别是如果你的应用因为某个外部依赖比如Redis连不上暂时不可用readiness失败但liveness成功K8s不会重启Pod而只是停流量如果连liveness都触发了说明进程本身已经进入无法自愈的状态只能重启。这个设计非常贴合Spring Boot的ReadinessStateHealthIndicator和LivenessStateHealthIndicator语义千万别只用单个/actuator/health同时配给两个探针不然数据库抖动的时候会变成整个Pod被反复重启。initialDelaySeconds要给足。Spring Boot冷启动慢如果是Java 21 微服务架构可能启动要30秒起步太短的initialDelay会直接打成CrashLoopBackOff。更保险的做法是用startupProbe专门负责兜底启动期间的健康检查startupProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 0 periodSeconds: 5 failureThreshold: 60startupProbe成功前livenessProbe不会启动避免启动慢导致误杀。2.2 Service与Ingress应用如何被访问Deployment只负责拉起Pod外部访问还要靠Service。Service类型有三类常用选择ClusterIP集群内访问、NodePort节点端口访问、LoadBalancer云厂商负载均衡。对Spring Boot企业应用来说生产环境最常见的是“ClusterIP Ingress”这套组合NodePort只适合本地调试LoadBalancer一般交给云平台自动创建价格和权限成本都不低。apiVersion: v1 kind: Service metadata: name: spring-boot-service namespace: production spec: selector: app: spring-boot-demo ports: - name: http port: 80 targetPort: 8080 type: ClusterIP注意selector要和Deployment里的Pod标签完全一致这是新手最容易分流失败的原因。port是Service暴露的端口targetPort是容器内应用监听的端口Spring Boot默认8080。Ingress一般用nginx-ingress-controllerapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: spring-boot-ingress namespace: production spec: ingressClassName: nginx rules: - host: app.example.com http: paths: - path: / pathType: Prefix backend: service: name: spring-boot-service port: number: 80企业项目里如果服务很多Ingress的路径转发和域名规划要提前设计好不然后期几十个服务挤在一个Ingress里改起来非常痛苦。2.3 配置管理ConfigMap与Secret的正确打开方式Spring Boot的配置天然是application.yml外部化这给K8s的ConfigMap提供了很好的接入点。把环境相关的配置数据源地址、Redis地址、日志级别、业务开关放到ConfigMap里镜像保持环境无关这在多环境部署时非常实用。常见的做法有两种。一种是通过环境变量注入env: - name: SPRING_PROFILES_ACTIVE value: prod - name: DB_HOST valueFrom: configMapKeyRef: name: app-config key: db.host另一种是把整个application.yml做成ConfigMap用volume挂载到容器里覆盖默认配置。第二种在配置项特别多的时候更清晰apiVersion: v1 kind: ConfigMap metadata: name: app-config namespace: production data: application.yml: | server: port: 8080 spring: datasource: url: jdbc:mysql://mysql-service:3306/appdb?useSSLfalse username: appuser password: ${DB_PASSWORD}volume挂载方式volumeMounts: - name: app-config mountPath: /app/config volumes: - name: app-config configMap: name: app-config重点是/app/config这个位置。Spring Boot的配置加载顺序里./config/目录优先于./所以只要jar包在/app下配置放/app/config就能自动被识别不需要额外指定spring.config.location。我测试过这个方案实测下来非常稳尤其适合保存完整的、带缩进的YAML文件。数据库密码、API密钥这类敏感信息一定放Secret而不是ConfigMap。Secret本质上只是Base64编码谈不上绝对安全但至少不会出现在ConfigMap明文里配合RBAC控制访问范围能降低泄露风险。从ConfigMap/Secret挂载到容器的文件在Pod运行期间如果ConfigMap发生更新文件内容会延迟同步有kubelet定期同步机制但进程不会自动重启加载新配置所以改了配置最好滚动更新一下Deployment这个很多人不知道。如果配置项特别多变且需要动态刷新建议上Nacos或Apollo这类配置中心而不是在K8s里硬磕ConfigMap。3. 完整实操把一个Spring Boot项目跑起来3.1 本地快速验证先把一个最小的Spring Boot服务构建成镜像。假设项目是标准的Maven结构本地已经能跑通mvn spring-boot:run接下来按顺序操作# 1. 构建镜像 docker build -t registry.company.com/demo/spring-boot-app:1.0.0 . # 2. 本地验证容器能否正常启动 docker run --rm -p 8080:8080 registry.company.com/demo/spring-boot-app:1.0.0 # 3. 推送到镜像仓库 docker push registry.company.com/demo/spring-boot-app:1.0.0注意推送的镜像名。K8s节点拉镜像时如果用的是私有仓库需要在Deployment里配置imagePullSecrets否则Pod启动时会报ImagePullBackOff。这个Secrets需要提前创建kubectl create secret docker-registry registry-secret \ --docker-serverregistry.company.com \ --docker-usernameyourname \ --docker-passwordyourpassword \ -n production3.2 YAML文件逐段解读与部署现在写一个完整的Deployment YAML。我强烈建议你自己手敲一遍而不是从网上复制因为里面每一个字段都得知道干什么apiVersion: apps/v1 kind: Deployment metadata: name: spring-boot-demo namespace: production labels: app: spring-boot-demo spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 25% maxUnavailable: 0 selector: matchLabels: app: spring-boot-demo template: metadata: labels: app: spring-boot-demo spec: imagePullSecrets: - name: registry-secret containers: - name: spring-boot-app image: registry.company.com/demo/spring-boot-app:1.0.0 imagePullPolicy: Always ports: - containerPort: 8080 env: - name: SPRING_PROFILES_ACTIVE value: prod resources: requests: cpu: 500m memory: 512Mi limits: cpu: 1 memory: 1Gi startupProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 0 periodSeconds: 5 failureThreshold: 60 livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 3 volumeMounts: - name: app-config mountPath: /app/config volumes: - name: app-config configMap: name: app-configresources里requests和limits的区别一定要搞清楚。requests是调度依据K8s根据它决定把Pod调度到哪个节点limits是运行限制超过会被限流甚至被杀。我见过很多Spring Boot应用只写了limits不写requests或者requests等于limits前者容易导致节点资源超卖时Pod被挤死后者容易让调度器以为Pod吃得很多而拒绝调度。合理的做法是requests略低于平时消耗limits设为峰值上限给JVM和GC留缓冲区。执行发布kubectl apply -f app-deployment.yaml kubectl apply -f app-service.yaml kubectl apply -f app-ingress.yaml # 查看状态 kubectl get pods -n production -o wide kubectl rollout status deployment/spring-boot-demo -n production等所有Pod都变成Running且Ready 1/1用kubectl port-forward先做本地验证kubectl port-forward service/spring-boot-demo -n production 8080:80 curl http://localhost:8080/actuator/health返回{status:UP}说明基础链路已经通了。3.3 滚动发布、回滚与优雅下线验证镜像更新后重新打tag再apply一次Deployment就触发滚动更新docker build -t registry.company.com/demo/spring-boot-app:1.0.1 . docker push registry.company.com/demo/spring-boot-app:1.0.1 kubectl set image deployment/spring-boot-demo spring-boot-appregistry.company.com/demo/spring-boot-app:1.0.1 -n production或者直接改YAML里的image标签再kubectl apply。观察滚动过程建议开一个窗口不停watch kubectl get pods你会看到新的Pod先起来等Readiness通过后旧的Pod才逐个被终止。这就是maxUnavailable: 0的直观效果流量全程没有空窗。如果发布后发现新版本有问题第一时间回滚kubectl rollout undo deployment/spring-boot-demo -n production回滚是重新部署上一版本的镜像同样走滚动更新。这个命令在企业故障处理里价值极高但回滚前一定要确认是要回到上一版本而不是撤销多次更新。用kubectl rollout history deployment/spring-boot-demo可以查历史的版本号。很多人在部署Spring Boot项目时忽略了优雅下线验证。发布过程中如果旧Pod还在处理长请求SIGTERM之后K8s会先从Service的Endpoints列表里把这个Pod摘掉再发SIGTERM。这个摘除是异步的可能有一小段时间Pod已经被移除但还是有连着的长连接。对策是给Service配上publishNotReadyAddresses: false默认就是false同时让application开启graceful shutdown。用压测工具稍微打一点QPS再触发滚动观察错误率是否为零这个测试建议每次结构调整后都做一遍。4. 企业落地时的常见问题与调试技巧4.1 Pod状态异常排查CrashLoopBackOff与ImagePullBackOff这类问题是新人的头号杀手。CrashLoopBackOff先看日志kubectl logs pod-name -n production如果上一次是OOMKilled需要加--previous看退出前日志。Spring Boot应用Crash最常见的原因是内存超限导致OOMKilled这种只会在资源限制很小的时候出现处理办法是调大limits或者压低-Xmx。其次是配置加载失败比如ConfigMap里application.yml格式错误Spring启动直接抛异常看日志会非常明显。还有一种情况是健康检查失败被反复重启这个要看kubectl describe pod里的事件。ImagePullBackOff的排查思路比较固定。先确认镜像名和tag是否正确再确认节点是否能访问镜像仓库最后确认私有仓库认证的secret是否存在于对应namespace。比较隐蔽的坑是Digest权限问题如果镜像仓库开启了严格的防篡改策略必须使用sha256摘要拉取这时要改用image: registry.company.com/demo/spring-boot-appsha256:xxxxx。# 快速定位Pod为什么起不来 kubectl describe pod pod-name -n production kubectl get events --sort-by.lastTimestamp -n production | tail -204.2 访问链路不通Service与Ingress排错服务部署好了但访问不了这是最常见的企业现场问题。先分清楚是Service不通还是Ingress不通。用kubectl exec进一个同namespace的Podcurl Service的ClusterIPkubectl run curl-test --imagecurlimages/curl -it --rm --restartNever --namespace production -- sh curl http://spring-boot-service:80/actuator/health如果curl通但浏览器/域名不通问题在Ingress或DNS。如果curl都不通大概率是Service的selector和Pod标签对不上。用kubectl get endpoints service-name看Endpoints是否有Pod地址如果没有说明selector匹配失败如果有但访问异常检查targetPort是否指向了正确的容器端口。另一个常见坑是Ingress controller和Service的端口协作。nginx-ingress转发到Service默认用port字段这里是80但如果targetPort写的是name要确认这个命名和容器端口一致。之前遇到过targetPort: web但Deployment容器端口没有定义name: web导致后端完全不可达这个问题在YAML校验时还不报错非常隐蔽。4.3 探针相关的玄学故障与JVM信号问题探针是把双刃剑配好了自动恢复配不好天天误杀。最常见的是内存充足但Pod不断重启查看describe后是Liveness探针失败。原因通常是Actuator的health端点里某个子依赖健康检查耗时太长比如数据库连接池在冷启动时会先初始化如果liveness探针的periodSeconds太短或timeoutSeconds不够就会被判定失败。解决方法是给health的依赖项配置合并不必要的检查或者对探针的timeout、failureThreshold放宽一些。JVM还有一个著名的坑K8s滚动更新时旧Pod收到SIGTERM但JVM没来得及处理完就被SIGKILL。原因通常有两个一是前面提到的graceful shutdown没开二是容器里的ENTRYPOINT写成了java -jar但没有正确接收信号。在Dockerfile里如果用了一个shell包装脚本要注意SIGTERM并不会自动转发给java子进程需要在脚本里加上exec或者正确的trap。上面的Dockerfile直接用sh -c java $JAVA_OPTS -jar app.jar这样sh其实会exec掉java信号能直达但如果用了自定义脚本循环等待就要非常小心。Spring Boot 3.x Java 21虚拟线程的部署环境探针行为也略有不同。虚拟线程不占平台线程栈启动阶段堆内存压力会小一些但因为线程数可以开到很大随便一个并发请求就可能创建几万个虚拟线程如果日志框架没有适配调试过程中会看到线程创建异常频繁需要调整日志的异步队列参数。4.4 企业项目里的安全基线防止未授权访问K8s未授权访问漏洞在业界被反复提及部署Spring Boot项目时尤其要注意控制面组件不能裸奔。API Server、Dashboard、kubelet的端口不要直接暴露到公网访问控制至少三层网络策略限制来源IP、RBAC最小权限、TLS证书认证。很多团队为了方便把Dashboard的Service类型改成NodePort直接暴露这是高危操作。如果你确实需要通过Dashboard操作集群尽量用kubectl proxy或绑定内网域名加上身份认证。还有一点是企业落地时容易忽略的命名空间隔离和资源配额ResourceQuota。仓库里只给测试环境上了生产后不同团队的服务混在一个namespace配置互相覆盖、Pod抢占资源极难排查。建议每个业务线一个namespace配上ResourceQuota和LimitRange让默认资源限制自动生效。4.5 可观测性日志、监控与告警Spring Boot应用在K8s里排查问题最舒服的方式是直接把日志打到stdout让容器运行时收集再用Loki或ELK统一检索。Actuator的metrics接PrometheusGrafana做面板点击就能看到JVM堆内存、GC、QPS、RT的指标。这个组合在企业项目里是标配部署时只需要在Deployment注解里加上Prometheus抓取配置metadata: annotations: prometheus.io/scrape: true prometheus.io/path: /actuator/prometheus prometheus.io/port: 8080不过前提是Actuator暴露了prometheus端点management: endpoints: web: exposure: include: health,info,prometheus我第一次排查生产问题就靠这套链路快速定位到是GC停顿太频繁导致接口变慢而不是以为K8s本身出毛病。日志采集那边Filebeat/DaemonSet方式在节点采集比每Pod塞sidecar省资源得多除非你们需要针对个别Pod做精细的日志解析一般不需要用sidecar模式。4.6 特殊部署形态GraalVM原生镜像与多架构Spring Boot应用除了标准JVM镜像现在也有不少人尝试用GraalVM Native Image打成原生可执行文件部署到K8s里最大的优势是启动时间从秒级降到毫秒级内存占用也大幅减少。这一套在K8s环境里收益非常明显尤其是弹性伸缩场景Pod扩容可以做到秒级完成。但代价是构建时需要对反射、动态代理、资源文件做额外配置很多Spring Boot的生态库比如MyBatis、Spring Security需要额外适配。如果你们的项目用了不少反射或SPI机制优先小范围试点别一上来全量迁移。多架构镜像在混合架构集群里也很实用。如果集群里有x86节点和ARM节点比如Mac M系列搭的集群和云上x86混编打镜像时用docker buildx同时构建linux/amd64和linux/arm64推送到镜像仓库后用manifest列表实现按需拉取。之前我们没注意这个结果一些Pod在ARM节点上拉了amd64镜像直接exec format error。改起来很简单就是构建命令加上--platform参数CI流水线里写两条build任务。4.7 常见问题速查表现象可能原因排查/解决思路Pod一直Pending节点资源不足、没有匹配的节点标签kubectl describe pod看调度事件检查节点资源和污点容忍度Pod Running但Ready 0/1启动慢或readiness失败kubectl logs看启动日志检查Actuator health状态确认探针路径CrashLoopBackOff启动异常、OOM、探针误杀kubectl logs --previous看退出码和OOMKilled事件ImagePullBackOff镜像名错误、仓库不可达、凭证缺失检查imagePullPolicy、imagePullSecrets、仓库网络连通性服务访问超时Service selector不匹配、targetPort错误、Ingress后端异常检查Endpoints、用临时Pod curl测试滚动发布中断readiness探针没通过、maxUnavailable配置不当观察rollout status检查新Pod日志必要时回滚内存被OOMKilledJVM堆设置超过容器limit显式设置MaxRAMPercentage或Xmx时间差8小时镜像层没设置时区Dockerfile里ENV TZAsia/Shanghai配置改了不生效ConfigMap更新不会热加载到进程改完配置滚动重启Deployment网关超时但日志正常线程池阻塞或GC停顿用PrometheusActuator看线程活跃数和GC时间实际执行中很多问题的根源都是资源配置和探针配置互相不匹配。我建议每次微调探针或resources之后都主动做一次滚动发布验证不要只在出问题时才去看。我个人在实际操作中的体会是把Spring Boot部署到Kubernetes这件事技术密度并不在于那一堆YAML的字段拼写而在于你到底愿不愿意花时间去搞清楚“流量的生命周期”——从镜像构建、到调度、到启动探活、到优雅停机、到滚动切换每一个环节里JVM和K8s的边界在哪里谁负责什么。早期我也经历过照着模板一梭子apply下去页面500了完全不知道从哪查起。后来习惯养成了每写一个资源先画一遍流量路径再看一眼对应的存活探针和资源配置问题数量直线下降。最后再分享一个小经验测试环境的集群配置别和生产差太多资源限制、探针参数都不一致会导致测试环境一切正常、生产发布必出事。尽量通过Helm或Kustomize维护一套可参数化的部署模板环境差异只体现在values里这样才能在上线前把绝大多数坑先踩掉。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。