天天看點

Kubernetes中的Service Mesh(第5部分):Dogfood環境和入口

A Service Mesh for Kubernetes (Part 5): Dogfood Environments and Ingress

原文作者:Alex Leong

原文位址:https://dzone.com/articles/a-service-mesh-for-kubernetes-part-v-dogfood-envir

譯者微網誌:@從流域到海域

譯者部落格:blog.csdn.net/solo95

Kubernetes中的Service Mesh(第5部分):Dogfood環境和入口

在這篇文章中,我們将向您展示如何使用連結執行個體的服務網格來處理Kubernetes上的入口流量,将流量分布到網格中的每個執行個體。我們還将通過一個示例來示範linkerd的進階路由功能,方法是建立一個 dogfood 環境,将某些請求路由到較新版本的基礎應用程式,例如用于内部的釋出前測試。

(删掉了原文中的某些連結,因為會被雲+的編輯器識别為非法連結,包含所有連結的譯文可以在譯者部落格裡檢視)

這篇文章是關于使用linkerd作為流量到Kubernetes網絡的入口點。從0.9.1版本開始,linkerd将直接支援Kubernetes Ingress資源,這是本文中一些用例的一個替代的,可能更簡單的起點。有關如何使用linkerd作為Kubernetes入口控制器的資訊,請參閱Sarah的部落格文章Linkerd作為入口控制器。

這是關于linkerd,Kubernetes和service mesh的一系列文章中的一篇文章。本系列的其他部分包括:

  1. Service重要名額
  2. 以DaemonSet方式運作linkerd
  3. 加密所有的東西
  4. 通過流量切換進行連續部署
  5. Dogfood環境,入口和邊緣路由(本文)
  6. 輕松釋出微服務
  7. 如何使分布式跟蹤變得容易
  8. 使用Linkerd作為入口控制器
  9. gRPC樂趣和收益
  10. 服務網格API
  11. 出口
  12. 重試預算,截止日期傳播,和如何讓失敗變得優雅(原文:Retry budgets, deadline propagation, and failing gracefully)
  13. 通過頂層名額(top-line metrics)實作自動縮放

在本系列的前幾期中,我們向您展示了如何使用linkerd來捕獲頂層名額(top-line metrics),透明地在服務調用中添加TLS,并執行bluegreen部署。這些文章展示了如何在像Kubernetes這樣的環境中使用linkerd作為srevice mesh,為内部服務對服務調用增加了一層彈性和性能。在這篇文章中,我們将把這個模型擴充到入口路由。

盡管本文中的示例是針對Kubernetes的,但我們不會使用 Kubernetes提供的内置 Ingress Resource(對此請參閱 Sarah的文章)。雖然Ingress Resource是一種基本路徑和基于主機路由的簡便方法,但在撰寫本文時,它們仍相當有限。在下面的例子中,我們做的将遠遠超出Ingress Resources所提供的功能。

步驟1:部署Linkerd Service Mesh

從前面的文章中我們針對Kubernetes中的基本linkerd service mesh配置開始,我們将進行兩個更改以支援入口(ingress):我們将修改linkerd配置以添加一個額外的邏輯路由器,然後調整圍繞着linkerd展開的Kubernetes服務對象中的VIP。(完整的配置在這裡: linkerd-ingress.yml。)

以下是linkerd執行個體上新的

ingress

邏輯路由器,它将處理入口流量并将其路由到相應的服務:

routers:
- protocol: http
  label: ingress
  dtab: |
    /srv                    => /#/io.l5d.k8s/default/http ;
    /domain/world/hello/www => /srv/hello ;
    /domain/world/hello/api => /srv/api ;
    /host                   => /$/io.buoyant.http.domainToPathPfx/domain ;
    /svc                    => /host ;
  interpreter:
    kind: default
    transformers:
    - kind: io.l5d.k8s.daemonset
      namespace: default
      port: incoming
      service: l5d
  servers:
  - port: 4142
    ip: 0.0.0.0           

複制

在這個配置中,我們使用linkerd的路由文法,dtabs來将請求從一個域轉發到另一個服務中去- 在這種情況下,從“api.hello.world”到

api

服務,從“www.hello.world”到

world

服務。為了簡單起見,我們為每個域添加了一條規則,這些映射可以很容易地被聚合以實作更複雜的設定。(如果你是一個linkerd配置愛好者,我們将通過組合linkerd預設的header token identifier在主機header上實作路由轉發,

the domainToPathPfx

namer 把虛主機名轉換成分級路徑,和并且

io.l5d.k8s.daemonset

transforme将請求發送到相應的主機 本地的linkerd上。)

我們已經将此入口路由器添加到每個linkerd執行個體 - 以真正的service mesh方式,我們将在這些執行個體之間完全配置設定入口流量,以便沒有哪一個執行個體成為單點故障。

我們還需要修改我們的

k8s

服務對象,以便用端口80上的

outgoing

VIP去替換

ingress

VIP。這将允許我們将入口流量直接發送到linkerd service mesh - 主要用于調試目的,因為在點選linkerd之前,流量不會被消毒。(下一步,我們将解決這個問題。)

Kubernetes變化看起來像這樣:

---
apiVersion: v1
kind: Service
metadata:
  name: l5d
spec:
  selector:
    app: l5d
  type: LoadBalancer
  ports:
  - name: ingress
    port: 80
    targetPort: 4142
  - name: incoming
    port: 4141
  - name: admin
    port: 9990           

複制

以上所有操作都可以通過運作以下指令來完成:使用完整的帶入口的linkerd service mesh配置:

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/linkerd-ingress.yml           

複制

第2步:部署服務

對于在這個例子中的服務,我們将使用相同的hello and world configs 從以前的部落格文章,我們将添加兩個新的服務:一個API service,這就要求既

hello

服務 和

world

服務,以及word服務的新版本:

world-v2

,這将傳回“earth”而不是“world”這個詞 - 正在逐漸壯大的hacker團隊已經向我們證明了,他們的A/B測試顯示這一變化将使參與度提高10倍。

以下指令将把三個Hello World服務部署到預設名稱空間:

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/hello-world.yml           

複制

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/api.yml           

複制

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/world-v2.yml           

複制

在這一點上,我們應該能夠通過Kubernetes的

ingress

VIP 發送流量來測試設定 。在沒有使用DNS的情況下,我們将在請求中手動設定一個主機頭:

$ INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}")
$ curl -s -H "Host: www.hello.world" $INGRESS_LB
Hello (10.0.5.7) world (10.0.4.7)!!
$ curl -s -H "Host: api.hello.world" $INGRESS_LB
{"api_result":"api (10.0.3.6) Hello (10.0.5.4) world (10.0.1.5)!!"}           

複制

成功!我們已經将linkerd設定為入口控制器,并且我們已經使用它将不同域中收到的請求路由轉發到不同的服務。正如你所看到的,生産流量正在實作

world-v1

服務 - 我們還沒有準備好把

world-v2

展示出來。

第3步:NGINX中的一層

到了這一步,我們有正在運作的入口(ingress)。但是,我們目前還沒有準備好生産。首先,我們的入口路由器不會從請求中去掉頭檔案,這意味着外部請求可能包含我們不想接受的頭檔案。例如,linkerd允許每個請求應用路由規則設定将其header設定為

l5d-dtab

。這對于新服務的臨時分級是一個非常有用的功能,但這可能不是來自外部世界的合适調用!

例如,我們可以使用

l5d-dtab

标題來覆寫使用的路由邏輯

world-v2

而不是

world-v1

外部的生産 服務:

$ curl -H "Host: www.hello.world" -H "l5d-dtab: /host/world => /srv/world-v2;" $INGRESS_LB
Hello (10.100.4.3) earth (10.100.5.5)!!           

複制

在響應中請注意 earth,表示這是

world-v2

服務的結果 。這很酷,但這種權限我們絕對不想給任何人!

我們可以通過添加NGINX 來解決這個問題和其他問題(例如如何服務靜态檔案) 。如果我們配置NGINX在其代理的請求到連結入口路由之前剝離傳入的報頭,我們将得到兩全其美的好處:一個能夠安全處理外部流量的入口層,還有linkerd進行的動态的,基于服務的路由。

讓我們把nginx添加到叢集。我們将使用這個nginx.conf來配置它 。我們将使用我們的虛拟伺服器下的

www.hello.world

api.hello.world

proxy_pass

指令發送請求到linkerd執行個體,為了最大程度地發揮作用,我們将使用Headers More提供的

more_clear_input_headers

指令(使用通配符比對)。

(還有另外的方法,我們可以通過使用nginx的

proxy_set_header

指令來避免使用第三方的Nginx子產品來清除封包頭。我們會需要為每個單獨的條目剝離

l5d-ctx-

封包頭還有

l5d-dtab

l5d-sample

封包頭。)

請注意,從 linkerd 0.9.0開始,我們可以通過設定

clearContext: true

清除在入口路由器伺服器傳入的

l5d-*

封包頭。然而,nginx還有很多我們可以使用的功能(就像你現在看到的那樣),是以把nginx和linkerd結合使用仍然是有價值的。

對于你們這些家工作的人,我們已經釋出了一個nginx的Docker鏡像,其中把安裝了 Headers More子產品的(Dockerfile)稱為buoyantio / nginx:1.11.5。我們可以使用這個Kubernetes配置檔案把上面提到的配置用這個鏡像部署:

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/nginx.yml           

複制

在等待外部IP出現之後,我們可以通過點選nginx.conf中的簡單測試終端來測試NGINX:

$ INGRESS_LB=$(kubectl get svc nginx -o jsonpath="{.status.loadBalancer.ingress[0].*}")
$ curl $INGRESS_LB
200 OK           

複制

我們現在應該能夠通過NGINX向我們的服務發送流量:

$ curl -s -H "Host: www.hello.world" $INGRESS_LB
Hello (10.0.5.7) world (10.0.4.7)!!
$ curl -s -H "Host: api.hello.world" $INGRESS_LB
{"api_result":"api (10.0.3.6) Hello (10.0.5.4) world (10.0.1.5)!!"}           

複制

最後,讓我們測試一下我們的封包頭技巧并嘗試一下與

world-v2

服務進行直接通信。

$ curl -H "Host: www.hello.world" -H "l5d-dtab: /host/world => /srv/world-v2;" $INGRESS_LB
Hello (10.196.1.8) world (10.196.2.13)!!           

複制

第四步:Dogfood的優勢時間

好吧,我們已經做好了準備:讓我們建立一個使用

world-v2

服務的dogfood環境 ,但僅限于使用某些流量!

為了簡單起見,我們為目标流量設定一個特定的cookie, 即

special_employee_cookie

。在實踐中,你可能想要比這更複雜的東西 - 要驗證它,需要來自公司内部網絡範圍的IP等等。

在NGINX和linkerd安裝之後,完成這些将會變得很簡單。我們将使用NGINX來檢查特定cookie(指special_employee_cookie)的存在,并為linkerd設定一個dtab重載頭來調整其路由方向。相關的NGINX配置如下所示:

if ($cookie_special_employee_cookie ~* "dogfood") {
  set $xheader "/host/world => /srv/world-v2;";
}

proxy_set_header 'l5d-dtab' $xheader;           

複制

如果您一直在遵循上述步驟,那麼已部署的NGINX已經包含了這個配置。我們可以像這樣測試它:

$ curl -H "Host: www.hello.world" --cookie "special_employee_cookie=dogfood" $INGRESS_LB
Hello (10.196.1.8) earth (10.196.2.13)!!           

複制

系統成功運作!當這個cookie被設定時,你将進入dogfood模式。沒有它,你就會進入正常生産環境的流量模式。最重要的是,dogfood模式可以包含出現在服務堆棧中的任何地方的新版本的服務 ,甚至是多層深度的服務代碼,其中包括服務代碼forwards linkerd context headers,linkerd service mesh将負責其餘的工作。

結論

在這篇文章中,我們看到了如何使用linkerd為Kubernetes叢集提供強大靈活的入口(ingress)。我們已經示範了如何部署正如其名的已經準備完畢的生産環境配置,該生産環境配置使用linkerd進行服務路由轉發。我們已經示範了如何使用linkerd的一些進階路由功能來将 traffic-serving 拓撲與 deployment拓撲分離,進而允許建立dogfood環境而不需要單獨的叢集或耗費很多的部署時間。

有關在Kubernetes中運作linkerd的更多資訊,或者如果您在配置入口時遇到任何問題,請随時通過我們的Linkerd社群Slack來查找相關資訊,發送郵件到我們的郵件清單或直接與我們聯系。