双向 TLS 迁移

本任务演示如何确保您的工作负载在迁移到 Istio 时仅使用双向 TLS 进行通信。

Istio 会自动配置工作负载 sidecar 以使用 双向 TLS 来调用其他工作负载。默认情况下,Istio 使用 PERMISSIVE 模式配置目标工作负载。当启用 PERMISSIVE 模式时,服务可以接受明文和双向 TLS 流量。为了只允许双向 TLS 流量,需要将配置更改为 STRICT 模式。

您可以使用 Grafana 仪表盘 检查哪些工作负载仍在向 PERMISSIVE 模式下的工作负载发送明文流量,并在迁移完成后选择锁定它们。

开始之前

在此任务中,您可以通过创建示例工作负载并修改策略以在工作负载之间强制执行严格的双向 TLS 来尝试迁移过程。

设置集群

  • 创建两个命名空间 foobar,并在两者上部署 httpbincurl,以及它们的 sidecar。

    ZipZipZipZip
    $ kubectl create ns foo
    $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n foo
    $ kubectl apply -f <(istioctl kube-inject -f @samples/curl/curl.yaml@) -n foo
    $ kubectl create ns bar
    $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n bar
    $ kubectl apply -f <(istioctl kube-inject -f @samples/curl/curl.yaml@) -n bar
    
  • 创建另一个命名空间 legacy,并在其中部署 curl,但没有 sidecar。

    Zip
    $ kubectl create ns legacy
    $ kubectl apply -f @samples/curl/curl.yaml@ -n legacy
    
  • 通过从 foobarlegacy 命名空间中的 curl pod(使用 curl)向 httpbin.foohttpbin.bar 发送 http 请求来验证设置。所有请求都应成功,返回码为 200。

    $ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=curl -n ${from} -o jsonpath={.items..metadata.name})" -c curl -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "curl.${from} to httpbin.${to}: %{http_code}\n"; done; done
    curl.foo to httpbin.foo: 200
    curl.foo to httpbin.bar: 200
    curl.bar to httpbin.foo: 200
    curl.bar to httpbin.bar: 200
    curl.legacy to httpbin.foo: 200
    curl.legacy to httpbin.bar: 200
    

按命名空间锁定到双向 TLS

在将所有客户端迁移到 Istio 并注入 Envoy sidecar 后,您可以将 foo 命名空间中的工作负载锁定为仅接受双向 TLS 流量。

$ kubectl apply -n foo -f - <<EOF
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
spec:
  mtls:
    mode: STRICT
EOF

现在,您应该看到来自 curl.legacyhttpbin.foo 的请求失败。

$ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=curl -n ${from} -o jsonpath={.items..metadata.name})" -c curl -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "curl.${from} to httpbin.${to}: %{http_code}\n"; done; done
curl.foo to httpbin.foo: 200
curl.foo to httpbin.bar: 200
curl.bar to httpbin.foo: 200
curl.bar to httpbin.bar: 200
curl.legacy to httpbin.foo: 000
command terminated with exit code 56
curl.legacy to httpbin.bar: 200

如果您使用 values.global.proxy.privileged=true 安装了 Istio,则可以使用 tcpdump 来验证流量是否已加密。

$ kubectl exec -nfoo "$(kubectl get pod -nfoo -lapp=httpbin -ojsonpath={.items..metadata.name})" -c istio-proxy -- sudo tcpdump dst port 80  -A
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

当分别从 curl.legacycurl.foo 发送请求时,您将在输出中看到明文和密文。

如果您无法将所有服务迁移到 Istio(即,无法在所有服务中注入 Envoy sidecar),则需要继续使用 PERMISSIVE 模式。但是,当使用 PERMISSIVE 模式配置时,默认情况下不会对明文流量执行身份验证或授权检查。我们建议您使用 Istio 授权 为不同的路径配置不同的授权策略。

为整个网格锁定双向 TLS

您可以通过将策略放在 Istio 安装的系统命名空间中,将所有命名空间中的工作负载锁定为仅接受双向 TLS 流量。

$ kubectl apply -n istio-system -f - <<EOF
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
spec:
  mtls:
    mode: STRICT
EOF

现在,foobar 命名空间都只强制执行双向 TLS 流量,因此您应该看到来自 curl.legacy 的请求对两者都失败。

$ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=curl -n ${from} -o jsonpath={.items..metadata.name})" -c curl -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "curl.${from} to httpbin.${to}: %{http_code}\n"; done; done

清理示例

  1. 删除网格范围的身份验证策略。

    $ kubectl delete peerauthentication -n foo default
    $ kubectl delete peerauthentication -n istio-system default
    
  2. 删除测试命名空间。

    $ kubectl delete ns foo bar legacy
    Namespaces foo bar legacy deleted.
    
这些信息对您有帮助吗?
您有任何改进建议吗?

感谢您的反馈!