TCP 流量

此任務說明如何在 Istio 網格中為 TCP 流量設定 Istio 授權策略。

開始之前

開始此任務之前,請執行以下操作:

  • 閱讀 Istio 授權概念

  • 使用 Istio 安裝指南 安裝 Istio。

  • 在名為 foo 的命名空間中,一同部署兩個名為 curltcp-echo 的工作負載。這兩個工作負載都會在其前端運行一個 Envoy 代理。 tcp-echo 工作負載監聽 9000、9001 和 9002 端口,並將接收到的任何流量加上前綴 hello 後回傳。例如,如果您發送 "world" 到 tcp-echo,它將回覆 hello worldtcp-echo Kubernetes 服務物件僅宣告了 9000 和 9001 端口,並省略了 9002 端口。一個直通(pass-through)過濾器鏈將處理 9002 端口的流量。使用以下命令部署範例命名空間和工作負載

    ZipZip
    $ 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 授權策略

  1. 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
    
  2. 使用以下命令驗證是否允許對 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
    
  3. 使用以下命令驗證是否允許對 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
    
  4. 驗證是否拒絕對 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
    
  5. 使用以下命令更新策略,為 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
    
  6. 驗證是否拒絕對 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
    
  7. 驗證是否拒絕對 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 授權策略

  1. 使用以下命令新增一個具有僅限 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
    
  2. 驗證是否拒絕對 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
    
  3. 驗證是否拒絕對 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
    
  4. 使用以下命令新增一個同時具有 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
    
  5. 驗證是否拒絕對 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
    
  6. 驗證是否允許對 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
此資訊是否有用?
您有任何改進建議嗎?

感謝您的回饋!