相互 TLS 遷移

此任務展示如何在將工作負載遷移到 Istio 時,確保其僅使用雙向 TLS 進行通訊。

當呼叫其他工作負載時,Istio 會自動配置工作負載 Sidecar 以使用雙向 TLS。預設情況下,Istio 使用 PERMISSIVE 模式配置目標工作負載。啟用 PERMISSIVE 模式時,服務可以接受純文字和雙向 TLS 流量。為了僅允許雙向 TLS 流量,需要將配置更改為 STRICT 模式。

您可以使用Grafana 儀表板來檢查哪些工作負載仍在向 PERMISSIVE 模式下的工作負載發送純文字流量,並在遷移完成後選擇鎖定它們。

開始之前

在此任務中,您可以透過建立範例工作負載並修改策略以在工作負載之間強制執行 STRICT 雙向 TLS 來嘗試遷移過程。

設定叢集

  • 建立兩個命名空間,foobar,並在這兩個命名空間上部署帶有 Sidecar 的 httpbincurl

    ZipZipZipZip
    $ kubectl create ns foo
    $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n foo
    $ kubectl apply -f <(istioctl kube-inject -f @samples/curl/curl.yaml@) -n foo
    $ kubectl create ns bar
    $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n bar
    $ kubectl apply -f <(istioctl kube-inject -f @samples/curl/curl.yaml@) -n bar
    
  • 建立另一個命名空間 legacy,並部署沒有 Sidecar 的 curl

    Zip
    $ kubectl create ns legacy
    $ kubectl apply -f @samples/curl/curl.yaml@ -n legacy
    
  • 透過從 foobarlegacy 命名空間中的 curl Pod 發送 HTTP 請求(使用 curl)到 httpbin.foohttpbin.bar 來驗證設定。所有請求都應該成功,並返回代碼 200。

    $ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=curl -n ${from} -o jsonpath={.items..metadata.name})" -c curl -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "curl.${from} to httpbin.${to}: %{http_code}\n"; done; done
    curl.foo to httpbin.foo: 200
    curl.foo to httpbin.bar: 200
    curl.bar to httpbin.foo: 200
    curl.bar to httpbin.bar: 200
    curl.legacy to httpbin.foo: 200
    curl.legacy to httpbin.bar: 200
    

限制命名空間使用雙向 TLS

將所有用戶端遷移到 Istio 並注入 Envoy Sidecar 後,您可以將 foo 命名空間中的工作負載鎖定為僅接受雙向 TLS 流量。

$ kubectl apply -n foo -f - <<EOF
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
spec:
  mtls:
    mode: STRICT
EOF

現在,您應該看到從 curl.legacyhttpbin.foo 的請求失敗。

$ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=curl -n ${from} -o jsonpath={.items..metadata.name})" -c curl -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "curl.${from} to httpbin.${to}: %{http_code}\n"; done; done
curl.foo to httpbin.foo: 200
curl.foo to httpbin.bar: 200
curl.bar to httpbin.foo: 200
curl.bar to httpbin.bar: 200
curl.legacy to httpbin.foo: 000
command terminated with exit code 56
curl.legacy to httpbin.bar: 200

如果您使用 values.global.proxy.privileged=true 安裝 Istio,則可以使用 tcpdump 來驗證流量是否已加密。

$ kubectl exec -nfoo "$(kubectl get pod -nfoo -lapp=httpbin -ojsonpath={.items..metadata.name})" -c istio-proxy -- sudo tcpdump dst port 80  -A
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

當請求分別從 curl.legacycurl.foo 發送時,您將在輸出中看到純文字和加密文字。

如果您無法將所有服務遷移到 Istio(即,在所有服務中注入 Envoy Sidecar),則需要繼續使用 PERMISSIVE 模式。但是,當配置為 PERMISSIVE 模式時,預設情況下不會對純文字流量執行任何身份驗證或授權檢查。我們建議您使用 Istio 授權來配置具有不同授權策略的不同路徑。

限制整個網格使用雙向 TLS

您可以透過將策略放在 Istio 安裝的系統命名空間中,將所有命名空間中的工作負載鎖定為僅接受雙向 TLS 流量。

$ kubectl apply -n istio-system -f - <<EOF
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
spec:
  mtls:
    mode: STRICT
EOF

現在,foobar 命名空間都強制僅使用雙向 TLS 流量,因此您應該看到來自 curl.legacy 的請求都失敗了。

$ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=curl -n ${from} -o jsonpath={.items..metadata.name})" -c curl -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "curl.${from} to httpbin.${to}: %{http_code}\n"; done; done

清除範例

  1. 移除網格範圍的身份驗證策略。

    $ kubectl delete peerauthentication -n foo default
    $ kubectl delete peerauthentication -n istio-system default
    
  2. 移除測試命名空間。

    $ kubectl delete ns foo bar legacy
    Namespaces foo bar legacy deleted.
    
此資訊是否有用?
您有任何改進建議嗎?

感謝您的回饋!