TCP トラフィック

このタスクでは、Istio メッシュ内で TCP トラフィックに対する Istio 認可ポリシーを設定する方法を示します。

始める前に

このタスクを開始する前に、次の手順を実行してください。

  • Istio の認可の概念 を読んでください。

  • Istio インストールガイドを使用して Istio をインストールしてください。

  • 例えば `foo` といった名前空間内に、curltcp-echo という2つのワークロードを一緒にデプロイします。両方のワークロードは、それぞれEnvoyプロキシをフロントエンドとして実行します。tcp-echo ワークロードはポート9000、9001、9002でリスンし、受信したトラフィックに接頭辞 `hello` を付けて返します。例えば、「world」をtcp-echo に送信すると、hello world が返されます。tcp-echo のKubernetesサービスオブジェクトは、ポート9000と9001のみを宣言し、ポート9002は省略されます。ポート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 がポート9000と9001でtcp-echo と正常に通信することを確認してください。

    $ 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 がポート9002でtcp-echo と正常に通信することを確認してください。ポート9002はtcp-echo のKubernetesサービスオブジェクトで定義されていないため、tcp-echo のPod IPアドレスに直接トラフィックを送信する必要があります。以下のコマンドを使用して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
この情報は役に立ちましたか?
改善のための提案はありますか?

ご意見ありがとうございます!