一、Envoy 基础

为了排除 Istio 的问题,对 Envoy 的工作原理有一个基本的了解是很有帮助的。Envoy 配置是一个 JSON 文件,分为多个部分。我们需要了解 Envoy 的基本概念是监听器、路由、集群和端点。

这些概念映射到 Istio 和 Kubernetes 资源,Envoy 概念与 Istio 和 Kubernetes 的映射如下图所示:

Day10-服务治理-图45

Listeners: 监听器是命名的网络位置,通常是一个 IP 和端口。Envoy 对这些位置进行监听,这是它接收连接和请求的地方。

每个 sidecar 都有一个监听器,它被绑定到 0. 0. 0. 0: 15006 。

这是 IP Tables 将所有入站流量发送到 Pod 的地址。第二个监听器被绑定到0.0.0.0:15001 ,这是所有从 Pod 中出站的流量地址

当一个请求被重定向(使用 IP Tables 配置)到 15001 端口时,监听器会把它交给与请 求的原始目的地最匹配的虚拟监听器。如果它找不到目的地,它就根据配置的OutboundTrafficPolicy 来发送流量。默认情况下,请求被发送到 PassthroughCluster,该集群连接到应用程序选择的目的地, Envoy 没有进行任何负载均衡。

Routers(路由图):Router是Envoy用于决定请求流量的下一步去向的组件

Cluster(集群):Cluster是Envoy用于标识后端服务实例组的组件,它定义了一组具有相同服务的终端节点

Endpoint(终端节点):Endpoint是Cluster的实际服务实例,也就是真正的后端服务.Envoy使用Endpoint发送请求并获取响应

二、Envoy示例

proxy-config 命令可以查看一个Envoy实例的配置,用于定位无法通过查看istio配置和用户资源发现的问题。 例如,使用如下命令可以获取特定pod的clusters,listeners或routes概要。

注:首先通过istioctl ps查看出不匹配的代理,然后使用istioctl pc查看具体的不匹配的信息。

需求:Envoy 如何确定将请求从 Web 前端发送到 customers 服务( customers.default.svc.cluster.local)的位置?

准备

[root@master01 istioyaml]# vim web-frontend.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-frontend
  labels:
    app: web-frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web-frontend
  template:
    metadata:
      labels:
        app: web-frontend
        version: v1
    spec:
      containers:
        - image: registry.cn-hangzhou.aliyuncs.com/github_images1024/web-frontend:1.0.0
          imagePullPolicy: Always
          name: web
          ports:
            - containerPort: 8080
          env:
            - name: CUSTOMER_SERVICE_URL
              value: 'http://customers.default.svc.cluster.local'
---
kind: Service
apiVersion: v1
metadata:
  name: web-frontend
  labels:
    app: web-frontend
spec:
  selector:
    app: web-frontend
  ports:
    - port: 80
      name: http
      targetPort: 8080

# 应用
[root@master01 istioyaml]# kaf web-frontend.yaml 

# 验证
[root@master01 istioyaml]# kgp | grep web
web-frontend-755bf5c8d8-56krh              2/2     Running   0               86s

使用 istioctl proxy-config 命令,我们可以列出 web 前端 pod 的所有监听器。

[root@master01 istioyaml]# istioctl proxy-config listeners web-frontend-755bf5c8d8-56krh

ADDRESSES       PORT  MATCH                                                                    DESTINATION
192.168.0.10    53    ALL                                                                      Cluster: outbound|53||kube-dns.kube-system.svc.cluster.local
0.0.0.0         80    Trans: raw_buffer; App: http/1.1,h2c                                     Route: 80
0.0.0.0         80    ALL                                                                      PassthroughCluster
192.168.12.200  80    Trans: raw_buffer; App: http/1.1,h2c                                     Route: ngx-hpa-svc.default.svc.cluster.local:80
192.168.12.200  80    ALL                                                                      Cluster: outbound|80||ngx-hpa-svc.default.svc.cluster.local
192.168.47.67   80    Trans: raw_buffer; App: http/1.1,h2c                                     Route: nginxsvc.microservice.svc.cluster.local:80
192.168.47.67   80    ALL                                                                      Cluster: outbound|80||nginxsvc.microservice.svc.cluster.local
192.168.89.68   80    Trans: raw_buffer; App: http/1.1,h2c                                     Route: skywalking-ui.devops.svc.cluster.local:80
192.168.89.68   80    ALL                                                                      Cluster: outbound|80||skywalking-ui.devops.svc.cluster.local
192.168.0.1     443   ALL                                                                      Cluster: outbound|443||kubernetes.default.svc.cluster.local
192.168.112.77  443   ALL                                                                      Cluster: outbound|443||ingress-nginx-controller.ingress-nginx.svc.cluster.local
192.168.139.213 443   ALL                                                                      Cluster: outbound|443||istio-egressgateway.istio-system.svc.cluster.local
192.168.149.121 443   ALL                                                                      Cluster: outbound|443||istio-ingressgateway.istio-system.svc.cluster.local
192.168.151.52  443   Trans: raw_buffer; App: http/1.1,h2c                                     Route: webhook-service.devops.svc.cluster.local:443
192.168.151.52  443   ALL                                                                      Cluster: outbound|443||webhook-service.devops.svc.cluster.local
192.168.154.52  443   ALL                                                                      Cluster: outbound|443||istiod.istio-system.svc.cluster.local
192.168.227.116 443   ALL                                                                      Cluster: outbound|443||metrics-server.kube-system.svc.cluster.local
192.168.230.88  443   Trans: raw_buffer; App: http/1.1,h2c                                     Route: kubernetes-dashboard.kubernetes-dashboard.svc.cluster.local:443
192.168.230.88  443   ALL                                                                      Cluster: outbound|443||kubernetes-dashboard.kubernetes-dashboard.svc.cluster.local
192.168.44.239  443   ALL                                                                      Cluster: outbound|443||ingress-nginx-controller-admission.ingress-nginx.svc.cluster.local
192.168.87.40   443   ALL                                                                      Cluster: outbound|443||prometheus-adapter.monitoring.svc.cluster.local
0.0.0.0         3000  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 3000
0.0.0.0         3000  ALL                                                                      PassthroughCluster
192.168.149.99  3000  Trans: raw_buffer; App: http/1.1,h2c                                     Route: grafana.istio-system.svc.cluster.local:3000
192.168.149.99  3000  ALL                                                                      Cluster: outbound|3000||grafana.istio-system.svc.cluster.local
192.168.199.228 3000  Trans: raw_buffer; App: http/1.1,h2c                                     Route: grafana.monitor.svc.cluster.local:3000
192.168.199.228 3000  ALL                                                                      Cluster: outbound|3000||grafana.monitor.svc.cluster.local
192.168.223.252 3306  ALL                                                                      Cluster: outbound|3306||svc-mysql.monitor.svc.cluster.local
10.0.0.60       4194  Trans: raw_buffer; App: http/1.1,h2c                                     Route: kubelet.kube-system.svc.cluster.local:4194
10.0.0.60       4194  ALL                                                                      Cluster: outbound|4194||kubelet.kube-system.svc.cluster.local
10.0.0.61       4194  Trans: raw_buffer; App: http/1.1,h2c                                     Route: kubelet.kube-system.svc.cluster.local:4194
10.0.0.61       4194  ALL                                                                      Cluster: outbound|4194||kubelet.kube-system.svc.cluster.local
10.0.0.62       4194  Trans: raw_buffer; App: http/1.1,h2c                                     Route: kubelet.kube-system.svc.cluster.local:4194
10.0.0.62       4194  ALL                                                                      Cluster: outbound|4194||kubelet.kube-system.svc.cluster.local
10.0.0.63       4194  Trans: raw_buffer; App: http/1.1,h2c                                     Route: kubelet.kube-system.svc.cluster.local:4194
10.0.0.63       4194  ALL                                                                      Cluster: outbound|4194||kubelet.kube-system.svc.cluster.local
10.0.0.64       4194  Trans: raw_buffer; App: http/1.1,h2c                                     Route: kubelet.kube-system.svc.cluster.local:4194
10.0.0.64       4194  ALL                                                                      Cluster: outbound|4194||kubelet.kube-system.svc.cluster.local
0.0.0.0         5000  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 5000
0.0.0.0         5000  ALL                                                                      PassthroughCluster
192.168.241.129 5473  Trans: raw_buffer; App: http/1.1,h2c                                     Route: calico-typha.kube-system.svc.cluster.local:5473
192.168.241.129 5473  ALL                                                                      Cluster: outbound|5473||calico-typha.kube-system.svc.cluster.local
192.168.90.90   8000  Trans: raw_buffer; App: http/1.1,h2c                                     Route: dashboard-metrics-scraper.kubernetes-dashboard.svc.cluster.local:8000
192.168.90.90   8000  ALL                                                                      Cluster: outbound|8000||dashboard-metrics-scraper.kubernetes-dashboard.svc.cluster.local
192.168.226.46  8060  Trans: raw_buffer; App: http/1.1,h2c                                     Route: webhook-dingtalk.monitor.svc.cluster.local:8060
192.168.226.46  8060  ALL                                                                      Cluster: outbound|8060||webhook-dingtalk.monitor.svc.cluster.local
0.0.0.0         8080  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 8080
0.0.0.0         8080  ALL                                                                      PassthroughCluster
192.168.211.80  8080  Trans: raw_buffer; App: http/1.1,h2c                                     Route: alertmanager-main.monitoring.svc.cluster.local:8080
192.168.211.80  8080  ALL                                                                      Cluster: outbound|8080||alertmanager-main.monitoring.svc.cluster.local
192.168.65.64   8080  Trans: raw_buffer; App: http/1.1,h2c                                     Route: springdemo2023.default.svc.cluster.local:8080
192.168.65.64   8080  ALL                                                                      Cluster: outbound|8080||springdemo2023.default.svc.cluster.local
192.168.94.50   8080  Trans: raw_buffer; App: http/1.1,h2c                                     Route: prometheus-k8s.monitoring.svc.cluster.local:8080
192.168.94.50   8080  ALL                                                                      Cluster: outbound|8080||prometheus-k8s.monitoring.svc.cluster.local
0.0.0.0         8081  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 8081
0.0.0.0         8081  ALL                                                                      PassthroughCluster
192.168.149.220 8081  Trans: raw_buffer; App: http/1.1,h2c                                     Route: kube-state-metrics.monitor.svc.cluster.local:8081
192.168.149.220 8081  ALL                                                                      Cluster: outbound|8081||kube-state-metrics.monitor.svc.cluster.local
0.0.0.0         8082  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 8082
0.0.0.0         8082  ALL                                                                      PassthroughCluster
0.0.0.0         8083  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 8083
0.0.0.0         8083  ALL                                                                      PassthroughCluster
0.0.0.0         8084  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 8084
0.0.0.0         8084  ALL                                                                      PassthroughCluster
0.0.0.0         8383  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 8383
0.0.0.0         8383  ALL                                                                      PassthroughCluster
172.18.71.14    8443  ALL                                                                      Cluster: outbound|8443||kube-state-metrics.monitoring.svc.cluster.local
172.18.71.60    8443  ALL                                                                      Cluster: outbound|8443||prometheus-operator.monitoring.svc.cluster.local
0.0.0.0         9090  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 9090
0.0.0.0         9090  ALL                                                                      PassthroughCluster
172.18.71.61    9090  Trans: raw_buffer; App: http/1.1,h2c                                     Route: prometheus-operated.monitoring.svc.cluster.local:9090
172.18.71.61    9090  ALL                                                                      Cluster: outbound|9090||prometheus-operated.monitoring.svc.cluster.local
172.20.59.228   9090  Trans: raw_buffer; App: http/1.1,h2c                                     Route: prometheus-operated.monitoring.svc.cluster.local:9090
172.20.59.228   9090  ALL                                                                      Cluster: outbound|9090||prometheus-operated.monitoring.svc.cluster.local
192.168.94.50   9090  Trans: raw_buffer; App: http/1.1,h2c                                     Route: prometheus-k8s.monitoring.svc.cluster.local:9090
192.168.94.50   9090  ALL                                                                      Cluster: outbound|9090||prometheus-k8s.monitoring.svc.cluster.local
0.0.0.0         9093  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 9093
0.0.0.0         9093  ALL                                                                      PassthroughCluster
172.18.71.20    9093  Trans: raw_buffer; App: http/1.1,h2c                                     Route: alertmanager-operated.monitoring.svc.cluster.local:9093
172.18.71.20    9093  ALL                                                                      Cluster: outbound|9093||alertmanager-operated.monitoring.svc.cluster.local
172.20.59.210   9093  Trans: raw_buffer; App: http/1.1,h2c                                     Route: alertmanager-operated.monitoring.svc.cluster.local:9093
172.20.59.210   9093  ALL                                                                      Cluster: outbound|9093||alertmanager-operated.monitoring.svc.cluster.local
172.29.55.52    9093  Trans: raw_buffer; App: http/1.1,h2c                                     Route: alertmanager-operated.monitoring.svc.cluster.local:9093
172.29.55.52    9093  ALL                                                                      Cluster: outbound|9093||alertmanager-operated.monitoring.svc.cluster.local
192.168.211.80  9093  Trans: raw_buffer; App: http/1.1,h2c                                     Route: alertmanager-main.monitoring.svc.cluster.local:9093
192.168.211.80  9093  ALL                                                                      Cluster: outbound|9093||alertmanager-main.monitoring.svc.cluster.local
172.18.71.20    9094  ALL                                                                      Cluster: outbound|9094||alertmanager-operated.monitoring.svc.cluster.local
172.20.59.210   9094  ALL                                                                      Cluster: outbound|9094||alertmanager-operated.monitoring.svc.cluster.local
172.29.55.52    9094  ALL                                                                      Cluster: outbound|9094||alertmanager-operated.monitoring.svc.cluster.local
10.0.0.60       9100  ALL                                                                      Cluster: outbound|9100||node-exporter.monitoring.svc.cluster.local
10.0.0.61       9100  ALL                                                                      Cluster: outbound|9100||node-exporter.monitoring.svc.cluster.local
10.0.0.62       9100  ALL                                                                      Cluster: outbound|9100||node-exporter.monitoring.svc.cluster.local
10.0.0.63       9100  ALL                                                                      Cluster: outbound|9100||node-exporter.monitoring.svc.cluster.local
10.0.0.64       9100  ALL                                                                      Cluster: outbound|9100||node-exporter.monitoring.svc.cluster.local
0.0.0.0         9115  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 9115
0.0.0.0         9115  ALL                                                                      PassthroughCluster
192.168.97.31   9115  ALL                                                                      Cluster: outbound|9115||blackbox-exporter.monitoring.svc.cluster.local
192.168.0.10    9153  Trans: raw_buffer; App: http/1.1,h2c                                     Route: kube-dns.kube-system.svc.cluster.local:9153
192.168.0.10    9153  ALL                                                                      Cluster: outbound|9153||kube-dns.kube-system.svc.cluster.local
172.31.112.191  9200  Trans: raw_buffer; App: http/1.1,h2c                                     Route: elasticsearch.devops.svc.cluster.local:9200
172.31.112.191  9200  ALL                                                                      Cluster: outbound|9200||elasticsearch.devops.svc.cluster.local
172.31.112.191  9300  Trans: raw_buffer; App: http/1.1,h2c                                     Route: elasticsearch.devops.svc.cluster.local:9300
172.31.112.191  9300  ALL                                                                      Cluster: outbound|9300||elasticsearch.devops.svc.cluster.local
0.0.0.0         9411  Trans: raw_buffer; App: http/1.1,h2c                                     Route: 9411
0.0.0.0         9411  ALL                                                                      PassthroughCluster
172.18.71.14    9443  ALL                                                                      Cluster: outbound|9443||kube-state-metrics.monitoring.svc.cluster.local
10.0.0.60       10250 ALL                                                                      Cluster: outbound|10250||kubelet.kube-system.svc.cluster.local
10.0.0.61       10250 ALL                                                                      Cluster: outbound|10250||kubelet.kube-system.svc.cluster.local
10.0.0.62       10250 ALL                                                                      Cluster: outbound|10250||kubelet.kube-system.svc.cluster.local
10.0.0.63       10250 ALL                                                                      Cluster: outbound|10250||kubelet.kube-system.svc.cluster.local
10.0.0.64       10250 ALL                                                                      Cluster: outbound|10250||kubelet.kube-system.svc.cluster.local
192.168.84.59   10254 Trans: raw_buffer; App: http/1.1,h2c                                     Route: ingress-nginx-controller-metrics.ingress-nginx.svc.cluster.local:10254
192.168.84.59   10254 ALL                                                                      Cluster: outbound|10254||ingress-nginx-controller-metrics.ingress-nginx.svc.cluster.local
0.0.0.0         10255 Trans: raw_buffer; App: http/1.1,h2c                                     Route: 10255
0.0.0.0         10255 ALL                                                                      PassthroughCluster
0.0.0.0         11800 Trans: raw_buffer; App: http/1.1,h2c                                     Route: 11800
0.0.0.0         11800 ALL                                                                      PassthroughCluster
192.168.106.196 12800 Trans: raw_buffer; App: http/1.1,h2c                                     Route: skywalking-oap.devops.svc.cluster.local:12800
192.168.106.196 12800 ALL                                                                      Cluster: outbound|12800||skywalking-oap.devops.svc.cluster.local
0.0.0.0         15001 ALL                                                                      PassthroughCluster
0.0.0.0         15001 Addr: *:15001                                                            Non-HTTP/Non-TCP
0.0.0.0         15006 Addr: *:15006                                                            Non-HTTP/Non-TCP
0.0.0.0         15006 Trans: tls; App: istio-http/1.0,istio-http/1.1,istio-h2; Addr: 0.0.0.0/0 InboundPassthroughClusterIpv4
0.0.0.0         15006 Trans: tls; Addr: 0.0.0.0/0                                              InboundPassthroughClusterIpv4
0.0.0.0         15006 Trans: tls; Addr: *:8080                                                 Cluster: inbound|8080||
0.0.0.0         15010 Trans: raw_buffer; App: http/1.1,h2c                                     Route: 15010
0.0.0.0         15010 ALL                                                                      PassthroughCluster
192.168.154.52  15012 ALL                                                                      Cluster: outbound|15012||istiod.istio-system.svc.cluster.local
192.168.233.160 15012 ALL                                                                      Cluster: outbound|15012||istio-eastwestgateway.istio-system.svc.cluster.local
0.0.0.0         15014 Trans: raw_buffer; App: http/1.1,h2c                                     Route: 15014
0.0.0.0         15014 ALL                                                                      PassthroughCluster
192.168.233.160 15017 ALL                                                                      Cluster: outbound|15017||istio-eastwestgateway.istio-system.svc.cluster.local
0.0.0.0         15021 ALL                                                                      Inline Route: /healthz/ready*
192.168.149.121 15021 Trans: raw_buffer; App: http/1.1,h2c                                     Route: istio-ingressgateway.istio-system.svc.cluster.local:15021
192.168.149.121 15021 ALL                                                                      Cluster: outbound|15021||istio-ingressgateway.istio-system.svc.cluster.local
192.168.233.160 15021 Trans: raw_buffer; App: http/1.1,h2c                                     Route: istio-eastwestgateway.istio-system.svc.cluster.local:15021
192.168.233.160 15021 ALL                                                                      Cluster: outbound|15021||istio-eastwestgateway.istio-system.svc.cluster.local
0.0.0.0         15090 ALL                                                                      Inline Route: /stats/prometheus*
192.168.149.121 15443 ALL                                                                      Cluster: outbound|15443||istio-ingressgateway.istio-system.svc.cluster.local
192.168.233.160 15443 ALL                                                                      Cluster: outbound|15443||istio-eastwestgateway.istio-system.svc.cluster.local
192.168.97.31   19115 Trans: raw_buffer; App: http/1.1,h2c                                     Route: blackbox-exporter.monitoring.svc.cluster.local:19115
192.168.97.31   19115 ALL                                                                      Cluster: outbound|19115||blackbox-exporter.monitoring.svc.cluster.local
0.0.0.0         20001 Trans: raw_buffer; App: http/1.1,h2c                                     Route: 20001
0.0.0.0         20001 ALL                                                                      PassthroughCluster
192.168.149.121 31400 ALL                                                                      Cluster: outbound|31400||istio-ingressgateway.istio-system.svc.cluster.local

从 Web 前端到 customers 的请求是一个向外的 HTTP 请求,端口为 80。这意味着它被移交给了 0.0.0.0:80的虚拟监听器。我们可以使用 Istio CLI 按地址和端口来过滤监听器。你可以添加 -o json 来获得监听器的 JSON 表示:

[root@master01 istioyaml]# istioctl proxy-config listeners web-frontend-755bf5c8d8-56krh --address 0.0.0.0 --port 80 -o json
...
{
    "rds": {
        "configSource": {
            "ads": {},
            "resourceApiVersion": "V3"
        },
        "routeConfigName": "80"
    }
}
...

# 完整回显
[root@master01 istioyaml]# istioctl proxy-config listeners web-frontend-755bf5c8d8-56krh --address 0.0.0.0 --port 80 -o json
[
    {
        "name": "0.0.0.0_80",
        "address": {
            "socketAddress": {
                "address": "0.0.0.0",
                "portValue": 80
            }
        },
        "filterChains": [
            {
                "filterChainMatch": {
                    "transportProtocol": "raw_buffer",
                    "applicationProtocols": [
                        "http/1.1",
                        "h2c"
                    ]
                },
                "filters": [
                    {
                        "name": "envoy.filters.network.http_connection_manager",
                        "typedConfig": {
                            "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
                            "statPrefix": "outbound_0.0.0.0_80",
                            "rds": {
                                "configSource": {
                                    "ads": {},
                                    "initialFetchTimeout": "0s",
                                    "resourceApiVersion": "V3"
                                },
                                "routeConfigName": "80"
                            },
                            "httpFilters": [
                                {
                                    "name": "istio.metadata_exchange",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
                                        "typeUrl": "type.googleapis.com/io.istio.http.peer_metadata.Config",
                                        "value": {
                                            "upstream_discovery": [
                                                {
                                                    "istio_headers": {}
                                                },
                                                {
                                                    "workload_discovery": {}
                                                }
                                            ],
                                            "upstream_propagation": [
                                                {
                                                    "istio_headers": {}
                                                }
                                            ]
                                        }
                                    }
                                },
                                {
                                    "name": "envoy.filters.http.grpc_stats",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig",
                                        "emitFilterState": true,
                                        "statsForAllMethods": false
                                    }
                                },
                                {
                                    "name": "istio.alpn",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/istio.envoy.config.filter.http.alpn.v2alpha1.FilterConfig",
                                        "alpnOverride": [
                                            {
                                                "alpnOverride": [
                                                    "istio-http/1.0",
                                                    "istio",
                                                    "http/1.0"
                                                ]
                                            },
                                            {
                                                "upstreamProtocol": "HTTP11",
                                                "alpnOverride": [
                                                    "istio-http/1.1",
                                                    "istio",
                                                    "http/1.1"
                                                ]
                                            },
                                            {
                                                "upstreamProtocol": "HTTP2",
                                                "alpnOverride": [
                                                    "istio-h2",
                                                    "istio",
                                                    "h2"
                                                ]
                                            }
                                        ]
                                    }
                                },
                                {
                                    "name": "envoy.filters.http.fault",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault"
                                    }
                                },
                                {
                                    "name": "envoy.filters.http.cors",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors"
                                    }
                                },
                                {
                                    "name": "istio.stats",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/stats.PluginConfig"
                                    }
                                },
                                {
                                    "name": "envoy.filters.http.router",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router"
                                    }
                                }
                            ],
                            "tracing": {
                                "clientSampling": {
                                    "value": 100
                                },
                                "randomSampling": {
                                    "value": 100
                                },
                                "overallSampling": {
                                    "value": 100
                                },
                                "customTags": [
                                    {
                                        "tag": "istio.authorization.dry_run.allow_policy.name",
                                        "metadata": {
                                            "kind": {
                                                "request": {}
                                            },
                                            "metadataKey": {
                                                "key": "envoy.filters.http.rbac",
                                                "path": [
                                                    {
                                                        "key": "istio_dry_run_allow_shadow_effective_policy_id"
                                                    }
                                                ]
                                            }
                                        }
                                    },
                                    {
                                        "tag": "istio.authorization.dry_run.allow_policy.result",
                                        "metadata": {
                                            "kind": {
                                                "request": {}
                                            },
                                            "metadataKey": {
                                                "key": "envoy.filters.http.rbac",
                                                "path": [
                                                    {
                                                        "key": "istio_dry_run_allow_shadow_engine_result"
                                                    }
                                                ]
                                            }
                                        }
                                    },
                                    {
                                        "tag": "istio.authorization.dry_run.deny_policy.name",
                                        "metadata": {
                                            "kind": {
                                                "request": {}
                                            },
                                            "metadataKey": {
                                                "key": "envoy.filters.http.rbac",
                                                "path": [
                                                    {
                                                        "key": "istio_dry_run_deny_shadow_effective_policy_id"
                                                    }
                                                ]
                                            }
                                        }
                                    },
                                    {
                                        "tag": "istio.authorization.dry_run.deny_policy.result",
                                        "metadata": {
                                            "kind": {
                                                "request": {}
                                            },
                                            "metadataKey": {
                                                "key": "envoy.filters.http.rbac",
                                                "path": [
                                                    {
                                                        "key": "istio_dry_run_deny_shadow_engine_result"
                                                    }
                                                ]
                                            }
                                        }
                                    },
                                    {
                                        "tag": "istio.canonical_revision",
                                        "literal": {
                                            "value": "v1"
                                        }
                                    },
                                    {
                                        "tag": "istio.canonical_service",
                                        "literal": {
                                            "value": "web-frontend"
                                        }
                                    },
                                    {
                                        "tag": "istio.mesh_id",
                                        "literal": {
                                            "value": "cluster.local"
                                        }
                                    },
                                    {
                                        "tag": "istio.namespace",
                                        "literal": {
                                            "value": "default"
                                        }
                                    }
                                ]
                            },
                            "streamIdleTimeout": "0s",
                            "accessLog": [
                                {
                                    "name": "envoy.access_loggers.file",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog",
                                        "path": "/dev/stdout",
                                        "logFormat": {
                                            "textFormatSource": {
                                                "inlineString": "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% %RESPONSE_CODE_DETAILS% %CONNECTION_TERMINATION_DETAILS% \"%UPSTREAM_TRANSPORT_FAILURE_REASON%\" %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" \"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" %UPSTREAM_CLUSTER% %UPSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_REMOTE_ADDRESS% %REQUESTED_SERVER_NAME% %ROUTE_NAME%\n"
                                            }
                                        }
                                    }
                                }
                            ],
                            "useRemoteAddress": false,
                            "upgradeConfigs": [
                                {
                                    "upgradeType": "websocket"
                                }
                            ],
                            "normalizePath": true,
                            "pathWithEscapedSlashesAction": "KEEP_UNCHANGED",
                            "requestIdExtension": {
                                "typedConfig": {
                                    "@type": "type.googleapis.com/envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig",
                                    "useRequestIdForTraceSampling": true
                                }
                            }
                        }
                    }
                ]
            }
        ],
        "defaultFilterChain": {
            "filterChainMatch": {},
            "filters": [
                {
                    "name": "istio.stats",
                    "typedConfig": {
                        "@type": "type.googleapis.com/stats.PluginConfig"
                    }
                },
                {
                    "name": "envoy.filters.network.tcp_proxy",
                    "typedConfig": {
                        "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
                        "statPrefix": "PassthroughCluster",
                        "cluster": "PassthroughCluster",
                        "accessLog": [
                            {
                                "name": "envoy.access_loggers.file",
                                "typedConfig": {
                                    "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog",
                                    "path": "/dev/stdout",
                                    "logFormat": {
                                        "textFormatSource": {
                                            "inlineString": "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% %RESPONSE_CODE_DETAILS% %CONNECTION_TERMINATION_DETAILS% \"%UPSTREAM_TRANSPORT_FAILURE_REASON%\" %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" \"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" %UPSTREAM_CLUSTER% %UPSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_REMOTE_ADDRESS% %REQUESTED_SERVER_NAME% %ROUTE_NAME%\n"
                                        }
                                    }
                                }
                            }
                        ]
                    }
                }
            ],
            "name": "PassthroughFilterChain"
        },
        "listenerFilters": [
            {
                "name": "envoy.filters.listener.tls_inspector",
                "typedConfig": {
                    "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector"
                }
            },
            {
                "name": "envoy.filters.listener.http_inspector",
                "typedConfig": {
                    "@type": "type.googleapis.com/envoy.extensions.filters.listener.http_inspector.v3.HttpInspector"
                }
            }
        ],
        "listenerFiltersTimeout": "0s",
        "continueOnListenerFiltersTimeout": true,
        "trafficDirection": "OUTBOUND",
        "bindToPort": false
    }
]

Listener 使用 RDS(路由发现服务)来寻找路由配置(在我们的例子中是 80)。路由 附属于监听器,包含将虚拟主机映射到集群的规则。这允许我们创建流量路由规则,因为 Envoy 可以查看头文件或路径(请求元数据)并对流量进行路由。

路由(route)选择集群(cluster):是一组接受流量的类似的上游主机 —— 它是一个端点的集合。例如,Web 前端服务的所有实例的集合就是一个集群。我们可以在一个 集群内配置弹性功能,如断路器、离群检测和 TLS 配置。

使用 routes 命令,我们可以通过名称过滤所有的路由来获得路由的详细信息

[root@master01 istioyaml]# istioctl proxy-config routes web-frontend-755bf5c8d8-56krh --name 80 -o json
...
[
    {
        "name": "80",
        "virtualHosts": [
            {
                "name": "customers.default.svc.cluster.local:80",
                "domains": [
                    "customers.default.svc.cluster.local",
                    "customers.default.svc.cluster.local:80",
                    "customers",
                    "customers:80",
                    "customers.default.svc.cluster",
                    "customers.default.svc.cluster:80",
                    "customers.default.svc",
                    "customers.default.svc:80",
                    "customers.default",
                    "customers.default:80",
                    "10.124.4.23",
                    "10.124.4.23:80"
                ]
            }
        ],
        "routes": [
            {
                "match": {
                    "prefix": "/"
                },
                "route": {
                    "cluster": "outbound|80|v1|customers.default.svc.cluster.local",
                    "timeout": "0s",
                    "retryPolicy": {
                        "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                        "numRetries": 2,
                        "retryHostPredicate": [
                            {
                                "name": "envoy.retry_host_predicates.previous_hosts"
                            }
                        ],
                        "hostSelectionRetryMaxAttempts": "5"
                    }
                }
            }
        ]
    }
]
...

# 完整回显
[root@master01 istioyaml]# istioctl proxy-config routes web-frontend-755bf5c8d8-56krh --name 80 -o json
[
    {
        "name": "80",
        "virtualHosts": [
            {
                "name": "ingress-nginx-controller.ingress-nginx.svc.cluster.local:80",
                "domains": [
                    "ingress-nginx-controller.ingress-nginx.svc.cluster.local",
                    "ingress-nginx-controller.ingress-nginx",
                    "ingress-nginx-controller.ingress-nginx.svc",
                    "192.168.112.77"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|80||ingress-nginx-controller.ingress-nginx.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
                                        }
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
                        "decorator": {
                            "operation": "ingress-nginx-controller.ingress-nginx.svc.cluster.local:80/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            },
            {
                "name": "istio-egressgateway.istio-system.svc.cluster.local:80",
                "domains": [
                    "istio-egressgateway.istio-system.svc.cluster.local",
                    "istio-egressgateway.istio-system",
                    "istio-egressgateway.istio-system.svc",
                    "192.168.139.213"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|80||istio-egressgateway.istio-system.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
                                        }
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
                        "decorator": {
                            "operation": "istio-egressgateway.istio-system.svc.cluster.local:80/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            },
            {
                "name": "istio-ingressgateway.istio-system.svc.cluster.local:80",
                "domains": [
                    "istio-ingressgateway.istio-system.svc.cluster.local",
                    "istio-ingressgateway.istio-system",
                    "istio-ingressgateway.istio-system.svc",
                    "192.168.149.121"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|80||istio-ingressgateway.istio-system.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
                                        }
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
                        "decorator": {
                            "operation": "istio-ingressgateway.istio-system.svc.cluster.local:80/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            },
            {
                "name": "nginx.default.svc.cluster.local:80",
                "domains": [
                    "nginx.default.svc.cluster.local",
                    "nginx",
                    "nginx.default.svc",
                    "nginx.default",
                    "192.168.229.216"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|80||nginx.default.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
                                        }
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
                        "decorator": {
                            "operation": "nginx.default.svc.cluster.local:80/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            },
            {
                "name": "nginxsvc.microservice.svc.cluster.local:80",
                "domains": [
                    "nginxsvc.microservice.svc.cluster.local",
                    "nginxsvc.microservice",
                    "nginxsvc.microservice.svc",
                    "192.168.47.67"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|80||nginxsvc.microservice.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
                                        }
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
                        "decorator": {
                            "operation": "nginxsvc.microservice.svc.cluster.local:80/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            },
            {
                "name": "ngx-hpa-svc.default.svc.cluster.local:80",
                "domains": [
                    "ngx-hpa-svc.default.svc.cluster.local",
                    "ngx-hpa-svc",
                    "ngx-hpa-svc.default.svc",
                    "ngx-hpa-svc.default",
                    "192.168.12.200"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|80||ngx-hpa-svc.default.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
                                        }
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
                        "decorator": {
                            "operation": "ngx-hpa-svc.default.svc.cluster.local:80/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            },
            {
                "name": "skywalking-ui.devops.svc.cluster.local:80",
                "domains": [
                    "skywalking-ui.devops.svc.cluster.local",
                    "skywalking-ui.devops",
                    "skywalking-ui.devops.svc",
                    "192.168.89.68"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|80||skywalking-ui.devops.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
                                        }
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
                        "decorator": {
                            "operation": "skywalking-ui.devops.svc.cluster.local:80/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            },
            {
                "name": "sleep.default.svc.cluster.local:80",
                "domains": [
                    "sleep.default.svc.cluster.local",
                    "sleep",
                    "sleep.default.svc",
                    "sleep.default",
                    "192.168.237.142"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|80||sleep.default.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
                                        }
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
                        "decorator": {
                            "operation": "sleep.default.svc.cluster.local:80/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            },
            {
                "name": "tracing.istio-system.svc.cluster.local:80",
                "domains": [
                    "tracing.istio-system.svc.cluster.local",
                    "tracing.istio-system",
                    "tracing.istio-system.svc",
                    "192.168.122.92"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|80||tracing.istio-system.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
                                        }
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
                        "decorator": {
                            "operation": "tracing.istio-system.svc.cluster.local:80/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            },
            {
                "name": "web-frontend.default.svc.cluster.local:80",
                "domains": [
                    "web-frontend.default.svc.cluster.local",
                    "web-frontend",
                    "web-frontend.default.svc",
                    "web-frontend.default",
                    "192.168.119.174"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|80||web-frontend.default.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
                                        }
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
                        "decorator": {
                            "operation": "web-frontend.default.svc.cluster.local:80/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            },
            {
                "name": "allow_any",
                "domains": [
                    "*"
                ],
                "routes": [
                    {
                        "name": "allow_any",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "PassthroughCluster",
                            "timeout": "0s",
                            "maxGrpcTimeout": "0s"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            }
        ],
        "validateClusters": false,
        "maxDirectResponseBodySizeBytes": 1048576,
        "ignorePortInHostMatching": true
    }
]

路由 80 配置为每个服务都有一个虚拟主机。然而,由于我们的请求被发送到customers.default.svc.cluster.local,Envoy 会选择与其中一个域匹配的虚拟主机( customers.default.svc.cluster.local:80)

一旦域被匹配,Envoy 就会查看路由,并选择第一个匹配请求的路由。由于我们没有定 义任何特殊的路由规则,它匹配第一个(也是唯一的)定义的路由,并指示 Envoy 将请 求发送到名为outbound|80|v1|customers.default.svc.cluster.local 的集群。

注意集群名称中的 v1 是因为我们部署了一个 DestinationRule 来创建 v1 子 集。如果一个服务没有子集,这部分就留空: outbound|80||customers.default.svc.cluster.local。

现在我们有了集群的名称,我们可以查询更多的细节。为了得到一个清楚显示 FQDN、 端口、子集和其他信息的输出,你可以省略 -o json 标志。

[root@master01 istioyaml]# istioctl proxy-config cluster web-frontend-755bf5c8d8-56krh --fqdn customers.default.svc.cluster.local

最后,使用集群的名称,我们可以查询请求最终将到达的实际端点:

[root@master01 istioyaml]# istioctl proxy-config endpoints web-frontend-755bf5c8d8-56krh --cluster "outbound|80|v1|customers.default.svc.cluster.local"

端点地址等于 customers 应用程序正在运行的 pod IP。如果我们扩展 customers 的部 署,额外的端点会出现在输出中,像这样:

[root@master01 istioyaml]# istioctl proxy-config endpoints web-frontend-755bf5c8d8-56krh --cluster "outbound|80|v1|customers.default.svc.cluster.local"

我们也可以用下图来形象地说明上述流程。

Day10-服务治理-图46

三、调试备忘录

每当你遇到配置问题时,你可以使用这组步骤来浏览和解决问题。在第一部分,我们要检查配置是否有效。如果配置是有效的,下一步就是看看运行时是如何处理配置的,为此,你需要对 Envoy 配置有基本的了解。

3.1 配置

3.1.1 配置是否有效?

Istio CLI 有一个叫validate的命令,我们可以用它来验证 YAML 配置。YAML 最常见 的问题是缩进和数组符号相关的问题。要验证一个配置,请将 YAML 文件传递给validate命令,像这样:

[root@master01 istioyaml]# istioctl validate -f web-frontend.yaml 
"web-frontend.yaml" is valid

如果资源是无效的,CLI 会给我们一个详细的错误。例如,如果我们拼错了一个字段名:

unknown field "worloadSelector" in v1alpha3.ServiceEntry

我们可以使用另一个命令 istioctl analyze。使用这个命令,我们可以检测 Istio 配置的潜在问题。我们可以针对本地的一组配置文件或实时集群运行它。同时,寻找来自istiod 的任何警告或错误。

下面是该命令的一个输出样本,它捕捉到了目的地主机名称中的一个错字:

[root@master01 istioyaml]# istioctl analyze

3.1.2 命名是否正确?资源是否在正确的命名空间?

几乎所有的 Istio 资源都是命名空间范围的。确保它们与你正在处理的服务处于同一命 名空间。将 Istio 资源放在同一命名空间中尤其重要,因为选择器也是有命名空间的。

一个常见的错误配置:在应用程序的命名空间中发布 VirtualService(例如 defaul t ),然后使用 istio: ingress gateway 选择器来绑定到 istio-system 命 名空间中的 ingress 网关部署。这只有在你的 VirtualService 也在 istio-system 命名空间中时才有效。

同样地,不要在 istio-system 命名空间中部署引用应用程序命名空间中的 VirtualService 的 Sidecar 资源。相反,为每个需要入口的应用程序部署一组 Envoy 网关。

3.1.3 资源选择器是否正确?

验证部署中的 pod 是否有正确的标签设置。正如上一步提到的,资源选择器与资源发布的命名空间绑定。

在这一点上,我们应该有理由相信,配置是正确的。接下来的步骤是进一步研究运行时系统是如何处理配置的。

3.2 运行时

Istio CLI 的一个实验性功能可以提供信息,帮助我们了解影响 Pod 或服务的配置。下面是一个针对 Pod 运行 describe 命令的例子,这个 Pod 的主机名称中有一个错字:

[root@master01 istioyaml]# istioctl x describe pod web-frontend-755bf5c8d8-56krh.default
Pod: web-frontend-755bf5c8d8-56krh
   Pod Revision: default
   Pod Ports: 8080 (web), 15090 (istio-proxy)
--------------------
Service: web-frontend
   Port: http 80/HTTP targets pod port 8080
--------------------
Effective PeerAuthentication:
   Workload mTLS mode: STRICT
Applied PeerAuthentication:
   default.default

3.2.1 Envoy 是否接受(ACK)该配置?

你可以使用 istioctl proxy-status 命令来检查状态,看看 Envoy 是否接受配置。我 们希望所有东西的状态都设置为 SYNCHED。任何其他值都可能表明有错误,你应该检查Pilot 的日志。

[root@master01 istioyaml]# istioctl proxy-status
NAME                                                    CLUSTER        CDS        LDS        EDS        RDS          ECDS         ISTIOD                      VERSION
helloworld-v1-77ccfb9cbb-mkdld.default                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-77cc598c96-5fvzp     1.20.8
helloworld-v2-5f7b5b7754-pzstc.default                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-77cc598c96-5fvzp     1.20.8
istio-eastwestgateway-7989cd5655-dx5q9.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     NOT SENT     NOT SENT     istiod-77cc598c96-5fvzp     1.20.8
istio-egressgateway-7cbb4d6cff-hfvj7.istio-system       Kubernetes     SYNCED     SYNCED     SYNCED     NOT SENT     NOT SENT     istiod-77cc598c96-5fvzp     1.20.8
istio-ingressgateway-7f8c8c6db7-wq4qn.istio-system      Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-77cc598c96-5fvzp     1.20.8
nginx-bc586c7d4-pfqqk.microservice                      Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-77cc598c96-5fvzp     1.20.8
sleep-5bb5cb8b67-2gqtl.default                          Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-77cc598c96-5fvzp     1.20.8
web-frontend-755bf5c8d8-56krh.default                   Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-77cc598c96-5fvzp     1.20.8

列表显示所有连接到 Pilot 实例的代理。如果列表中缺少一个代理,这意味着它没有连接到Pilot,也没有收到任何配置。如果任何一个代理被标记为 STALE,可能有网络问题, 或者我们需要扩展 Pilot。

如果 Envoy 接受了配置,但我们仍然看到问题,我们需要确保配置在 Envoy 中的表现符合预期。

3.2.2 配置在 Envoy 中的表现和预期的一样吗?

我们可以 使用 proxy-config 命令来检索特定 Envoy 实例的信息 。请参考下面的表格,可以检索不同的代理配置:

命令 描述
istioctl proxy-config cluster [POD] -n [NAMESPACE] 检索特定pod中的Envoy实例的集群配置信息
istioctl proxy-config bootstrap [POD] -n [NAMESPACE] 检索特定pod中的Envoy实例的 bootstrap配置信息。
istioctl proxy-config listener [POD] -n [NAMESPACE] 检索特定pod中的Envoy实例的 listener(监听器)配置信息。
istioctl proxy-config route [POD] -n [NAMESPACE] 检索特定pod中的Envoy实例的 route(路由)配置信息。
istioctl proxy-config endpoints [POD] -n [NAMESPACE] 检索特定pod中的Envoy实例的 endpoint (后端)配置信息。

该命令从 Envoy 的管理端点(主要是 /conf i g_dump )收集数据,它包含了很多有用的信息

另外,请参考显示 Envoy 和 Istio 资源之间映射的图。

例如,许多 VirtualService 规则将表现为 Envoy 路由,而 DestinationRules 和 ServiceEntries 则表现为 Cluster。

DestinationRules 不会出现在配置中,除非其主机的 ServiceEntry 首先存在。

让我们以客户的 VirtualService 为例。

# 定义
[root@master01 istioyaml]# vim customers-vs-5.yaml 
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: customers
spec:
  hosts:
    - 'customers.default.svc.cluster.local'
  http:
    - route:
        - destination:
            host: customers.default.svc.cluster.local
            port:
              number: 80
            subset: v1
          weight: 80
        - destination:
            host: customers.default.svc.cluster.local
            port:
              number: 80
            subset: v2
          weight: 20
      timeout: 5s

# 应用     
[root@master01 istioyaml]# vim customers-vs-5.yaml 

如果你运行 istioctl proxy-config routes [POD] -o json 命令,你会看到加权目的地和超时是如何在配置中体现的:

{
    "name": "80",
    "virtualHosts": [
        {
            "name": "customers.default.svc.cluster.local:80",
            "domains": [
                "customers.default.svc.cluster.local",

            ],
            "routes": [
                {
                    "match": {
                        "prefix": "/"
                    },
                    "route": {
                        "weightedClusters": {
                            "clusters": [
                                {
                                    "name": "outbound|80|v1|customers.default.svc.cluster.local",
                                    "weight": 80
                                },
                                {
                                    "name": "outbound|80|v2|customers.default.svc.cluster.local",
                                    "weight": 20
                                }
                            ]
                        },
                        "timeout": "5s"
                    }
                }
            ]
        }
    ]
}
...
...

当你评估 VirtualService 时,你要寻找主机名是否像你写的那样出现在 Envoy 配置中 (例如customers.default.svc.cluster.local),以及路由是否存在(见输出中的80-20 流量分割)。你也可以使用之前的例子,通过监听器、路由和集群(和端点)来追踪调用。

Envoy 过滤器会表现在你告诉 Istio 把它们放在哪里(EnvoyFilter 资源中的 applyTo 字 段)。通常情况下,一个坏的过滤器会表现为 Envoy 拒绝配置(即不显示 SYNCED 状 态)。在这种情况下,你需要检查Istiod 日志中的错误。

3.2.3 Istiod(Pilot)中是否有错误?

从 Pilot 查看错误的最快方法是跟踪日志(使用 --follow 标志),然后应用配置。下 面是一个来自Pilot 的错误的例子,这是由于过滤器的内联代码中的一个错字而导致的。

2023-07-29T21:49:16.017487Z warn ads ADS:LDS: ACK ERROR
sidecar~10.120.1.8~web-frontend-58d497b6f8-lwqkg.default~default.svc.cluster.local-4
Internal: Error adding/updating listener(s) virtualInbound:
script load error: [string "fction envoy_on_response (response_handle)..."]:1: '=' expected near 'envoy_on_response'

如果配置根本没有出现在 Envoy 中(Envoy 没有 ACK 它),或者它是一个 EnvoyFilter配置,那么这个配置很可能是无效的。Istio 无法从语法上验证 EnvoyFilter 内部的配置。另一个问题可能是,过滤器在 Envoy 的配置中位于错误的位置。

无论哪种情况,Envoy 都会拒绝该配置,因为它是无效的,Pilot 会记录这个错误。一般 来说,你可以搜索你的资源的名称来找到错误。

在这里,你必须使用判断力来确定它是你写的配置中的错误,还是 Pilot 的错误导致它产生了一个无效的配置。

3.3 检查 Envoy 日志

要检查 Envoy 代理的日志,我们可以使用 kubectl logs 命令:

$ kubectl logs PODNAME -c istio-proxy -n NAMESPACE

要了解访问日志的格式和响应标志,我们可以参考 Envoy 访问日志 的内容。 最常见的响应标志。

  • NR:没有配置路由,检查 DestinationRule 或 VirtualService。
  • UO:上游溢出并断路。检查 DestinationRule 中的断路器配置。
  • UF:上游连接失败,如果使用 Istio 认证,检查 mTLS 配置。
  • UH:没有健康的上游主机。

3.4 配置 istiod 日志

我们可以使用 ControlZ 仪表板,通过 Logging Scopes 菜单配置堆栈跟踪级别和日志级别。

要打开仪表板,请运行:

# istioctl dashboard controlz $(kubectl -n istio-system get pods -l app=istiod -o jsonpath='{.items [0].metadata.name}').istio-system

仪表板打开后,点击 Logging Scopes 选项,调整日志级别和堆栈跟踪级别。

四、日常故障排除

当使用 Istio 进行微服务的管理和通信时,以下是一些常见场景和可能出现的问题以及相应的排查方法:

1、服务无法通过 Istio 网格进行通信

  • 问题:某些服务无法与其他服务通过 Istio 网格进行通信。
  • 排查方法:
  • 检查目标服务的 Sidecar 是否注入成功,并且代理容器是否正在运行。
  • 验证服务之间的网络策略(DestinationRule 和 VirtualService)是否正确 配置。
  • 检查服务是否遵循命名约定并具有正确的服务和端口名称。

2、流量未正确路由到期望的服务版本

  • 问题:经过流量管理规则配置后,流量仍然没有按预期路由到期望的服务版 本。
  • 排查方法:
  • 检查 VirtualService 和 DestinationRule 的配置是否正确。确保指定了正确的匹配规则和目标子集。
  • 校验标签选择器是否正确,以确保将流量正确路由到特定的版本或子集。
  • 使用 kubectl describe 命令检查相关资源的详细信息,确认是否存在语 法错误或其他配置问题。

3、Istio 报告 TLS 握手错误

  • 问题:在启用 mTLS 时,Istio 报告 TLS 握手错误。
  • 排查方法:
  • 检查服务的证书和密钥是否正确配置,并且与目标服务的身份验证策略相匹 配。
  • 验证密钥和证书是否由 Istio Citadel CA 管理并成功生成。
  • 检查 Sidecar 是否正常注入,并且 Envoy 代理是否具有正确的证书和密 钥。

4、应用程序在使用 Istio 时出现性能问题

  • 问题:应用程序在使用 Istio 时出现延迟增加或吞吐量降低等性能问题。
  • 排查方法:
  • 使用 kubectl top 命令检查集群资源(如 Pod、节点)的使用情况,验证 是否存在资源瓶颈。
  • 检查 Istio 控制平面组件(如 istiod)的资源使用情况。
  • 使用 Prometheus 和 Grafana 监控工具检查 Istio 组件的指标,以确定是 否存在异常行为或负载过重的情况。

5、升级 Istio 版本后出现问题

  • 问题:在升级 Istio 版本后,应用程序或 Istio 生态系统的某些功能未按预期工 作。
  • 排查方法:
  • 阅读 Istio 升级文档,确保大家是否遵循了正确的升级步骤和建议。
  • 检查官方发布说明,了解新版本中的变化,尤其是兼容性和已知的问题。
  • 使用 Istio 提供的诊断工具(如 istioctl analyze)检查配置和设置是否与新版本兼容。

五、Istio常见问题

官方链接:Istio / 常见问题

额外扩展(1): 序言- istio 实践指南

额外扩展(2):常见问题 · istio

额外扩展(3):Istio的运维-诊断工具