1 - 编译

1 官方镜像编译

为隔离开发者本地环境和简化编译流程,我们提供容器化编译方式,你可以直接通过 docker build,构建完成的镜像(包含底层采集器 huatuo-bamai、bpf obj、工具等)。在项目根目录运行:

docker build --network host -t huatuo/huatuo-bamai:latest .

2 自定义镜像编译

文件 Dockerfile.dev 内容:

FROM golang:1.23.0-alpine AS base
# 镜像构建加速
# RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk add --no-cache \
                make \
                clang15 \
                libbpf-dev \
                bpftool \
                curl \
                git

ENV PATH=$PATH:/usr/lib/llvm15/bin

# build huatuo components
FROM base AS build
ARG BUILD_PATH=${BUILD_PATH:-/go/huatuo-bamai}
ARG RUN_PATH=${RUN_PATH:-/home/huatuo-bamai}
WORKDIR ${BUILD_PATH}

2.1 构建 dev 镜像

docker build --network host -t huatuo/huatuo-bamai-dev:latest -f ./Dockerfile.dev .

2.2 运行 dev 容器

docker run -it --privileged --cgroupns=host --network=host -v /path/to/huatuo:/go/huatuo-bamai huatuo/huatuo-bamai-dev:latest sh

2.3 编译

容器内执行

make

编译完成后,所有产出物在 ./_output 下。

3 物理机或 VM 编译

采集器编译依赖以下工具,可自行根据本地实际环境安装:

  • make
  • git
  • clang15
  • libbpf
  • bpftool
  • curl

考虑本地环境差异过大,遇到编译可能问题会很多,为隔离环境差异,排查问题也方便建议尽量使用 docker 编译方式。

2 - 部署

HUATUO 采集器 huatuo-bamai 运行在物理机或 VM 上,提供了二进制包和 docker 镜像,可完全通过自定义方式部署,如 k8s daemonset 方式、systemd/supervisord 托管方式等。

  • systemd 托管、daemonset 方式适合生产环境
  • docker / compose 方式适合开发和快速验证场景

二进制包下载

提供最近版本 v2.1.0 的二进制包,master 仅供安装可参考。

国内镜像下载

镜像默认存储在 dockerhub,也提供国内镜像获取方式,手动同步了采集器 huatuo/huatuo-bamai v2.1.0 版本到渡渡鸟镜像站,注意别下载 latest (渡渡鸟镜像站不会自动更新 latest 版本):

2.1 - Daemonset

HUATUO 为减少理解成本,提供了最简单的 daemonset 部署方式。

通过 daemonset 方式部署 HUATUO 采集器有如下步骤。

1 拉取采集器配置文件

curl -L -o huatuo-bamai.conf https://github.com/ccfos/huatuo/raw/main/huatuo-bamai.conf

配置文件需要根据你的实际环境作修改,如连接 kubelet 和 elasticsrearch 的相关配置。

2 创建 configMap

kubectl create configmap huatuo-bamai-config --from-file=./huatuo-bamai.conf

3 部署采集器

kubectl apply -f huatuo-daemonset.minimal.yaml

文件 huatuo-daemonset.minimal.yaml 内容:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: huatuo
  namespace: default
  labels:
    app: huatuo
spec:
  selector:
    matchLabels:
      app: huatuo
  template:
    metadata:
      labels:
        app: huatuo
    spec:
      containers:
      - name: huatuo
        image: docker.io/huatuo/huatuo-bamai:latest
        resources:
          limits:
            cpu: '1'
            memory: 2Gi
          requests:
            cpu: 500m
            memory: 512Mi
        securityContext:
          privileged: true
        volumeMounts:
        - name: proc
          mountPath: /proc
        - name: sys
          mountPath: /sys
        - name: run
          mountPath: /run
        - name: var
          mountPath: /var
        - name: etc
          mountPath: /etc
        - name: huatuo-local
          mountPath: /home/huatuo-bamai/huatuo-local
        - name: huatuo-bamai-config-volume
          mountPath: /home/huatuo-bamai/conf/huatuo-bamai.conf
          subPath: huatuo-bamai.conf
      volumes:
      - name: proc
        hostPath:
          path: /proc
      - name: sys
        hostPath:
          path: /sys
      - name: run
        hostPath:
          path: /run
      - name: var
        hostPath:
          path: /var
      - name: etc
        hostPath:
          path: /etc
      - name: huatuo-local
        hostPath:
          path: /var/log/huatuo/huatuo-local
          type: DirectoryOrCreate
      - name: huatuo-bamai-config-volume
        configMap:
          name: huatuo-bamai-config
      hostNetwork: true
      hostPID: true

2.2 - Docker

镜像下载

镜像默认存储在 dockerhub

也提供国内镜像获取方式,手动同步了采集器 huatuo/huatuo-bamai v2.1.0 版本到渡渡鸟镜像站,注意别下载 latest (渡渡鸟镜像站不会自动更新 latest 版本):

只部署采集器

启动容器

docker run --privileged --cgroupns=host --network=host -v /sys:/sys -v /proc:/proc -v /run:/run huatuo/huatuo-bamai:latest

⚠️:这会使用容器内的默认配置文件,容器内的默认配置不会连接 ES,完整配置可将 huatuo-bamai.conf 通过 -v 方式挂载到容器内部,需要根据你的实际环境对 huatuo-bamai.conf 作修改,如连接 kubelet 和 elasticsrearch 的相关配置、本地存储异常事件日志的路径等。

部署所有组件(docker compose)

在本地开发、验证使用 docker compose 是最便捷的方式,可通过该方式快速地在本地搭建部署一套完整的环境自行管理采集器、ES、prometheus、grafana 等组件。

docker compose --project-directory ./build/docker up

docker compose 建议使用 plugins 方式安装,参考 https://docs.docker.com/compose/install/linux/

2.3 - Systemd

rpm 方式安装

目前腾讯提供 v2.1.0 版本的 rpm 包,master 仅供安装可参考。

腾讯 OpenCloudOS 提供了 HUATUO 安装包,因此在 OpenCloudOS 上可快速启用 HUATUO。

  • x86_64 架构
wget https://mirrors.opencloudos.tech/epol/9/Everything/x86_64/os/Packages/huatuo-bamai-2.1.0-2.oc9.x86_64.rpm  
  • arm64 架构
wget https://mirrors.opencloudos.tech/epol/9/Everything/aarch64/os/Packages/huatuo-bamai-2.1.0-2.oc9.aarch64.rpm
  • OC8 通过下载的 rpm 包安装 HUATUO
sudo rpm -ivh huatuo-bamai*.rpm

类似其他使用 rpm 包管理的 OS 也可通过该方式下载和安装,配置文件需要根据你的实际环境作修改,如连接 kubelet 和 elasticsrearch 的相关配置等。

腾讯 OpenCloudOS 完整安装可参考https://mp.weixin.qq.com/s/Gmst4_FsbXUIhuJw1BXNnQ

二进制安装

提供最近版本 v2.1.0 的二进制包,master 仅供安装可参考。

可下载二进制包自定义配置托管方式,同上配置文件需要根据你的实际环境作修改,如连接 kubelet 和 elasticsrearch 的相关配置等。

3 - 添加自定义采集

在本地开发、验证使用 docker compose 是最便捷的方式,可通过该方式快速地在本地搭建部署一套完整的环境自行管理采集器、ES、prometheus、grafana 等组件。

docker compose --project-directory ./build/docker up

docker compose 建议使用 plugins 方式安装,参考 https://docs.docker.com/compose/install/linux/

3.1 - 添加自定义采集

框架提供了非常便捷的 API,包括模块启动、数据存储、容器信息、bpf 相关 (load, attach, read, detach, unload)等,用户可通过自定义的采集逻辑,灵活选择合适的采集模式和数据存储的方式。

tracing 类型

根据实际场景,你可以在 core/autotracingcore/events 目录下实现接口 ITracingEvent 即可完成 tracing 类型的采集。

// ITracingEvent represents a tracing/event
type ITracingEvent interface {
    Start(ctx context.Context) error
}

步骤如下:

type exampleTracing struct{}

// 注册回调
func init() {
    tracing.RegisterEventTracing("example", newExample)
}

// 创建 tracing
func newExample() (*tracing.EventTracingAttr, error) {
    return &tracing.EventTracingAttr{
        TracingData: &exampleTracing{},
        Internal:    10, // 再次开启 tracing 的间隔时间 seconds
        Flag:        tracing.FlagTracing, // 标记为 tracing 类型
    }, nil
}

// 实现接口 ITracingEvent
func (t *exampleTracing) Start(ctx context.Context) error {
    // do something
    ...

    // 存储数据到 ES 和 本地
    storage.Save("example", ccontainerID, time.Now(), tracerData)
}

// 也可同时实现接口 Collector 以 Prometheus 格式输出 (可选)
func (c *exampleTracing) Update() ([]*metric.Data, error) {
    // from tracerData to prometheus.Metric 
    ...

    return data, nil
}

Metric 类型

core/metrics 目录下添加接口 Collector 的实现即可完成 Metric 类型的采集。

type Collector interface {
    // Get new metrics and expose them via prometheus registry.
    Update() ([]*Data, error)
}

步骤如下:

type exampleMetric struct{}

// 注册回调
func init() {
    tracing.RegisterEventTracing("example", newExample)
}

// 创建 Metric
func newExample() (*tracing.EventTracingAttr, error) {
    return &tracing.EventTracingAttr{
        TracingData: &filenrCollector{
            metric: []*metric.Data{
                metric.NewGaugeData("name1", 0, "description of example_name1", nil),
                metric.NewGaugeData("name2", 0, "description of example_name2", nil),                
            },
        },
        Flag: tracing.FlagMetric, // 标记为 Metric 类型
    }, nil
}

// 实现接口 Collector 以 Prometheus 格式输出
func (c *exampleMetric) Update() ([]*metric.Data, error) {
    // do something
    ...

    return data, nil
}

在项目 core 目录下已集成了 3 个采集模块的多种实际场景的示例,包括 bpf 代码、map 数据交互、容器信息等,更多详情可参考对应代码实现。

3.2 - 如何添加自定义 Autotracing

概述

  • 类型:异常事件驱动(tracing/autotracing)
  • 功能:自动跟踪系统异常状态,并在异常发生时再触发抓取现场上下文信息
  • 特点
    • 当系统出现异常时,autotracing 会自动触发,捕获相关的上下文信息
    • 事件数据会实时存储在本地并存储到远端ES,同时你也可以生成Prometheus 统计指标进行观测。
    • 适用于获取现场时性能开销较大的场景,例如检测到指标上升到一定阈值、上升速度过快再触发抓取
  • 已集成:cpu 异常使用跟踪(cpu idle)、D状态跟踪(dload)、容器内外部争抢(waitrate)、内存突发分配(memburst)、磁盘异常跟踪(iotracer)

如何添加 Autotracing ?

AutoTracing 只需实现 ITracingEvent 接口并完成注册,即可将事件添加到系统中。

AutoTracingEvent 类型在框架实现上没有任何区别,只是针对不同的场景进行了实际应用的区分。

// ITracingEvent represents a autotracing or event
type ITracingEvent interface {
    Start(ctx context.Context) error
}

1. 创建结构体

type exampleTracing struct{}

2. 注册回调函数

func init() {
    tracing.RegisterEventTracing("example", newExample)
}

func newExample() (*tracing.EventTracingAttr, error) {
    return &tracing.EventTracingAttr{
        TracingData: &exampleTracing{},
        Internal:    10, // 再次开启 tracing 的间隔时间 seconds
        Flag:        tracing.FlagTracing, // 标记为 tracing 类型; | tracing.FlagMetric(可选)
    }, nil
}

3. 实现接口 ITracingEvent

func (t *exampleTracing) Start(ctx context.Context) error {
    // detect your care about 
    ...

    // 存储数据到 ES 和 本地
    storage.Save("example", ccontainerID, time.Now(), tracerData)
}

另外也可同时实现接口 Collector 以 Prometheus 格式输出 (可选)

func (c *exampleTracing) Update() ([]*metric.Data, error) {
    // from tracerData to prometheus.Metric 
    ...

    return data, nil
}

在项目 core/autotracing 目录下已集成了多种实际场景的 autotracing 示例,以及框架提供的丰富底层接口,包括 bpf prog,map 数据交互、容器信息等,更多详情可参考对应代码实现。

3.3 - 如何添加自定义 Event

概述

  • 类型:异常事件驱动(tracing/event)
  • 功能:常态运行在系统达到预设阈值后抓取上下文信息
  • 特点
    • autotracing 不同,event 是常态运行,而不是在异常时再触发。
    • 事件数据会实时存储在本地并存储到远端ES,同时你也可以生成Prometheus 统计指标进行观测。
    • 适合用于常态监控实时分析,能够及时发现系统中的异常行为, event 类型的采集对系统性能影响可忽略。
  • 已集成:软中断异常(softirq)、内存异常分配(oom)、软锁定(softlockup)、D 状态进程(hungtask)、内存回收(memreclaim)、异常丢包(dropwatch)、网络入向延迟(net_rx_latency) 等

如何添加事件指标

只需实现 ITracingEvent 接口并完成注册,即可将事件添加到系统。

AutoTracingEvent 类型在框架实现上没有任何区别,只是针对不同的场景进行了实际应用的区分。

// ITracingEvent represents a tracing/event
type ITracingEvent interface {
    Start(ctx context.Context) error
}

1. 创建 Event 结构体

type exampleTracing struct{}

2. 注册回调函数

func init() {
    tracing.RegisterEventTracing("example", newExample)
}

func newExample() (*tracing.EventTracingAttr, error) {
    return &tracing.EventTracingAttr{
        TracingData: &exampleTracing{},
        Internal:    10, // 再次开启 tracing 的间隔时间 seconds
        Flag:        tracing.FlagTracing, // 标记为 tracing 类型;| tracing.FlagMetric(可选)
    }, nil
}

3. 实现接口 ITracingEvent

func (t *exampleTracing) Start(ctx context.Context) error {
    // do something
    ...

    // 存储数据到 ES 和 本地
    storage.Save("example", ccontainerID, time.Now(), tracerData)
}

另外也可同时实现接口 Collector 以 Prometheus 格式输出 (可选)

func (c *exampleTracing) Update() ([]*metric.Data, error) {
    // from tracerData to prometheus.Metric 
    ...

    return data, nil
}

在项目 core/events 目录下已集成了多种实际场景的 events 示例,以及框架提供的丰富底层接口,包括 bpf prog, map 数据交互、容器信息等,更多详情可参考对应代码实现。

3.4 - 如何添加自定义 Metrics

概述

Metrics 类型用于采集系统性能等指标数据,可输出为 Prometheus 格式,作为服务端对外提供数据,通过接口 /metrics (curl localhost:<port>/metrics) 获取。

  • 类型:指标数据采集

  • 功能:采集各子系统的性能指标数据

  • 特点

    • metrics 主要用于采集系统的性能指标,如 CPU 使用率、内存使用率、网络等,适合用于监控系统的性能指标,支持实时分析和长期趋势观察。
    • 指标数据可以来自常规 procfs/sysfs 采集,也可以从 tracing (autotracing, event) 类型生成指标数据
    • Prometheus 格式输出,便于无缝集成到 Prometheus 观测体系
  • 已集成

    • cpu (sys, usr, util, load, nr_running…)
    • memory(vmstat, memory_stat, directreclaim, asyncreclaim…)
    • IO (d2c, q2c, freeze, flush…)
    • 网络(arp, socket mem, qdisc, netstat, netdev, socketstat…)

如何添加统计指标

只需实现 Collector 接口并完成注册,即可将指标添加到系统中。

type Collector interface {
    // Get new metrics and expose them via prometheus registry.
    Update() ([]*Data, error)
}

1. 创建结构体

core/metrics 目录下创建实现 Collector 接口的结构体:

type exampleMetric struct{
}

2. 注册回调函数

func init() {
    tracing.RegisterEventTracing("example", newExample)
}

func newExample() (*tracing.EventTracingAttr, error) {
    return &tracing.EventTracingAttr{
        TracingData: &exampleMetric{},
        Flag: tracing.FlagMetric, // 标记为 Metric 类型
    }, nil
}

3. 实现 Update 方法

func (c *exampleMetric) Update() ([]*metric.Data, error) {
    // do something
    ...
	return []*metric.Data{
		metric.NewGaugeData("example", value, "description of example", nil),
	}, nil

}

在项目 core/metrics 目录下已集成了多种实际场景的 Metrics 示例,以及框架提供的丰富底层接口,包括 bpf prog, map 数据交互、容器信息等,更多详情可参考对应代码实现。