TCP トラフィック
このタスクでは、Istio メッシュ内で TCP トラフィックに対する Istio 認可ポリシーを設定する方法を示します。
始める前に
このタスクを開始する前に、次の手順を実行してください。
Istio の認可の概念 を読んでください。
Istio インストールガイドを使用して Istio をインストールしてください。
例えば `foo` といった名前空間内に、
curl
とtcp-echo
という2つのワークロードを一緒にデプロイします。両方のワークロードは、それぞれEnvoyプロキシをフロントエンドとして実行します。tcp-echo
ワークロードはポート9000、9001、9002でリスンし、受信したトラフィックに接頭辞 `hello` を付けて返します。例えば、「world」をtcp-echo
に送信すると、hello world
が返されます。tcp-echo
のKubernetesサービスオブジェクトは、ポート9000と9001のみを宣言し、ポート9002は省略されます。ポート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
がポート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 認可ポリシーの設定
`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