TCP 流量
本任务演示如何在 Istio 网格中为 TCP 流量设置 Istio 授权策略。
开始之前
在开始此任务之前,请执行以下操作
阅读Istio 授权概念。
使用Istio 安装指南安装 Istio。
在命名空间(例如
foo
)中部署两个名为curl
和tcp-echo
的工作负载。这两个工作负载都在其前面运行一个 Envoy 代理。tcp-echo
工作负载侦听端口 9000、9001 和 9002,并以hello
前缀回显接收到的任何流量。例如,如果您向tcp-echo
发送“world”,它将回复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
通信。您需要将流量直接发送到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
使用以下命令更新策略以添加名为
methods
的仅 HTTP 字段以用于端口 9000$ 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 的请求是否被拒绝。发生这种情况是因为请求与上述拒绝策略中的
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