Istio實戰系列-Envoy Proxy構建分析

ServiceMesher2018-11-12 03:31:59

目錄

前言

Istio由控制面和數據面組成。其中Envoy是Istio在數據面缺省使用的轉發代理,Istio利用Envoy的四層和七層代理功能對網格中微服務之間的調用流量進行轉發。今天我們來分析一下Istio 使用到的Envoy流程。

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 = "",
    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下載該依賴的源碼,並進行編譯。

編譯過程中的依賴關係如下圖所示:

閱讀原文

TAGS: