TCP 流量

本任务演示如何在 Istio 网格中为 TCP 流量设置 Istio 授权策略。

开始之前

在开始此任务之前,请执行以下操作

  • 阅读Istio 授权概念

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

  • 在命名空间(例如 foo)中部署两个名为 curltcp-echo 的工作负载。这两个工作负载都在其前面运行一个 Envoy 代理。tcp-echo 工作负载侦听端口 9000、9001 和 9002,并以 hello 前缀回显接收到的任何流量。例如,如果您向 tcp-echo 发送“world”,它将回复 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/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 授权策略

  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. 使用以下命令更新策略以添加名为 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
    
  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 的请求是否被拒绝。发生这种情况是因为请求与上述拒绝策略中的 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
这些信息是否有用?
您是否有任何改进建议?

感谢您的反馈!