Istio實戰系列-Envoy Proxy構建分析
Istio由控制面和資料面組成。其中Envoy是Istio在資料面預設使用的轉發代理,Istio利用Envoy的四層和七層代理功能對網格中微服務之間的呼叫流量進行轉發。今天我們來分析一下Istio 使用到的Envoy構建流程。
ofollow,noindex" target="_blank">https://github.com/istio/proxy 這個庫中包含了Istio對Envoy的擴充套件,包括用於對接Mixer的Filter和安全認證的Filter。但這個庫中並不包含Envoy自身的原始碼,因此這個庫在構建時會從Github上下載Envoy原始碼進行聯合編譯。
編譯工具
Envoy採用了Bazel進行構建。 Bazel是一種高層構建語言,類似Make,Maven和Gradle。其特點是可讀性較好,支援跨語言,跨平臺編譯;並且可以定義程式碼庫之間的依賴關係,支援跨程式碼庫的聯合構建。Bazel定義構建的依賴關係和規則,並管理構建生成的臨時檔案及二進位制檔案,具體的編譯工作是呼叫各個語言的編譯工具如GCC, JAVAC等完成的。
為了理解Envoy的編譯過程,我們需要先了解Bazel的幾個基礎概念
-
workspace: 檔案系統中的一個目錄,該目錄中包含了用於編譯軟體所需的所有原始檔。每個工作空間中有一個WORKSPACE檔案,該檔案用於描述該工作空間的外部依賴,例如依賴的Github上的第三方程式碼。
-
Package: 是一組用於相關檔案的集合,該目錄中包含一個BUILD檔案,此檔案中描述了該程式包的構建方式。
-
target: 生成的目標,一般是一個lib或者二進位制檔案。 target是一個構建規則(build rule)的例項,一般包含構建所需的原始檔,構建目標的名稱。rule還可以巢狀,一個rule的輸出檔案可以作為另一個rule的輸入檔案。例如一個二進位制檔案編譯的target可以依賴另一個target生成的lib。另外target還可以依賴外部Repository中的另一個target,這個外部Repository可以是檔案系統上另一個資料夾下的專案,github的專案或者http下載的程式碼。外部Repository在WORKSPACE檔案中進行定義。
編譯Envoy
首先參考Bazel的官方文件安裝Bazel,並且需要安裝gcc等相關工具。
設定gcc及g++環境變數
export CC=/usr/bin/gcc-5; export CXX=/usr/bin/g++-5
下載原始碼並進行構建
git clone https://github.com/istio/proxy.git cd proxy make build_envoy
如果出現錯誤提示,一般是由於編譯所需的軟體未安裝導致,請根據提示資訊進行安裝。
如果一切順利,bazel會在proxy目錄下建立一個目錄連結bazel-bin,指向生成的二進位制檔案。
編譯過程分析
原始碼目錄結構如下,主要的構建邏輯在引號包含的檔案中。
├── "BUILD" ├── "Makefile" ├── "WORKSPACE" ├── src │├── envoy-- envoy filter 外掛原始碼 ││├── alts │││├── *.cc │││├── *.h │││└── "BUILD" ││├── "BUILD" ││├── http │││├── authn--認證 filte ││││├── *.cc ││││├── *.h ││││└── "BUILD" │││├── jwt_auth--jwt 認證 filter ││││├── *.cc ││││├── *.h ││││└── "BUILD" │││└── mixer--mixer filter,實現metrics上報,Quota(Rate Limiting (處理http協議) │││├── *.cc │││├── *.h │││└── "BUILD" ││├── tcp │││└── mixer--mixer filter(處理tcp協議) │││├── *.cc │││├── *.h │││└── "BUILD" ││└── utils ││├── *.cc ││├── *.h ││└── "BUILD" │└── istio │└── ** ├── test │└── ** └── tools └── **
編譯的入口是根目錄下的Makefile檔案
# Build only envoy - fast build_envoy: CC=$(CC) CXX=$(CXX) bazel $(BAZEL_STARTUP_ARGS) build $(BAZEL_BUILD_ARGS) //src/envoy:envoy @bazel shutdown
從中可以看到,呼叫了bazel進行構建,其構建的target為 //src/envoy:envoy 。這是bazel的語法,表明呼叫src/envoy這個目錄下BUILD檔案中Envoy這個target。
開啟src/BUILD檔案,檢視該target的內容
envoy_cc_binary( name = "envoy", repository = "@envoy", visibility = ["//visibility:public"], deps = [ "//src/envoy/http/authn:filter_lib", "//src/envoy/http/jwt_auth:http_filter_factory", "//src/envoy/http/mixer:filter_lib", "//src/envoy/tcp/mixer:filter_lib", "//src/envoy/alts:alts_socket_factory", "@envoy//source/exe:envoy_main_entry_lib", ], )
cc_binary表明該target對應的是c++二進位制rule,其中deps部分是其依賴的其他target。前5個target都是本地依賴,對應到原始碼目錄中的其他子目錄下的BUILD檔案,其中最後一個比較特殊,是一個外部依賴,該外部庫為envoy。
外部庫定義在根目錄下的WORKSPACE檔案中。
ENVOY_SHA = "de039269f54aa21aa0da21da89a5075aa3db3bb9" http_archive( name = "envoy", strip_prefix = "envoy-" + ENVOY_SHA, url = "https://github.com/envoyproxy/envoy/archive/" + ENVOY_SHA + ".zip", )
該檔案通過http_archive定義了一個外部repository,bazel在執行//src/envoy:envoy這個target時,發現該target依賴這個外部repository,根據http_archive中的描述,從指定的url下載該依賴的原始碼,並進行編譯。
編譯過程中的依賴關係如下圖所示: