https://avatars.githubusercontent.com/u/42119758?v=4

davidlei blog

golang 在 alpine image 的一個常見坑

紀錄一下前幾天在實驗 dapr 遇到的一個小問題,通常發生在簡單的 golang 程式使用 apline image 當作基底的時候,程式如下 package main import ( "log" "net/http" ) func main() { log.Println("Start echo server") http.HandleFunc("/echo", echoHandler) if err := http.ListenAndServe(":3000", nil); err != nil { log.Fatal(err) } } func echoHandler(w http.ResponseWriter, r *http.Request) { r.ParseForm() log.Println("receive message: ", r.Form.Get("msg")) w.Write([]byte(r.Form.Get("msg") + "www\n")) } 因為只是要快速實驗,所以 Dockerfile 也寫得很簡略 FROM alpine:latest ADD echo-server . ENTRYPOINT [ "/echo-server" ] 經過 go build -o echo-server main.go 之後建立 image docker build -t echo-server .

Bypassing the Load Balancer Without Regrets - SoCC ’20

前言 最近為了找論文題目看了不少論文,剛好趁這個機會寫點文章當作讀這些 paper 的學習筆記,這篇 主要提出一個新的 Load balance 的機制,希望可以消除 LB 在 data path 花費的時間,讓 LB 專注於處理連線請求,決定 connection 去往哪台 server 之後就讓 Client 與 server 之間直接連線,細節就看底下的簡介或者論文內文吧,我覺得這篇 paper 在概念講解的地方畫了幾張不錯的示意圖,如果想要解釋 L4 的 load balancer 怎麼運作的,這是一篇滿推薦的論文。 這篇論文的作者也用了 P4, eBPF 等技術實現了他們的論文,如果有興趣的也可以研究看看實現的 code 常見 LB 技術分類 這篇論文在前面的幾個段落介紹了常見了 Load Belance 技術,然後規劃了一些簡單的實驗來分析各種不同技術的優劣,文中用以下五個標準/指標來分類不同種類的 LB 技術,如下圖所示 比較圖表如下: 其中 L4 的 Load Balancer 以形式可以分成有沒有支援 DSR(Direct Server Return),又或者分為 Stateless 和 Stateful,以筆者的理解大規模的服務來說會盡量把 Load Balancer 設計成無狀態的,這樣才能把雲端環境的動態優勢發揮出來,像是另一篇關於 LB 的論文 A High-Speed Load-Balancer Design with Guaranteed Per-Connection-Consistency NSDI2020 有提到一個觀點,為什麼現在主流的 LB 技術都不依靠像是 weighted round robin 或者 power of two choices 這種可以根據伺服器狀態來最佳化負載的演算法,以下引用該文章的說法

搭建最小化的 xdp 實驗環境

前言 一般來說學習 xdp 都會參考 xdp-tutorial,這個教學非常完整,雖然有一些範例可能需要額外查一些資源才能完成,但依舊被很多文章譽為學習 xdp 的最佳資源。 但是這個專案包裝了一些 testenv 的腳本方便學習的人不用自己架設環境,或者煩惱編譯的問題,在學習過程中的確很方便,不過如果想要自己建立新的 xdp 專案可能就需要理解編譯過程具體用了哪些工具,依賴的部份要怎麼引入,本篇文章想要搭建一個最簡化的實驗環境滿足以下幾點要求: /bpf 底下存放 xdp 程式碼 Makefile 只包含 make all, make clean 兩個最簡單的功能,剩下根據需求再自行添加 main.go 負責把編譯好的 byte code 載入 kernel,並且能對 map 進行操作 我認為只要符合以上幾點就能最小化的建立實驗環境,會用 go 語言是因為這樣可以不用處理 c++ 一些要編譯的前置作業。 理想上我們最後的目錄會長這樣,符合我們希望的最小化專案需求 實際上可能會因為 go.mod 這些額外的配置多一些檔案,或者放一些編譯時需要的 header,不過本文會盡可能的讓目錄保持整潔,讓學習 xdp 的人不會被眼花撩亂的配置檔案搞的不知所措。 底下我們會根據 xdp-tutorial 編寫一個簡單的 xdp 程式,然後編譯成 .o 檔之後由 user space 的程式(由 go 語言編寫) 來負責載入 xdp Program。 編寫 xdp 範例 這邊我們參考 xdp-tutorial 的 packet01-parsing 中出現的一個例子,接收 ICMP 封包,並把 sequence number 為偶數的封包丟棄,不需要改動封包內容,算是一個很基本的範例。

查找動態庫(.so) 是否安裝過以及路徑使用 ldconfig

在編譯過程中可能會用到一些動態庫(.so) 來編譯,時常會遇到找不到需要的 .so 檔案 error while loading shared libraries… cannot open shared object file: No such file or directory 像是上面的這個錯誤訊息就是常常會看見的老朋友XD,這時我們就可以使用 ldconfig 來搜索是否有安裝過指定的 .so 一般來說 Linux 底下的 .so 都存放在 /lib, /usr/lib 底下,ldconfig 指令會在預設的路徑底下查找 詳細的用法可以參考 ldconfig,一般如果只是要根據關鍵字查找,只要配合 -p 即可,像是我如果想在本地找到 ngtcp2 相關的 .so 我就可以輸入 $ ldconfig -p | grep ngtcp2

Linux file descriptor 理解

前言 file descriptor 常被簡稱為 fd, 在學習 Linux 的過程中,會看到很多 system call 藉由 fd 來操作文件或抽象資源,像是 network programming 中呼叫 socket 之後會使用回傳的 socket fd 去進行後續的操作,或者 I/O 領域的 epoll 同樣在呼叫 epoll_create 之後會回傳 fd,此後對於 epoll 相關的操作都要把 fd 當作第一個參數傳入。 在 Linux 中常常會看到 fd 的身影,但一直沒有花時間去深入了解這個 fd 底層的實現,只是有模糊的概念而已,所以趁這個機會來整理一篇筆記,紀錄一下。 在 File descriptor 中可以簡單看一下,究竟在 Linux 中有多少 system call 使用了 File descriptor 的概念,就知道 fd 在 Linux 中的重要性了。 Everything is a file Linux 秉持著 UNIX 哲學 Everything is a file,這個概念的好處是可以用一組通用的 Interface 來操作不同資源,在資源跟使用者之間加上一層抽象層,進而延伸出 Universal I/O Model 的概念。

Docker 網路模型與 Linux namespace, bridge 機制探討

在 Container 中最重要的一個特性就是資源的隔離,在 Linux 中透過 namespace 提供不同資源的隔離機制,這篇文章會特別探討其中出現最頻繁的 network 的隔離機制,並且透過簡單的實驗來觀察 Docker 的網路模型是怎麼透過 namespace 實現的。 Network Namespace 在 command line 操作 network namespace 通常會使用 ip netns 來操作,先引用 ip-netns 的 man page 來介紹一下 network namespace 的定義 A network namespace is logically another copy of the network stack, with its own routes, firewall rules, and network devices. 也可以查看 NETWORK_NAMESPACES(7) 因為 network namespace 本身隔離了整個 network stack, 所以幾乎所有關於 network 的資源都會被隔離,每個 namespace 內這些資源都是獨立存在的。 如果有牽涉到 fork() 等建立新的 process 的行為,原則上 child process 會繼承 parent 的 network space。