K8s 环境部署夜莺监控(Nightingale)平台(核心告警管理版)
本文部署夜莺监控的核心目的,是实现告警策略、告警规则及告警渠道的集中管理,重点解决原生 Prometheus+Alertmanager 部署中"规则修改需重启服务、告警渠道配置繁琐不灵活"的核心痛点。无需部署夜莺完整功能组件,在 K8s 环境中仅部署夜莺主服务、MySQL、Redis 三个关键服务,即可满足核心需求。
一、快速参考:Docker Compose 极简部署
如需快速搭建环境、验证告警管理核心功能,可通过官方提供的 Docker Compose 一键部署,无需复杂配置,流程简洁高效。
具体部署步骤(遵循官方标准流程):
-
确保服务器已安装 Git、Docker 及 Docker Compose,未安装则先完成依赖部署;
-
克隆夜莺官方仓库,获取 Docker Compose 配置文件:
git clone https://github.com/ccfos/nightingale.git -
进入官方指定配置目录:
cd nightingale/docker/compose-bridge -
一键启动所有组件,无需额外配置:
docker-compose up -d -
查看组件运行状态,确认所有服务为 Up 状态:
docker-compose ps -
访问控制台:浏览器输入
http://服务器IP:17000,默认账号 root、密码 root.2020,登录后即可验证告警管理核心功能。
二、K8s 环境部署夜莺监控(核心三服务)
2.1 核心说明与前置条件
核心说明
-
核心目标:聚焦告警策略、规则、渠道的集中管理,仅部署夜莺主服务、MySQL、Redis 三个关键服务,不部署多余配套组件,精准解决 Prometheus+Alertmanager 的核心痛点。
-
数据存储:MySQL 用于存储告警规则、告警通道、权限等核心数据;Redis 用于会话缓存及告警相关临时数据,两者均需配置持久化,确保数据不丢失。
-
部署架构:采用 StatefulSet 部署 MySQL、Redis(有状态服务,保障数据稳定);采用 Deployment 部署夜莺主服务(无状态服务,便于横向扩展);通过 Service 实现集群内服务通信,借助 NodePort 暴露夜莺控制台,供外部访问。
-
建库建表: 正常情况不需要自行登录MySQL 创建夜莺用的数据库名和相关表结构和表数据。夜莺应用会自动初始化数据库(前提是数据库用户有建库建表等必要的权限) 目前 8.5.0 版本是会自动建库建表,其他版本若是不会自动建库建表,需要自行按照官方的进行建库建表。
前置条件
-
已完成 K8s 集群部署,拥有集群完整操作权限(可正常使用 kubectl 命令);
-
集群节点可直接访问公网,用于拉取三个核心服务的镜像(mysql:8、redis:6.2、flashcatcloud/nightingale:8.5.0);
-
若使用私有镜像仓库,需提前完成 K8s 与私有仓库的连接配置,确保镜像可正常拉取。
2.2 部署步骤
步骤1:环境准备
登录 K8s 主节点,创建部署工作目录及夜莺专属命名空间(实现资源隔离,避免与集群内其他服务冲突):
bash
# 创建工作目录,用于存放所有部署配置文件
mkdir -p /tmp/n9e && cd /tmp/n9e
# 创建夜莺专属命名空间
kubectl create ns nightingale
步骤2:拉取基础镜像
提前拉取三个关键服务的基础镜像,可按需推送至私有镜像仓库(若有),确保后续部署时镜像可正常拉取:
bash
# 拉取公网镜像(三个核心服务)
docker pull mysql:8
docker pull redis:6.2
docker pull flashcatcloud/nightingale:8.5.0
步骤3:部署 MySQL 服务(StatefulSet + Service)
MySQL 为有状态服务,采用 StatefulSet 部署,配置自定义参数、持久化存储及健康检查,通过 Headless Service 和普通 Service 提供集群内访问能力,保障数据稳定存储。创建 n9e-mysql.yaml 配置文件,内容如下:
yaml
---
# MySQL 自定义配置 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
namespace: nightingale
data:
my.cnf: |
[mysqld]
default-time-zone = '+8:00'
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
lower_case_table_names = 1
max_connections = 1000
skip_name_resolve
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
[client]
default-character-set = utf8mb4
---
# MySQL StatefulSet 有状态部署
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: nightingale
labels:
app: mysql
spec:
serviceName: mysql-headless
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8
imagePullPolicy: IfNotPresent
env:
- name: TZ
value: Asia/Shanghai
- name: MYSQL_ROOT_PASSWORD
value: "1234" # 建议修改为复杂密码,提升安全性
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
- name: mysql-config
mountPath: /etc/my.cnf
subPath: my.cnf
#resources:
# limits:
# cpu: 2000m
# memory: 4Gi
# requests:
# cpu: 1000m
# memory: 2Gi
# 健康检查配置,确保服务正常运行
livenessProbe:
tcpSocket:
port: 3306
initialDelaySeconds: 60
periodSeconds: 15
timeoutSeconds: 3
readinessProbe:
tcpSocket:
port: 3306
initialDelaySeconds: 15
periodSeconds: 15
timeoutSeconds: 3
volumes:
- name: mysql-data
emptyDir: {} # 建议替换为 PVC 持久化存储,避免数据丢失
- name: mysql-config
configMap:
name: mysql-config
---
# MySQL Headless Service(StatefulSet 依赖,保障网络稳定)
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
namespace: nightingale
labels:
app: mysql
spec:
type: ClusterIP
clusterIP: None
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
name: mysql
---
# MySQL 普通 Service(供集群内其他服务访问)
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: nightingale
labels:
app: mysql
spec:
type: ClusterIP
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
name: mysql
---
步骤4:部署 Redis 服务(StatefulSet + Service)
Redis 为有状态缓存服务,采用 StatefulSet 部署,配置资源限制及健康检查,为夜莺主服务提供会话缓存和临时数据存储支持。创建 n9e-redis.yaml 配置文件,内容如下:
yaml
---
# Redis StatefulSet 有状态部署
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: nightingale
labels:
app: redis
spec:
serviceName: redis-headless
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:6.2
imagePullPolicy: IfNotPresent
env:
- name: TZ
value: Asia/Shanghai
ports:
- containerPort: 6379
name: redis
volumeMounts:
- name: redis-data
mountPath: /data
#resources:
# limits:
# cpu: 500m
# memory: 512Mi
# requests:
# cpu: 100m
# memory: 128Mi
# 健康检查配置,确保缓存服务可用
livenessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
volumes:
- name: redis-data
emptyDir: {} # 建议替换为 PVC 持久化存储,避免数据丢失
---
# Redis Headless Service(StatefulSet 依赖)
apiVersion: v1
kind: Service
metadata:
name: redis-headless
namespace: nightingale
labels:
app: redis
spec:
type: ClusterIP
clusterIP: None
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
name: redis
---
# Redis 普通 Service(供集群内其他服务访问)
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: nightingale
labels:
app: redis
spec:
type: ClusterIP
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
name: redis
---
步骤5:部署夜莺主程序(ConfigMap + Deployment + Service)
夜莺主服务为无状态服务,通过 ConfigMap 挂载核心配置文件,配置 MySQL、Redis 连接信息,采用 Deployment 部署,借助 NodePort 暴露外部访问端口,供用户登录控制台进行告警管理操作。
5.1 创建夜莺配置 ConfigMap
创建 n9e-cm.yaml 配置文件,核心配置 MySQL、Redis 连接信息,其余保持官方默认配置,无需额外修改:
yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nightingale-config
namespace: nightingale
data:
config.toml: |
[Global]
RunMode = "release"
TimeZone = "Asia/Shanghai"
[Log]
Dir = "logs"
Level = "INFO"
Output = "stdout"
[HTTP]
Host = "0.0.0.0"
Port = 17000
PrintAccessLog = false
PProf = false
ExposeMetrics = true
ShutdownTimeout = 30
ReadTimeout = 20
WriteTimeout = 40
IdleTimeout = 120
[HTTP.JWTAuth]
AccessExpired = 1500
RefreshExpired = 10080
RedisKeyPrefix = "/jwt/"
[DB]
# 数据库连接地址(与K8s内MySQL Service一致,无需修改)
DSN="root:1234@tcp(mysql:3306)/n9e_v6?charset=utf8mb4&parseTime=True&loc=Local&allowNativePasswords=true"
Debug = false
DBType = "mysql"
MaxLifetime = 7200
MaxOpenConns = 150
MaxIdleConns = 50
[Redis]
# Redis连接地址(与K8s内Redis Service一致,无需修改)
Address = "redis:6379"
RedisType = "standalone"
[Alert]
[Alert.Heartbeat]
Interval = 1000
EngineName = "default"
[Center]
MetricsYamlFile = "./etc/metrics.yaml"
I18NHeaderKey = "X-Language"
[Pushgw]
LabelRewrite = true
ForceUseServerTS = true
[[Pushgw.Writers]]
# 无需集成额外存储,保持默认配置即可
Url = "http://victoriametrics:8428/api/v1/write"
Timeout = 10000
[Ibex]
Enable = false
Address = ""
---
5.2 部署夜莺 Deployment 与 Service
创建 n9e.yaml 配置文件,部署夜莺主服务,配置端口、资源限制、健康检查,通过 NodePort 暴露外部访问入口:
yaml
---
# 夜莺主程序 Deployment(无状态部署)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nightingale
namespace: nightingale
labels:
app: nightingale
spec:
replicas: 1 # 可根据集群负载调整副本数,提升高可用
selector:
matchLabels:
app: nightingale
template:
metadata:
labels:
app: nightingale
spec:
containers:
- name: nightingale
# 镜像地址可替换为私有仓库地址(若有)
image: flashcatcloud/nightingale:8.5.0
imagePullPolicy: IfNotPresent
env:
- name: TZ
value: Asia/Shanghai
ports:
- containerPort: 17000
name: web # 夜莺控制台访问端口
- containerPort: 20090
name: rpc # 内部通信端口,无需外部暴露
volumeMounts:
- name: nightingale-config
mountPath: /app/etc/config.toml
subPath: config.toml
command: ["/app/n9e"]
#resources:
# limits:
# cpu: 2000m
# memory: 2Gi
# requests:
# cpu: 1000m
# memory: 1Gi
# 健康检查配置,确保夜莺服务正常运行
livenessProbe:
httpGet:
path: /health
port: 17000
initialDelaySeconds: 60
periodSeconds: 15
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /health
port: 17000
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
volumes:
- name: nightingale-config
configMap:
name: nightingale-config
---
# 夜莺集群内访问 Service(供内部服务通信)
apiVersion: v1
kind: Service
metadata:
name: nightingale
namespace: nightingale
labels:
app: nightingale
spec:
type: ClusterIP
selector:
app: nightingale
ports:
- port: 17000
targetPort: 17000
name: web
- port: 20090
targetPort: 20090
name: rpc
---
# 夜莺外部访问 NodePort Service(供用户登录控制台)
apiVersion: v1
kind: Service
metadata:
name: nightingale-nodeport
namespace: nightingale
labels:
app: nightingale
spec:
type: NodePort
selector:
app: nightingale
ports:
- port: 17000
targetPort: 17000
name: web
nodePort: 30080 # 自定义NodePort端口,范围30000-32767
---
步骤6:部署验证与控制台登录
6.1 执行部署命令
切换至部署工作目录,按顺序执行部署命令,创建三个关键服务的相关资源:
bash
# 按顺序部署 MySQL、Redis、夜莺配置及主服务
kubectl apply -f n9e-mysql.yaml
kubectl apply -f n9e-redis.yaml
kubectl apply -f n9e-cm.yaml -f n9e.yaml
6.2 验证部署状态
执行以下命令,查看夜莺、MySQL、Redis 的 Pod 运行状态,所有 Pod 显示 Running 即为部署正常:
bash
# 查看nightingale命名空间下所有Pod状态
kubectl -n nightingale get po
# 查看夜莺服务日志,确认服务启动正常(无报错)
kubectl -n nightingale logs <nightingale-pod名称>
6.3 登录夜莺Web控制台
-
访问地址:
http://K8s节点IP:30080(NodePort 端口为配置的 30080); -
默认账号密码:
root / root.2020; -
登录后即可进入控制台,进行后续告警通道、数据源接入、告警策略等配置。
三、配置告警通道(以钉钉为例)
部署完成后,需配置告警通道,确保告警信息能及时推送至相关人员。夜莺支持钉钉、邮件、企业微信等多种渠道,以下以最常用的钉钉为例,讲解完整配置流程。
3.1 前置准备:获取钉钉机器人Webhook
-
打开钉钉,创建/使用用于接收告警的群组,进入群组设置;
-
找到「智能群助手」→「添加机器人」→「自定义机器人」;
-
设置机器人名称(如「夜莺监控告警」),勾选「自定义关键词」(如「夜莺告警」),避免机器人被滥用;
-
完成配置后,复制机器人的「Webhook 地址」(格式:https://oapi.dingtalk.com/robot/send?access_token=xxx),保存备用。

3.2 夜莺控制台配置钉钉告警通道
-
登录夜莺Web控制台(http://K8s节点IP:30080),使用 root 账号登录;
-
左侧导航栏找到「告警管理」→「通知渠道」,点击右上角「新增渠道」;
-
配置渠道信息:
-
渠道名称:自定义(如「钉钉告警群组」,便于区分);
-
渠道类型:下拉选择「钉钉」;
-
Webhook 地址:粘贴前置准备获取的钉钉机器人 Webhook 地址;
-
关键词:填写钉钉机器人配置的自定义关键词(如「夜莺告警」);
-
其他配置:超时时间默认10秒,通知模板可使用默认模板(支持变量替换,如{{.AlertName}}、{{.Severity}}等)。
-
-
点击「测试」,若钉钉群组能收到测试告警消息,说明渠道配置成功;
-
点击「保存」,完成钉钉告警通道的创建。
提示:邮件、企业微信等其他告警通道配置流程类似,选择对应渠道类型,填写相关配置并测试通过后保存即可。
四、接入Prometheus数据源及配置告警策略
夜莺核心功能是集中管理多 Prometheus 数据源的告警规则,以下详细讲解外部 Prometheus 数据源接入及告警策略配置步骤,实现多数据源集中化告警管理。
4.1 接入外部Prometheus数据源
假设集群内或集群外已部署 Prometheus 服务,需将其接入夜莺,实现指标采集与告警规则统一管理,步骤如下:
-
登录夜莺Web控制台,左侧导航栏 →「数据源管理」→「Prometheus」,点击「新增数据源」;
-
配置数据源信息:
-
数据源名称:自定义(如「集群Prometheus」「测试环境Prometheus」,便于区分多个数据源);
-
地址:填写 Prometheus 的访问地址(集群内:http://prometheus:9090;外部:公网/内网IP:端口);
-
超时时间:默认10秒,可根据网络情况调整;
-
认证配置:若 Prometheus 配置了 Basic Auth,填写用户名和密码;无认证则留空;
-
标签:按需添加标签,用于对数据源进行分类管理(非必填)。
-
-
点击「测试连接」,提示「连接成功」即为接入正常;
-
点击「保存」,完成外部 Prometheus 数据源接入(可重复步骤接入多个数据源)。


4.2 配置告警策略(基于Prometheus指标)
告警策略是夜莺实现告警管理的核心,需基于接入的 Prometheus 指标,设置触发条件、关联告警通道,步骤如下:
4.2.1 创建告警策略
-
控制台左侧导航栏 →「告警管理」→「告警策略」,点击「新增策略」;
-
配置策略基本信息:
-
策略名称:自定义(如「K8s节点CPU使用率过高」「Redis内存使用率告警」);
-
所属分组:按需选择或创建分组,用于对告警策略分类管理;
-
数据源:下拉选择已接入的 Prometheus 数据源;
-
告警级别:选择告警严重程度(紧急、重要、一般、提示),不同级别可关联不同告警通道。
-
4.2.2 设置告警规则(指标查询与触发条件)
-
在「规则配置」模块,点击「添加规则」;
-
输入 PromQL 查询语句(用于采集监控指标),例如:
-
K8s节点CPU使用率:
avg(rate(node_cpu_seconds_total{mode!="idle"}[5m])) by (instance) * 100; -
Redis内存使用率:
redis_memory_used_bytes / redis_memory_max_bytes * 100。
-
-
点击「测试查询」,验证查询语句可正常返回数据;
-
设置触发条件:如「CPU使用率 > 80% 持续5分钟」,即当指标值超过阈值且持续指定时间后,触发告警;
-
按需配置抑制规则(避免重复告警)、标签过滤(仅对特定标签的指标生效)。


4.2.3 关联告警通道与通知配置
-
在「通知配置」模块,勾选已创建的告警通道(如「钉钉告警群组」);
-
设置通知频率:如「每5分钟通知一次,最多通知3次」,避免告警消息刷屏;
-
自定义通知内容:可修改通知模板,添加告警名称、触发时间、指标值、影响范围等信息(支持变量替换)。

4.2.4 启用并测试告警策略
-
所有配置完成后,点击「保存」;
-
在告警策略列表中,确保该策略处于「启用」状态;
-
测试验证:手动模拟指标超限(如通过压测工具提升CPU使用率),观察告警通道是否能正常收到告警消息,确认策略生效。


五、优化建议
为保障夜莺告警管理服务稳定运行,结合生产环境需求,提出以下优化建议:
-
持久化存储优化:将 MySQL、Redis 的
emptyDir替换为 PVC 持久化存储,可使用 Ceph、NFS 等分布式存储,确保数据在 Pod 重启后不丢失; -
高可用配置:MySQL、Redis 可部署主从或集群模式,夜莺 Deployment 适当增加副本数,提升服务抗故障能力;
-
安全加固:修改 MySQL、Redis 初始密码,配置 K8s 网络策略,限制 Pod 访问范围;启用 HTTPS 加密访问夜莺控制台,提升安全性;
-
资源调优:根据集群实际负载,调整 MySQL、Redis、夜莺主服务的资源限制与请求值,避免资源浪费或性能瓶颈;
-
运维监控:为夜莺、MySQL、Redis 配置监控指标,采集服务运行状态及性能数据,实现全链路监控,及时发现并解决问题。