TCP 流量
此任務說明如何在 Istio 網格中為 TCP 流量設定 Istio 授權策略。
開始之前
開始此任務之前,請執行以下操作:
閱讀 Istio 授權概念。
使用 Istio 安裝指南 安裝 Istio。
在名為
foo
的命名空間中,一同部署兩個名為curl
和tcp-echo
的工作負載。這兩個工作負載都會在其前端運行一個 Envoy 代理。tcp-echo
工作負載監聽 9000、9001 和 9002 端口,並將接收到的任何流量加上前綴hello
後回傳。例如,如果您發送 "world" 到tcp-echo
,它將回覆hello world
。tcp-echo
Kubernetes 服務物件僅宣告了 9000 和 9001 端口,並省略了 9002 端口。一個直通(pass-through)過濾器鏈將處理 9002 端口的流量。使用以下命令部署範例命名空間和工作負載$ kubectl create ns foo $ kubectl apply -f <(istioctl kube-inject -f @samples/tcp-echo/tcp-echo.yaml@) -n foo $ kubectl apply -f <(istioctl kube-inject -f @samples/curl/curl.yaml@) -n foo
使用以下命令驗證
curl
是否成功與tcp-echo
的 9000 和 9001 端口通信$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' hello port 9000 connection succeeded
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' hello port 9001 connection succeeded
驗證
curl
是否成功與tcp-echo
的 9002 端口通信。您需要直接將流量發送到tcp-echo
的 Pod IP,因為 9002 端口未在tcp-echo
的 Kubernetes 服務物件中定義。取得 Pod IP 位址並使用以下命令發送請求$ TCP_ECHO_IP=$(kubectl get pod "$(kubectl get pod -l app=tcp-echo -n foo -o jsonpath={.items..metadata.name})" -n foo -o jsonpath="{.status.podIP}") $ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ "echo \"port 9002\" | nc $TCP_ECHO_IP 9002" | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' hello port 9002 connection succeeded
設定 TCP 工作負載的 ALLOW 授權策略
在
foo
命名空間中,為tcp-echo
工作負載建立tcp-policy
授權策略。執行以下命令以應用該策略,允許對 9000 和 9001 端口的請求$ kubectl apply -f - <<EOF apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: tcp-policy namespace: foo spec: selector: matchLabels: app: tcp-echo action: ALLOW rules: - to: - operation: ports: ["9000", "9001"] EOF
使用以下命令驗證是否允許對 9000 端口的請求
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' hello port 9000 connection succeeded
使用以下命令驗證是否允許對 9001 端口的請求
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' hello port 9001 connection succeeded
驗證是否拒絕對 9002 端口的請求。這是由授權策略強制執行的,該策略也適用於直通過濾器鏈,即使該端口未在
tcp-echo
Kubernetes 服務物件中明確宣告。執行以下命令並驗證輸出$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ "echo \"port 9002\" | nc $TCP_ECHO_IP 9002" | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' connection rejected
使用以下命令更新策略,為 9000 端口新增一個名為
methods
的僅限 HTTP 的欄位$ kubectl apply -f - <<EOF apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: tcp-policy namespace: foo spec: selector: matchLabels: app: tcp-echo action: ALLOW rules: - to: - operation: methods: ["GET"] ports: ["9000"] EOF
驗證是否拒絕對 9000 端口的請求。發生這種情況是因為當它對 TCP 流量使用僅限 HTTP 的欄位 (
methods
) 時,該規則會失效。Istio 會忽略無效的 ALLOW 規則。最終結果是請求被拒絕,因為它不符合任何 ALLOW 規則。執行以下命令並驗證輸出$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' connection rejected
驗證是否拒絕對 9001 端口的請求。發生這種情況是因為請求不符合任何 ALLOW 規則。執行以下命令並驗證輸出
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' connection rejected
設定 TCP 工作負載的 DENY 授權策略
使用以下命令新增一個具有僅限 HTTP 欄位的 DENY 策略
$ kubectl apply -f - <<EOF apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: tcp-policy namespace: foo spec: selector: matchLabels: app: tcp-echo action: DENY rules: - to: - operation: methods: ["GET"] EOF
驗證是否拒絕對 9000 端口的請求。發生這種情況是因為 Istio 在為 tcp 端口建立 DENY 規則時無法理解僅限 HTTP 的欄位,並且由於其限制性,它會拒絕所有到 tcp 端口的流量
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' connection rejected
驗證是否拒絕對 9001 端口的請求。原因同上。
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' connection rejected
使用以下命令新增一個同時具有 TCP 和 HTTP 欄位的 DENY 策略
$ kubectl apply -f - <<EOF apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: tcp-policy namespace: foo spec: selector: matchLabels: app: tcp-echo action: DENY rules: - to: - operation: methods: ["GET"] ports: ["9000"] EOF
驗證是否拒絕對 9000 端口的請求。發生這種情況是因為請求符合上述 deny 策略中的
ports
。$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' connection rejected
驗證是否允許對 9001 端口的請求。發生這種情況是因為請求不符合 DENY 策略中的
ports
。$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" \ -c curl -n foo -- sh -c \ 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected' hello port 9001 connection succeeded
清理
移除 foo 命名空間
$ kubectl delete namespace foo