通过 Istioctl Describe 理解您的网格

在 Istio 1.3 中,我们新增了 istioctl experimental describe 命令。 一些配置可以影响 pod,要理解这些配置,您可以利用这个命令行工具得到一些必要的信息。 这份指南向您展示如何使用这个实验性质的命令来查看一个 pod 是否在网格中并验证它的配置。

该命令的基本用法如下:

$ istioctl experimental describe <pod-name>[.<namespace>]

向 pod 名字后面加上一个命名空间与使用 istioctl-n 参数来指定一个非默认的命名空间效果一样。

该指南假定您已经在您的网格中部署了 Bookinfo 示例。 如果您还没部署,先参考启动应用服务确定 ingress 的 IP 和端口

验证 pod 是否在网格中

如果 pod 里没有 Envoy 代理或者代理没启动,istioctl describe 命令会返回一个警告。 另外,如果 pods 的 Istio 需求未完全满足,该命令也会警告。

例如,下面的命令发出的警告表示一个 kube-dns pod 不被包含在服务网格内,因为它没有 sidecar:

$ export KUBE_POD=$(kubectl -n kube-system get pod -l k8s-app=kube-dns -o jsonpath='{.items[0].metadata.name}')
$ istioctl x describe pod -n kube-system $KUBE_POD
Pod: coredns-f9fd979d6-2zsxk
   Pod Ports: 53/UDP (coredns), 53 (coredns), 9153 (coredns)
WARNING: coredns-f9fd979d6-2zsxk is not part of mesh; no Istio sidecar
--------------------
2021-01-22T16:10:14.080091Z     error   klog    an error occurred forwarding 42785 -> 15000: error forwarding port 15000 to pod 692362a4fe313005439a873a1019a62f52ecd02c3de9a0957cd0af8f947866e5, uid : failed to execute portforward in network namespace "/var/run/netns/cni-3c000d0a-fb1c-d9df-8af8-1403e6803c22": failed to dial 15000: dial tcp4 127.0.0.1:15000: connect: connection refused[]
Error: failed to execute command on sidecar: failure running port forward process: Get "http://localhost:42785/config_dump": EOF

但对于服务网格内的 pod,如 Bookinfo 的 ratings 服务,该命令就不会报警,而是输出该 pod 的 Istio 配置:

$ export RATINGS_POD=$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')
$ istioctl experimental describe pod $RATINGS_POD
Pod: ratings-v1-7dc98c7588-8jsbw
   Pod Ports: 9080 (ratings), 15090 (istio-proxy)
--------------------
Service: ratings
   Port: http 9080/HTTP targets pod port 9080

该输出展示了下列信息:

  • Pod 内的服务容器的端口,如本例中的 ratings 容器的 9080
  • Pod 内的 istio-proxy 容器的端口,如本例中的 15090
  • Pod 内的服务所用的协议,如本例中的端口 9080 上的 HTTP

验证 destination rule 配置

您可以使用 istioctl describe 查看哪些 destination rule 规则被用来将请求路由到 pod。例如,应用 Bookinfo 双向 TLS destination rule 规则

Zip
$ kubectl apply -f @samples/bookinfo/networking/destination-rule-all-mtls.yaml@

现在再来 describe 一次 ratings 的 pod:

$ istioctl x describe pod $RATINGS_POD
Pod: ratings-v1-f745cf57b-qrxl2
   Pod Ports: 9080 (ratings), 15090 (istio-proxy)
--------------------
Service: ratings
   Port: http 9080/HTTP
DestinationRule: ratings for "ratings"
   Matching subsets: v1
      (Non-matching subsets v2,v2-mysql,v2-mysql-vm)
   Traffic Policy TLS Mode: ISTIO_MUTUAL

该命令现在显示了更多的输出:

  • 用于路由到 ratings 服务的请求的 destination rule。
  • 匹配该 pod 的 ratings destination rule 的子集,本例中为 v1
  • 该 destination rule 所定义的其它子集。
  • 该 pod 同时接受 HTTP 和 双向 TLS 请求,客户端使用 双向 TLS。

验证 virtual service 规则

virtual services 配置路由到一个 pod 时,istioctl describe 也会在它的输出中包含这些路由。 例如,应用 Bookinfo virtual services 这个将所有请求都路由到 v1 pods 的规则:

Zip
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@

然后,describe 一个实现了 reviews 服务的 v1 版本的 pod:

$ export REVIEWS_V1_POD=$(kubectl get pod -l app=reviews,version=v1 -o jsonpath='{.items[0].metadata.name}')
$ istioctl x describe pod $REVIEWS_V1_POD
...
VirtualService: reviews
   1 HTTP route(s)

该输出包括了与上面展示的 ratings pod 类似的信息,同时还有 virtual service 的到该 pod 的路由。

istioctl describe 命令不仅仅展示影响该 pod 的 virtual service。 如果一条 virtual service 配置了 pod 的服务主机但却没有流量到达它,该命令将会输出一个警告。 这种情况可能会发生在 virtual service 实际上已经不再将流量路由到该 pod 的子集而拦截了流量时。例如:

$ export REVIEWS_V2_POD=$(kubectl get pod -l app=reviews,version=v2 -o jsonpath='{.items[0].metadata.name}')
$ istioctl x describe pod $REVIEWS_V2_POD
...
VirtualService: reviews
   WARNING: No destinations match pod subsets (checked 1 HTTP routes)
      Route to non-matching subset v1 for (everything)

该警告包含了这个问题的原因,检查了多少个路由,甚至还会告诉您其它路由的信息。 在本例中,没有流量会到达 v2 的 pod,因为 virtual service 中的路由将所有流量都路由到 v1 子集。

如果您选择删除掉 Bookinfo destination rules:

Zip
$ kubectl delete -f @samples/bookinfo/networking/destination-rule-all-mtls.yaml@

您可以看到 istioctl describe 的另外一个有用的功能:

$ istioctl x describe pod $REVIEWS_V1_POD
...
VirtualService: reviews
   WARNING: No destinations match pod subsets (checked 1 HTTP routes)
      Warning: Route to subset v1 but NO DESTINATION RULE defining subsets!

该输出说明您删除了 destination rule,但是依赖它的 virtual service 还在。 Virtual service 想将流量路由到 v1 子集,但是没有 destination rule 来定义 v1 子集。 因此,要去 v1 的流量就无法流向该 pod。

如果您现在刷新浏览器来向 Bookinfo 发送一个新的请求,您将会看到这条消息:Error fetching product reviews。 要修复这个问题,请重新应用 destination rule:

Zip
$ kubectl apply -f @samples/bookinfo/networking/destination-rule-all-mtls.yaml@

重新刷新浏览器,可以看到应用恢复工作了,运行 istioctl experimental describe pod $REVIEWS_V1_POD 也不再报出警告了。

验证流量路由

istioctl describe 命令还可以展示流量的分隔权重。 例如,运行如下命令将 90% 的流量路由到 revis 服务的 v1 子集,将 10% 路由到 v2 子集:

Zip
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-90-10.yaml@

现在来 describe reviews v1 pod:

$ istioctl x describe pod $REVIEWS_V1_POD
...
VirtualService: reviews
   Weight 90%

该输出显示了 reviews virtual service 在 v1 子集上有 90% 的权重。

该功能对于别的类型的路由也很有用。例如,您可以部署指定请求头的路由:

Zip
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-jason-v2-v3.yaml@

然后,再次 describe 该 pod:

$ istioctl x describe pod $REVIEWS_V1_POD
...
VirtualService: reviews
   WARNING: No destinations match pod subsets (checked 2 HTTP routes)
      Route to non-matching subset v2 for (when headers are end-user=jason)
      Route to non-matching subset v3 for (everything)

该输出显示了一个警告,因为该 pod 在 v1 子集。 但是,如果请求头包含 end-user=jason,该 virtual service 配置将会把流量路由到 v2 子集,其余情况下都路由到 v3 子集。

验证严格双向 TLS

按照双向 TLS 迁移的说明,您可以为 ratings 服务启用严格双向 TLS:

$ kubectl apply -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "ratings-strict"
spec:
  selector:
    matchLabels:
      app: ratings
  mtls:
    mode: STRICT
EOF

运行下列命令来 describe ratings 的 pod:

$ istioctl x describe pod $RATINGS_POD
Pilot reports that pod enforces mTLS and clients speak mTLS

该输出说明到 ratings pod 的请求已被锁定并且是安全的。

尽管如此,一个部署在切换双向 TLS 到 STRICT 模式时有时还是会中断。 这可能是因为 destination rule 与新配置不匹配。 例如,如果您配置 Bookinfo 的客户端不用双向 TLS 而是用普通 HTTP destination rules

Zip
$ kubectl apply -f @samples/bookinfo/networking/destination-rule-all.yaml@

如果您在浏览器中打开 Bookinfo,您会看到 Ratings service is currently unavailable。 想知道原因,请运行以下命令:

$ istioctl x describe pod $RATINGS_POD
...
WARNING Pilot predicts TLS Conflict on ratings-v1-f745cf57b-qrxl2 port 9080 (pod enforces mTLS, clients speak HTTP)
  Check DestinationRule ratings/default and AuthenticationPolicy ratings-strict/default

该输出包含了一个警告,描述了 destination rule 和认证策略之间的冲突。

您可以通过应用一个使用双向 TLS 的 destination rule 来修复问题:

Zip
$ kubectl apply -f @samples/bookinfo/networking/destination-rule-all-mtls.yaml@

结论和清理

我们对于 istioctl x describe 命令的目标是帮助您理解您的 Istio 网格中的流量和安全配置。

我们也希望能听到您的改善意见! 请在 https://discuss.istio.io 参与讨论。

运行以下命令以删除 Bookinfo 的 pods 和本指南中用到的配置:

ZipZipZipZip
$ kubectl delete -f @samples/bookinfo/platform/kube/bookinfo.yaml@
$ kubectl delete -f @samples/bookinfo/networking/bookinfo-gateway.yaml@
$ kubectl delete -f @samples/bookinfo/networking/destination-rule-all-mtls.yaml@
$ kubectl delete -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@
这些信息有用吗?
Do you have any suggestions for improvement?

Thanks for your feedback!