信任域迁移

该任务阐述了如何在不更改授权策略的前提下从一个信任域迁移到另一个。

在 Istio 1.4 中,我们引入了一个 Alpha 特性以支持授权策略 trust domain migration。 这意味着如果一个 Istio 网格需要改变它的 trust domain, 其授权策略是不需要手动更新的。在 Istio 中,如果一个 workload 运行在命名空间 foo 中,服务账户为 bar,系统的信任域为 my-td,那么该工作负载的身份就是 spiffe://my-td/ns/foo/sa/bar。默认情况下,Istio 网格的信任域是 cluster.local, 除非您在安装时另外指定了。

开始之前

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

  1. 阅读授权指南。

  2. 安装 Istio,自定义信任域,并启用双向 TLS。

    1. $ istioctl install --set profile=demo --set meshConfig.trustDomain=old-td
  3. httpbin 示例部署于 default 命名空间中, 将 curl 示例部署于 defaultcurl-allow 命名空间中:

    ZipZipZip

    1. $ kubectl label namespace default istio-injection=enabled
    2. $ kubectl apply -f @samples/httpbin/httpbin.yaml@
    3. $ kubectl apply -f @samples/curl/curl.yaml@
    4. $ kubectl create namespace curl-allow
    5. $ kubectl label namespace curl-allow istio-injection=enabled
    6. $ kubectl apply -f @samples/curl/curl.yaml@ -n curl-allow
  4. 应用如下授权策略以拒绝所有到 httpbin 的请求,除了来自 curl-allow 命名空间的 curl 服务。

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: security.istio.io/v1
    3. kind: AuthorizationPolicy
    4. metadata:
    5. name: service-httpbin.default.svc.cluster.local
    6. namespace: default
    7. spec:
    8. rules:
    9. - from:
    10. - source:
    11. principals:
    12. - old-td/ns/curl-allow/sa/curl
    13. to:
    14. - operation:
    15. methods:
    16. - GET
    17. selector:
    18. matchLabels:
    19. app: httpbin
    20. ---
    21. EOF

    请注意授权策略传播到这些 Sidecar 大约需要几十秒。

  5. 验证从以下请求源发送至 httpbin 的请求:

    • 来自 default 命名空间的 curl 服务的请求被拒绝。

      1. $ kubectl exec "$(kubectl get pod -l app=curl -o jsonpath={.items..metadata.name})" -c curl -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n"
      2. 403
    • 来自 curl-allow 命名空间的 curl 服务的请求通过了。

      1. $ kubectl exec "$(kubectl -n curl-allow get pod -l app=curl -o jsonpath={.items..metadata.name})" -c curl -n curl-allow -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n"
      2. 200

迁移信任域但不使用别名

  1. 使用一个新的信任域安装 Istio。

    1. $ istioctl install --set profile=demo --set meshConfig.trustDomain=new-td
  2. 重新部署 istiod 以使信任域发生更改。

    1. $ kubectl rollout restart deployment -n istio-system istiod

    Istio 网格现在运行于一个新的信任域 new-td 了。

  3. 重新部署 httpbincurl 应用以从新的 Istio 控制平面获取更新。

    1. $ kubectl delete pod --all
    1. $ kubectl delete pod --all -n curl-allow
  4. 验证来自 defaultcurl-allow 命名空间的 curlhttpbin 的访问都被拒绝。

    1. $ kubectl exec "$(kubectl get pod -l app=curl -o jsonpath={.items..metadata.name})" -c curl -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n"
    2. 403
    1. $ kubectl exec "$(kubectl -n curl-allow get pod -l app=curl -o jsonpath={.items..metadata.name})" -c curl -n curl-allow -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n"
    2. 403

    这是因为我们指定了一个授权策略,它会拒绝所有到 httpbin 的请求,除非请求来源的身份是 old-td/ns/curl-allow/sa/curl,而这个身份是 curl-allow 命名空间的 curl 的旧身份。 当我们迁移到一个新的信任域,即 new-tdcurl 应用的身份就变成 new-td/ns/curl-allow/sa/curl, 与 old-td/ns/curl-allow/sa/curl 不同。因此,curl-allow 命名空间中的 curl 应用之前的请求被放行,但现在被拒绝。在 Istio 1.4 之前,修复该问题的唯一方式就是手动调整授权策略。 而在 Istio 1.4 中,我们引入了一种更简单的方法,如下所示。

使用别名迁移信任域

  1. 使用一个新的信任域和信任域别名安装 Istio。

    1. $ cat <<EOF > ./td-installation.yaml
    2. apiVersion: install.istio.io/v1alpha2
    3. kind: IstioControlPlane
    4. spec:
    5. meshConfig:
    6. trustDomain: new-td
    7. trustDomainAliases:
    8. - old-td
    9. EOF
    10. $ istioctl install --set profile=demo -f td-installation.yaml -y
  2. 不调整授权策略,验证到 httpbin 的请求:

    • 来自 default 命名空间的 curl 的请求被拒绝。

      1. $ kubectl exec "$(kubectl get pod -l app=curl -o jsonpath={.items..metadata.name})" -c curl -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n"
      2. 403
    • 来自 curl-allow 命名空间的 curl 通过了。

      1. $ kubectl exec "$(kubectl -n curl-allow get pod -l app=curl -o jsonpath={.items..metadata.name})" -c curl -n curl-allow -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n"
      2. 200

最佳实践

从 Istio 1.4 起,在编辑授权策略时,您应该在策略中的信任域部分使用 cluster.local。 例如,应该是 cluster.local/ns/curl-allow/sa/curl,而不是 old-td/ns/curl-allow/sa/curl。 请注意,在这种情况下,cluster.local 并不是 Istio 网格的信任域(信任域依然是 old-td)。 在策略中,cluster.local 是一个指针,指向当前信任域,即 old-td(后来是 new-td)及其别名。 通过在授权策略中使用 cluster.local,当您迁移到新的信任域时,Istio 将检测到此情况, 并将新的信任域视为旧的信任域,而无需包含别名。

清理

  1. $ kubectl delete authorizationpolicy service-httpbin.default.svc.cluster.local
  2. $ kubectl delete deploy httpbin; kubectl delete service httpbin; kubectl delete serviceaccount httpbin
  3. $ kubectl delete deploy curl; kubectl delete service curl; kubectl delete serviceaccount curl
  4. $ istioctl uninstall --purge -y
  5. $ kubectl delete namespace curl-allow istio-system
  6. $ rm ./td-installation.yaml