跳到主要内容

VictoriaLogs + Alloy 二进制部署

前置说明

如果你还没做 MongoDB 日志切割,请先看 MongoDB 日志切割。 该方案不包含 Grafana,需要现场提前准备好可用的 Grafana;安装 VictoriaLogs 数据源插件时, Grafana 版本必须满足插件要求。当前参考的 VictoriaLogs 数据源插件版本为 0.32.0, Grafana 版本必须满足 >= 10.4.0,不满足时请先参考 Grafana 升级步骤参考

部署 VictoriaLogs

  1. 准备安装目录

    mkdir -p /data/mdtemp
    mkdir -p /usr/local/victorialogs
    mkdir -p /data/victorialogs
    cd /data/mdtemp
  2. 下载 VictoriaLogs 安装包

    wget https://pdpublic.mingdao.com/private-deployment/offline/common/victoria-logs-linux-amd64-v1.52.0.tar.gz
  3. 解压到安装目录

    tar xzvf victoria-logs-linux-amd64-v1.52.0.tar.gz -C /usr/local/victorialogs/
    chmod +x /usr/local/victorialogs/victoria-logs-prod

    确认版本:

    /usr/local/victorialogs/victoria-logs-prod --version

    预期包含版本 v1.52.0

  4. 创建数据目录

    mkdir -p /data/victorialogs
  5. 写入环境变量文件

    cat > /usr/local/victorialogs/victorialogs.env <<'EOF'
    # 数据目录
    STORAGE_DATA_PATH=/data/victorialogs

    # HTTP 监听端口
    HTTP_LISTEN_ADDR=:9428

    # Basic Auth,生产环境必须修改
    HTTP_AUTH_USERNAME=myuser
    HTTP_AUTH_PASSWORD=mypassword

    # 数据保留
    RETENTION_PERIOD=30d
    RETENTION_DISK_USAGE=50GiB

    # 内存和并发
    MEMORY_ALLOWED_BYTES=1GiB
    MAX_CONCURRENT_INSERTS=4
    MAX_CONCURRENT_REQUESTS=2

    # 查询限制
    SEARCH_MAX_QUERY_DURATION=30s
    SEARCH_MAX_QUERY_TIMERANGE=24h
    SEARCH_MAX_QUEUE_DURATION=5s
    SEARCH_LOG_SLOW_QUERY_DURATION=3s

    # 写入保护
    INSERT_MAX_LINE_SIZE_BYTES=262144
    INSERT_MAX_FIELDS_PER_LINE=300

    # 日志级别
    LOGGER_LEVEL=INFO
    EOF

    必须按现场修改:

    HTTP_AUTH_USERNAME
    HTTP_AUTH_PASSWORD
    RETENTION_PERIOD
    RETENTION_DISK_USAGE
  6. 写入 systemd 服务文件

    cat > /etc/systemd/system/victorialogs.service <<'EOF'
    [Unit]
    Description=VictoriaLogs Logging Service
    Wants=network-online.target
    After=network-online.target

    [Service]
    Type=simple
    EnvironmentFile=/usr/local/victorialogs/victorialogs.env
    Environment="GOMEMLIMIT=2GiB"

    WorkingDirectory=/usr/local/victorialogs

    ExecStart=/usr/local/victorialogs/victoria-logs-prod \
    -storageDataPath=${STORAGE_DATA_PATH} \
    -httpListenAddr=${HTTP_LISTEN_ADDR} \
    -retentionPeriod=${RETENTION_PERIOD} \
    -retention.maxDiskSpaceUsageBytes=${RETENTION_DISK_USAGE} \
    -memory.allowedBytes=${MEMORY_ALLOWED_BYTES} \
    -maxConcurrentInserts=${MAX_CONCURRENT_INSERTS} \
    -search.maxConcurrentRequests=${MAX_CONCURRENT_REQUESTS} \
    -search.maxQueryDuration=${SEARCH_MAX_QUERY_DURATION} \
    -search.maxQueryTimeRange=${SEARCH_MAX_QUERY_TIMERANGE} \
    -search.maxQueueDuration=${SEARCH_MAX_QUEUE_DURATION} \
    -search.logSlowQueryDuration=${SEARCH_LOG_SLOW_QUERY_DURATION} \
    -insert.maxLineSizeBytes=${INSERT_MAX_LINE_SIZE_BYTES} \
    -insert.maxFieldsPerLine=${INSERT_MAX_FIELDS_PER_LINE} \
    -httpAuth.username=${HTTP_AUTH_USERNAME} \
    -httpAuth.password=${HTTP_AUTH_PASSWORD} \
    -loggerLevel=${LOGGER_LEVEL}

    Restart=on-failure
    RestartSec=3s

    LimitNOFILE=65536
    TasksMax=2048

    CPUAccounting=true
    CPUQuota=100%

    MemoryAccounting=true
    MemoryMax=2G
    MemorySwapMax=0

    StandardOutput=journal
    StandardError=journal

    [Install]
    WantedBy=multi-user.target
    EOF
  7. 启动 VictoriaLogs

    systemctl daemon-reload
    systemctl enable --now victorialogs
    systemctl status victorialogs --no-pager
    ss -lnt | grep '9428'
    curl -s -u 'myuser:mypassword' http://localhost:9428/health
    journalctl -u victorialogs -n 100 --no-pager

部署 Alloy

Alloy 需要部署在每一台 MongoDB 节点上,直接读取本机的 mongodb.log 并把慢查询日志推送到 VictoriaLogs。每个节点都要单独部署一份,采集本机日志, 这样才能保证慢查询日志来源和节点一一对应。

注意事项:

  • VICTORIALOGS_PUSH_URL 需要改成实际的 VictoriaLogs 地址
  • VICTORIALOGS_USERNAMEVICTORIALOGS_PASSWORD 需要改成真实认证信息
  • Alloy 会自动使用本机 IPv4 作为 job 标识,每个节点不需要手工修改节点名
  • MONGODB_LOG_PATH 需要改成当前节点 MongoDB 日志文件的绝对路径
  • /data/alloy-vlogs-data 保存日志读取位置,不能随意删除,否则可能重复采集
  1. 确认 MongoDB 日志路径

    ls -lh /data/logs/mongodb/mongodb.log
    tail -n 3 /data/logs/mongodb/mongodb.log
  2. 创建 Alloy 安装目录

    mkdir -p /data/mdtemp
    mkdir -p /usr/local/alloy-vlogs/bin
    mkdir -p /data/alloy-vlogs-data
    cd /data/mdtemp
  3. 下载 Alloy 安装包

    wget https://pdpublic.mingdao.com/private-deployment/offline/common/alloy-linux-amd64-v1.19.2.zip
  4. 解压安装

    unzip -o alloy-linux-amd64-v1.19.2.zip -d /data/mdtemp/
    mv -f /data/mdtemp/alloy-linux-amd64 /usr/local/alloy-vlogs/bin/alloy
    chmod +x /usr/local/alloy-vlogs/bin/alloy
    /usr/local/alloy-vlogs/bin/alloy --version

    预期版本为 v1.19.2

  5. 写入 Alloy 环境变量文件

    cat > /usr/local/alloy-vlogs/alloy.env <<'EOF'
    # VictoriaLogs 地址,请修改为实际 IP
    VICTORIALOGS_PUSH_URL="http://VictoriaLogs_IP:9428/insert/loki/api/v1/push?preserve_json_keys=attr&_stream_fields=job,host&ignore_fields=filename"

    # VictoriaLogs Basic Auth
    VICTORIALOGS_USERNAME="myuser"
    VICTORIALOGS_PASSWORD="mypassword"

    # MongoDB 日志绝对路径
    MONGODB_LOG_PATH="/data/logs/mongodb/mongodb.log"
    EOF
    chmod 600 /usr/local/alloy-vlogs/alloy.env

    以下参数需要按现场修改:

    VictoriaLogs_IP
    VICTORIALOGS_USERNAME
    VICTORIALOGS_PASSWORD
    MONGODB_LOG_PATH
  6. 写入 Alloy 配置文件

    cat > /usr/local/alloy-vlogs/config.alloy <<'EOF'
    // ============================================================
    // Grafana Alloy
    // MongoDB Slow Query -> VictoriaLogs
    // ============================================================

    logging {
    level = "info"
    format = "logfmt"
    }

    // ============================================================
    // 1. 读取 MongoDB 日志
    // ============================================================
    loki.source.file "mongodb" {
    targets = [
    {
    __path__ = sys.env("MONGODB_LOG_PATH"),
    job = string.format("mongodb-%s", sys.env("HOST_IP")),
    host = constants.hostname,
    },
    ]

    forward_to = [
    loki.process.mongodb.receiver,
    ]
    }

    // ============================================================
    // 2. MongoDB Slow Query 处理
    // ============================================================
    loki.process "mongodb" {
    forward_to = [
    loki.write.victorialogs.receiver,
    ]

    // 解析 MongoDB JSON 日志
    stage.json {
    expressions = {
    ts = "t.\"$date\"",
    severity = "s",
    c = "",
    msg = "",
    attr = "attr",
    durationMillis = "attr.durationMillis",
    ns = "attr.ns",
    planSummary = "attr.planSummary",
    docsExamined = "attr.docsExamined",
    reslen = "attr.reslen",
    }
    }

    // 使用 MongoDB 原始日志时间
    stage.timestamp {
    source = "ts"
    format = "RFC3339"
    }

    // c / msg 仅用于下面过滤
    stage.labels {
    values = {
    c = "",
    msg = "",
    }
    }

    // 只保留 c=COMMAND
    stage.match {
    selector = "{c!=\"COMMAND\"}"
    action = "drop"
    drop_counter_reason = "not_command"
    }

    // 只保留 msg=Slow query
    stage.match {
    selector = "{msg!=\"Slow query\"}"
    action = "drop"
    drop_counter_reason = "not_slow_query"
    }

    // 删除临时 label
    stage.label_drop {
    values = [
    "c",
    "msg",
    ]
    }

    // MongoDB 日志级别转换
    stage.template {
    source = "level"

    template = `{{ if eq .severity "I" }}info{{ else if eq .severity "W" }}warn{{ else if eq .severity "E" }}error{{ else if eq .severity "F" }}critical{{ else if eq .severity "D" }}debug{{ else }}info{{ end }}`
    }

    stage.labels {
    values = {
    level = "",
    }
    }

    // 常用字段保留为 Structured Metadata
    stage.structured_metadata {
    values = {
    durationMillis = "",
    ns = "",
    planSummary = "",
    docsExamined = "",
    reslen = "",
    }
    }

    // Grafana Logs 面板展示内容
    stage.template {
    source = "display_msg"

    template = `{
    "ns": {{ toJson .ns }},
    "durationMillis": {{ toJson (printf "%v" .durationMillis) }},
    "planSummary": {{ toJson .planSummary }},
    "docsExamined": {{ toJson (printf "%v" .docsExamined) }},
    "reslen": {{ toJson (printf "%v" .reslen) }},
    "attr": {{ toJson (fromJson .attr) }}
    }`
    }

    // 最终发送给 VictoriaLogs 的 JSON
    stage.template {
    source = "vl_line"

    template = `{"_msg":{{ toJson .display_msg }},"ns":{{ toJson .ns }},"durationMillis":{{ toJson (printf "%v" .durationMillis) }},"planSummary":{{ toJson .planSummary }},"docsExamined":{{ toJson (printf "%v" .docsExamined) }},"reslen":{{ toJson (printf "%v" .reslen) }},"attr":{{ toJson (fromJson .attr) }}}`
    }

    stage.output {
    source = "vl_line"
    }
    }

    // ============================================================
    // 3. 发送到 VictoriaLogs
    // ============================================================
    loki.write "victorialogs" {
    endpoint {
    url = sys.env("VICTORIALOGS_PUSH_URL")

    batch_wait = "1s"
    batch_size = "100KiB"

    basic_auth {
    username = sys.env("VICTORIALOGS_USERNAME")
    password = sys.env("VICTORIALOGS_PASSWORD")
    }
    }
    }
    EOF
  7. 校验 Alloy 配置

    加载环境变量:

    set -a
    . /usr/local/alloy-vlogs/alloy.env
    set +a

    临时生成本机 IP:

    export HOST_IP="$(ip -4 route get 1.1.1.1 2>/dev/null \
    | sed -n 's/.* src \([^ ]*\).*/\1/p' \
    | head -n1)"

    确认环境变量:

    echo "$HOST_IP"
    echo "$MONGODB_LOG_PATH"

    校验配置:

    /usr/local/alloy-vlogs/bin/alloy validate \
    /usr/local/alloy-vlogs/config.alloy

    无报错后再继续。

  8. 写入 Alloy 启动脚本

    cat > /usr/local/alloy-vlogs/bin/start-alloy.sh <<'EOF'
    #!/bin/sh

    # 根据默认 IPv4 路由自动获取服务器实际出口 IP
    HOST_IP=$(ip -4 route get 1.1.1.1 2>/dev/null \
    | sed -n 's/.* src \([^ ]*\).*/\1/p' \
    | head -n1)

    if [ -z "$HOST_IP" ]; then
    echo "ERROR: failed to detect local IPv4 address"
    exit 1
    fi

    if [ -z "$MONGODB_LOG_PATH" ]; then
    echo "ERROR: MONGODB_LOG_PATH is empty"
    exit 1
    fi

    if [ ! -r "$MONGODB_LOG_PATH" ]; then
    echo "ERROR: MongoDB log is not readable: $MONGODB_LOG_PATH"
    exit 1
    fi

    export HOST_IP

    echo "Alloy HOST_IP=${HOST_IP}"
    echo "MongoDB LOG=${MONGODB_LOG_PATH}"

    /usr/local/alloy-vlogs/bin/alloy validate \
    /usr/local/alloy-vlogs/config.alloy || exit 1

    exec /usr/local/alloy-vlogs/bin/alloy run \
    --server.http.listen-addr=127.0.0.1:9081 \
    --storage.path=/data/alloy-vlogs-data \
    /usr/local/alloy-vlogs/config.alloy
    EOF

    增加执行权限:

    chmod +x /usr/local/alloy-vlogs/bin/start-alloy.sh

    验证自动 IP:

    ip -4 route get 1.1.1.1

    只查看 IP:

    ip -4 route get 1.1.1.1 \
    | sed -n 's/.* src \([^ ]*\).*/\1/p'
  9. 写入 systemd 服务文件

    cat > /etc/systemd/system/alloy-vlogs.service <<'EOF'
    [Unit]
    Description=Grafana Alloy VictoriaLogs Collector
    Wants=network-online.target
    After=network-online.target

    [Service]
    Type=simple

    EnvironmentFile=/usr/local/alloy-vlogs/alloy.env

    Environment="GOMEMLIMIT=768MiB"

    ExecStart=/usr/local/alloy-vlogs/bin/start-alloy.sh

    Restart=on-failure
    RestartSec=3s

    CPUAccounting=true
    CPUQuota=100%

    MemoryAccounting=true
    MemoryMax=1G
    MemorySwapMax=0

    LimitNOFILE=65536
    TasksMax=1024

    StandardOutput=journal
    StandardError=journal

    [Install]
    WantedBy=multi-user.target
    EOF
  10. 启动 Alloy

systemctl daemon-reload
systemctl enable --now alloy-vlogs

查看状态:

systemctl status alloy-vlogs --no-pager

查看日志:

journalctl -u alloy-vlogs -n 50 --no-pager

应看到:

Alloy HOST_IP=<本机IP>
MongoDB LOG=/data/logs/mongodb/mongodb.log
  1. Alloy 健康检查

端口:

ss -lntp | grep ':9081'

Ready:

curl -s http://127.0.0.1:9081/-/ready

正常返回:

Alloy is ready.

Healthy:

curl -s http://127.0.0.1:9081/-/healthy

正常返回:

All Alloy components are healthy.
  1. 检查 Alloy 采集和发送
curl -s http://127.0.0.1:9081/-/healthy
journalctl -u alloy-vlogs -n 50 --no-pager
curl -s http://127.0.0.1:9081/metrics | egrep -i 'loki_.*(sent|dropped|error|retry|read)' | head -n 80

Grafana 配置

该方案不包含 Grafana,需要现场已有可用的 Grafana。 如果现场还没有 Grafana,请先完成 Grafana 的安装或升级,再继续下面步骤。 当前参考的 VictoriaLogs 数据源插件版本为 0.32.0,安装时 Grafana 版本必须满足 >= 10.4.0,不满足时请先参考 Grafana 升级步骤参考

  1. 安装 VictoriaLogs 数据源插件

    cd /data/mdtemp
    # Grafana >= 10.4.0,若不满足请先升级 Grafana
    wget https://pdpublic.mingdao.com/private-deployment/offline/common/victoriametrics-logs-datasource-v0.32.0.tar.gz
    tar xzvf victoriametrics-logs-datasource-v0.32.0.tar.gz -C /usr/local/grafana/data/plugins/
    systemctl restart grafana
  2. 配置数据源

    • url 填写 VictoriaLogs 地址,例如 http://127.0.0.1:9428
    • Basic auth 打开
    • User 填写 HTTP_AUTH_USERNAME
    • Password 填写 HTTP_AUTH_PASSWORD
    • Maximum lines 建议保持 2000000
  3. 导入慢查询面板

    这个面板文件已经准备好了,直接下载后导入 Grafana 即可。

    点击查看 / 下载面板 JSON
    • 面板文件:mongodb-VictoriaLogs-Slow-Query-v1.1.0.json
    • 导入方式:在 Grafana 里点击 Import dashboard,然后上传这个文件
    • 导入完成后,请确认选择的是当前 VictoriaLogs 的数据源
    • 如果想先看看内容,也可以直接在浏览器里打开这个 JSON 文件
    下载面板 JSON
    在浏览器中打开 JSON 文件