在本文中,我們将講述如何使用linkerd作為service mesh在不需要修改任何應用代碼的情況下,也能添加TLS至所有的“服務到服務”HTTP請求中。
注意:這是關于Linkerd、Kubernetes和service mesh的系列文章其中一篇,其餘部分包括:
- Top-line service metrics
- Pods are great, until they’re not
- Encrypting all the things (本文)
- Continuous deployment via traffic shifting
- Dogfood environments, ingress, and edge routing
- Staging microservices without the tears
- Distributed tracing made easy
- Linkerd as an ingress controller
- gRPC for fun and profit
- The Service Mesh API
- Egress
- Retry budgets, deadline propagation, and failing gracefully
- 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 – 第三部分:将一切加密