TCP 流量

该任务向您展示了在 Istio 网格中如何为 TCP 流量设置 Istio 授权策略。

开始之前

在您开始之前,请先完成以下内容:

  • 阅读Istio 授权概念

  • 按照 Istio 安装指南安装 Istio。

  • 在命名空间例如 foo 中部署两个工作负载,sleeptcp-echo。 这两个工作负载每个前面都会运行一个 Envoy 代理。 tcp-echo 工作负载会监听端口 9000、9001 和 9002,并以前缀 hello 输出它收到的所有流量。 例如,如果你发送 “world” 给 tcp-echo,那么它将会回复 hello worldtcp-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/sleep/sleep.yaml@) -n foo
    
  • 使用以下命令确认 sleep 可以成功与 tcp-echo 的端口 9000 和 9001 交互:

    $ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -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=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
    hello port 9001
    connection succeeded
    
  • 确认 sleep 可以成功与 tcp-echo 的端口 9002 交互。 您需要将流量直接发送到 tcp-echo 的 pod IP,因为在 tcp-echo 的 Kubernetes 服务对象中未定义端口 9002。 使用以下命令获取 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=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -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 工作负载的访问控制

  1. foo 命名空间中为 tcp-echo 工作负载创建 tcp-policy 授权策略。 运行以下命令来应用策略以允许请求到端口 9000 和 9001:

    $ kubectl apply -f - <<EOF
    apiVersion: security.istio.io/v1beta1
    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=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -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=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -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=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -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-only 字段来更新策略:

    $ kubectl apply -f - <<EOF
    apiVersion: security.istio.io/v1beta1
    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-only 字段(methods),这会导致规则无效。Istio 会忽略无效的 ALLOW 规则。 最终结果是该请求被拒绝,因为它与任何 ALLOW 规则都不匹配。 运行以下命令并验证输出:

    $ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -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=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
    connection rejected
    
  8. 使用以下命令将策略更新为 DENY 策略:

    $ kubectl apply -f - <<EOF
    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: tcp-policy
      namespace: foo
    spec:
      selector:
        matchLabels:
          app: tcp-echo
      action: DENY
      rules:
      - to:
        - operation:
            methods: ["GET"]
            ports: ["9000"]
    EOF
    
  9. 验证对端口 9000 的请求是否被拒绝。发生这种情况是因为 Istio 忽略了无效的 DENY 规则中的 HTTP-only 字段。这与无效的 ALLOW 规则不同,ALLOW 规则会导致 Istio 忽略整个规则。这里最终的结果是 Istio 仅使用 ports 字段来判断,请求会被拒绝正是因为它们与 ports 匹配:

    $ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
    connection rejected
    
  10. 验证是否允许对端口 9001 的请求。发生这种情况是因为请求与 DENY 策略中的 ports 不匹配:

    $ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
    hello port 9001
    connection succeeded
    

清理

  1. 删除命名空间 foo:

    $ kubectl delete namespace foo
    
这些信息有用吗?
Do you have any suggestions for improvement?

Thanks for your feedback!