ARTICLE · 1219735
DeepFlow部署实施文档
在已有 K8s 集群中部署 DeepFlow v7.1,使用已有 Grafana 作为可视化前端。
项目概述
1.1 DeepFlow 简介
DeepFlow 是基于 eBPF 和 Wasm 的全栈可观测性平台,提供:
1.2 组件架构

1.3 环境信息
镜像准备
2.1 所需镜像
2.2 同步到 Harbor(在 Docker 节点执行)
# == 在 XXX.XXX.28.30 执行 ==# 1. 创建 Harbor 项目curl -u admin:Harbor12345 -X POST "https://dai30.test.com/api/v2.0/projects" \ -H "Content-Type: application/json" \ -d '{"project_name":"deepflow","public":true}' -k# 2. 拉取 + 推送IMAGES=( "registry.cn-hongkong.aliyuncs.com/deepflow-ce/deepflow-server:v7.1" "registry.cn-hongkong.aliyuncs.com/deepflow-ce/deepflow-app:v7.1" "registry.cn-hongkong.aliyuncs.com/deepflow-ce/deepflow-agent:v7.1" "registry.cn-hongkong.aliyuncs.com/deepflow-ce/clickhouse-server:23.10" "registry.cn-hongkong.aliyuncs.com/deepflow-ce/mysql:8.0.39")for img in "${IMAGES[@]}"; do name=$(basename $img | cut -d: -f1) tag=$(basename $img | cut -d: -f2) docker pull $img docker tag $img dai30.test.com/deepflow/$name:$tag docker push dai30.test.com/deepflow/$name:$tagdone
部署 DeepFlow
3.1 添加 Helm Repo
# == 在 master-0 执行 ==helm repo add deepflow https://deepflowio.github.io/deepflow-chartshelm repo update
3.2 创建 values.yaml
# deepflow-values.yamlglobal: image: repository: dai30.test.com/deepflow # 使用 Harbor 镜像 pullPolicy: IfNotPresent storageClass: managed-nfs-storage timezone: "Asia/Shanghai" replicas: 1# 禁用内置 Grafanagrafana: enabled: false# Server 配置deepflow-server: replicas: 1 service: type: NodePort# App(API 后端,ClusterIP 即可)deepflow-app: service: type: ClusterIP# MySQLmysql: persistence: size: 20Gi# ClickHouseclickhouse: persistence: size: 50Gi replicas: 1# Agent DaemonSetdeepflow-agent: enabled: true
3.3 安装
# == 在 master-0 执行 ==kubectl create ns deepflow# 方式1:Helm(网络通时)helm install deepflow deepflow/deepflow \ --version 7.1.002 \ -n deepflow \ -f deepflow-values.yaml \ --timeout 10m# 方式2:离线(如果 GitHub 不通,先下载 chart 到本地)# helm pull deepflow/deepflow --version 7.1.002# helm install deepflow ./deepflow-7.1.002.tgz -n deepflow -f deepflow-values.yaml
3.4 验证部署
kubectl -n deepflow get pods -o widekubectl -n deepflow get svckubectl -n deepflow get statefulsetkubectl -n deepflow get daemonset
预期状态:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES deepflow-agent-6qf9r 1/1 Running 0 8d 172.18.181.195 master-1.test.com <none> <none> deepflow-agent-nslvb 1/1 Running 0 22d 172.25.112.99 worker-1.test.com <none> <none> deepflow-agent-smspl 1/1 Running 0 8d 172.21.121.33 master-2.test.com <none> <none> deepflow-agent-thq5f 1/1 Running 0 22d 172.31.67.218 worker-0.test.com <none> <none> deepflow-agent-vtkrg 1/1 Running 0 22d 172.23.161.22 master-0.test.com <none> <none> deepflow-app-7cb7d6f745-9xk2t 1/1 Running 0 22d 172.25.112.84 worker-1.test.com <none> <none> deepflow-clickhouse-0 1/1 Running 0 22d 172.25.112.78 worker-1.test.com <none> <none> deepflow-mysql-7fd9b57bdc-k84bm 1/1 Running 0 22d 172.18.181.199 master-1.test.com <none> <none> deepflow-server-7fcfc4689f-vmzfr 1/1 Running 0 22d 172.25.112.114 worker-1.test.com <none> <none> [root@master-0 ~]# kubectl -n deepflow get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE deepflow-agent ClusterIP XX.104.232.33 <none> 80/TCP 22d deepflow-app ClusterIP XX.111.51.193 <none> 20418/TCP 22d deepflow-clickhouse ClusterIP XX.109.44.40 <none> 8123/TCP,9000/TCP,9009/TCP 22d deepflow-clickhouse-headless ClusterIP None <none> 8123/TCP,9000/TCP,9009/TCP 22d deepflow-mysql ClusterIP XX.111.247.16 <none> 30130/TCP 22d deepflow-server NodePort XX.102.231.153 <none> 20416:31963/TCP,20419:31813/TCP,20417:30417/TCP,20035:30621/TCP,30035:30035/TCP,20135:31201/TCP,20033:31100/TCP,30033:30033/TCP 22d [root@master-0 ~]# kubectl -n deepflow get statefulset NAME READY AGE deepflow-clickhouse 1/1 22d [root@master-0 ~]# kubectl -n deepflow get daemonset NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE deepflow-agent 5 5 5 5 5 <none> 22d [root@master-0 ~]#
Grafana 集成
4.1 架构说明
┌──────────────────────────────────────────────────────┐│ Grafana (XXX.XXX.28.23:32000) ││ ├─ DeepFlow Querier 数据源 ││ │ └─ http://deepflow-server.deepflow:20416 ││ │ ├─ /v1/query/ — PromQL 兼容查询 ││ │ ├─ /v1/health/ — 健康检查 ││ │ └─ /v1/trace_map/ — 分布式追踪拓扑 ││ └─ Dashboard 19418/19419/19420 │└──────────────────────────────────────────────────────┘
4.2 安装 Grafana 插件(手动 — 推荐)
1)提取预编译插件(v7.1)
注:必须使用与 Server 版本匹配的插件:v7.1 Server 需要 v7.1 插件,v6.x 插件会导致 Dashboard 报错 tag resource_gl0_0 not found。
# == 在可访问 Docker Hub 的节点执行(如 XXX.XXX.28.30)==# 拉取 v7.1 插件镜像(171MB)docker pull ghcr.io/deepflowio/deepflow-ce/deepflowio-init-grafana:v7.1# 提取插件文件CID=$(docker create ghcr.io/deepflowio/deepflow-ce/deepflowio-init-grafana:v7.1)mkdir -p /tmp/df-plugins-v7docker cp $CID:/deepflow-plugins/. /tmp/df-plugins-v7/docker rm $CID# 复制到 NFS 持久化目录rm -rf /data/nfs-sc/grafana-plugins/*cp -r /tmp/df-plugins-v7/* /data/nfs-sc/grafana-plugins/# v7.1 插件 ID(与 v6.x 不同!):# deepflowio-deepflow-datasource — 数据源(v6 叫 deepflow-querier-datasource)# deepflowio-topo-panel — 服务拓扑面板(v6 叫 deepflow-topo-panel)# deepflowio-tracing-panel — 应用追踪面板(v6 叫 deepflow-apptracing-panel)# grafana-clickhouse-datasource — ClickHouse 数据源
2)创建 NFS PV/PVC
# == 在 master-0 执行 ==cat <<'EOF' | kubectl apply -f -apiVersion: v1kind: PersistentVolumemetadata: name: grafana-plugins-pvspec: capacity: storage: 1Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain nfs: server: XXX.XXX.28.30 path: /data/nfs-sc/grafana-plugins---apiVersion: v1kind: PersistentVolumeClaimmetadata: name: grafana-plugins-pvc namespace: monitoringspec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi volumeName: grafana-plugins-pv storageClassName: ""EOF
关键:必须设置 storageClassName: "" 避免触发 managed-nfs-storage 动态供应。
3)镜像推送到 Harbor(加速拉取)
Grafana 和 busybox 镜像较大,推送到 Harbor 后 initContainer 可秒级启动:
# == 在 Docker 节点(XXX.XXX.28.30)执行 ==docker pull busyboxdocker tag busybox dai30.test.com/study/busybox:latestdocker push dai30.test.com/study/busybox:latestdocker pull grafana/grafana:10.4.15docker tag grafana/grafana:10.4.15 dai30.test.com/study/grafana:10.4.15docker push dai30.test.com/study/grafana:10.4.15
4)部署 Grafana(initContainer + emptyDir)
关键设计:不直接挂载 NFS 到 Grafana 主容器(会导致 kubectl exec 超时),而是在 initContainer 中从 NFS 读取插件,拷贝到 emptyDir,主容器使用本地 emptyDir。
# == 在 master-0 执行 ==kubectl -n monitoring delete deploy grafana --ignore-not-foundcat <<'EOF' | kubectl apply -f -apiVersion: apps/v1kind: Deploymentmetadata: name: grafana namespace: monitoringspec: replicas: 1 selector: matchLabels: app: grafana template: metadata: labels: app: grafana spec: initContainers: - name: copy-plugins image: dai30.test.com/study/busybox:latest command: ["sh", "-c", "cp -r /nfs-plugins/* /target-plugins/"] volumeMounts: - name: nfs-plugins mountPath: /nfs-plugins - name: grafana-plugins mountPath: /target-plugins containers: - name: grafana image: dai30.test.com/study/grafana:10.4.15 ports: - containerPort: 3000 name: http env: - name: GF_SECURITY_ADMIN_PASSWORD value: deepflow volumeMounts: - name: grafana-storage mountPath: /var/lib/grafana - name: grafana-plugins mountPath: /var/lib/grafana/plugins volumes: - name: grafana-storage emptyDir: {} - name: grafana-plugins emptyDir: {} - name: nfs-plugins persistentVolumeClaim: claimName: grafana-plugins-pvcEOF
为什么不用 NFS 直接挂载?
NFS 挂载到 /var/lib/grafana/plugins 后,kubectl exec 进入 Grafana 容器会超时(NFS I/O 阻塞)。initContainer + emptyDir 方案只在启动时读写一次 NFS,后续完全本地。
5)添加数据源
Grafana 启动后通过 API 添加数据源。DeepFlow v7.1 需要 traceUrl和requestUrl两个字段,缺一不可:
# DeepFlow Querier 数据源(含 traceUrl + requestUrl)curl -s -X POST -H "Content-Type: application/json" -d '{"name":"DeepFlow","type":"deepflowio-deepflow-datasource","url":"http://deepflow-server.deepflow:20416","access":"proxy","jsonData":{"traceUrl":"http://deepflow-server.deepflow:20416","requestUrl":"http://deepflow-server.deepflow:20416"}}' "http://admin:deepflow@XXX.XXX.28.23:32000/api/datasources"
持久化:数据源已写入 monitoring/grafana-datasources Secret (editable: true) ,Grafana 重启后自动加载,UI可编辑。
# Secret 内容apiVersion: 1datasources:- name: DeepFlow type: deepflowio-deepflow-datasource url: http://deepflow-server.deepflow:20416 access: proxyeditalbe: true jsonData: traceUrl: http://deepflow-server.deepflow:20416 requestUrl: http://deepflow-server.deepflow:20416
关键配置项:
type: 必须是 deepflowio-deepflow-datasource(v7.1 插件 ID,不同于 v6.x 的 deepflow-querier-datasource);
traceUrl: 必须设置,否则 Dashboard 报错 missing data: traceUrl;
GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS:必须包含 v7.1 的插件 ID。
6)验证
# 确认插件已加载kubectl -n monitoring exec deploy/grafana -- ls /var/lib/grafana/plugins/# 预期: deepflowio-deepflow-datasource deepflowio-tracing-panel deepflowio-topo-panel grafana-clickhouse-datasource
7)Dashboard 自动加载
v7.1 插件(deepflow-querier-datasource/dashboards/)包含 28 个预置 Dashboard JSON(11 个 System + 17 个 Templates),通过 initContainer 在启动时自动复制到 /grafana-dashboard-definitions/:
# initContainer 脚本(已包含在 4.2.4 的 Deployment YAML 中)cd /target-plugins/deepflow-querier-datasource/dashboardsfor dir in */; do dname=deepflow-${dir%/} mkdir -p /dashboards/$dname cp ${dir}*.json /dashboards/$dname/done
Grafana 的 Dashboard Provisioning(/etc/grafana/provisioning/dashboards/dashboards.yaml)扫描 /grafana-dashboard-definitions/,启动时自动导入。
实际加载结果:
4.3 当前 Grafana 状态
URL: http://XXX.XXX.28.23:32000用户: admin密码: deepflowDashboard: 69 个(28 K8s + 13 DeepFlow + 28 其他)数据源: Prometheus + DeepFlow(v7.1 插件,Secret 持久化)
4.4 查看Dashboard


端口详解
5.1 端口全景图
外部访问 集群内部───────── ─────────20418 ◄── deepflow-app (API 后端,无界面)32000 ◄── grafana (监控面板) │ ├──► deepflow-server:20416 (Querier — Grafana 数据源) │ ├─ 20417 Controller (健康检查/选举) │ ├─ 20035 gRPC (内部通信) │ ├─ 20033 Ingester (Agent 数据上报入口) │ ├─ 30033 Ingester (NodePort:30033,Agent 跨网段上报) │ └─ 30035 gRPC (NodePort:30035,跨节点 gRPC) │ ├──► deepflow-clickhouse:9000 (时序数据存储) │ └─ 8123 HTTP 接口 │ └──► deepflow-mysql:30130 (元数据存储)
5.2 端口清单
5.3 数据流向

5.4 连通性测试
# 从 Grafana Pod 测试 Querier 连通性kubectl -n monitoring exec deploy/grafana -- curl -s http://deepflow-server.deepflow:20416/v1/health/# 从 Server Pod 测试 ClickHousekubectl -n deepflow exec deploy/deepflow-server -- curl -s http://deepflow-clickhouse:8123/ping# 从 Server Pod 测试 MySQLkubectl -n deepflow exec deploy/deepflow-server -- nc -zv deepflow-mysql 30130
配置与优化
6.1 Agent 资源配置
# deepflow-values.yaml 追加deepflow-agent: resources: requests: memory: 256Mi cpu: 200m limits: memory: 1Gi cpu: 1000m
6.2 ClickHouse 存储优化
clickhouse: persistence: size: 100Gi # 根据数据量调整 config: max_memory_usage: 4000000000 # 4GB max_concurrent_queries: 50
6.3 数据保留策略
在 ClickHouse 中设置 TTL:
-- 连接 ClickHousekubectl -n deepflow exec -it deepflow-clickhouse-0 -- clickhouse-client-- 设置 30 天自动清理ALTER TABLE flow_tag.flow_log_local MODIFY TTL time + INTERVAL 30 DAY;ALTER TABLE flow_tag.flow_metrics_local MODIFY TTL time + INTERVAL 30 DAY;
排错指南
7.1 Pod 启动失败
# 查看 Pod 日志kubectl -n deepflow logs -l component=deepflow-server --tail=100# 查看事件kubectl -n deepflow describe pod deepflow-server-0
7.2 Agent 无法采集
# 检查 Agent 日志kubectl -n deepflow logs -l app=deepflow-agent --tail=50 | grep -i error# 检查 eBPF 支持kubectl -n deepflow exec -it ds/deepflow-agent -- ls /sys/kernel/btf/vmlinux
7.3 Grafana 查询无数据
1)确认数据源连接状态
Grafana → Data Sources → DeepFlow → Save & Test2)检查 Server Querier 端口
kubectl -n deepflow port-forward svc/deepflow-server 204163)手动测试
curl http://localhost:20416/v1/health/7.4 常见错误
卸载
helm -n deepflow uninstall deepflowkubectl delete ns deepflow# 手动清理 PVC(如需要)kubectl -n deepflow delete pvc --all
附录
附录 A:完整 values.yaml 参考
global: image: repository: dai30.test.com/deepflow pullPolicy: IfNotPresent storageClass: managed-nfs-storage timezone: "Asia/Shanghai" replicas: 1 hostNetwork: falsegrafana: enabled: falsedeepflow-server: replicas: 1 service: type: NodePortdeepflow-app: service: type: ClusterIPdeepflow-agent: enabled: true resources: requests: memory: 256Mi cpu: 200m limits: memory: 1Gi cpu: 1000mmysql: persistence: size: 20Giclickhouse: persistence: size: 50Gi replicas: 1
附录 B:Grafana 集成实录与排错
1)插件版本不兼容问题现象
从 deepflowce/deepflow-init-grafana:v6.1.8.5 提取的 4 个 Grafana 插件无法在 DeepFlow v7.1 上正常使用,Dashboard 报错:
Templating: Failed to upgrade legacy queriestag resource_gl0_0 未在 vtap_app_edge_port, flow_metrics 中找到
2)根因
插件和 Dashboard 是 v6.1.8.5 版本,DeepFlow Server 是 v7.1,ClickHouse 的表结构和 tag 名称已变化(resource_gl0_0 在 v7.1 中已移除/重命名),版本不兼容。

本文作者:代长江 (上海新炬中北团队)
本文来源:“IT那活儿”公众号
















































































