# 边缘节点日志链路部署(Fluent Bit + ClickHouse) 与 [日志链路调整方案](../../log-pipeline-migration-plan.md) 配套的配置与部署说明。本文档为 **Fluent Bit 部署教程**,按步骤即可在边缘节点或日志采集机上跑通采集 → ClickHouse 写入。 --- ## Fluent Bit 跑在哪台机器上? **Fluent Bit 应部署在写日志文件的节点机器上**(EdgeNode / EdgeDNS 同机),不要部署在 EdgeAPI 机器上。 - HTTP 日志文件默认在 `/var/log/edge/edge-node/*.log`,由 **EdgeNode** 本机写入;若配置了公用访问日志策略的文件 `path`,节点会优先复用该 `path` 所在目录。 - DNS 日志文件默认在 `/var/log/edge/edge-dns/*.log`,由 **EdgeDNS** 本机写入;若配置了公用访问日志策略的文件 `path`,节点会优先复用该 `path` 所在目录。 - Fluent Bit 使用 **tail** 读取本机路径,因此必须运行在这些日志文件所在机器上。 - EdgeAPI 机器主要负责查询 ClickHouse/MySQL,不需要承担日志采集。 - 多机部署时,每台写日志节点都跑一份 Fluent Bit,上报到同一 ClickHouse 集群。 --- ## 一、前置条件 - **边缘节点(EdgeNode)** 已开启本地日志落盘,目录优先取“公用访问日志策略”的文件 `path`(取目录),为空时回退 `EDGE_LOG_DIR`,再回退默认 `/var/log/edge/edge-node`;生成 `access.log`、`waf.log`、`error.log`(JSON Lines)。 - **DNS 节点(EdgeDNS)** 已开启本地日志落盘,目录优先取“公用访问日志策略”的文件 `path`(取目录),为空时回退 `EDGE_DNS_LOG_DIR`,再回退默认 `/var/log/edge/edge-dns`;生成 `access.log`(JSON Lines)。 - **ClickHouse** 已安装并可访问(单机或集群),且已创建好 `logs_ingest` 表(见下文「五、ClickHouse 建表」)。 - 若 Fluent Bit 与 ClickHouse 不在同一台机,需保证网络可达(默认 HTTP 端口 8123)。 --- ## 二、安装 Fluent Bit ### 2.1 Ubuntu / Debian ```bash # 添加 Fluent Bit 官方源并安装(以 Ubuntu 22.04 为例) curl https://raw.githubusercontent.com/fluent/fluent-bit/master/install.sh | sh sudo apt-get install -y fluent-bit # 或使用 TD Agent Bit 源(若需 ClickHouse 等扩展) # 见:https://docs.fluentbit.io/manual/installation/linux/ubuntu ``` ### 2.2 CentOS / RHEL / Amazon Linux ```bash # 使用官方 install 脚本 curl https://raw.githubusercontent.com/fluent/fluent-bit/master/install.sh | sh # 或 yum/dnf 安装(以提供的仓库为准) # sudo yum install -y fluent-bit ``` ### 2.3 使用二进制包 从 [Fluent Bit 官方 Release](https://github.com/fluent/fluent-bit/releases) 下载对应架构的 tarball,解压后将 `bin/fluent-bit` 放到 PATH,并确保其 **Output 插件支持 ClickHouse**(部分发行版或自编译需启用 `out_clickhouse`)。 --- ## 三、部署配置文件 ### 3.1 放置配置 将本目录下配置文件放到同一目录,例如 `/etc/fluent-bit/` 或 `/opt/edge/fluent-bit/`: ```bash sudo mkdir -p /etc/fluent-bit sudo cp fluent-bit.conf clickhouse-upstream.conf /etc/fluent-bit/ ``` 两文件需在同一目录,因 `fluent-bit.conf` 中有 `@INCLUDE clickhouse-upstream.conf`。 ### 3.2 修改 ClickHouse 地址(必做) 编辑 `clickhouse-upstream.conf`,按实际环境填写 ClickHouse 的 Host/Port: - **单机**:保留一个 `[NODE]`,改 `Host`、`Port`(默认 8123)。 - **集群**:复制多段 `[NODE]`,每段一个节点,例如: ```ini [UPSTREAM] Name ch_backends [NODE] Name node-01 Host 192.168.1.10 Port 8123 [NODE] Name node-02 Host 192.168.1.11 Port 8123 ``` ### 3.3 ClickHouse 账号密码(有密码时必做) 不在 `clickhouse-upstream.conf` 里配置密码,而是通过 **环境变量** 传给 Fluent Bit: - `CH_USER`:ClickHouse 用户名(如 `default`)。 - `CH_PASSWORD`:对应用户的密码。 在 systemd 或启动脚本中设置(见下文「四、以 systemd 方式运行」)。 ### 3.4 日志路径与 parsers.conf - **日志路径**:`fluent-bit.conf` 里已同时配置 HTTP 与 DNS 两类路径: - HTTP:`/var/log/edge/edge-node/*.log` - DNS:`/var/log/edge/edge-dns/*.log` 若你配置了公用访问日志策略的文件 `path`,或改了 `EDGE_LOG_DIR` / `EDGE_DNS_LOG_DIR`,请同步修改对应 `Path`。 - **Parsers_File**:主配置引用了 `parsers.conf`。若安装包自带(如 `/etc/fluent-bit/parsers.conf`),无需改动;若启动报错找不到文件,可: - 从 Fluent Bit 官方仓库复制 [conf/parsers.conf](https://github.com/fluent/fluent-bit/blob/master/conf/parsers.conf) 到同一目录,或 - 在同一目录新建空文件 `parsers.conf`(仅当不使用任何 parser 时)。 ### 3.5 数据与状态目录 Fluent Bit 会使用配置里的 `storage.path` 和 DB 路径,需保证进程有写权限: ```bash sudo mkdir -p /var/lib/fluent-bit/storage sudo chown -R <运行 fluent-bit 的用户>:<同组> /var/lib/fluent-bit ``` --- ## 四、以 systemd 方式运行 ### 4.1 使用自带服务(若安装包已提供) 若通过 apt/yum 安装,通常已有 `fluent-bit.service`。先改配置路径和环境变量: ```bash # 编辑服务文件(路径以实际为准,如 /lib/systemd/system/fluent-bit.service) sudo systemctl edit fluent-bit --full ``` 在 `[Service]` 中增加或修改: - `EnvironmentFile` 指向你的环境变量文件,或直接写: - `Environment="CH_USER=default"` - `Environment="CH_PASSWORD=你的密码"` - `ExecStart` 中的配置文件路径改为你的 `fluent-bit.conf`,例如: - `ExecStart=/opt/fluent-bit/bin/fluent-bit -c /etc/fluent-bit/fluent-bit.conf` 然后: ```bash sudo systemctl daemon-reload sudo systemctl enable fluent-bit sudo systemctl start fluent-bit sudo systemctl status fluent-bit ``` ### 4.2 自定义 systemd 单元(无自带服务时) 新建 `/etc/systemd/system/fluent-bit-edge.service`: ```ini [Unit] Description=Fluent Bit - Edge Node Logs to ClickHouse After=network.target [Service] Type=simple ExecStart=/usr/bin/fluent-bit -c /etc/fluent-bit/fluent-bit.conf Restart=always RestartSec=5 # ClickHouse 认证(按需修改) Environment="CH_USER=default" Environment="CH_PASSWORD=your_clickhouse_password" [Install] WantedBy=multi-user.target ``` 若密码含特殊字符,建议用 `EnvironmentFile=/etc/fluent-bit/fluent-bit.env`,并在该文件中写: ```bash CH_USER=default CH_PASSWORD=your_clickhouse_password ``` 然后: ```bash sudo systemctl daemon-reload sudo systemctl enable fluent-bit-edge sudo systemctl start fluent-bit-edge sudo systemctl status fluent-bit-edge ``` ### 4.3 前台调试 不依赖 systemd 时可直接前台跑(便于看日志): ```bash export CH_USER=default export CH_PASSWORD=your_clickhouse_password fluent-bit -c /etc/fluent-bit/fluent-bit.conf ``` --- ## 五、ClickHouse 建表 平台(EdgeAPI)会查询两张表: - HTTP:`logs_ingest` - DNS:`dns_logs_ingest` 需在 ClickHouse 中先建表。库名默认为 `default`,若使用其它库,需与 EdgeAPI 的 `CLICKHOUSE_DATABASE` 一致。 在 ClickHouse 中执行(按需改库名或引擎): ```sql CREATE TABLE IF NOT EXISTS default.logs_ingest ( timestamp DateTime, node_id UInt64, cluster_id UInt64, server_id UInt64, host String, ip String, method String, path String, status UInt16, bytes_in UInt64, bytes_out UInt64, cost_ms UInt32, ua String, referer String, log_type String, trace_id String, firewall_policy_id UInt64 DEFAULT 0, firewall_rule_group_id UInt64 DEFAULT 0, firewall_rule_set_id UInt64 DEFAULT 0, firewall_rule_id UInt64 DEFAULT 0, request_headers String DEFAULT '', request_body String DEFAULT '', response_headers String DEFAULT '', response_body String DEFAULT '' ) ENGINE = MergeTree() ORDER BY (timestamp, node_id, server_id, trace_id) SETTINGS index_granularity = 8192; ``` DNS 日志建表: ```sql CREATE TABLE IF NOT EXISTS default.dns_logs_ingest ( timestamp DateTime, request_id String, node_id UInt64, cluster_id UInt64, domain_id UInt64, record_id UInt64, remote_addr String, question_name String, question_type String, record_name String, record_type String, record_value String, networking String, is_recursive UInt8, error String, ns_route_codes Array(String), content_json String DEFAULT '' ) ENGINE = MergeTree() ORDER BY (timestamp, request_id, node_id) SETTINGS index_granularity = 8192; ``` - **log_type**:`access` / `waf` / `error`;攻击日志同时看 **firewall_rule_id** 或 **firewall_policy_id** 是否大于 0(与原有 MySQL 通过规则 ID 判断攻击日志一致)。 - **request_headers / response_headers**:JSON 字符串;**request_body / response_body**:请求/响应体(单条建议限制长度,如 512KB)。 - **request_body 为空**:需在管理端为该站点/服务的「访问日志」策略中勾选「请求Body」后才会落盘;默认未勾选。路径大致为:站点/服务 → 访问日志 → 策略 → 记录字段 → 勾选「请求Body」。WAF 拦截且策略开启「记录请求Body」时也会记录。 - **response_body 为空**:当前版本未实现(proto 与节点均未支持响应体落盘),表中已预留字段,后续可扩展。 - **原有 MySQL 日志同步到 ClickHouse**:见 [mysql-to-clickhouse-migration.md](mysql-to-clickhouse-migration.md)。 若表已存在且缺少新字段,可执行: ```sql ALTER TABLE default.logs_ingest ADD COLUMN IF NOT EXISTS firewall_policy_id UInt64 DEFAULT 0; ALTER TABLE default.logs_ingest ADD COLUMN IF NOT EXISTS firewall_rule_group_id UInt64 DEFAULT 0; ALTER TABLE default.logs_ingest ADD COLUMN IF NOT EXISTS firewall_rule_set_id UInt64 DEFAULT 0; ALTER TABLE default.logs_ingest ADD COLUMN IF NOT EXISTS firewall_rule_id UInt64 DEFAULT 0; ALTER TABLE default.logs_ingest ADD COLUMN IF NOT EXISTS request_headers String DEFAULT ''; ALTER TABLE default.logs_ingest ADD COLUMN IF NOT EXISTS request_body String DEFAULT ''; ALTER TABLE default.logs_ingest ADD COLUMN IF NOT EXISTS response_headers String DEFAULT ''; ALTER TABLE default.logs_ingest ADD COLUMN IF NOT EXISTS response_body String DEFAULT ''; ALTER TABLE default.dns_logs_ingest ADD COLUMN IF NOT EXISTS content_json String DEFAULT ''; ``` Fluent Bit 写入时使用 `json_date_key timestamp` 和 `json_date_format epoch`,会将 JSON 中的 `timestamp`(Unix 秒)转为 DateTime。 --- ## 六、验证与排错 1. **看 Fluent Bit 日志** - systemd:`journalctl -u fluent-bit-edge -f`(或你的服务名) - 前台:直接看终端输出。 2. **看 ClickHouse 是否有数据** ```sql SELECT count() FROM default.logs_ingest; SELECT * FROM default.logs_ingest LIMIT 5; SELECT count() FROM default.dns_logs_ingest; SELECT * FROM default.dns_logs_ingest LIMIT 5; ``` 3. **常见问题** - **连接被拒**:检查 `clickhouse-upstream.conf` 的 Host/Port、防火墙、ClickHouse 的 `listen_host`。 - **认证失败**:检查 `CH_USER`、`CH_PASSWORD` 是否与 ClickHouse 用户一致,环境变量是否被 systemd 正确加载。 - **找不到 parsers.conf**:见上文 3.4。 - **没有新数据**:确认 EdgeNode/EdgeDNS 已写日志到 `Path` 下,且 Fluent Bit 对目录有读权限;可分别执行 `tail -f /var/log/edge/edge-node/access.log` 与 `tail -f /var/log/edge/edge-dns/access.log`。 - **Node 上没有 `/var/log/edge/edge-node/access.log`**:见下文「八、Node 上找不到日志文件」。 --- ## 七、与其它组件的关系(简要) | 组件 | 说明 | |------|------| | **EdgeNode** | 日志落盘路径优先复用公用访问日志策略文件 `path`(取目录);若为空回退 `EDGE_LOG_DIR`,再回退默认 `/var/log/edge/edge-node`;生成 `access.log`、`waf.log`、`error.log`;支持 SIGHUP 重开句柄,可与 logrotate 的 `copytruncate` 配合。 | | **EdgeDNS** | DNS 访问日志落盘路径优先复用公用访问日志策略文件 `path`(取目录);若为空回退 `EDGE_DNS_LOG_DIR`,再回退默认 `/var/log/edge/edge-dns`;生成 `access.log`(JSON Lines),由 Fluent Bit 采集写入 `dns_logs_ingest`。 | | **logrotate** | 使用 `deploy/fluent-bit/logrotate.conf` 示例做轮转,避免磁盘占满。 | | **平台(EdgeAPI)** | 配置 ClickHouse 只读连接(`CLICKHOUSE_HOST`、`CLICKHOUSE_PORT`、`CLICKHOUSE_USER`、`CLICKHOUSE_PASSWORD`、`CLICKHOUSE_DATABASE`);当请求带 `Day` 且已配置 ClickHouse 时,访问日志列表查询走 ClickHouse。 | --- ## 八、Node 上找不到日志文件 若在 EdgeNode 机器上执行 `tail -f /var/log/edge/edge-node/access.log` 报 **No such file or directory**,按下面检查: 1. **EdgeNode 版本** 本地日志落盘是较新功能,需使用**包含该功能的 EdgeNode 构建**(当前仓库版本在首次加载配置时会预创建目录和三个空日志文件)。 2. **预创建目录(可选)** 若进程以非 root 运行,可先手动建目录并赋权,避免无权限创建 `/var/log/edge`: ```bash sudo mkdir -p /var/log/edge/edge-node sudo chown <运行 edge-node 的用户>:<同组> /var/log/edge/edge-node ``` 3. **重启 EdgeNode** 新版本在**首次成功加载节点配置后**会调用 `EnsureInit()`,自动创建 `/var/log/edge/edge-node` 及 `access.log`、`waf.log`、`error.log`。重启一次 edge-node 后再看目录下是否已有文件。 4. **自定义路径** 若在管理端设置了公用访问日志策略的文件 `path`,节点会优先使用该目录;否则才使用 `EDGE_LOG_DIR`。Fluent Bit 的 `Path` 需与实际目录一致。 以上完成即完成 Fluent Bit 的部署与验证。 --- ## 九、HTTPS 模式(ClickHouse) 当 ClickHouse 只开放 HTTPS(如 8443)或链路必须加密时,使用本目录新增模板: - `fluent-bit-https.conf`:Node+DNS 同机采集(HTTP+DNS 双输入) - `fluent-bit-dns-https.conf`:仅 DNS 节点采集 - `fluent-bit-windows-https.conf`:Windows 节点 HTTPS 采集 ### 9.1 什么时候用 HTTPS 模板 - ClickHouse 仅开放 HTTPS 端口; - 节点到 ClickHouse 跨公网或需要传输加密; - 你希望启用证书校验和 SNI。 ### 9.2 最小切换步骤(Linux) 1. 备份当前配置: ```bash sudo cp /etc/fluent-bit/fluent-bit.conf /etc/fluent-bit/fluent-bit.conf.bak ``` 2. 切换为 HTTPS 模板(Node+DNS 同机示例): ```bash sudo cp /path/to/fluent-bit-https.conf /etc/fluent-bit/fluent-bit.conf ``` 3. 设置账号密码(按你的服务文件方式设置): ```bash export CH_USER=default export CH_PASSWORD='your_password' ``` 4. 修改模板中的关键项: - `Host` / `Port`(HTTPS 常见端口 `8443`) - `tls.verify`:`On`/`Off` - `tls.ca_file`:自签名证书建议配置 CA 文件 - `tls.vhost`:证书 CN/SAN 对应主机名(SNI) 5. 重启并检查: ```bash sudo systemctl restart fluent-bit sudo systemctl status fluent-bit journalctl -u fluent-bit -f ``` ### 9.3 验证点 - `default.logs_ingest` 有新增数据(HTTP) - `default.dns_logs_ingest` 有新增数据(DNS) - Fluent Bit 日志中无 TLS 握手失败(`certificate`, `x509`, `tls`) ### 9.4 回滚 TLS 配置错误导致中断时,快速回滚: ```bash sudo cp /etc/fluent-bit/fluent-bit.conf.bak /etc/fluent-bit/fluent-bit.conf sudo systemctl restart fluent-bit ``` 回滚后恢复原 HTTP 模式,不影响平台 API/管理端配置。