一、日志管理
日志这个东西,说大不大,说小不小。平时跑得好好的,一出了毛病,第一个想打开的就是日志。Nomad作为调度器,跑在上面的任务多了,日志管理自然就成了日常操作里最频繁碰到的事。
1.1 应用场景:什么时候特别需要关注日志?
想象一下,周五晚上你正打算收工,测试环境突然告警。你打开Nomad界面,看到几十个任务在跑,可不知道哪个出了问题。这时候你特别希望有一条命令能直接看到每个任务的输出。这就是典型的日志管理需求。
另一个常见场景:任务启动失败。有时候配置写错了,任务起来几秒就退出,你只能通过启动日志找原因。还有,线上服务内存泄漏,崩溃前的最后几行输出往往藏着线索。再严格一点,安全审计要求日志保留180天,你不能说“重启之后日志没了”就算交差。这些,都算日志管理的范畴。
1.2 先用最简单的方式:Nomad自带的日志命令
Nomad本身提供了很直白的日志查看方式,就像平时用 tail -f 一样。不需要额外部署,几秒钟就能上手。你想看某个任务的最新输出,可以这样:
# 技术栈:Bash/Shell + Nomad CLI
# 先列出所有作业,找到你要看的任务
nomad job status
# 假设任务名叫redis,查看它的标准输出(stdout)最后200行
nomad job logs -tail -lines 200 redis
# 如果任务里有多个分配,可以指定分配ID
nomad alloc logs -tail 8f3c2a1b redis
这里 -tail 表示持续输出,就像跟着尾巴走。-lines 控制显示行数。这样排查问题,效率比去机器上翻文件高多了。因为Nomad把任务的stdout和stderr都收集到了分配目录里,命令只是帮你读出来。
不过,自带的命令只管查看,不管存储。任务重启后,旧的日志可能就没了(取决于驱动配置)。如果你需要集中管理,得想别的招。
1.3 让日志有个“家”:存储与轮转策略
Nomad跑任务时,日志默认交给容器运行时或者进程的stdout/stderr。如果直接存文件,文件会越来越大,最后把磁盘塞满。所以得配上轮转。
在Nomad的docker驱动里,可以设置日志轮转参数。看个例子:
# 技术栈:Bash/Shell + Nomad job文件(HCL)
# 生成一个带日志轮转配置的任务定义,存成 java-web.nomad.hcl
cat > java-web.nomad.hcl <<'EOF'
job "java-web" {
group "web" {
task "app" {
driver = "docker"
config {
image = "openjdk:17"
# 这里是关键:限制日志大小和文件数量
logging {
type = "json-file"
config {
max-size = "10m"
max-file = "3"
}
}
}
}
}
}
EOF
# 部署这个任务
nomad job run java-web.nomad.hcl
看到没?max-size 设置单个日志文件最大10MB,max-file 设置保留3个文件。这样日志最多占用30MB磁盘空间,心里踏实。这个配置对docker驱动尤其管用,其他驱动也有类似选项,具体看官方文档。
1.4 把散落的日志收起来:集中管理
等你跑了几百个任务,再看单机日志就头疼了。这时候可以引入Loki或者Elasticsearch这类日志聚合系统。Loki比Elasticsearch轻很多,它只索引标签,不索引日志内容,查询起来也够用。采集日志的活一般交给Promtail或Fluentd这类agent去干。它们读Nomad任务写出来的日志文件,再统一推到存储里。
用Promtail举例子,它的配置很简单,把任务的日志目录作为目标:
# 技术栈:Bash/Shell + Promtail(YAML配置)
# 创建Promtail配置
cat > promtail-config.yml <<'EOF'
scrape_configs:
- job_name: nomad-alloc
static_configs:
- targets:
- localhost
labels:
job: nomad
__path__: /var/lib/nomad/alloc/**/alloc/logs/*.stdout
EOF
这里把 /var/lib/nomad/alloc 下所有任务的stdout都采集了。有了集中日志,你在Grafana里一条查询就能把几个实例的日志拼在一起,排查问题就像刷朋友圈一样顺畅。不过,Loki本身也需要运维,磁盘、内存、查询性能都是要照顾的对象。
二、监控策略
日志是“事后诸葛”,监控才是“事前预警”。日志出了问题,我们看日志;但很多问题还没到写日志的时候,就已经把服务搞挂了。所以得盯着指标。
2.1 监控什么?先从这些关键指标下手
Nomad本身暴露了很多运行指标,比如节点CPU、内存、磁盘,还有调度的队列深度、任务状态变化次数等。你可以用一条命令直接看到原始指标:
# 技术栈:Bash/Shell + curl
# 这是Node指标接口,返回Prometheus格式
curl -s http://localhost:9101/metrics | head -20
接口返回一长串数字,肉眼肯定看不过来,所以我们要用Prometheus来抓取和存储。Prometheus是监控界的老熟人,它的生态非常完善,Grafana面板随便切。
2.2 用Prometheus抓取Nomad指标
Prometheus靠拉取的方式采集数据,只要让Nomad把指标吐出来,Prometheus定期去拉就行。首先要确认Nomad启动时开启了指标接口。通常默认都有。然后写Prometheus的抓取配置:
# 技术栈:Bash/Shell + Prometheus(YAML配置)
# 生成Prometheus配置文件
cat > /etc/prometheus/prometheus.yml <<'EOF'
global:
scrape_interval: 30s
scrape_configs:
- job_name: 'nomad'
metrics_path: /v1/metrics
params:
format: ['prometheus']
static_configs:
- targets: ['node1:9101', 'node2:9101', 'node3:9101']
labels:
cluster: 'production'
EOF
# 启动Prometheus
systemctl restart prometheus
注意,这里 metrics_path 是 /v1/metrics,而且加了参数 format=prometheus,这样返回的才是标准Prometheus格式。这一步很关键,不然抓回来一堆JSON,Prometheus不认。另外,Nomad还支持把9101换成你自己的端口,只要在启动代理时通过-telemetry参数指定即可。
抓回来后,我们就可以在Grafana里做仪表盘了。比如画一个“当前节点内存使用量”的趋势图,在Grafana的查询框里写PromQL。但咱们统一用Shell,所以可以用curl调Prometheus的API来查:
# 技术栈:Bash/Shell + Prometheus API
# 调用Prometheus API执行查询,看看每个node分配了多少内存
curl -G 'http://prometheus:9090/api/v1/query' \
--data-urlencode 'query=sum(nomad_client_allocated_memory) by (node)'
返回的JSON里有每个节点的内存值,配合Grafana就能画出趋势图。PromQL本身不复杂,但值得花时间学。毕竟监控告警离不开它。
2.3 告警规则:出了问题脚本提前给“打电话”
光有仪表盘还不够,最好能在指标异常时主动通知。Prometheus的告警规则可以做到。举一个简单例子:如果节点内存使用率超过90%,持续5分钟,就告警。
# 技术栈:Bash/Shell + Prometheus告警规则(YAML)
# 创建告警规则文件
cat > /etc/prometheus/alert.rules.yml <<'EOF'
groups:
- name: nomad-node.rules
rules:
- alert: NodeMemoryUsageHigh
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
for: 5m
labels:
severity: warning
annotations:
summary: "节点内存快爆了"
description: "{{ $labels.instance }} 内存使用率超90%,持续5分钟。"
EOF
然后在Prometheus配置里引入这个规则文件,重启Prometheus即可。这样一旦指标越界,告警就会通过Alertmanager发到钉钉、邮件或别的渠道。
这里不得不提一句Alertmanager。它是Prometheus生态里专门处理告警的组件,负责去重、分组、静默,还能把告警路由到不同接收人。比如你的核心服务告警发给值班群,非核心服务只发邮件,都可以在Alertmanager里配置。可以说,有了Alertmanager,告警才不至于深夜轰炸得你怀疑人生。
三、技术的优缺点
哪种方案都不是万能的。咱们聊聊这套日志+监控方案的优点和坑。
3.1 优点
首先,省心。用Nomad自带的日志命令,日常调试不需要额外装任何东西。其次,Prometheus生态成熟,各种Exporter随便配,Grafana模板一大堆,美观又直观。再有,配置都是文本文件,方便版本化,比如用Git管理,团队协作时互相review,改了什么一目了然。
3.2 缺点
缺点也很明显。日志文件的轮转虽然限制了大小,但轮转之后旧日志就没了,出了问题想回溯,发现已经无据可查。集中日志方案(比如Loki)本身又是一个大组件,增加了部署维护成本。监控方面,Prometheus默认是拉模式,如果你的网络隔离复杂,拉取的端口可能被安全策略卡住,得专门开防火墙洞,运维同学可能不太乐意。
四、注意事项(这几点一定要记牢)
别忘了给指标接口加鉴权。Nomad
/v1/metrics默认可能不设防,如果暴露在公网,等于把家底亮给别人看。建议用反向代理加认证,或者用防火墙限制来源IP。更保险的做法是让Nomad只监听内网IP,不要挂在0.0.0.0上。日志轮转的“容量”要算好。比如
max-file=3, max-size=10m,要是任务特别能刷日志,10分钟就写满三个文件,那重要日志照样丢。最好估算任务峰值,留足余量。还有,轮转策略不是只有docker驱动支持,其他驱动(比如raw_exec)也有类似机制,但配置项不一样,别照搬。Prometheus抓取间隔别设太短。默认15秒其实挺耗资源,对大量节点来说,30秒足够。规则里的
for持续时间也别设成1秒,不然有点抖动就告警,容易变成“狼来了”。一般至少持续3分钟以上才有意义。监控指标别贪多。一上来就接几十个面板,根本看不过来。建议先从CPU、内存、磁盘、任务状态这几个核心看起,运行一段时间后再加。记住,监控是为了发现异常,不是表演数据大屏。
集中日志的采集器需要适当“让步”。比如Promtail的文件读取位置记录在单独文件里,千万别把那个位置文件也采集了,否则会循环采集自己,把磁盘搞满。最好在配置文件里显式排除它。
Nomad的日志和监控是两套体系,但可以打通。比如,任务在日志里打印了特定错误,你想在监控面板上突出显示,可以用Promtail里加个标签,然后用Prometheus的
log_entries指标(如果你是Loki)做关联查询。不过这个比较高级,等基础磨合好了再玩也不迟。
五、总结
日志和监控就像一双眼睛,一只管历史,一只管未来。Nomad本身提供了轻量级的日志查看能力,适合临时排障;要想长期留存,就得配上日志轮转加集中收集。监控这块,Prometheus加上Grafana是社区里最顺手的组合,配上告警规则能让你提前发现问题,不用等用户来骂。
方案没有最好的,只有最合适的。你可以从小规模的“Nomad自带命令+手工盯面板”起步,等规模上来了再逐步引入Loki和Alertmanager。关键是别把坑踩了一遍才想起写文档,提前规划好轮转、鉴权、抓取间隔,日子会好过很多。日志别裸奔,监控别全堆,告警别乱炸,做到这三样,你的Nomad集群就已经很能打了。
评论
围绕“Nomad的日志管理与监控策略解析”参与讨论