聊聊Service Mesh:linkerd

【編者的話】隨着企業逐漸將傳統的單體應用向微服務或雲原生應用的轉變,雖然微服務或者雲原生應用能給企業帶來更多的好處,但也會帶來一些具備挑戰的問題,如怎麼管理從單體應用轉向微服務所帶來的服務間通信的複雜性,怎麼實現微服務間安全,高效,可靠的訪問,如何知足多語言多環境的透明通信,服務發現、熔斷,動態流量遷移,金絲雀部署,跨數據中心訪問等等。本次分享給你們引入一新概念服務網格(Service Mesh)以及介紹業界主要服務網格(Service Mesh)工具linkerd。html

【3 天燒腦式容器存儲網絡訓練營 | 深圳站】本次培訓以容器存儲和網絡爲主題,包括:Docker Plugin、Docker storage driver、Docker Volume Pulgin、Kubernetes Storage機制、容器網絡實現原理和模型、Docker網絡實現、網絡插件、Calico、Contiv Netplugin、開源企業級鏡像倉庫Harbor原理及實現等。node

在開始介紹linkerd以前,首先不知道你們對Service Mesh這個概念或者名詞有多深的瞭解,反正我在今年以前是沒有據說過這麼個新詞兒(孤陋寡聞了)。Service Mesh實際上是在當前微服務或者雲原生應用領域的一個buzzword。那麼,Service Mesh究竟是什麼東東?能作什麼?能給微服務或者雲原生應用帶來什麼好處?有必要使用或者部署Service Mesh嗎?好,那今晚就跟你們聊聊linkerd,順便回答這些問題。算法

什麼是Service Mesh?

  • Service Mesh是專用的基礎設施層。
  • 輕量級高性能網絡代理。
  • 提供安全的、快速的、可靠地服務間通信。
  • 與實際應用部署一塊兒但對應用是透明的。

Service Mesh能作什麼?後端

  • 提供熔斷機制(circuit-breaking)。
  • 提供感知延遲的負載均衡(latency-awareload balancing)。
  • 最終一致的服務發現(service discovery)。
  • 鏈接重試(retries)及終止(deadlines)。
  • 管理微服務和雲原生應用通信的複雜性,確保可靠地交付應用請求。

Service Mesh是必要的嗎?這可能沒有一個絕對的答案,可是:緩存

  • Service Mesh可以使得快速轉向微服務或者雲原生應用。
  • Service Mesh以一種天然的機制擴展應用負載,解決分佈式系統不可避免的部分失敗,捕捉高度動態分佈式系統的變化。
  • 徹底解耦於應用。

業界有哪些Service Mesh產品?安全

  • Buoyant的linkerd,基於Twitter的Fingle,長期的實際產線運行經驗及驗證,支持Kubernetes、DC/OS容器管理平臺,也是CNCF官方支持的項目之一。
  • Lyft的Envoy,7層代理及通訊總線,支持7層HTTP路由、TLS、gRPC、服務發現以及健康監測等。
  • IBM、Google、Lyft支持的Istio,一個開源的微服務鏈接、管理平臺以及給微服務提供安全管理,支持Kubernetes、Mesos等容器管理工具,其底層依賴於Envoy。

什麼是linkerd?

  • 爲雲原生應用提供彈性的Service Mesh。
  • 透明高性能網絡代理。
  • 提供服務發現機制、動態路由、錯誤處理機制及應用運行時可視化。

linkerd的特性:微信

  • 快速、輕量級、高性能。網絡

    1. 每秒以最小的時延及負載處理萬級請求。
    2. 易於水平擴展。
  • 支持任意開發語言及任意環境。app

  • 提供基於感知時延的負載均衡。負載均衡

    1. 經過實時性能數據分發請求。
    2. 因爲linkerd工做於RPC層,可根據實時觀測到的RPC延遲、要處理請求隊列大小決定如何分發請求,優於傳統啓發式負載均衡算法如LRU、TCP活動狀況等。
    3. 提供多種負載均衡算法如:Power of Two Choices (P2C): Least Loaded、Power of Two Choices: Peak EWMA、Aperture: Least Loaded、Heap: Least Loaded以及Round-Robin。
  • 運行時流量路由。

    1. 經過特定HTTP頭進行Per-Request級別路由。
    2. 動態修改dtab規則實現流量遷移、藍綠部署、金絲雀部署、跨數據中心failover等。
  • 熔斷機制。

    1. Fail Fast — 會話驅動的熔斷器。
    2. Failure Accrual — 請求驅動的熔斷器。
  • 插入式服務發現。

    1. 支持各類服務發現機制如:基於文件(File-based),Zookeeper,Consul及Kubernetes。
  • 支持多種協議:HTTP/1.一、HTTP/二、gRPC、Thrift、Mux。

  • 通過產線測試及驗證。

linkerd術語:
{{{ ##################################################################################

A basic service mesh for internal linkerd config. This config contains an

outgoing router that proxies requests from local applications to the linkerd

running on the destination host and an incoming router that reverse-proxies

incoming requests to the application instance running on the local host.

##################################################################################
admin:
port: 9990

namers:

  • kind: io.l5d.consul
    host: 127.0.0.1
    port: 8500
    includeTag: false
    setHost: false
  • kind: io.l5d.rewrite
    prefix: /srv
    pattern: "/{service}"
    name: 「/srv/{service}"

routers:

  • protocol: http
    identifier:
    kind: io.l5d.path
    segments: 1
    label: routerA_outgoing
    dtab: |
    /srv => /#/io.l5d.consul/dc;
    /svc => /#/srv;
    httpAccessLog: /alloc/logs/access_routerA.log
    servers:
    • port: 8080
      ip: 0.0.0.0
  • protocol: http
    label: outgoing
    dtab: |
    /consul => /#/io.l5d.consul/dc;
    /svc => /$/io.buoyant.http.subdomainOfPfx/svc.consul/consul;
    httpAccessLog: /alloc/logs/access_outgoing.log
    servers:

    • port: 80
      ip: 0.0.0.0
      interpreter:
      kind: default
      transformers:

      Instead of sending the request directly to the destination, send it to

      the linkerd (listening on port 81) running on the destination host.

      • kind: io.l5d.port
        port: 81
  • protocol: http
    label: incoming
    dtab: |
    /consul => /#/io.l5d.consul/dc;
    /svc => /$/io.buoyant.http.subdomainOfPfx/svc.consul/consul;
    servers:

    • port: 81
      ip: 0.0.0.0
      interpreter:
      kind: default
      transformers:

      Instead of sending the request to a random destination instance, send it

      only to instances running on localhost.

      • kind: io.l5d.localhost

telemetry:

  • kind: io.l5d.recentRequests
    sampleRate: 1.0
  • kind: io.l5d.prometheus

    usage:
    enabled: false}}}

  • Router:linkerd配置必須定義router模塊,能夠定義多個router,其它包括服務所使用協議Protocol、Identifier、Transformer、Server、Dtab、Client、Service以及Interpreter。

  • Identifier:用於給請求賦值邏輯名字(logical name)或者成路徑(path),經常使用的Identifier如:io.l5d.methodAndHost,io.l5d.path,io.l5d.header,io.l5d.header.token和io.l5d.static,例如Identifer:io.l5d.header.token將GET http://example/hello賦值邏輯名字/svc/example。能夠開發自定製的Indentifier插件。更多參考https://linkerd.io/config/1.1.0/linkerd/index.html#http-1-1-identifiers.
  • Namer: 定義如何將客戶端名字和真實地址進行綁定,本質上是如何經過服務發現系統進行服務發現,經常使用Namer如:io.l5d.fs,io.l5d.consul,io.l5d.k8s,io.l5d.marathon和 io.l5d.rewrite,更多參考linkerd.io/config/1.1.…
  • Interpreter:決定如何解析namer, 經常使用如:default, io.l5d.namerd, io.l5d.namerd.http, io.l5d.mesh和io.l5d.fs,更多參考linkerd.io/config/1.1.…
  • Transformer:根據Interpreter如何轉換已解析的地址,Transformer以出現的順序生效,如:io.l5d.localhost,io.l5d.specificHost,io.l5d.port,io.l5d.k8s.daemonset,io.l5d.k8s.localnode,io.l5d.replace和io.l5d.const,更多參考linkerd.io/config/1.1.…
  • Delegation Table(a.k.a. Dtab):定義如何把服務名字(service name)(邏輯名字)轉換爲客戶端名字(client name), 客戶端名字對應用於服務發現條目,服務發現工具根據這個條目如何發現服務,其必須以/$或者/#打頭,如/#/io.l5d.consul/dc/product。

linkerd如何處理應用請求?

在細聊linkerd如何處理應用請求以前,咱們來看看linkerd官方給出的數據處理流程圖。


從圖中咱們能夠把整個流程分解爲4個主要步驟:

  • Identification: 把實際應用請求如foo.com實際爲GET foo.com轉換爲邏輯名字(logical name)或服務名字(service name),具體轉換規則由Identifier決定,linkerd提供多種Identifier並根據實際需求選擇使用,如圖中Identifier爲io.l5d.header.token將GET foo.com轉換爲/svc/foo.com。
  • Binding:在Identification完成後,Dtab開始登場,將產生的服務名字跟客戶端名字綁定起來,如何綁定取決於Dtab規則如何設置,如圖中所示Dtab,則將/svc/foo.com綁定爲/#/io.l5d.fs/foo.com。
  • Resolution:即便Binding完成後,此時linkerd仍然未能將請求轉發給後端服務,實際上還不知道客戶端名字/#/io.l5d.fs/foo.com具體表明什麼,而Resolution則將客戶端名字轉換爲真實服務地址,IP地址以及端口。轉換邏輯由指定的Namer來肯定,不一樣的Namer轉換邏輯不同,若Namer爲io.l5d.consul則查找Consul Catalog API獲取IP地址和端口信息,而圖中Namer爲io.l5d.fs,File-based的Namer,linkerd將讀取名爲foo.com的本地文件,文件具體位置由配置所決定,該文件會包含圖中的2條記錄1.1.1.1:8080和1.1.1.2:8080,而後返回上述2條記錄。
  • Loadbalancing:一旦完成Resolution,找到真實的服務地址,而後linkerd會根據前面所述配置的負載均衡算法選取一服務地址提供服務。

至此,linkerd已完成如何處理應用請求,下面是一個演習如何從服務名字到真實地址轉換的例子。

簡單Demo

  1. 以host模式部署linkerd。
  2. 建立服務customer和product,customer會跟product進行通信並返回一些信息,二者都以容器的方式運行。
  3. 註冊服務customer和product到Consul。
  4. 經過linkerd訪問服務customer,curl -s -H 「Host: customer.svc.consul」 10.xx.xx.199/product會輸出以下信息:

Q&A

Q:具體的測試性能有麼,對比LVS、Nginx?

A:linkerd雖然是網絡代理,但跟LVS、Nginx仍是有不一樣的,所解決的問題也不一樣,好比linkerd經常使用的部署方式以sidecar模式部署。 對於性能數據,單個linkerd是能夠能夠處理20K/sec請求,p99延遲在10ms之內,可是超過20K,在個人測試環境,提升不大。而跟Nginx和LVS的對比,還沒作過。

Q:可否說說 「熔斷機制(circuit-breaking) 」怎麼理解?

A:linkerd支持2種方式進行熔斷,一種是基於會話或者連接,另外一種是基於請求的熔斷。對於會話層的熔斷,linkerd在轉發請求到後端應用實例時,若是發現其中一個連接出現問題,linkerd會將它從維護的一個池子裏移除,不會有真實請求發送到該實例,而在後臺,linkerd會嘗試鏈接,一旦鏈接成功,linkerd再次將它加入池子繼續提供服務。
而對基於請求的熔斷,linkerd會根據linkerd的配置進行處理,好比配置爲io.l5d.consecutiveFailures, linkerd觀察到指定數量的連續錯誤,則熔斷,其餘的方式能夠查看linkerd.io/config/1.1.…

Q:linkerd如何實現水平擴展的?集羣對linkerd計算節點數量有限制嗎?

A:linkerd自己是無狀態的,因此水平擴展很是容易,集羣對linkerd的數量取決於你是怎麼部署linkerd的,linkerd.io/in-depth/de…

Q:看最後的表格好像能實現展現服務調用鏈,展現上下游關係?能不能借此發現具體服務壓力瓶頸在哪一環,是否有性能監控?

A:linkerd提供詳細的metric, 這些metric會告訴你性能出如今哪一個地方,還有linkerd原生跟zipkin集成,因此你能trace到服務的訪問流,會展現每一環節的性能狀況。

Q:能否對比一下Istio?

A:對應Istio的底層Envoy和linkerd本質上實現了差很少相似的功能,linkerd支持Kubernetes、DC/OS,而且跟多種服務發現工具集成,而Istio,就我瞭解,目前支持Kubernetes,具體Istio的使用,沒有使用過,不太清楚。

Q:若是linkd是無狀態,那怎麼維護內部的熔斷池?

A:這裏的無狀態是指linkerd工做時各個實例之間不須要信息的同步,即便一個實例出現問題,對個整個環境的正常工做無關痛癢,只需從新啓動便可,全部服務發現的信息都是存儲在外部,好比Consul、ZK等,本地只會有緩存,沒有持久化的數據,而熔斷池的信息就是來自於服務發現系統。

以上內容根據2017年07月04日晚微信羣分享內容整理。分享人楊章顯,思科高級系統工程師。主要關注雲計算,容器,微服務等領域,目前在思科負責內部PaaS平臺的構建相關工做。 DockOne每週都會組織定向的技術分享,歡迎感興趣的同窗加微信:liyingjiesa,進羣參與,您有想聽的話題或者想分享的話題均可以給咱們留言。

原文連接:聊聊Service Mesh:linkerd

相關文章
相關標籤/搜索