K8s 环境部署夜莺监控(Nightingale)平台(核心告警管理版)

K8s 环境部署夜莺监控(Nightingale)平台(核心告警管理版)

本文部署夜莺监控的核心目的,是实现告警策略、告警规则及告警渠道的集中管理,重点解决原生 Prometheus+Alertmanager 部署中"规则修改需重启服务、告警渠道配置繁琐不灵活"的核心痛点。无需部署夜莺完整功能组件,在 K8s 环境中仅部署夜莺主服务、MySQL、Redis 三个关键服务,即可满足核心需求。

一、快速参考:Docker Compose 极简部署

如需快速搭建环境、验证告警管理核心功能,可通过官方提供的 Docker Compose 一键部署,无需复杂配置,流程简洁高效。

具体部署步骤(遵循官方标准流程):

  1. 确保服务器已安装 Git、Docker 及 Docker Compose,未安装则先完成依赖部署;

  2. 克隆夜莺官方仓库,获取 Docker Compose 配置文件:
    git clone https://github.com/ccfos/nightingale.git

  3. 进入官方指定配置目录:cd nightingale/docker/compose-bridge

  4. 一键启动所有组件,无需额外配置:
    docker-compose up -d

  5. 查看组件运行状态,确认所有服务为 Up 状态:
    docker-compose ps

  6. 访问控制台:浏览器输入 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

  1. 打开钉钉,创建/使用用于接收告警的群组,进入群组设置;

  2. 找到「智能群助手」→「添加机器人」→「自定义机器人」;

  3. 设置机器人名称(如「夜莺监控告警」),勾选「自定义关键词」(如「夜莺告警」),避免机器人被滥用;

  4. 完成配置后,复制机器人的「Webhook 地址」(格式:https://oapi.dingtalk.com/robot/send?access_token=xxx),保存备用。

3.2 夜莺控制台配置钉钉告警通道

  1. 登录夜莺Web控制台(http://K8s节点IP:30080),使用 root 账号登录;

  2. 左侧导航栏找到「告警管理」→「通知渠道」,点击右上角「新增渠道」;

  3. 配置渠道信息:

    • 渠道名称:自定义(如「钉钉告警群组」,便于区分);

    • 渠道类型:下拉选择「钉钉」;

    • Webhook 地址:粘贴前置准备获取的钉钉机器人 Webhook 地址;

    • 关键词:填写钉钉机器人配置的自定义关键词(如「夜莺告警」);

    • 其他配置:超时时间默认10秒,通知模板可使用默认模板(支持变量替换,如{{.AlertName}}、{{.Severity}}等)。

  4. 点击「测试」,若钉钉群组能收到测试告警消息,说明渠道配置成功;

  5. 点击「保存」,完成钉钉告警通道的创建。

提示:邮件、企业微信等其他告警通道配置流程类似,选择对应渠道类型,填写相关配置并测试通过后保存即可。

四、接入Prometheus数据源及配置告警策略

夜莺核心功能是集中管理多 Prometheus 数据源的告警规则,以下详细讲解外部 Prometheus 数据源接入及告警策略配置步骤,实现多数据源集中化告警管理。

4.1 接入外部Prometheus数据源

假设集群内或集群外已部署 Prometheus 服务,需将其接入夜莺,实现指标采集与告警规则统一管理,步骤如下:

  1. 登录夜莺Web控制台,左侧导航栏 →「数据源管理」→「Prometheus」,点击「新增数据源」;

  2. 配置数据源信息:

    • 数据源名称:自定义(如「集群Prometheus」「测试环境Prometheus」,便于区分多个数据源);

    • 地址:填写 Prometheus 的访问地址(集群内:http://prometheus:9090;外部:公网/内网IP:端口);

    • 超时时间:默认10秒,可根据网络情况调整;

    • 认证配置:若 Prometheus 配置了 Basic Auth,填写用户名和密码;无认证则留空;

    • 标签:按需添加标签,用于对数据源进行分类管理(非必填)。

  3. 点击「测试连接」,提示「连接成功」即为接入正常;

  4. 点击「保存」,完成外部 Prometheus 数据源接入(可重复步骤接入多个数据源)。

4.2 配置告警策略(基于Prometheus指标)

告警策略是夜莺实现告警管理的核心,需基于接入的 Prometheus 指标,设置触发条件、关联告警通道,步骤如下:

4.2.1 创建告警策略

  1. 控制台左侧导航栏 →「告警管理」→「告警策略」,点击「新增策略」;

  2. 配置策略基本信息:

    • 策略名称:自定义(如「K8s节点CPU使用率过高」「Redis内存使用率告警」);

    • 所属分组:按需选择或创建分组,用于对告警策略分类管理;

    • 数据源:下拉选择已接入的 Prometheus 数据源;

    • 告警级别:选择告警严重程度(紧急、重要、一般、提示),不同级别可关联不同告警通道。

4.2.2 设置告警规则(指标查询与触发条件)

  1. 在「规则配置」模块,点击「添加规则」;

  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

  3. 点击「测试查询」,验证查询语句可正常返回数据;

  4. 设置触发条件:如「CPU使用率 > 80% 持续5分钟」,即当指标值超过阈值且持续指定时间后,触发告警;

  5. 按需配置抑制规则(避免重复告警)、标签过滤(仅对特定标签的指标生效)。

4.2.3 关联告警通道与通知配置

  1. 在「通知配置」模块,勾选已创建的告警通道(如「钉钉告警群组」);

  2. 设置通知频率:如「每5分钟通知一次,最多通知3次」,避免告警消息刷屏;

  3. 自定义通知内容:可修改通知模板,添加告警名称、触发时间、指标值、影响范围等信息(支持变量替换)。

4.2.4 启用并测试告警策略

  1. 所有配置完成后,点击「保存」;

  2. 在告警策略列表中,确保该策略处于「启用」状态;

  3. 测试验证:手动模拟指标超限(如通过压测工具提升CPU使用率),观察告警通道是否能正常收到告警消息,确认策略生效。

五、优化建议

为保障夜莺告警管理服务稳定运行,结合生产环境需求,提出以下优化建议:

  • 持久化存储优化:将 MySQL、Redis 的 emptyDir 替换为 PVC 持久化存储,可使用 Ceph、NFS 等分布式存储,确保数据在 Pod 重启后不丢失;

  • 高可用配置:MySQL、Redis 可部署主从或集群模式,夜莺 Deployment 适当增加副本数,提升服务抗故障能力;

  • 安全加固:修改 MySQL、Redis 初始密码,配置 K8s 网络策略,限制 Pod 访问范围;启用 HTTPS 加密访问夜莺控制台,提升安全性;

  • 资源调优:根据集群实际负载,调整 MySQL、Redis、夜莺主服务的资源限制与请求值,避免资源浪费或性能瓶颈;

  • 运维监控:为夜莺、MySQL、Redis 配置监控指标,采集服务运行状态及性能数据,实现全链路监控,及时发现并解决问题。

相关推荐
@土豆2 小时前
kubernetes场景基于limits内存百分比实现横向Pod自动扩缩容(HPA)
云原生·容器·kubernetes
秦渝兴2 小时前
从手工高可用到全容器化:我的 Keepalived+Nginx+Tomcat+MySQL 项目迁移实战
linux·运维·mysql·nginx·容器·tomcat
sugar15692 小时前
Trae快速构建自己项目的docker镜像
docker·容器·trae
Elastic 中国社区官方博客2 小时前
Observabilty:自动化错误分诊 - 从被动到自主
大数据·运维·人工智能·elasticsearch·搜索引擎·自动化·全文检索
Elasticsearch2 小时前
Elasticsearch:shell 工具不是上下文工程的银弹
elasticsearch
泡沫·3 小时前
docker的基本认识
运维·docker·容器
学习使我快乐——玉祥3 小时前
ElasticSearch离线安装
大数据·elasticsearch·jenkins
H_老邪3 小时前
Docker 学习之路-从入门到放弃-Jenkins:4
容器·jenkins
sugar15693 小时前
Trae 添加项目规则,快速完成crmeb项目本地开发环境搭建
docker·容器·trae