eBPF 助力 NAS 分鐘級別 Pod 實(shí)例溯源
一、背景
二、流量溯源方案調(diào)研和驗(yàn)證
1. NAS 工作原理
2. 方案調(diào)研和驗(yàn)證
三、架構(gòu)設(shè)計和實(shí)現(xiàn)
1. 整體架構(gòu)設(shè)計
2. 內(nèi)核 eBPF 程序流程
3. 用戶空間程序架構(gòu)
四、總結(jié)
一、 背景
云存儲 NAS 產(chǎn)品是一個可共享訪問、彈性擴(kuò)展、高可靠、高性能的分布式文件系統(tǒng)。 NAS 兼容了 POSIX 文件接口,可支持?jǐn)?shù)千臺計算節(jié)點(diǎn)共享訪問,可掛載到彈性計算 ECS、容器實(shí)例等計算業(yè)務(wù)上,提供高性能的共享存儲服務(wù)。
鑒于多主機(jī)間共享的便利性和高性能, NAS 在得物的算法訓(xùn)練、應(yīng)用構(gòu)建等場景中均成為了基礎(chǔ)支撐。
圖片
在多業(yè)務(wù)共享的場景中,單個業(yè)務(wù)流量異常容易引發(fā)全局故障。目前,異常發(fā)生后需依賴云服務(wù)廠商 NAS 的溯源能力,但只能定位到主機(jī)級別,無法識別具體異常服務(wù)。要定位到服務(wù)級別,仍需依賴所有使用方協(xié)同排查,并由 SRE 多輪統(tǒng)計分析,效率低下(若服務(wù)實(shí)例發(fā)生遷移或重建,排查難度進(jìn)一步增加)。
為避免因 NAS 異?;驇捳紳M導(dǎo)致模型訓(xùn)練任務(wù)受阻,因此需構(gòu)建支持服務(wù)級流量監(jiān)控、快速溯源及 NAS 異常實(shí)時感知的能力,以提升問題定位效率并減少業(yè)務(wù)中斷。
二、 流量溯源方案調(diào)研和驗(yàn)證
NAS工作原理
NAS 本地掛載原理
在 Linux 平臺上,NAS 的產(chǎn)品底層是基于標(biāo)準(zhǔn)網(wǎng)絡(luò)文件系統(tǒng) NFS(Network File System),通過將遠(yuǎn)端文件系統(tǒng)掛載到本地,實(shí)現(xiàn)用戶對遠(yuǎn)端文件的透明訪問。
NFS 協(xié)議(主要支持 NFS v3 和 v4,通常以 v3 為主)允許將遠(yuǎn)端服務(wù)掛載到本地,使用戶能夠像訪問本地文件目錄一樣操作遠(yuǎn)端文件。文件訪問請求通過 RPC 協(xié)議發(fā)送到遠(yuǎn)端進(jìn)行處理,其整體流程如下:
文件系統(tǒng)訪問時的數(shù)據(jù)流向示意
Linux 內(nèi)核中 NFS 文件系統(tǒng)
在 Linux NFS 文件系統(tǒng)的實(shí)現(xiàn)中,文件操作接口由 nfs_file_operations 結(jié)構(gòu)體定義,其讀取操作對應(yīng)的函數(shù)為:
//NFS 文件系統(tǒng)的 VFS 層實(shí)現(xiàn)的函數(shù)如下所示:
const struct file_operations nfs_file_operations = {
        .llseek           = nfs_file_llseek,
        .read_iter        = nfs_file_read,
        .write_iter       = nfs_file_write,
        // ...
};針對 NFS 文件系統(tǒng)的讀操作涉及到 2 個階段(寫流程類似,只是函數(shù)名字有所差異,本文僅以讀取為例介紹)。由于文件讀取涉及到網(wǎng)絡(luò)操作因此這兩個階段涉及為異步操作:
※ 兩個階段
- 讀取請求階段:當(dāng)應(yīng)用程序針對 NFS 文件系統(tǒng)發(fā)起 read() 讀操作時,內(nèi)核會在VFS層調(diào)用 nfs_file_read 函數(shù),然后調(diào)用 NFS 層的 nfs_initiate_read 函數(shù),通過 RPC 的 rpc_task_begin 函數(shù)將讀請求發(fā)送到 NFS Server,至此向 NFS Server 發(fā)起的請求工作完成。
 - 讀響應(yīng)階段:在 NFS Server 返回消息后,會調(diào)用 rpc_task_end 和 nfs_page_read_done 等函數(shù),將數(shù)據(jù)返回到用戶空間的應(yīng)用程序。
 
圖片
在了解 NFS 文件系統(tǒng)的讀流程后,我們回顧一下 NFS Server 為什么無法區(qū)分單機(jī)訪問的容器實(shí)例或進(jìn)程實(shí)例。
這是因?yàn)?NFS 文件系統(tǒng)的讀寫操作是在內(nèi)核空間實(shí)現(xiàn)的。當(dāng)容器 A/B 和主機(jī)上的進(jìn)程 C 發(fā)起讀請求時,這些請求在進(jìn)入內(nèi)核空間后,統(tǒng)一使用主機(jī) IP(如 192.168.1.2)作為客戶端 IP 地址。因此,NFS Server 端的統(tǒng)計信息只能定位到主機(jī)維度,無法進(jìn)一步區(qū)分主機(jī)內(nèi)具體的容器或進(jìn)程。
內(nèi)核空間實(shí)現(xiàn)示意
方案調(diào)研和驗(yàn)證
進(jìn)程對應(yīng)容器上下文信息關(guān)聯(lián)
內(nèi)核中進(jìn)程以 PID 作為唯一編號,與此同時,內(nèi)核會建立一個 struct task_struct 對象與之關(guān)聯(lián),在 struct task_struct 結(jié)構(gòu)會保存進(jìn)程對應(yīng)的上下文信息。如實(shí)現(xiàn) PID 信息與用戶空間容器上下文的對應(yīng)(進(jìn)程 PID 1000 的進(jìn)程屬于哪個 Pod 哪個 Container 容器實(shí)例),我們需基于內(nèi)核 task_struct 結(jié)構(gòu)獲取到容器相關(guān)的信息。
通過分析內(nèi)核代碼和資料確認(rèn),發(fā)現(xiàn)可以通過 task_struct 結(jié)構(gòu)中對應(yīng)的 cgroup 信息獲取到進(jìn)程對應(yīng)的 cgroup_name 的信息,而該信息中包含了容器 ID 信息,例如 docker-2b3b0ba12e92...983.scope ,完整路徑較長,使用 .... 省略?;谌萜?ID 信息,我們可進(jìn)一步管理到進(jìn)程所歸屬的 Pod 信息,如 Pod NameSpace 、 Pod Name 、 Container Name 等元信息,最終完成進(jìn)程 PID 與容器上下文信息元數(shù)據(jù)關(guān)聯(lián)。
struct task_struct {
        struct css_set __rcu                *cgroups;
}
struct css_set {
        struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
}
struct cgroup_subsys_state {
        struct cgroup *cgroup;
}
struct cgroup {
  struct kernfs_node *kn;                /* cgroup kernfs entry */
}
struct kernfs_node {
        const char                *name;  // docker-2b3b0ba12e92...983.scope
}以某容器進(jìn)程為例,該進(jìn)程在 Docker 容器環(huán)境中的 cgroup 路徑完整為 /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podefeb3229_4ecb_413a_8715_5300a427db26.slice/docker-2b3b0ba12e925820ac8545f67c8cadee864e5b4033b3d5004d8a3aa742cde2ca.scope 。
經(jīng)驗(yàn)證,我們在內(nèi)核中讀取 task->cgroups->subsys[0]->kn->name 的值為 docker-2b3b0ba12e925820ac8545f67c8cadee864e5b4033b3d5004d8a3aa742cde2ca.scope 。
圖片
其中容器 ID 字段為 docker- 與 .scope 間的字段信息,在 Docker 環(huán)境中一般取前 12 個字符作為短 ID,如 2b3b0ba12e92 ,可通過 docker 命令進(jìn)行驗(yàn)證,結(jié)果如下:
docker ps -a|grep 2b3b0ba
2b3b0ba12e92        registry-cn-hangzhou-vpc.ack.aliyuncs.com/acs/pause:3.5NAS 上下文信息關(guān)聯(lián)
NAS 產(chǎn)品的訪問通過掛載命令完成本地文件路徑的掛載。我們可以通過 mount 命令將 NAS 手工掛載到本地文件系統(tǒng)中。
mount -t nfs -o vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport \
  3f0f3489aa-xxxx.cn-shanghai.nas.aliyuncs.com:/test /mnt/nas執(zhí)行上述掛載命令成功后,通過 mount 命令則可查詢到類似的掛載記錄:
5368 47 0:660 / /mnt/nas rw,relatime shared:1175 \
     - nfs 3f0f3489aa-xxxx.cn-shanghai.nas.aliyuncs.com:/test \    
     rw,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,nolock,\
     noresvport,proto=tcp,timeo=600,retrans=2,sec=sys, \
     mountaddr=192.168.0.91,mountvers=3,mountport=2049,mountproto=tcp,\
     local_lock=all,addr=192.168.0.92核心信息分析如下:
# 掛載點(diǎn) 父掛載點(diǎn) 掛載設(shè)備號   目錄     掛載到本機(jī)目錄  協(xié)議   NAS地址
5368     47       0:660     /       /mnt/nas     nfs    3f0f3489aa-xxxx.cn-shanghai.nas.aliyuncs.com:/test
                maror:minor掛載記錄中的 0:660 為本地設(shè)備編號,格式為 major:minor , 0 為 major 編號, 660 為 minor 編號,系統(tǒng)主要以 minor 為主。在系統(tǒng)的 NFS 跟蹤點(diǎn) nfs_initiate_read 的信息中的 dev 字段則為在掛載記錄中的 minor 編號。
cat /sys/kernel/debug/tracing/events/nfs/nfs_initiate_read/format
format:
      
        field:dev_t dev;        offset:8;         size:4;        signed:0;
         ...
        field:u32 count;        offset:32;        size:4;        signed:0;通過用戶空間 mount 信息和跟蹤點(diǎn)中 dev_id 信息,則可實(shí)現(xiàn)內(nèi)核空間設(shè)備編號與 NAS 詳情的關(guān)聯(lián)。
內(nèi)核空間信息獲取
如容器中進(jìn)程針對掛載到本地的目錄 /mnt/nas 下的文件讀取時,會調(diào)用到 nfs_file_read() 和 nfs_initiate_read 函數(shù)。通過 nfs_initiate_read 跟蹤點(diǎn)我們可以實(shí)現(xiàn)進(jìn)程容器信息和訪問 NFS 服務(wù)器的信息關(guān)聯(lián)。
通過編寫 eBPF 程序針對跟蹤點(diǎn) tracepoint/nfs/nfs_initiate_read 觸發(fā)事件進(jìn)行數(shù)據(jù)獲取,我們可獲取到訪問進(jìn)程所對應(yīng)的 cgroup_name 信息和訪問 NFS Server 在本機(jī)的設(shè)備 dev_id 編號。
圖片
獲取cgroup_name信息
- 進(jìn)程容器上下文獲?。?nbsp;通過 cgroup_name 信息,如樣例中的 docker-2b3b0ba12e92...983.scope ,后續(xù)可以基于 container_id 查詢到容器對應(yīng)的 Pod NameSpace 、 Pod Name 和 Container Name 等信息,從而定位到訪問進(jìn)程關(guān)聯(lián)的 Pod 信息。
 - NAS 上下文信息獲?。?nbsp;通過 dev 信息,樣例中的 660 ,通過掛載到本地的記錄,可以通過 660 查詢到對應(yīng)的 NAS 產(chǎn)品的地址,比如3f0f3489aa-xxxx.cn-shanghai.nas.aliyuncs.com 。
 
用戶空間元信息緩存
圖片
在用戶空間中,可以通過解析掛載記錄來獲取 DEV 信息,并將其與 NAS 信息關(guān)聯(lián),從而建立以 DevID 為索引的查詢緩存。如此,后續(xù)便可以基于內(nèi)核獲取到 dev_id 進(jìn)行關(guān)聯(lián),進(jìn)一步補(bǔ)全 NAS 地址及相關(guān)詳細(xì)信息。
對于本地容器上下文的信息獲取,最直接的方式是通過 K8s kube-apiserver 通過 list-watch 方法進(jìn)行訪問。然而,這種方式會在每個節(jié)點(diǎn)上啟動一個客戶端與 kube-apiserver 通信,顯著增加 K8s 管控面的負(fù)擔(dān)。因此,我們選擇通過本地容器引擎進(jìn)行訪問,直接在本地獲取主機(jī)的容器詳情。通過解析容器注解中的 Pod 信息,可以建立容器實(shí)例緩存。后續(xù)在處理指標(biāo)數(shù)據(jù)時,則可以通過 container-id 實(shí)現(xiàn)信息的關(guān)聯(lián)與補(bǔ)全。
三、架構(gòu)設(shè)計和實(shí)現(xiàn)
整體架構(gòu)設(shè)計
內(nèi)核空間的信息采集采用 Linux eBPF 技術(shù)實(shí)現(xiàn),這是一種安全且高效的內(nèi)核數(shù)據(jù)采集方式。簡單來說,eBPF 的原理是在內(nèi)核中基于事件運(yùn)行用戶自定義程序,并通過內(nèi)置的 map 和 perf 等機(jī)制實(shí)現(xiàn)用戶空間與內(nèi)核空間之間的雙向數(shù)據(jù)交換。
在 NFS 和 RPC 調(diào)用事件觸發(fā)的基礎(chǔ)上,可以通過編寫內(nèi)核空間的 eBPF 程序來獲取必要的原始信息。當(dāng)用戶空間程序搜集到內(nèi)核指標(biāo)數(shù)據(jù)后,會對這些原始信息進(jìn)行二次處理,并在用戶空間的采集程序中補(bǔ)充容器進(jìn)程信息(如 NameSpace、Pod 和 Container 名稱)以及 NFS 地址信息(包括 NFS 遠(yuǎn)端地址)。
圖片
內(nèi)核eBPF程序流程
以 NFS 文件讀為例,通過編寫 eBPF 程序跟蹤 nfs_initiate_read / rpc_task_begin / rpc_task_end / nfs_page_read_done 等關(guān)鍵鏈路上的函數(shù),用于獲取到 NFS 讀取的數(shù)據(jù)量和延時數(shù)據(jù),并將訪問鏈路中的進(jìn)程上下文等信息保存到內(nèi)核中的指標(biāo)緩存中。
圖片
如上圖所示, nfs_initate_read 和 rpc_task_begin 發(fā)生在同一進(jìn)程上下文中,而 rpc_task_begin 與 rpc_task_end 是異步操作,盡管兩者不處于同一進(jìn)程上下文,但可以通過 task_id 進(jìn)行關(guān)聯(lián)。同時, page_read_done 和 rpc_task_end 則發(fā)生在同一進(jìn)程上下文中。
圖片
nfs_initiate_read 函數(shù)調(diào)用觸發(fā)的 eBPF 代碼示例如下所示:
SEC("tracepoint/nfs/nfs_initiate_read")
int tp_nfs_init_read(struct trace_event_raw_nfs_initiate_read *ctx)
    // 步驟1 獲取到 nfs 訪問的設(shè)備號信息,比如 3f0f3489aa-xxxx.cn-shanghai.nas.aliyuncs.com
    // dev_id 則為: 660 
    dev_t dev_id = BPF_CORE_READ(ctx, dev);
    u64 file_id = BPF_CORE_READ(ctx, fileid);
    u32 count = BPF_CORE_READ(ctx, count);
   
    struct task_struct *task = (struct task_struct *)bpf_get_current_task();
    // 步驟2 獲取進(jìn)程上下文所在的容器 cgroup_name 信息
    // docker-2b3b0ba12e925820ac8545f67c8cadee864e5b4033b3d5004d8a3aa742cde2ca.scope
    const char *cname = BPF_CORE_READ(task, cgroups, subsys[0], cgroup, kn, name);
    if (cname)
    {
        bpf_core_read_str(&info.container, MAX_PATH_LEN, cname);
    }
    bpf_map_update_elem(&link_begin, &tid, &info, BPF_ANY);
}
SEC("tracepoint/nfs/nfs_readpage_done")
int tp_nfs_read_done(struct trace_event_raw_nfs_readpage_done *ctx)
{
   //... 省略
}
SEC("tracepoint/sunrpc/rpc_task_begin")
int tp_rpc_task_begin(struct trace_event_raw_rpc_task_running *ctx)
{
    //... 省略
}
SEC("tracepoint/sunrpc/rpc_task_end")
int tp_rpc_task_done(struct trace_event_raw_rpc_task_running *ctx)
{
   //... 省略
}用戶空間程序架構(gòu)
圖片
元數(shù)據(jù)緩存
※ NAS 掛載信息緩存
通過解析掛載記錄,可以獲取 DEV 信息與 NAS 信息的關(guān)聯(lián)關(guān)系。以下是實(shí)現(xiàn)該功能的關(guān)鍵代碼詳情:
scanner := bufio.NewScanner(mountInfoFile)
count := 0
for scanner.Scan() {
    line := scanner.Text()
    devID,remoteDir, localDir, NASAddr = parseMountInfo(line)
    mountInfo := MountInfo{
       DevID:         devID,
       RemoteDir:     remoteDir,
       LocalMountDir: localDir,
       NASAddr: NASAddr,
    }
    mountInfos = append(mountInfos, mountInfo)※ 容器元信息緩存
通過 Docker 或 Containerd 客戶端,從本地讀取單機(jī)的容器實(shí)例信息,并將容器的上下文數(shù)據(jù)保存到本地緩存中,以便后續(xù)查詢使用。
podInfo := PodInfo{
    NameSpace:     labels["io.kubernetes.pod.namespace"],
    PodName:       labels["io.kubernetes.pod.name"],
    ContainerName: labels["io.kubernetes.container.name"],
    UID:           labels["io.kubernetes.pod.uid"],
    ContainerID:   conShortID,
}數(shù)據(jù)處置流程
用戶空間程序的主要任務(wù)是持續(xù)讀取內(nèi)核 eBPF 程序生成的指標(biāo)數(shù)據(jù),并對讀取到的原始數(shù)據(jù)進(jìn)行處理,提取訪問設(shè)備的 dev_id 和 container_id 。隨后,通過查詢已建立的元數(shù)據(jù)緩存,分別獲取 NAS 信息和容器 Pod 的上下文數(shù)據(jù)。最終,經(jīng)過數(shù)據(jù)合并與處理,生成指標(biāo)數(shù)據(jù)緩存供后續(xù)使用。
func (m *BPFEventMgr) ProcessIOMetric() {
    // ...
    events := m.ioMetricMap
    iter := events.Iterate()
    for iter.Next(&nextKey, &event) {
       // ① 讀取到的 dev_id 轉(zhuǎn)化為對應(yīng)的完整 NAS 信息
       devId := nextKey.DevId
       mountInfo, ok := m.mountMgr.Find(int(devId))
       // ② 讀取 containerID 格式化并查詢對應(yīng)的 Pod 上下文信息
       containerId := getContainerID(nextKey.Container)
       podInfo, ok = m.criMgr.Find(containerId)
      
       // ③ 基于事件信息、NAS 掛載信息和 Pod 上下文信息,生成指標(biāo)數(shù)據(jù)緩存 
       metricKey, metricValue := formatMetricData(nextKey, mountInfo, podInfo)
       value, loaded := metricCache.LoadOrStore(metricKey, metricValue)
    }
    
    // ④ 指標(biāo)數(shù)據(jù)緩存,生成最終的 Metrics 指標(biāo)并更新 
    var ioMetrics []metric.Counter
    metricCache.Range(func(key, value interface{}) bool {
       k := key.(metric.IOKey)
       v := value.(metric.IOValue)
       ioMetrics = append(ioMetrics, metric.Counter{"read_count", float64(v.ReadCount),
             []string{k.NfsServer, v.NameSpace, v.Pod, v.Container})
         // ...
       }
       return true
    })
    
    m.metricMgr.UpdateIOStat(ioMetrics)
}啟動 Goroutine 處理指標(biāo)數(shù)據(jù):通過啟動一個 Goroutine,循環(huán)讀取內(nèi)核存儲的指標(biāo)數(shù)據(jù),并對數(shù)據(jù)進(jìn)行處理和信息補(bǔ)齊,最終生成符合導(dǎo)出格式的 Metrics 指標(biāo)。
※ 具體步驟
- 獲取 NAS 信息:從讀取的原始數(shù)據(jù)中提取 dev_id ,并通過 dev_id 查詢掛載的 NAS 信息,例如遠(yuǎn)端訪問地址等相關(guān)數(shù)據(jù)。
 - 查詢 Pod 上下文:對 containerID 進(jìn)行格式化處理,并查詢對應(yīng)的容器 Pod 上下文信息。
 - 生成指標(biāo)數(shù)據(jù)緩存:基于事件數(shù)據(jù)、NAS 掛載信息和 Pod 上下文信息,生成指標(biāo)數(shù)據(jù)緩存。此過程主要包括對相同容器上下文的數(shù)據(jù)進(jìn)行合并和累加。
 - 導(dǎo)出 Metrics 指標(biāo):根據(jù)指標(biāo)數(shù)據(jù)緩存,生成最終的 Metrics 指標(biāo),并更新到指標(biāo)管理器。隨后,通過自定義的 Collector 接口對外導(dǎo)出數(shù)據(jù)。當(dāng) Prometheus 拉取數(shù)據(jù)時,指標(biāo)會被轉(zhuǎn)換為最終的 Metrics 格式。
 
通過上述步驟,用戶空間能夠高效地處理內(nèi)核 eBPF 程序生成的原始數(shù)據(jù),并結(jié)合 NAS 掛載信息和容器上下文信息,生成符合 Prometheus 標(biāo)準(zhǔn)的 Metrics 指標(biāo),為后續(xù)的監(jiān)控和分析提供了可靠的數(shù)據(jù)基礎(chǔ)。
自定義指標(biāo)導(dǎo)出器
在導(dǎo)出指標(biāo)的場景中,我們需要基于保存在 Go 語言中的 map 結(jié)構(gòu)中的動態(tài)數(shù)據(jù)實(shí)時生成,因此需要實(shí)現(xiàn)自定義的 Collector 接口。自定義 Collector 接口需要實(shí)現(xiàn)元數(shù)據(jù)描述函數(shù) Describe() 和指標(biāo)搜集的函數(shù) Collect() ,其中 Collect() 函數(shù)可以并發(fā)拉取,因此需要通過加鎖實(shí)現(xiàn)線程安全。該接口需要實(shí)現(xiàn)以下兩個核心函數(shù):
- Describe() :用于定義指標(biāo)的元數(shù)據(jù)描述,向 Prometheus 注冊指標(biāo)的基本信息。
 - Collect() :用于搜集指標(biāo)數(shù)據(jù),該函數(shù)支持并發(fā)拉取,因此需要通過加鎖機(jī)制確保線程安全。
 
type Collector interface {
    // 指標(biāo)的定義描述符
    Describe(chan<- *Desc)
   
    // 并將收集的數(shù)據(jù)傳遞到Channel中返回
    Collect(chan<- Metric)
}我們在指標(biāo)管理器中實(shí)現(xiàn) Collector 接口, 部分實(shí)現(xiàn)代碼,如下所示:
nfsIOMetric := prometheus.NewDesc(
    prometheus.BuildFQName(prometheusNamespace, "", "io_metric"),
    "nfs io metrics by cgroup",
    []string{"nfs_server", "ns", "pod", "container", "op", "type"},
    nil,
)
// Describe and Collect implement prometheus collect interface
func (m *MetricMgr) Describe(ch chan<- *prometheus.Desc) {
    ch <- m.nfsIOMetric
}
func (m *MetricMgr) Collect(ch chan<- prometheus.Metric) {
    // Note:加鎖保障線程并發(fā)安全
    m.activeMutex.Lock()
    defer m.activeMutex.Unlock()
    
    for _, v := range m.ioMetricCounters {
       ch <- prometheus.MustNewConstMetric(m.nfsIOMetric, prometheus.GaugeValue, v.Count, v.Labels...)
    }四、總結(jié)
當(dāng)前 NAS 溯源能力已正式上線,以下是主要功能和視圖介紹:
※ 單 NAS 實(shí)例整體趨勢
支持基于環(huán)境和 NAS 訪問地址過濾,展示 NAS 產(chǎn)品的讀寫 IOPS 和吞吐趨勢圖。同時,基于內(nèi)核空間統(tǒng)計的延時數(shù)據(jù),提供 P95 讀寫延時指標(biāo),用于判斷讀寫延時情況,輔助問題分析和定位。
圖片
圖片
在 NAS 流量溯源方面,我們結(jié)合業(yè)務(wù)場景設(shè)計了基于任務(wù)和 Pod 實(shí)例維度的流量分析視圖:
※ 任務(wù)維度流量溯源
通過聚合具有共同屬性的一組 Pod 實(shí)例,展示任務(wù)級別的整體流量情況。該視圖支持快速定位任務(wù)級別的流量分布,幫助用戶進(jìn)行流量溯源和多任務(wù)錯峰使用的依據(jù)。
圖片
※ Pod 實(shí)例維度流量溯源
以 Pod 為單位進(jìn)行流量分析和匯總,提供 Pod NameSpace 和 Name 信息,支持快速定位和分析實(shí)例級別的流量趨勢,幫助細(xì)粒度監(jiān)控和異常流量的精準(zhǔn)定位。
圖片
在整體能力建設(shè)完成后,我們成功構(gòu)建了 NAS 實(shí)例級別的 IOPS、吞吐和讀寫延時數(shù)據(jù)監(jiān)控大盤。通過該能力,進(jìn)一步實(shí)現(xiàn)了 NAS 實(shí)例的 IOPS 和吞吐可以快速溯源到任務(wù)級別和 Pod 實(shí)例級別,流量溯源時效從小時級別縮短至分鐘級別,有效提升了異常問題定位與解決的效率。同時,基于任務(wù)流量視圖,我們?yōu)楹罄m(xù)帶寬錯峰復(fù)用提供了直觀的數(shù)據(jù)支持。















 
 
 














 
 
 
 