微服务日志从“翻文件”到“秒级检索”:用华为云 CSS 搭建统一日志平台
【摘要】 摘要:微服务拆分后,日志散落在几十个 Pod 里,线上出问题靠“kubectl logs | grep”翻文件,排查一次半小时起步。本文以 Spring Cloud 微服务集群为场景,基于华为云云搜索服务 CSS(Elasticsearch + Kibana),打通日志采集、结构化解析、全文检索、聚合分析与告警全链路,把日志排查从“人肉翻”升级到“秒级定位”。标签建议:云搜索服务 CSS、E...
摘要:微服务拆分后,日志散落在几十个 Pod 里,线上出问题靠“kubectl logs | grep”翻文件,排查一次半小时起步。本文以 Spring Cloud 微服务集群为场景,基于华为云云搜索服务 CSS(Elasticsearch + Kibana),打通日志采集、结构化解析、全文检索、聚合分析与告警全链路,把日志排查从“人肉翻”升级到“秒级定位”。
标签建议:云搜索服务 CSS、Elasticsearch、日志分析、云原生、云端实践
一、背景与痛点
订单服务 6 个实例、用户服务 4 个实例、库存服务 4 个实例,全跑在 CCE 容器里。出问题时的排查流程:
# 1. 找到异常 Pod
kubectl get pods | grep order
# 2. 翻日志
kubectl logs order-service-7b8f6c9d-x2k4p --tail=500 | grep "ERROR"
# 3. 时间不对?再翻
kubectl logs order-service-7b8f6c9d-x2k4p --since=1h | grep "NullPointer"
# 4. 还找不到?换一个 Pod 再翻
痛点清单:
- 日志散落:15 个 Pod 各有一份日志,跨服务串联请求靠手工比对时间戳
- 检索低效:grep 只能做简单匹配,没法按字段过滤、没法统计错误趋势
- 容器重建即丢失:Pod 重启后本地日志清空,事后追溯无门
- 无聚合分析:不知道哪个接口报错最多、哪个异常是高频问题
- 没告警:等用户投诉了才知道系统一直在报错
核心诉求:集中采集、结构化存储、秒级检索、可视化分析、异常告警。
二、方案选型
2.1 为什么用 CSS 而不是自建 ES
|
维度
|
自建 ES
|
华为云 CSS
|
|---|---|---|
|
部署运维
|
自己装集群、配 JVM、管分片
|
控制台一键创建
|
|
版本升级
|
自己滚,容易翻车
|
平台托管升级
|
|
高可用
|
自己配副本、选主
|
自动多 AZ 副本
|
|
存储扩展
|
加盘要停机或做迁移
|
在线扩节点/磁盘
|
|
安全
|
自己配 TLS、账号体系
|
内置 IAM 认证 + HTTPS
|
|
成本
|
机器成本 + 运维人力
|
仅计算+存储,省运维
|
2.2 日志链路架构
微服务 Pod(Spring Boot)
│ 输出 JSON 格式日志到 stdout
▼
Filebeat(DaemonSet,每个节点一个)
│ 采集 stdout / 应用日志文件
▼
Logstash(可选,做结构化解析)
│ Grok 解析 + 字段提取 + 类型转换
▼
CSS 集群(Elasticsearch)
│ 索引存储 + 分片副本
▼
Kibana
├─ Discover:交互式检索
├─ Dashboard:聚合可视化
└─ Alerting:异常告警
日志量 < 50GB/天 可跳过 Logstash,Filebeat 直写 CSS;量大或格式复杂时加 Logstash 做缓冲和解析。
三、实操步骤
3.1 创建 CSS 集群
- 进入云搜索服务 CSS 控制台 → 创建集群
- 版本选 Elasticsearch 7.10(稳定主流版)
- 节点规格:
- 数据节点:4 核 16GB × 3(测试环境可 2 节点)
- 磁盘:超高 I/O(SSD),单节点 100GB
- 网络:与 CCE 集群同 VPC
- 安全模式:开启(IAM 认证 + HTTPS),创建账号
- 等待集群状态变为"可用"
避坑:数据节点内存建议 ≥ 16GB,ES 的 JVM heap 占一半,剩下的给 Lucene 做文件系统缓存。8GB 节点跑起来会很憋屈。
3.2 应用日志 JSON 化
Spring Boot 配置
logback-spring.xml,输出 JSON 格式:<appender name="JSON_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp><fieldName>timestamp</fieldName></timestamp>
<logLevel><fieldName>level</fieldName></logLevel>
<message><fieldName>message</fieldName></loggerName>
<mdc/>
<arguments/>
<stackTrace/>
</providers>
</encoder>
</appender>
输出样例:
{
"timestamp": "2024-03-15T10:23:45.123+08:00",
"level": "ERROR",
"message": "Order create failed: NullPointerException",
"mdc": {
"traceId": "a3f2c1d4e5b6",
"spanId": "b7c8d9e0",
"service": "order-service"
}
}
结构化是第一步。日志不 JSON 化,后面 Grok 解析就是噩梦。
3.3 部署 Filebeat 采集
CCE 集群中以 DaemonSet 方式部署 Filebeat:
filebeat-daemonset.yaml 核心配置:filebeat.inputs:
- type: container
paths:
- /var/log/containers/*.log
processors:
- add_kubernetes_metadata:
host: ${NODE_NAME}
matchers:
- logs_path:
logs_path: "/var/log/containers/"
output.logstash:
hosts: ["logstash-svc:5044"]
# 如果直写 CSS:
# output.elasticsearch:
# hosts: ["https://css-endpoint:9200"]
# username: "admin"
# password: "${CSS_PWD}"
# ssl.verification_mode: certificate
# ssl.certificate_authorities: ["/etc/ssl/certs/ca.crt"]
容器日志路径/var/log/containers/*.log是 CCE 标准路径,Filebeat 自动读取。
3.4 Logstash 结构化解析
如果日志已经是 JSON,Logstash 配置很简单:
input {
beats { port => 5044 }
}
filter {
json {
source => "message"
target => "log"
remove_field => ["message"]
}
mutate {
rename => {
"[log][timestamp]" => "@timestamp"
"[log][level]" => "log_level"
"[log][mdc][traceId]" => "trace_id"
"[log][mdc][service]" => "service_name"
}
}
date {
match => ["@timestamp", "ISO8601"]
}
}
output {
elasticsearch {
hosts => ["https://css-endpoint:9200"]
index => "app-logs-%{+YYYY.MM.dd}"
user => "admin"
password => "${CSS_PWD}"
ssl => true
ssl_certificate_verification => true
cacert => "/etc/ssl/certs/ca.crt"
}
}
索引按天滚动app-logs-YYYY.MM.dd,方便按时间清理和冷热分离。
3.5 Kibana 配置
① 创建索引模式
Management → Stack Management → Index Patterns → Create:
- Name:
app-logs-* - Timestamp field:
@timestamp
② 创建 Dashboard
核心面板:
- 错误日志时序图:按
log_level: ERROR聚合,时间线柱状图 - Top 10 异常类型:按
message关键词聚合 - 服务 QPS 趋势:按
service_name分组计数 - 响应时间 P99:如果有耗时字段的话
③ 保存常用检索
trace_id: "xxx"→ 链路追踪service_name: "order-service" AND log_level: "ERROR"→ 订单服务错误message: "NullPointer" AND @timestamp > "now-1h"→ 近一小时空指针
3.6 告警配置
CSS 内置告警(Kibana Alerting):
告警规则:错误日志突增
- Index:
app-logs-* - Condition:
log_level: ERROR数量 > 50/5min - Action: 发送 Webhook 到钉钉/企业微信
告警规则:特定异常出现
- Condition:
message: "OutOfMemoryError" - Action: 立即告警 + 触发 PagerDuty
四、验证结果
|
验证项
|
操作
|
预期
|
|---|---|---|
|
日志采集
|
手动触发一个异常
|
1 分钟内 Kibana 可检索到
|
|
结构化
|
查看文档字段
|
timestamp/level/service/traceId 均为独立字段
|
|
跨服务串联
|
用 traceId 搜索
|
一次请求在 order/user/inventory 的日志全部列出
|
|
聚合分析
|
Dashboard 查看
|
错误趋势、Top 异常、服务 QPS 实时更新
|
|
告警触发
|
模拟 50+ 错误/5min
|
钉钉收到告警消息
|
效率对比:
|
场景
|
改造前
|
改造后
|
|---|---|---|
|
查一个异常
|
kubectl logs + grep,15 分钟
|
Kibana 搜索,10 秒
|
|
跨服务追踪
|
不可能
|
traceId 一键串联
|
|
错误趋势
|
不知道
|
Dashboard 实时可见
|
|
告警响应
|
用户投诉后
|
异常发生 5 分钟内
|
五、生产避坑清单
❌ 常见错误
- 日志不结构化直接灌 ES:全部塞进
message字段,检索只能靠全文匹配,聚合分析做不了 - 索引不按时间滚动:单索引几百 GB,查询慢、删除难、分片爆炸
- 不分热冷层:所有日志存高性能 SSD,成本翻倍
- JVM heap 设超过 32GB:指针压缩失效,反而更慢
- 副本数设为 0:节点故障直接丢日志
- 没限制索引生命周期:日志一直写,磁盘打满,集群只读
- 采集器资源不限:Filebeat/Logstash 吃光节点 CPU,影响业务 Pod
- Kibana 暴露公网无鉴权:日志数据裸奔
✅ 正确姿势
- 日志必须 JSON 化:Spring Boot 用 logstash-logback-encoder,别偷懒
- 索引生命周期管理(ILM):热数据 3 天、温数据 7 天、冷数据转 OBS、30 天自动删除
- 分片规划:单分片 20-50GB 最佳,别一个索引建 50 个分片
- 副本数 ≥ 1:生产环境至少 1 副本
- 采集器资源限制:Filebeat 限 0.1 CPU / 128MB 内存
- 冷热分离:新索引放 SSD 热节点,7 天后迁到 HDD 温节点
- 安全:CSS 开安全模式 + IAM,Kibana 走 VPN 或堡垒机访问
- 监控 CSS 本身:集群健康、JVM 堆、磁盘使用率接云监控告警
六、成本结构
|
计费项
|
说明
|
优化
|
|---|---|---|
|
数据节点
|
按规格和数量
|
日志场景选通用型,不必上内存优化型
|
|
磁盘
|
SSD 按 GB/月
|
ILM 自动迁移冷数据到 OBS
|
|
流量
|
内网流量免费
|
确保采集器和 CSS 同 VPC
|
|
Kibana
|
随集群免费
|
无额外费用
|
经验:日志量 100GB/天 以下,3 节点 4U16G + 100GB SSD/节点足够撑住,月成本可控。
七、总结与扩展
日志平台的搭建把运维排查从"人肉翻文件"升级到"数据驱动分析":
- 采集自动化:Filebeat DaemonSet 一部署,新 Pod 自动纳入
- 检索秒级响应:ES 倒排索引,百万级日志亚秒返回
- 分析可视化:Dashboard 一眼看全局,不用再逐台登机器
- 告警主动化:异常在用户感知前被拦截
后续演进:
- APM 联动:日志 traceId 和 APM 链路追踪打通,日志和调用链双向跳转
- 日志审计合规:关键操作日志接入 LTS + 审计存储,满足等保要求
- 机器学习异常检测:ES ML 模块做日志异常模式自动发现,不用手写规则
- 多集群联邦:跨 Region 日志汇总到统一 CSS,全局检索
- SQL 查询接口:通过 CSS 的 SQL 能力,让数据分析师直接用 SQL 查日志
本文为原创实践,基于华为云云搜索服务 CSS 整理,操作步骤以当前控制台页面为准。转载请注明出处。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)