使用 New Relic APM 和 Kubernetes Metrics 监控 EKS 上的 Java 微服务

简介: 在阿里云AKS上运行Java微服务常遇性能瓶颈与OOMKilled等问题。本文教你通过New Relic实现集群与JVM双层监控,集成Helm部署、JVM代理注入、GC调优及告警仪表盘,打通从节点资源到应用内存的全链路观测,提升排障效率,保障服务稳定。

在阿里云 AKS(容器服务 Kubernetes 版)上跑 Java 微服务,是不是总遇到这些头疼事?明明看 pod 的 CPU、内存都正常,服务却卡得不行;突然就报 OOMKilled,查半天不知道是 JVM 内存没调好还是代码有内存泄漏;想盯 GC(垃圾回收)情况,却没个直观的方式…


别慌!今天就教你用 New Relic 把 AKS 集群监控和 JVM 深度观测捏到一块儿,从集群的 pod、节点状态,到 JVM 的堆内存、GC 停顿、线程活动,全给你扒得明明白白,还能自定义仪表盘和告警,再也不用 “瞎猜” 排障了。


一、先理清楚:为啥要这么监控?

咱先不说复杂术语,直白讲清楚监控的核心逻辑 ——AKS 和 Java 微服务要 “两层都盯紧”:


  1. AKS 集群层:看 pod 是不是正常运行、节点资源够不够、部署有没有问题(比如副本数够不够),这是 “表面健康度”;
  2. JVM 应用层:Java 服务的 “猫腻” 都在 JVM 里 —— 堆内存满没满、GC 是不是频繁卡顿、线程有没有死锁,这些光看 pod 的 CPU / 内存是看不出来的,但一旦出问题,服务直接崩给你看。


而 New Relic 刚好能把这两层打通:一边用 Helm 装集群监控组件,抓 AKS 的 K8s 指标;一边给 Java 服务挂个轻量的 JVM 代理,扒 JVM 内部数据,最后在一个界面里统一展示,排障时不用来回切工具,效率直接拉满。


二、准备工作:这些东西得先有

开始前先把 “装备” 备齐,不用复杂,几样基础的就行:


  • 一个阿里云 AKS 集群:已经创建好,并且本地装了kubectl(能连 AKS)和helm(用来装 New Relic 组件);
  • 一个Java 微服务:比如 Spring Boot 服务,已经部署到 AKS 上(没部署也没事,后面能跟着调);
  • 一个New Relic 账号:免费版就够咱练手,注册后能拿到license key(关键凭证,后面要用到);
  • 懂点基础概念:知道 JVM 的堆内存、GC 是啥,能看懂简单的 K8s YAML 配置。


三、第一步:用 Helm 在 AKS 上装 New Relic 集群监控

先把 New Relic 的 “集群监控插件” 装到 AKS 里,这样就能抓 pod、节点、K8s 对象(比如 deployments、services)的指标了。

1. 加 New Relic 的 Helm 仓库

打开终端,先把 New Relic 的 Helm 仓库拉到本地,再更新一下确保是最新版本:


# 添加New Relic Helm仓库
helm repo add newrelic https://helm-charts.newrelic.com
# 更新仓库(确保拿到最新的chart)
helm repo update

2. 装 New Relic 监控包(核心组件)

执行下面的命令,把集群监控的核心组件装到 AKS 的newrelic命名空间里(会自动创建这个命名空间)。注意把<你的New Relic License Key><你的AKS集群名>换成自己的实际信息:

helm install newrelic-bundle newrelic/nri-bundle \
  --set global.licenseKey=<你的New Relic License Key> \
  --set global.cluster=<你的AKS集群名> \  # 比如aks-prod-cluster
  --namespace newrelic --create-namespace \
  --set newrelic-infrastructure.enabled=true \  # 抓节点/容器指标
  --set kube-state-metrics.enabled=true \       # 抓K8s对象指标(如deployments、pods状态)
  --set prometheus.enabled=true                 # 支持自定义指标(后续扩展用)


等个 1-2 分钟,用kubectl get pods -n newrelic看看组件是不是都跑起来了( STATUS 是 Running 就没问题)。


四、第二步:给 Java 服务挂 New Relic JVM 代理

集群监控装好了,但还看不了 JVM 内部数据 —— 得给 Java 服务加个 “代理”(New Relic Java Agent),让它把 JVM 的堆、GC、线程数据发去 New Relic。

1. 改 Dockerfile:把代理包塞进镜像里

不管你是自己写的 Spring Boot 服务,还是用别人的镜像,都要在 Dockerfile 里加几行,把 New Relic 的 Java 代理下载并解压到镜像里:

# 下载New Relic Java代理(最新版)
ADD https://download.newrelic.com/newrelic/java-agent/newrelic-agent/current/newrelic-java.zip /opt/
# 解压到/opt/newrelic目录
RUN unzip /opt/newrelic-java.zip -d /opt/


然后重新构建镜像,推到阿里云容器镜像服务(ACR),再更新 AKS 里的 Deployment。

2. 加 JVM 启动参数:启用代理

在 Java 服务的启动命令里,加个-javaagent参数,指定代理的 jar 包路径。比如在 K8s 的 Deployment YAML 里,改spec.containers.commandargs(如果是 Spring Boot,也可以在application.yml里配,但启动参数更直接):

spec:
  containers:
  - name: your-java-app  # 你的服务名
    image: 你的ACR镜像地址:版本  # 比如 registry.cn-hangzhou.aliyuncs.com/xxx/xxx:v1
    args: ["java", "-javaagent:/opt/newrelic/newrelic.jar", "-jar", "/app/your-app.jar"]  # 关键是加-javaagent这部分

3. 加环境变量:配置代理(连 New Relic)

还要在 Deployment YAML 里加两个环境变量:一个是服务名(方便在 New Relic 里识别),一个是 New Relic 的 license key(用 K8s Secret 存,别明文写!)。

第一步:创建 K8s Secret 存 license key

先在 AKS 里创建一个 Secret,把 New Relic 的 license key 存进去:

kubectl create secret generic newrelic-license \
  --from-literal=license_key=<你的New Relic License Key> \
  --namespace 你的服务所在命名空间  # 比如default

第二步:在 Deployment 里引用 Secret

修改 Deployment YAML,加环境变量:

spec:
  containers:
  - name: your-java-app
    image: 你的ACR镜像地址:版本
    args: ["java", "-javaagent:/opt/newrelic/newrelic.jar", "-jar", "/app/your-app.jar"]
    env:
    - name: NEW_RELIC_APP_NAME  # 给服务起个名,New Relic里会显示这个
      value: "java-springboot-demo"
    - name: NEW_RELIC_LICENSE_KEY  # 从Secret里读license key
      valueFrom:
        secretKeyRef:
          name: newrelic-license  # 刚才创建的Secret名
          key: license_key        # Secret里的key


改完后 apply 一下:kubectl apply -f your-deployment.yaml,等 pod 重启,代理就生效了。


五、第三步:JVM 调优!避免 AKS 里的 OOMKilled

在 AKS 里跑 Java,最容易踩的坑就是 “JVM 不认 K8s 的内存限制”—— 比如你给 pod 设了 1G 内存限制,但 JVM 默认会用主机内存的 1/4(可能远超 1G),结果直接被 AKS 杀了(OOMKilled)。


所以必须给 JVM 加几个关键参数,让它 “听话”:

# 在Deployment的args里加JVM调优参数
args: [
  "java", 
  "-javaagent:/opt/newrelic/newrelic.jar",
  "-XX:+UseContainerSupport",  # 让JVM识别容器环境(关键!)
  "-XX:MaxRAMPercentage=75.0", # JVM最大堆内存占pod内存限制的75%(别设100%,留空间给其他进程)
  "-XshowSettings:vm",         # 启动时打印JVM配置(方便排查)
  "-XX:+PrintGCDetails",       # 打印GC详细日志
  "-XX:+PrintGCDateStamps",    # GC日志加时间戳
  "-Xloggc:/tmp/gc.log",       # GC日志存到/tmp/gc.log
  "-jar", "/app/your-app.jar"
]


同时,要给 pod 设好资源限制(和 JVM 参数对齐):

spec:
  containers:
  - name: your-java-app
    # 其他配置...
    resources:
      requests:  # 最小资源需求(AKS调度用)
        memory: "512Mi"
        cpu: "250m"
      limits:    # 最大资源限制(JVM要认这个)
        memory: "1Gi"  # 和上面的MaxRAMPercentage对应(1G的75%就是768M堆内存)
        cpu: "500m"


这样一来,JVM 不会超内存,AKS 也不会随便杀 pod 了。


六、第四步:看监控、建仪表盘、设告警

现在数据都在往 New Relic 传了,接下来就是 “怎么看” 和 “怎么及时发现问题”。

1. 先看基础数据:AKS 集群 + JVM 指标

打开 New Relic 官网,登录后按路径找:


  • AKS 集群指标:左边菜单 → Infrastructure → Kubernetes → 找到你的 AKS 集群名,能看到节点 CPU / 内存、pod 状态、部署情况;
  • JVM 指标:左边菜单 → APM & Services → 找到你设的NEW_RELIC_APP_NAME(比如 java-springboot-demo),点进去:
  • 看堆内存:Heap Usage 图表,有没有持续上涨(持续涨可能是内存泄漏);
  • 看 GC:GC Activity 图表,停顿时间是不是太长(超过 1 秒就要注意);
  • 看线程:Threads 图表,有没有死锁或线程数暴增。

2. 建自定义仪表盘:把关键指标放一起

默认的图表可能不够直观,自己建个仪表盘,把 “pod 内存 + JVM 堆 + GC 停顿 + 服务延迟” 放一块:


  1. 左边菜单 → Dashboards → Create dashboard;
  2. 点 “Add widget”,选要加的指标:
  • AKS 相关:Kubernetes → Pod → Memory Usage(选你的服务 pod);
  • JVM 相关:JVM → Heap → Used,JVM → GC → Longest Pause;
  • 服务相关:APM → Response Time(服务响应时间);
  1. 拖放调整位置,保存仪表盘(比如叫 “AKS-Java 服务监控面板”),以后打开就能一眼看全。

3. 设告警:出问题立刻通知

最怕的是 “问题发生了才知道”,所以必须设告警。比如 GC 停顿超过 1 秒就报警:


  1. 左边菜单 → Alerts & AI → Create alert;
  2. 选 “Metric alert”,然后选指标:JVM → GC → Longest GC Pause;
  3. 设阈值:比如 “持续 1 分钟,值大于 1000 毫秒(1 秒)”;
  4. 设通知方式:可以连 Slack、钉钉(需要装插件),或者发邮件,确保运维能及时收到。


七、额外技巧:GC 日志存到阿里云 OSS(替代 S3)

前面把 GC 日志存在了 pod 的/tmp/gc.log里,但 pod 一删日志就没了。阿里云没有 S3,但有 OSS,咱可以把 GC 日志存到 OSS 里,方便后续分析。

怎么存?用 Fluent Bit(日志收集工具)

  1. 在 pod 里挂载 emptyDir:让/tmp目录在 pod 重启时不丢日志(虽然 pod 删了还是没,但能撑到重启):

spec:
  containers:
  - name: your-java-app
    # 其他配置...
    volumeMounts:
    - name: gc-log-volume
      mountPath: /tmp  # GC日志存在这里
  volumes:
  - name: gc-log-volume
    emptyDir: {}  # 临时存储,pod重启不丢,pod删除才丢


  1. 部署 Fluent Bit 到 AKS:用 Fluent Bit 的 OSS 输出插件,把/tmp/gc.log推到阿里云 OSS:
  • 先在阿里云控制台创建 OSS 桶(比如aks-java-gc-logs);
  • 给 AKS 节点绑定 IAM 角色(要有 OSS 的PutObject权限);
  • 用 Helm 装 Fluent Bit,配置输出到 OSS(具体 YAML 可以参考阿里云文档,核心是output.oss的配置)。


这样 GC 日志会实时存到 OSS,就算 pod 删了,也能在 OSS 里找日志分析。


八、排障小技巧:遇到问题怎么办?

万一监控数据没出来,或者服务有问题,按下面的表查:


问题现象 怎么排查?
New Relic 里看不到 AKS 数据 1. 查 newrelic 命名空间的 pod 是不是都 Running;2. 确认 Helm 安装时 license key 没输错
看不到 JVM 指标 1. 查 Java 服务 pod 日志:kubectl logs <pod名> --container <容器名>,看有没有代理报错;2. 确认-javaagent路径对不对
GC 日志没存到 OSS 1. 查 Fluent Bit 日志:kubectl logs <fluent-bit-pod名>;2. 确认 OSS 权限够不够


九、总结:这套监控好在哪?

  1. 全链路观测:从 AKS 集群到 JVM 内部,不用切工具,一个界面搞定;
  2. 提前预防问题:通过 GC、堆内存监控,能在服务崩之前发现苗头(比如内存泄漏);
  3. 排障快:知道是集群资源不够,还是 JVM 参数没调好,不用瞎猜;
  4. 灵活扩展:后续能加分布式追踪(看服务间调用),还能连钉钉、企业微信告警。


其实这套方案不复杂,跟着步骤走,1-2 小时就能搭好。对于在 AKS 上跑 Java 微服务的团队来说,监控做好了,运维压力能小一大半 —— 毕竟 “看得见问题”,才能 “快速解决问题” 嘛!

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
2月前
|
监控 Java 数据库
从零学 Dropwizard:手把手搭轻量 Java 微服务,告别 Spring 臃肿
Dropwizard 整合 Jetty、Jersey 等成熟组件,开箱即用,无需复杂配置。轻量高效,启动快,资源占用少,内置监控、健康检查与安全防护,搭配 Docker 部署便捷,是构建生产级 Java 微服务的极简利器。
250 2
|
2月前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1566 9
存储 jenkins 持续交付
450 2
|
2月前
|
Prometheus 监控 Java
日志收集和Spring 微服务监控的最佳实践
在微服务架构中,日志记录与监控对系统稳定性、问题排查和性能优化至关重要。本文介绍了在 Spring 微服务中实现高效日志记录与监控的最佳实践,涵盖日志级别选择、结构化日志、集中记录、服务ID跟踪、上下文信息添加、日志轮转,以及使用 Spring Boot Actuator、Micrometer、Prometheus、Grafana、ELK 堆栈等工具进行监控与可视化。通过这些方法,可提升系统的可观测性与运维效率。
270 1
日志收集和Spring 微服务监控的最佳实践
|
3月前
|
存储 Prometheus 监控
从入门到实战:一文掌握微服务监控系统 Prometheus + Grafana
随着微服务架构的发展,系统监控变得愈发重要。本文介绍如何利用 Prometheus 和 Grafana 构建高效的监控系统,涵盖数据采集、存储、可视化与告警机制,帮助开发者提升系统可观测性,及时发现故障并优化性能。内容涵盖 Prometheus 的核心组件、数据模型及部署方案,并结合 Grafana 实现可视化监控,适合初学者和进阶开发者参考实践。
525 6
|
4月前
|
缓存 Cloud Native Java
Java 面试微服务架构与云原生技术实操内容及核心考点梳理 Java 面试
本内容涵盖Java面试核心技术实操,包括微服务架构(Spring Cloud Alibaba)、响应式编程(WebFlux)、容器化(Docker+K8s)、函数式编程、多级缓存、分库分表、链路追踪(Skywalking)等大厂高频考点,助你系统提升面试能力。
228 0
|
4月前
|
IDE Java API
Java 17 新特性与微服务开发的实操指南
本内容涵盖Java 11至Java 17最新特性实战,包括var关键字、字符串增强、模块化系统、Stream API、异步编程、密封类等,并提供图书管理系统实战项目,帮助开发者掌握现代Java开发技巧与工具。
253 1
|
4月前
|
存储 监控 算法
企业上网监控场景下布隆过滤器的 Java 算法构建及其性能优化研究
布隆过滤器是一种高效的数据结构,广泛应用于企业上网监控系统中,用于快速判断员工访问的网址是否为违规站点。相比传统哈希表,它具有更低的内存占用和更快的查询速度,支持实时拦截、动态更新和资源压缩,有效提升系统性能并降低成本。
161 0
|
4月前
|
存储 监控 Shell
SkyWalking微服务监控部署与优化全攻略
综上所述,虽然SkyWalking的初始部署流程相对复杂,但通过一步步的准备和配置,可以充分发挥其作为可观测平台的强大功能,实现对微服务架构的高效监控和治理。尽管未亲临,心已向往。将一件事做到极致,便是天分的展现。
|
1月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
127 1