1. 准备工作

将两个名为sleep和tcp-echo的工作负载一起部署到一个名称空间中,例如foo。这两个工作负载都在前面有一个enovy代理。tcp-echo工作负载在端口9000、9001和9002上进行侦听,并回送它收到的带有前缀hello的任何通信量。例如,如果您将“world”发送到tcp-echo,它将回复hello world。tcp-echo Kubernetes服务对象只声明了端口9000和9001,而忽略了端口9002。一个直通过滤器链将处理端口9002流量。使用以下命令部署示例名称空间和工作负载:

  1. $ kubectl create ns foo
  2. $ kubectl apply -f <(istioctl kube-inject -f samples/tcp-echo/tcp-echo.yaml) -n foo
  3. $ kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo
  • 校验sleep成功和tcp-echo端口的9000,9001成功通信,使用如下命令
  1. $ 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'
  1. $ 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'
  • 校验sleep成功和tcp-echo端口的9002通信。
  1. 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}")
  2. 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'

2. 配置针对TCP工作流的访问控制

  1. 在foo名称空间中为tcp-echo工作负载创建tcp-policy授权策略。运行以下命令应用策略,以允许请求到端口9000和9001:
  1. $ kubectl apply -f - <<EOF
  2. apiVersion: security.istio.io/v1beta1
  3. kind: AuthorizationPolicy
  4. metadata:
  5. name: tcp-policy
  6. namespace: foo
  7. spec:
  8. selector:
  9. matchLabels:
  10. app: tcp-echo
  11. action: ALLOW
  12. rules:
  13. - to:
  14. - operation:
  15. ports: ["9000", "9001"]
  16. EOF
  1. 校验请求9000的端口是允许的
  1. $ 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'
  1. 校验请求的9001端口是允许的
  1. $ 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'
  1. 校验到9002端口的请求是拒绝的。 这是由授权策略实施的,该策略也适用于pass - through过滤器链,即使端口没有在tcp-echo Kubernetes服务对象中显式声明。运行以下命令并验证输出:
  1. $ 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'
  1. 更新添加的策略,去添加一个HTTP-only字段,命名为methods,端口号为9000.
  1. $ kubectl apply -f - <<EOF
  2. apiVersion: security.istio.io/v1beta1
  3. kind: AuthorizationPolicy
  4. metadata:
  5. name: tcp-policy
  6. namespace: foo
  7. spec:
  8. selector:
  9. matchLabels:
  10. app: tcp-echo
  11. action: ALLOW
  12. rules:
  13. - to:
  14. - operation:
  15. methods: ["GET"]
  16. ports: ["9000"]
  17. EOF
  1. 验证对端口9000的请求被拒绝。发生这种情况是因为当规则为TCP通信使用一个只支持http的字段(方法)时,该规则变得无效。Istio忽略无效的允许规则。最后的结果是请求被拒绝,因为它不匹配任何允许规则。运行以下命令并验证输出
  1. $ 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'
  1. 校验请求到9001端口为拒绝。 这是因为请求不匹配任何允许规则。运行以下命令并验证输出:
  1. $ 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'
  1. 使用如下命令更新策略为DENY
  1. $ kubectl apply -f - <<EOF
  2. apiVersion: security.istio.io/v1beta1
  3. kind: AuthorizationPolicy
  4. metadata:
  5. name: tcp-policy
  6. namespace: foo
  7. spec:
  8. selector:
  9. matchLabels:
  10. app: tcp-echo
  11. action: DENY
  12. rules:
  13. - to:
  14. - operation:
  15. methods: ["GET"]
  16. ports: ["9000"]
  17. EOF
  1. 验证对端口9000的请求被拒绝。出现这种情况是因为Istio在一个无效的DENY规则中忽略了只支持http的字段。这与无效的ALLOW规则不同,后者会导致Istio忽略整个规则。最后的结果是只有ports字段被Istio使用,请求被拒绝,因为它们与端口匹配:
  1. $ 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'
  1. 校验请求到9001端口是允许的,在拒绝策略中因为请求不匹配
  1. 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'

3. 清除本小节实验

  1. $ kubectl delete namespace foo