在 Cloud Service Mesh 1.5 以上版本中,系統會預設啟用自動雙向 TLS (自動 mTLS)。有了自動 mTLS,用戶端 sidecar proxy 會自動偵測伺服器是否有 sidecar。用戶端 sidecar 會將 mTLS 傳送至含 sidecar 的工作負載,並將純文字傳送至不含 sidecar 的工作負載。不過請注意,服務會接受純文字和 mTLS 流量。在為 Pod 注入補充 Proxy時,建議您也將服務設為只接受 mTLS 流量。
您可以透過 Cloud Service Mesh 套用單一 YAML 檔案,在應用程式程式碼之外強制執行 mTLS。Cloud Service Mesh 可讓您靈活套用驗證政策,適用於整個服務網格、命名空間或個別工作負載。
費用
在本文件中,您會使用 Google Cloud的下列計費元件:
您可以使用 Pricing Calculator 根據預測用量產生預估費用。
完成本教學課程後,您可以刪除已建立的資源,以免持續產生費用。詳情請參閱「清除所用資源」。
事前準備
確認專案已啟用計費功能。
在 GKE 叢集中佈建 Cloud Service Mesh。系統支援多種設定方法:
複製存放區:
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples cd anthos-service-mesh-samples
部署入口閘道
將
kubectl
的目前背景資訊設為叢集:gcloud container clusters get-credentials CLUSTER_NAME \ --project=PROJECT_ID \ --zone=CLUSTER_LOCATION
為 Ingress Gateway 建立命名空間:
kubectl create namespace asm-ingress
啟用要用於插入的命名空間。步驟取決於控制層實作。
代管 (TD)
將預設的注入標籤套用至命名空間:
kubectl label namespace asm-ingress \ istio.io/rev- istio-injection=enabled --overwrite
受管理 (Istiod)
建議做法:執行下列指令,將預設注入標籤套用至命名空間:
kubectl label namespace asm-ingress \ istio.io/rev- istio-injection=enabled --overwrite
如果您是現有的 Managed Istiod 控制平面使用者:我們建議您使用預設插入作業,但也支援以修訂版本為基礎的插入作業。請按照下列操作說明進行:
執行下列指令,找出可用的發布版本:
kubectl -n istio-system get controlplanerevision
輸出結果會與下列內容相似:
NAME AGE asm-managed-rapid 6d7h
在輸出內容中,
NAME
欄下方的值是修訂版本標籤,對應至 Cloud Service Mesh 版本的發布管道。將修訂版本標籤套用至命名空間:
kubectl label namespace asm-ingress \ istio-injection- istio.io/rev=REVISION_LABEL --overwrite
在
anthos-service-mesh-samples
存放區中部署範例閘道:kubectl apply -n asm-ingress \ -f docs/shared/asm-ingress-gateway
預期輸出內容:
serviceaccount/asm-ingressgateway configured service/asm-ingressgateway configured deployment.apps/asm-ingressgateway configured gateway.networking.istio.io/asm-ingressgateway configured
部署 Online Boutique 範例應用程式
如果您尚未設定,請將
kubectl
的目前背景資訊設為叢集:gcloud container clusters get-credentials CLUSTER_NAME \ --project=PROJECT_ID \ --zone=CLUSTER_LOCATION
為範例應用程式建立命名空間:
kubectl create namespace onlineboutique
為
onlineboutique
命名空間加上標籤,以便自動插入 Envoy Proxy。按照這篇文章中的步驟啟用自動 Sidecar Inject 功能。部署範例應用程式、前端的
VirtualService
,以及工作負載的服務帳戶。在本教學課程中,您將部署 Online Boutique,這是一個微服務示範應用程式。kubectl apply \ -n onlineboutique \ -f docs/shared/online-boutique/virtual-service.yaml kubectl apply \ -n onlineboutique \ -f docs/shared/online-boutique/service-accounts
查看服務
查看
onlineboutique
命名空間中的 Pod:kubectl get pods -n onlineboutique
預期輸出內容:
NAME READY STATUS RESTARTS AGE adservice-85598d856b-m84m6 2/2 Running 0 2m7s cartservice-c77f6b866-m67vd 2/2 Running 0 2m8s checkoutservice-654c47f4b6-hqtqr 2/2 Running 0 2m10s currencyservice-59bc889674-jhk8z 2/2 Running 0 2m8s emailservice-5b9fff7cb8-8nqwz 2/2 Running 0 2m10s frontend-77b88cc7cb-mr4rp 2/2 Running 0 2m9s loadgenerator-6958f5bc8b-55q7w 2/2 Running 0 2m8s paymentservice-68dd9755bb-2jmb7 2/2 Running 0 2m9s productcatalogservice-84f95c95ff-c5kl6 2/2 Running 0 114s recommendationservice-64dc9dfbc8-xfs2t 2/2 Running 0 2m9s redis-cart-5b569cd47-cc2qd 2/2 Running 0 2m7s shippingservice-5488d5b6cb-lfhtt 2/2 Running 0 2m7s
應用程式的所有 Pod 都應已啟動並執行,且
READY
欄中應有2/2
。這表示 Pod 已成功插入 Envoy 邊車 Proxy。如果幾分鐘後仍未顯示2/2
,請參閱疑難排解指南。取得外部 IP,並將其設為變數:
kubectl get services -n asm-ingress export FRONTEND_IP=$(kubectl --namespace asm-ingress \ get service --output jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}' \ )
畫面會顯示類似以下內容的輸出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE asm-ingressgateway LoadBalancer 10.19.247.233 35.239.7.64 80:31380/TCP,443:31390/TCP,31400:31400/TCP 27m
在網路瀏覽器中造訪
EXTERNAL-IP
位址。瀏覽器中應會顯示 Online Boutique 商店。
建立 TestCurl Pod
建立 TestCurl Pod,以便傳送測試用的純文字流量。
apiVersion: v1
kind: Pod
metadata:
name: testcurl
namespace: default
annotations:
sidecar.istio.io/inject: "false"
spec:
containers:
- name: curl
image: curlimages/curl
command: ["sleep", "600"]
存取線上精品店
將
kubectl
的目前背景資訊設為部署 Online Boutique 的叢集:gcloud container clusters get-credentials CLUSTER_NAME \ --project=PROJECT_ID \ --zone=CLUSTER_LOCATION
列出
frontend
命名空間中的服務:kubectl get services -n frontend
請注意,
frontend-external
是LoadBalancer
,且具有外部 IP 位址。範例應用程式包含負載平衡器服務,因此可在沒有 Cloud Service Mesh 的情況下部署在 GKE 上。使用
frontend-external
服務的外部 IP 位址,在瀏覽器中造訪應用程式:http://FRONTEND_EXTERNAL_IP/
Cloud Service Mesh 可讓您部署入口網關。您也可以使用入口網關的外部 IP 位址存取線上精品店。取得閘道的外部 IP。將預留位置替換為下列資訊:
- GATEWAY_SERVICE_NAME:Ingress Gateway 服務的名稱。如果您部署的是未經修改的範例閘道,或是部署了預設入口閘道,名稱會是
istio-ingressgateway
。 - GATEWAY_NAMESPACE:部署入口網站閘道的命名空間。如果您部署了預設輸入閘道,命名空間就是
istio-system
。
kubectl get service GATEWAY_NAME -n GATEWAY_NAMESPACE
- GATEWAY_SERVICE_NAME:Ingress Gateway 服務的名稱。如果您部署的是未經修改的範例閘道,或是部署了預設入口閘道,名稱會是
在瀏覽器中開啟另一個分頁,然後使用入口網關的外部 IP 位址造訪應用程式:
http://INGRESS_GATEWAY_EXTERNAL_IP/
執行下列指令,透過另一個 Pod 使用純 HTTP
curl
frontend
服務。由於這些服務位於不同的命名空間,因此您需要捲曲frontend
服務的 DNS 名稱。kubectl debug --image istio/base --target istio-proxy -it \ $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \ -n product-catalog -- \ curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
根據預設,系統會同時接受 TLS 和純文字流量,因此要求會成功並顯示狀態
200
。
為每個命名空間啟用 mTLS
您可以透過 kubectl
套用 PeerAuthentication
政策來強制執行 mTLS。
將下列驗證政策儲存為
mtls-namespace.yaml
。cat <<EOF > mtls-namespace.yaml apiVersion: "security.istio.io/v1beta1" kind: "PeerAuthentication" metadata: name: "namespace-policy" spec: mtls: mode: STRICT EOF
YAML 中的
mode: STRICT
行會將服務設為只接受 mTLS。根據預設,mode
為PERMISSIVE
,可將服務設為同時接受純文字和 mTLS。套用驗證政策,將所有線上精品店服務設為只接受 mTLS:
for ns in ad cart checkout currency email frontend loadgenerator \ payment product-catalog recommendation shipping; do kubectl apply -n $ns -f mtls-namespace.yaml done
預期的輸出內容:
peerauthentication.security.istio.io/namespace-policy created peerauthentication.security.istio.io/namespace-policy created peerauthentication.security.istio.io/namespace-policy created peerauthentication.security.istio.io/namespace-policy created peerauthentication.security.istio.io/namespace-policy created peerauthentication.security.istio.io/namespace-policy created peerauthentication.security.istio.io/namespace-policy created peerauthentication.security.istio.io/namespace-policy created peerauthentication.security.istio.io/namespace-policy created peerauthentication.security.istio.io/namespace-policy created peerauthentication.security.istio.io/namespace-policy created
在瀏覽器中前往使用
frontend-external
服務外部 IP 位址存取線上精品店的分頁:http://FRONTEND_EXTERNAL_IP/
重新整理頁面。瀏覽器會顯示以下錯誤:
重新整理頁面會導致純文字傳送至
frontend
服務。由於STRICT
驗證政策,側邊 Proxy 會封鎖對服務的要求。在瀏覽器中前往使用
istio-ingressgateway
外部 IP 位址存取網路商店的分頁,然後重新整理頁面,即可成功顯示。使用入口網頁閘道存取線上精品店時,要求會沿著下列路徑傳送:mTLS 驗證流程:
- 瀏覽器會將純文字 HTTP 要求傳送至伺服器。
- 入口閘道 Proxy 容器會攔截要求。
- 網頁閘道 Proxy 會與伺服器端 Proxy (本例中的前端服務) 執行 TLS 握手。這項握手程序包括憑證交換。這些憑證會由 Cloud Service Mesh 預先載入至 Proxy 容器。
- 入口閘道 Proxy 會對伺服器的憑證執行安全命名檢查,驗證伺服器是否由授權身分執行。
- 入口網頁閘道和伺服器 Proxy 會建立 TLS 雙向連線,而伺服器 Proxy 會將要求轉送至伺服器應用程式容器 (前端服務)。
執行下列指令,使用另一個 Pod 中的純 HTTP
frontend
服務curl
。kubectl exec testcurl -n default -- curl \ http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
由於我們會從已套用嚴格
peerAuthentication
政策的無側載工作負載傳送純文字流量,因此您的要求會失敗。
尋找及刪除驗證政策
如需服務中介網中的所有
PeerAuthentication
政策清單,請參閱:kubectl get peerauthentication --all-namespaces
輸出結果會與下列內容相似:
NAMESPACE NAME MODE AGE ad namespace-policy STRICT 17m cart namespace-policy STRICT 17m checkout namespace-policy STRICT 17m currency namespace-policy STRICT 17m email namespace-policy STRICT 17m frontend namespace-policy STRICT 17m loadgenerator namespace-policy STRICT 17m payment namespace-policy STRICT 17m product-catalog namespace-policy STRICT 17m recommendation namespace-policy STRICT 17m shipping namespace-policy STRICT 17m
從所有線上精品店命名空間中刪除驗證政策:
for ns in ad cart checkout currency email frontend loadgenerator payment \ product-catalog recommendation shipping; do kubectl delete peerauthentication -n $ns namespace-policy done;
預期輸出內容:
peerauthentication.security.istio.io "namespace-policy" deleted peerauthentication.security.istio.io "namespace-policy" deleted peerauthentication.security.istio.io "namespace-policy" deleted peerauthentication.security.istio.io "namespace-policy" deleted peerauthentication.security.istio.io "namespace-policy" deleted peerauthentication.security.istio.io "namespace-policy" deleted peerauthentication.security.istio.io "namespace-policy" deleted peerauthentication.security.istio.io "namespace-policy" deleted peerauthentication.security.istio.io "namespace-policy" deleted peerauthentication.security.istio.io "namespace-policy" deleted peerauthentication.security.istio.io "namespace-policy" deleted
使用
frontend-external
服務的外部 IP 位址存取線上精品店,然後重新整理頁面。頁面會如預期顯示。執行下列指令,使用另一個 Pod 中的純 HTTP
frontend
服務curl
。kubectl debug --image istio/base --target istio-proxy -it \ $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \ -n product-catalog -- \ curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
根據預設,系統會同時接受 TLS 和純文字流量,因此要求會成功並顯示狀態
200
。
如果您在顯示工作負載清單的 Google Cloud 控制台中重新整理頁面,現在會顯示 mTLS 狀態為 Permissive
。
為每個工作負載啟用 mTLS
如要為特定工作負載設定 PeerAuthentication
政策,您必須設定 selector
部分,並指定符合所需工作負載的標籤。不過,Cloud Service Mesh 無法針對服務的傳出 mTLS 流量,匯總工作負載層級政策。您需要設定目標規則來管理這項行為。
將驗證政策套用至特定工作負載。請注意,下列政策如何使用標籤和選取器指定特定
frontend
部署作業。cat <<EOF | kubectl apply -n frontend -f - apiVersion: "security.istio.io/v1beta1" kind: "PeerAuthentication" metadata: name: "frontend" namespace: "frontend" spec: selector: matchLabels: app: frontend mtls: mode: STRICT EOF
預期輸出內容:
peerauthentication.security.istio.io/frontend created
設定比對目的地規則。
cat <<EOF | kubectl apply -n frontend -f - apiVersion: "networking.istio.io/v1alpha3" kind: "DestinationRule" metadata: name: "frontend" spec: host: "frontend.demo.svc.cluster.local" trafficPolicy: tls: mode: ISTIO_MUTUAL EOF
預期輸出內容:
destinationrule.networking.istio.io/frontend created
使用
frontend-external
服務的外部 IP 位址存取線上精品店,然後重新整理頁面。由於frontend service
已設為STRICT
mTLS,而側載代理程式會封鎖要求,因此頁面不會顯示。執行下列指令,使用另一個 Pod 中的純 HTTP
frontend
服務curl
。kubectl exec testcurl -n default -- curl \ http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
由於我們會從已套用嚴格
peerAuthentication
政策的無側載工作負載傳送純文字流量,因此您的要求會失敗。刪除驗證政策:
kubectl delete peerauthentication -n frontend frontend
預期輸出內容:
peerauthentication.security.istio.io "frontend" deleted
刪除目的地規則:
kubectl delete destinationrule -n frontend frontend
預期輸出內容:
destinationrule.networking.istio.io "frontend" deleted
強制執行網格範圍的 mTLS
如要防止網格中的所有服務接受純文字流量,請設定網格層級的 PeerAuthentication
政策,並將 mTLS 模式設為 STRICT
。網格層級 PeerAuthentication
政策不應包含選取器,且必須套用至根命名空間 istio-system
。部署政策時,控制平面會自動佈建 TLS 憑證,讓工作負載彼此驗證。
強制執行網格全域 mTLS:
kubectl apply -f - <<EOF apiVersion: "security.istio.io/v1beta1" kind: "PeerAuthentication" metadata: name: "mesh-wide" namespace: "istio-system" spec: mtls: mode: STRICT EOF
預期的輸出內容:
peerauthentication.security.istio.io/mesh-wide created
使用
frontend-external
服務的外部 IP 位址存取線上精品店,然後重新整理頁面。網頁未顯示。執行下列指令,使用另一個 Pod 中的純 HTTP
frontend
服務curl
。kubectl exec testcurl -n default -- curl \ http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
由於我們會從已套用嚴格
peerAuthentication
政策的無側載工作負載傳送純文字流量,因此您的要求會失敗。刪除
mesh-wide
政策:kubectl delete peerauthentication -n istio-system mesh-wide
預期輸出內容:
peerauthentication.security.istio.io "mesh-wide" deleted
清除所用資源
如要避免系統向您的 Google Cloud 帳戶收取本教學課程中所用資源的相關費用,請刪除含有該項資源的專案,或者保留專案但刪除個別資源。
如要避免產生額外費用,請刪除叢集:
gcloud container clusters delete CLUSTER_NAME \ --project=PROJECT_ID \ --zone=CLUSTER_LOCATION
如果您想保留叢集並移除 Online Boutique 範例,請按照下列步驟操作:
- 刪除應用程式命名空間:
kubectl delete -f online-boutique/kubernetes-manifests/namespaces
預期輸出內容:
namespace "ad" deleted namespace "cart" deleted namespace "checkout" deleted namespace "currency" deleted namespace "email" deleted namespace "frontend" deleted namespace "loadgenerator" deleted namespace "payment" deleted namespace "product-catalog" deleted namespace "recommendation" deleted namespace "shipping" deleted
- 刪除服務項目:
kubectl delete -f online-boutique/istio-manifests/allow-egress-googleapis.yaml
預期輸出內容:
serviceentry.networking.istio.io "allow-egress-googleapis" deleted serviceentry.networking.istio.io "allow-egress-google-metadata" deleted
後續步驟
- 如需設定
PeerAuthentication
政策的一般指南,請參閱「設定傳輸安全性」。