使用 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 微服务的团队来说,监控做好了,运维压力能小一大半 —— 毕竟 “看得见问题”,才能 “快速解决问题” 嘛!

目录
相关文章
|
1天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1055 0
|
10天前
|
人工智能 运维 安全
|
1天前
|
弹性计算 Kubernetes jenkins
如何在 ECS/EKS 集群中有效使用 Jenkins
本文探讨了如何将 Jenkins 与 AWS ECS 和 EKS 集群集成,以构建高效、灵活且具备自动扩缩容能力的 CI/CD 流水线,提升软件交付效率并优化资源成本。
241 0
|
8天前
|
人工智能 异构计算
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
|
8天前
|
人工智能 测试技术 API
智能体(AI Agent)搭建全攻略:从概念到实践的终极指南
在人工智能浪潮中,智能体(AI Agent)正成为变革性技术。它们具备自主决策、环境感知、任务执行等能力,广泛应用于日常任务与商业流程。本文详解智能体概念、架构及七步搭建指南,助你打造专属智能体,迎接智能自动化新时代。
|
9天前
|
机器学习/深度学习 人工智能 自然语言处理
B站开源IndexTTS2,用极致表现力颠覆听觉体验
在语音合成技术不断演进的背景下,早期版本的IndexTTS虽然在多场景应用中展现出良好的表现,但在情感表达的细腻度与时长控制的精准性方面仍存在提升空间。为了解决这些问题,并进一步推动零样本语音合成在实际场景中的落地能力,B站语音团队对模型架构与训练策略进行了深度优化,推出了全新一代语音合成模型——IndexTTS2 。
725 23