在阿里云 AKS(容器服务 Kubernetes 版)上跑 Java 微服务,是不是总遇到这些头疼事?明明看 pod 的 CPU、内存都正常,服务却卡得不行;突然就报 OOMKilled,查半天不知道是 JVM 内存没调好还是代码有内存泄漏;想盯 GC(垃圾回收)情况,却没个直观的方式…
别慌!今天就教你用 New Relic 把 AKS 集群监控和 JVM 深度观测捏到一块儿,从集群的 pod、节点状态,到 JVM 的堆内存、GC 停顿、线程活动,全给你扒得明明白白,还能自定义仪表盘和告警,再也不用 “瞎猜” 排障了。
一、先理清楚:为啥要这么监控?
咱先不说复杂术语,直白讲清楚监控的核心逻辑 ——AKS 和 Java 微服务要 “两层都盯紧”:
- AKS 集群层:看 pod 是不是正常运行、节点资源够不够、部署有没有问题(比如副本数够不够),这是 “表面健康度”;
- 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.command
或args
(如果是 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 停顿 + 服务延迟” 放一块:
- 左边菜单 → Dashboards → Create dashboard;
- 点 “Add widget”,选要加的指标:
- AKS 相关:Kubernetes → Pod → Memory Usage(选你的服务 pod);
- JVM 相关:JVM → Heap → Used,JVM → GC → Longest Pause;
- 服务相关:APM → Response Time(服务响应时间);
- 拖放调整位置,保存仪表盘(比如叫 “AKS-Java 服务监控面板”),以后打开就能一眼看全。
3. 设告警:出问题立刻通知
最怕的是 “问题发生了才知道”,所以必须设告警。比如 GC 停顿超过 1 秒就报警:
- 左边菜单 → Alerts & AI → Create alert;
- 选 “Metric alert”,然后选指标:JVM → GC → Longest GC Pause;
- 设阈值:比如 “持续 1 分钟,值大于 1000 毫秒(1 秒)”;
- 设通知方式:可以连 Slack、钉钉(需要装插件),或者发邮件,确保运维能及时收到。
七、额外技巧:GC 日志存到阿里云 OSS(替代 S3)
前面把 GC 日志存在了 pod 的/tmp/gc.log
里,但 pod 一删日志就没了。阿里云没有 S3,但有 OSS,咱可以把 GC 日志存到 OSS 里,方便后续分析。
怎么存?用 Fluent Bit(日志收集工具)
- 在 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删除才丢
- 部署 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 权限够不够 |
九、总结:这套监控好在哪?
- 全链路观测:从 AKS 集群到 JVM 内部,不用切工具,一个界面搞定;
- 提前预防问题:通过 GC、堆内存监控,能在服务崩之前发现苗头(比如内存泄漏);
- 排障快:知道是集群资源不够,还是 JVM 参数没调好,不用瞎猜;
- 灵活扩展:后续能加分布式追踪(看服务间调用),还能连钉钉、企业微信告警。
其实这套方案不复杂,跟着步骤走,1-2 小时就能搭好。对于在 AKS 上跑 Java 微服务的团队来说,监控做好了,运维压力能小一大半 —— 毕竟 “看得见问题”,才能 “快速解决问题” 嘛!