天天看點

Kubernetes的service mesh – 第三部分:将一切加密

在本文中,我們将講述如何使用linkerd作為service mesh在不需要修改任何應用代碼的情況下,也能添加TLS至所有的“服務到服務”HTTP請求中。

注意:這是關于Linkerd、Kubernetes和service mesh的系列文章其中一篇,其餘部分包括:

  1. Top-line service metrics
  2. Pods are great, until they’re not
  3. Encrypting all the things (本文)
  4. Continuous deployment via traffic shifting
  5. Dogfood environments, ingress, and edge routing
  6. Staging microservices without the tears
  7. Distributed tracing made easy
  8. Linkerd as an ingress controller
  9. gRPC for fun and profit
  10. The Service Mesh API
  11. Egress
  12. Retry budgets, deadline propagation, and failing gracefully
  13. Autoscaling by top-line metrics

在該系列的

第一部分

,我講述了當linkerd被作為service mesh安裝後如何監控頂層名額(成功率、延遲、請求率)。本文中,我将講述service mesh的另一優勢:它允許你将應用程式的協定與網絡上使用的協定分離。換句話說,應用可以使用與在電纜上傳輸位元組不同的協定。

在不需要資料轉換的情況下,linkerd可以利用這個解耦功能進行自動的協定更新。linkerd可以做協定更新的例子包括HTTP/1.x至HTTP/2,thrift至thrift-mux,還有HTTP至HTTPS,這也是本文的主題。

Kubernetes的service mesh

當linkerd在Kubernetes中作為service mesh部署後,我們使用DaemonSet在每個主控端上部署一個linkerd執行個體。對于HTTP服務而言,pod可以通過使用http_proxy環境變量發送HTTP流量到它們本地的linkerd。(非HTTP流量情況下會稍微複雜些)

我們之前曾講過在TLS中通過在連接配接的兩端代理始發TLS和終止TLS,來使用linkerd“打包”HTTP請求的基本模式。然而,現在我們有了service mesh,問題顯然變得簡單了。将全部的跨主控端通信加密是service mesh提供TLS證書的關鍵。

接下來舉具體例子來說。接下來的例子的前兩步與本系列PRAT 1相同,安裝linkerd并安裝簡單的微服務“hello world”應用程式。如果你已經做過這些了,可以直接跳到第三步。

第一步:安裝Linkerd

使用Kubernetes配置檔案安裝Linkerd。它會将Linkerd作為DaemonSet安裝,且運作在Kubernetes的default命名空間:

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

你可以通過檢視Linkerd的管理頁面确認是否安裝成功:

INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}")
open http://$INGRESS_LB:9990 # on OS X      

如果叢集不支援外部負載均衡,使用hostIP:

HOST_IP=$(kubectl get po -l app=l5d -o jsonpath="{.items[0].status.hostIP}")
open http://$HOST_IP:$(kubectl get svc l5d -o 'jsonpath={.spec.ports[2].nodePort}') # on OS X      

第二步:安裝樣例應用程式

在default命名空間下安裝兩個Service,“hello”和“world”。這些應用程式依賴于Kubernetes downward API提供的nodeName來發現Linkerd。為了檢測你的叢集是否支援nodeName,你可以運作:

kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/node-name-test.yml      

然後看它的日志:

kubectl logs node-name-test      

如果你看到了一個IP就說明支援。接下來繼續部署hello world應用程式如下:

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

如果你看到報錯“server can’t find…”,就部署舊版本hello-world,它依賴于hostIP而非nodeName:

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

這兩個Service——“hello”和“world”——功能在一起使得高度可擴充,“hello world”微服務(“hello”Service調用“world”Service完成這個請求)。

你可以通過給Linkerd的外部IP發送請求來檢視此操作:

http_proxy=$INGRESS_LB:4140 curl -s http://hello      

或者直接使用hostIP:

http_proxy=$HOST_IP:$(kubectl get svc l5d -o 'jsonpath={.spec.ports[0].nodePort}') curl -s http://hello      

你應該可以看到字元串“Hello world”。

第三步:為使用TLS配置linkerd

現在linkerd已經安裝好了,我們可以使用它來給流量加密了。我們在每一個主控端上安裝TLS證書,并為使用這些證書而配置linkerd。

我們将使用一個我們自己生成的全局證書。因為這個證書沒有綁定公共DNS域名,我們就不需要使用Let’s Encrypt這樣的服務了。我們可以生成自己的CA憑證,并使用它來簽署我們的mesh證書(“自簽名”)。我們将為每個Kubernetes節點配置設定三樣東西:CA憑證,mesh密鑰和mesh證書。

接下來的這個腳本使用我們自己生成的樣本證書。請不要在生産環境中使用這些證書。

第四步:為Kubernetes部署證書并配置變更

我們已經做好準備為給流量加密而更新linkerd。我們将如Kubernetes secrets對象那樣配置設定樣例證書。

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

現在,我們将通過這個配置檔案配置linkerd并重新開機它以使用這些證書:

kubectl delete ds/l5d configmap/l5d-config
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/linkerd-tls.yml      

第五步:成功

此時,linkerd應該透明地包裹TLS中的這些服務之間的所有通信。我們通過運作與之前相同的指令來驗證這一點:

http_proxy=$INGRESS_LB:4140 curl -s http://hello      

或者使用hostIP:

http_proxy=$HOST_IP:$(kubectl get svc l5d -o 'jsonpath={.spec.ports[0].nodePort}') curl -s http://hello      

如果一切順利進行,你應該仍然可以看到字元串“Hello world”。但是實際上,hello和world服務之間的通信正在被加密。我們可以通過直接向端口4141發送HTTPS請求來進行驗證,其中,linkerd正在監聽來自其他linkerd執行個體的請求:

curl -skH 'l5d-dtab: /svc=>/#/io.l5d.k8s/default/admin/l5d;' https://$INGRESS_LB:4141/admin/ping      
curl -skH 'l5d-dtab: /svc=>/#/io.l5d.k8s/default/admin/l5d;'
https://$HOST_IP:$(kubectl get svc l5d -o 'jsonpath={.spec.ports[1].nodePort}')/admin/ping      

這裡,我們要求用curl進行HTTPS調用,并告訴它跳過TLS驗證(因為curl期望一個站點,而不是linkerd)。我們還添加了一個dtab override來将請求路由到linkerd執行個體自己的管理界面。如果一切順利,你應該再次看到一個成功的“pong”響應。恭喜! 你已加密了跨服務流量。

結束語

在這篇文章中,我們已經講述了如何使用諸如linkerd的service mesh來透明地加密Kubernetes叢集中的所有跨節點通信。我們還使用TLS來確定linkerd執行個體可以驗證它們是否與其他linkerd執行個體進行通信,進而防止中間人攻擊(和配置錯誤)。當然,這個應用程式仍然不知道任何這些變化。

TLS是一個複雜的主題,我們已經考慮了一些重要的安全注意事項以使示範變得簡單些。在你于生産叢集上嘗試此過程之前,請確定你已經花時間充分了解了相關步驟。

最後,将TLS添加到通信中隻是service mesh可以實作的許多事情之一。一定要檢視本系列的其餘文章以了解更多。

本文轉自kubernetes中文社群-

Kubernetes的service mesh – 第三部分:将一切加密

繼續閱讀