日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

前面我們創建了一個 Gateway 和 VirtualService 對象,用來對外暴露應用,然后我們就可以通過 ingressgateway 來訪問 Bookinfo 應用了。那么這兩個資源對象是如何實現的呢?

Gateway 資源是用來配置允許外部流量進入 Istio 服務網格的流量入口,用于接收傳入的 HTTP/TCP 連接。它會配置暴露的端口、協議等,但與 Kube.NETes Ingress 資源不同,不會包括任何流量路由配置,真正的路由規則是通過 VirtualService 來配置的。

我們再查看一下前面創建的 Gateway 對象的定義:

# samples/bookinfo/networking/bookinfo-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  selector: # 如果使用的是 Helm 方式安裝,則默認應該是 istio=ingress 標簽
    istio: ingressgateway # 匹配 ingress gateway pod 的標簽(kubectl get pods -l istio=ingressgateway -n istio-system)
  servers:
    - port:
        number: 8080
        name: http
        protocol: HTTP
      hosts:
        - "*"

這里定義的 Gateway 對象中有一個 selector 標簽選擇器,它會匹配 istio=ingressgateway 標簽的 Pod,其實就是 istio-ingressgateway 這個組件。

其實本質上 istio-ingressgateway 也是一個 Envoy 代理,用來作為 Istio 的統一入口網關,它會接收外部流量,然后根據 VirtualService 中定義的路由規則來進行流量的轉發。

我們可以查看下 istio-ingressgateway 的 Envoy 配置來驗證下:

# 進入 ingressgateway 組件所在的 Pod 中
$ kubectl exec -it istio-ingressgateway-9c8b9b586-s6s48 -n istio-system -- /bin/bash
istio-proxy@istio-ingressgateway-9c8b9b586-s6s48:/$ ll /etc/istio/proxy
total 20
drwxrwsrwx 2 root        istio-proxy    66 Nov  3 02:16 ./
drwxr-xr-x 7 root        root          103 Nov  3 02:16 ../
srw-rw-rw- 1 istio-proxy istio-proxy     0 Nov  3 02:16 XDS=
-rw-r--r-- 1 istio-proxy istio-proxy 14130 Nov  3 02:16 envoy-rev.json
-rw-r--r-- 1 istio-proxy istio-proxy  2699 Nov  3 02:16 grpc-bootstrap.json
istio-proxy@istio-ingressgateway-9c8b9b586-s6s48:/$

在 istio-ingressgateway 組件的 Pod 目錄中有一個配置文件 envoy-rev.json,這個文件就是 Envoy 的配置文件,該文件通過 istio 為 sidecar 注入的參數在啟動的時候修改或生成,由于這里采用的是 xDS 動態配置的方式,所以直接看不到前面我們添加的 Gateway 相關信息的,但是我們可以利用 Envoy 的 Admin 提供的 config_dump 來查看下配置文件:

kubectl exec istio-ingressgateway-9c8b9b586-s6s48 -c istio-proxy -n istio-system  -- curl 'localhost:15000/config_dump' > ingressgateway_envoy_conf.json

istio envoy 默認配置為 json 格式,導出來的配置文件非常長(有 10000+行),我們可以先只看上層內容:

Istio Envoy 配置解讀,看這篇就夠了
istio envoy 配置

我們可以看到這個配置文件中其實就一個 configs 數組,每個元素都是一項配置,每個配置都指定了一個獨特的 @type 字段,來指定該配置是是干嘛的。接下來我們就來看下這個配置文件中的每個配置項都是干嘛的。

BootStrapConfigDump

用于在 Envoy 啟動時加載的一些靜態配置,包括類似 Sidecar 的環境變量等信息。我們也可以使用 istioctl proxy-config bootstrap 命令來查看這部分配置:

$ istioctl proxy-config bootstrap istio-ingressgateway-9c8b9b586-s6s48 -n istio-system -o yaml
bootstrap:
  admin:
    address:
      socketAddress:
        address: 127.0.0.1
        portValue: 15000
    profilePath: /var/lib/istio/data/envoy.prof
  dynamicResources:  # 動態配置發現服務信息
    adsConfig:
      apiType: GRPC
      grpcServices:
      - envoyGrpc:
          clusterName: xds-grpc
      setNodeOnFirstMessageOnly: true
      transportApiVersion: V3
    cdsConfig:
      ads: {}
      initialFetchTimeout: 0s
      resourceApiVersion: V3
    ldsConfig:
      ads: {}
      initialFetchTimeout: 0s
      resourceApiVersion: V3
  node:  # 節點信息
    cluster: istio-ingressgateway.istio-system
    id: router~10.244.2.52~istio-ingressgateway-9c8b9b586-s6s48.istio-system~istio-system.svc.cluster.local
    # ......
  staticResources:
    clusters:
    - connectTimeout: 0.250s  # prometheus cluster
      loadAssignment:
        clusterName: prometheus_stats
        endpoints:
        - lbEndpoints:
          - endpoint:
              address:
                socketAddress:
                  address: 127.0.0.1
                  portValue: 15000
      name: prometheus_stats
      type: STATIC
    - connectTimeout: 0.250s  # agent cluster
      loadAssignment:
        clusterName: agent
        endpoints:
        - lbEndpoints:
          - endpoint:
              address:
                socketAddress:
                  address: 127.0.0.1
                  portValue: 15020
      name: agent
      type: STATIC
    - connectTimeout: 1s
      loadAssignment:
        clusterName: sds-grpc
        endpoints:
        - lbEndpoints:
          - endpoint:
              address:
                pipe:
                  path: ./var/run/secrets/workload-spiffe-uds/socket
      name: sds-grpc
      type: STATIC
      typedExtensionProtocolOptions:
        envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
          '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
          explicitHttpConfig:
            http2ProtocolOptions: {}
    - circuitBreakers:
        thresholds:
        - maxConnections: 100000
          maxPendingRequests: 100000
          maxRequests: 100000
        - maxConnections: 100000
          maxPendingRequests: 100000
          maxRequests: 100000
          priority: HIGH
      connectTimeout: 1s
      loadAssignment:  # xds-grpc cluster
        clusterName: xds-grpc
        endpoints:
        - lbEndpoints:
          - endpoint:
              address:
                pipe:
                  path: ./etc/istio/proxy/XDS
      maxRequestsPerConnection: 1
      name: xds-grpc
      type: STATIC
      typedExtensionProtocolOptions:
        envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
          '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
          explicitHttpConfig:
            http2ProtocolOptions: {}
      upstreamConnectionOptions:
        tcpKeepalive:
          keepaliveTime: 300
    - connectTimeout: 1s
      DNSLookupFamily: V4_ONLY
      dnsRefreshRate: 30s
      loadAssignment:  # zipkin cluster
        clusterName: zipkin
        endpoints:
        - lbEndpoints:
          - endpoint:
              address:
                socketAddress:
                  address: zipkin.istio-system
                  portValue: 9411
      name: zipkin
      respectDnsTtl: true
      type: STRICT_DNS
    listeners:
    - address:
        socketAddress:
          address: 0.0.0.0
          portValue: 15090  # prometheus listener
      filterChAIns:
      - filters:
        - name: envoy.filters.network.http_connection_manager
          typedConfig:
            '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
            httpFilters:
            - name: envoy.filters.http.router
              typedConfig:
                '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
            routeConfig:
              virtualHosts:
              - domains:
                - '*'
                name: backend
                routes:
                - match:
                    prefix: /stats/prometheus
                  route:
                    cluster: prometheus_stats
            statPrefix: stats
    - address:
        socketAddress:
          address: 0.0.0.0
          portValue: 15021  # agent listener(健康檢查)
      filterChains:
      - filters:
        - name: envoy.filters.network.http_connection_manager
          typedConfig:
            '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
            httpFilters:
            - name: envoy.filters.http.router
              typedConfig:
                '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
            routeConfig:
              virtualHosts:
              - domains:
                - '*'
                name: backend
                routes:
                - match:
                    prefix: /healthz/ready
                  route:
                    cluster: agent
            statPrefix: agent
  statsConfig:
  # ......
  tracing: # 鏈路追蹤
    http:
      name: envoy.tracers.zipkin
      typedConfig:
        '@type': type.googleapis.com/envoy.config.trace.v3.ZipkinConfig
        collectorCluster: zipkin
        collectorEndpoint: /api/v2/spans
        collectorEndpointVersion: HTTP_JSON
        sharedSpanContext: false
        traceId128bit: true

上面的配置和之前我們介紹的 Envoy 配置基本一致,在上面配置中定義了一個 Prometheus 監聽器,用來暴露 Prometheus 監控指標,還定義了一個 Agent 監聽器,用來暴露健康檢查接口,另外還定義了一個 zipkin 集群,用來定義鏈路追蹤的配置。另外通過 dynamicResources 定義了動態配置發現服務信息,xds-grpc 就是用來定義 Envoy 與 Pilot 之間的 xDS 通信的。

ListenersConfigDump

這里存儲著 Envoy 的 listeners 配置,也就是 Envoy 的監聽器。Envoy 在攔截到請求后,會根據請求的地址與端口,將請求交給匹配的 listener 處理。

我們看到這個 ListenersConfigDump 中的 listener 配置分成了 static_listners 和 dynamic_listeners,分別對應 Envoy 的靜態配置和動態配置,靜態配置,是 Envoy 配置文件中直接指定的,而 dynamic_listeners的 listener 則是 istiod 通過 xDS 協議為 Envoy 下發的。

同樣我們也可以使用 istioctl proxy-config listener 命令來查看這部分配置:

istioctl proxy-config listener istio-ingressgateway-9c8b9b586-s6s48 -n istio-system -o yaml

對應的配置文件如下所示:

- accessLog:
    - filter:
        responseFlagFilter:
          flags:
            - NR
      name: envoy.access_loggers.file
      typedConfig:
        "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
        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%
        path: /dev/stdout
  address:
    socketAddress:
      address: 0.0.0.0
      portValue: 8080
  continueOnListenerFiltersTimeout: true
  filterChains:
    - filters:
        - name: istio_authn
          typedConfig:
            "@type": type.googleapis.com/udpa.type.v1.TypedStruct
            typeUrl: type.googleapis.com/io.istio.network.authn.Config
        - name: envoy.filters.network.http_connection_manager
          typedConfig:
            "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
            accessLog:
              - name: envoy.access_loggers.file
                typedConfig:
                  "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
                  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%
                  path: /dev/stdout
            forwardClientCertDetails: SANITIZE_SET
            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
                    - alpnOverride:
                        - istio-http/1.1
                        - istio
                        - http/1.1
                      upstreamProtocol: HTTP11
                    - alpnOverride:
                        - istio-h2
                        - istio
                        - h2
                      upstreamProtocol: HTTP2
              - 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
                  disableHostHeaderFallback: true
              - name: envoy.filters.http.router
                typedConfig:
                  "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
            httpProtocolOptions: {}
            normalizePath: true
            pathWithEscapedSlashesAction: KEEP_UNCHANGED
            rds:
              configSource:
                ads: {}
                initialFetchTimeout: 0s
                resourceApiVersion: V3
              routeConfigName: http.8080
            requestIdExtension:k
              typedConfig:
                "@type": type.googleapis.com/envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig
                useRequestIdForTraceSampling: true
            serverName: istio-envoy
            setCurrentClientCertDetails:
              cert: true
              dns: true
              subject: true
              uri: true
            statPrefix: outbound_0.0.0.0_8080
            streamIdleTimeout: 0s
            tracing:
              # ......
            upgradeConfigs:
              - upgradeType: websocket
            useRemoteAddress: true
  name: 0.0.0.0_8080
  trafficDirection: OUTBOUND
- address:
    socketAddress:
      address: 0.0.0.0
      portValue: 15090
  # ......
- address:
    socketAddress:
      address: 0.0.0.0
      portValue: 15021
  # ......

雖然上面看到的 listener 配置還是很長,但是我們應該也還是非常熟悉的,本質就是 Envoy 的配置文件中的 listener 配置。我們這里重點看下動態配置對應的配置,靜態的就是前面指定 prometheus 和 agent 對應的監聽器配置。

我們可以看到上面的動態配置對應的監聽器名稱為 0.0.0.0_8080,對應的監聽地址為 0.0.0.0:8080,也就是說在 Envoy 中監聽了 8080 端口:

address:
  socketAddress:
    address: 0.0.0.0
    portValue: 8080

而前面我們是不是創建了一個 Gateway 資源對象,并指定了 8080 端口,其實這個端口就是我們前面創建的 Gateway 對象中定義的端口,這個監聽器的配置就是通過 istiod 通過 xDS 協議下發的。

那么請求是如何到達這個監聽器的呢?我們可以查看下 istio-ingressgateway 組建的 Service 數據:

$ kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                                      AGE
istio-ingressgateway   LoadBalancer   10.103.227.57   <pending>     15021:32459/TCP,80:31896/TCP,443:30808/TCP,31400:31535/TCP,15443:30761/TCP   46h

我們可以看到 istio-ingressgateway 組件的 Service 中定義了 5 個端口,還記得前面我們去訪問 Productpage 的時候是如何訪問的嗎?是不是通過 http://$GATEWAY_URL/productpage 訪問的,而我們這里沒有 LoadBalancer,所以直接使用 NodePort 形式訪問就行,最終我們是通過 http://NodeIP:31896/productpage 來訪問應用的,而這個 31896 端口對應 istio-ingressgateway 組件的 Service 中定義的 80 端口,也就是說我們的請求是通過 80 端口到達 istio-ingressgateway 組件的,那么這個 80 端口是如何到達 istio-ingressgateway 組件的呢?

$ kubectl describe svc istio-ingressgateway -n istio-system
Name:                     istio-ingressgateway
Namespace:                istio-system
# ......
Port:                     http2  80/TCP
TargetPort:               8080/TCP
NodePort:                 http2  31896/TCP
Endpoints:                10.244.2.52:8080

我們查看 Service 的定義就明白了,實際上 istio-ingressgateway 這個 Service 定義的 80 端口對應的是 istio-ingressgateway 組件 Pod 的 8080 端口,也就是說我們的請求是通過 80 端口到達 istio-ingressgateway 組件的 8080 端口的,而這個 8080 端口就是我們前面在 Envoy 配置中看到的監聽器的端口了,所以當我們訪問 http://$GATEWAY_URL/productpage 的時候請求到達了 istio-ingressgateway 這個組件的 8080 端口了。

當請求到達 istio-ingressgateway 組件時,就會被這個監聽器所匹配,然后將請求交給 http_connection_manager 這個 filter 來處理,當然后面就是用各種具體的 filter 來處理請求了,比如 envoy.filters.http.fault 這個 filter 就是用來處理故障注入的,envoy.filters.http.router 則是用來處理路由轉發的、envoy.filters.http.cors 則是用來處理跨域請求的等等。

但是我們的請求進到 Envoy 后是又該如何路由呢?我應該將請求轉發到哪里去呢?這個是不是就是 Envoy 中的路由配置來決定的了,對于靜態配置我們清楚直接在 Envoy 配置文件中就可以看到,比如:

routeConfig:
  virtualHosts:
    - domains:
        - "*"
      name: backend
      routes:
        - match:
            prefix: /healthz/ready
          route:
            cluster: agent

但是我們這里的路由配置是動態配置的,我們看到對應的配置中有一個 rds 字段,這個字段就是用來指定動態路由配置的,其中的 routeConfigName 字段就是用來指定對應的路由配置名稱的:

rds:
  configSource:
    ads: {}
    initialFetchTimeout: 0s
    resourceApiVersion: V3
  routeConfigName: http.8080

RoutesConfigDump

這里面保存著 Envoy 的路由配置,和 listeners 一樣,RoutesConfigDump 也分為 static_route_configs 和 dynamic_route_configs,分別對應著靜態的路由配置和動態下發的路由配置。

同樣我們也可以使用 istioctl proxy-config route 命令來查看這部分配置:

istioctl proxy-config route istio-ingressgateway-9c8b9b586-s6s48 -n istio-system -o yaml

對應的配置如下所示:

- ignorePortInHostMatching: true
  maxDirectResponseBodySizeBytes: 1048576
  name: http.8080
  validateClusters: false
  virtualHosts:
    - domains:
        - "*"
      includeRequestAttemptCount: true
      name: "*:8080"
      routes:
        - decorator:
            operation: productpage.default.svc.cluster.local:9080/productpage
          match:
            caseSensitive: true
            path: /productpage
          metadata:
            filterMetadata:
              istio:
                config: /apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/bookinfo
          route:
            cluster: outbound|9080||productpage.default.svc.cluster.local
            maxGrpcTimeout: 0s
            retryPolicy:
              hostSelectionRetryMaxAttempts: "5"
              numRetries: 2
              retriableStatusCodes:
                - 503
              retryHostPredicate:
                - name: envoy.retry_host_predicates.previous_hosts
                  typedConfig:
                    "@type": type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate
              retryOn: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes
            timeout: 0s
        - decorator:
            operation: productpage.default.svc.cluster.local:9080/static*
          match:
            caseSensitive: true
            prefix: /static
          metadata:
            filterMetadata:
              istio:
                config: /apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/bookinfo
          route:
            cluster: outbound|9080||productpage.default.svc.cluster.local
            maxGrpcTimeout: 0s
            retryPolicy:
              hostSelectionRetryMaxAttempts: "5"
              numRetries: 2
              retriableStatusCodes:
                - 503
              retryHostPredicate:
                - name: envoy.retry_host_predicates.previous_hosts
                  typedConfig:
                    "@type": type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate
              retryOn: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes
            timeout: 0s
        - decorator:
            operation: productpage.default.svc.cluster.local:9080/login
          match:
            caseSensitive: true
            path: /login
          metadata:
            filterMetadata:
              istio:
                config: /apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/bookinfo
          route:
            cluster: outbound|9080||productpage.default.svc.cluster.local
            maxGrpcTimeout: 0s
            retryPolicy:
              hostSelectionRetryMaxAttempts: "5"
              numRetries: 2
              retriableStatusCodes:
                - 503
              retryHostPredicate:
                - name: envoy.retry_host_predicates.previous_hosts
                  typedConfig:
                    "@type": type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate
              retryOn: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes
            timeout: 0s
        - decorator:
            operation: productpage.default.svc.cluster.local:9080/logout
          match:
            caseSensitive: true
            path: /logout
          metadata:
            filterMetadata:
              istio:
                config: /apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/bookinfo
          route:
            cluster: outbound|9080||productpage.default.svc.cluster.local
            maxGrpcTimeout: 0s
            retryPolicy:
              hostSelectionRetryMaxAttempts: "5"
              numRetries: 2
              retriableStatusCodes:
                - 503
              retryHostPredicate:
                - name: envoy.retry_host_predicates.previous_hosts
                  typedConfig:
                    "@type": type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate
              retryOn: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes
            timeout: 0s
        - decorator:
            operation: productpage.default.svc.cluster.local:9080/api/v1/products*
          match:
            caseSensitive: true
            prefix: /api/v1/products
          metadata:
            filterMetadata:
              istio:
                config: /apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/bookinfo
          route:
            cluster: outbound|9080||productpage.default.svc.cluster.local
            maxGrpcTimeout: 0s
            retryPolicy:
              hostSelectionRetryMaxAttempts: "5"
              numRetries: 2
              retriableStatusCodes:
                - 503
              retryHostPredicate:
                - name: envoy.retry_host_predicates.previous_hosts
                  typedConfig:
                    "@type": type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate
              retryOn: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes
            timeout: 0s
- virtualHosts:
    - domains:
        - "*"
      name: backend
      routes:
        - match:
            prefix: /stats/prometheus
          route:
            cluster: prometheus_stats
- virtualHosts:
    - domains:
        - "*"
      name: backend
      routes:
        - match:
            prefix: /healthz/ready
          route:
            cluster: agent

后面的兩個 virtualHosts 就是我們的靜態路由配置,第一個是動態的路由配置,我們可以看到該配置的名稱就是 http.8080,是不是和前面的 routeConfigName 是一致的。那么這個配置又是什么地方定義的呢?

其實仔細看這里面的配置和前面我們創建的 VirtualService 這個資源對象是不是很像,我們再看下前面創建的 VirtualService 對象的定義:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
    - "*"
  gateways:
    - bookinfo-gateway
  http:
    - match:
        - uri:
            exact: /productpage
        - uri:
            prefix: /static
        - uri:
            exact: /login
        - uri:
            exact: /logout
        - uri:
            prefix: /api/v1/products
      route:
        - destination:
            host: productpage
            port:
              number: 9080

我們可以看到在 VirtualService 對象中定義了 5 個路由規則,而這里的 RoutesConfigDump 中也定義了 5 個路由規則,VirtualService 中定義的 5 個路由分別為 /productpage、/static、/login、/logout、/api/v1/products,而 RoutesConfigDump 中定義的 5 個路由分別為 /productpage、/static、/login、/logout/api/v1/products,是不是一一對應的。最終匹配這些路由規則的請求是被轉發到 productpage 這個服務的 9080 端口的。

比如 /productpage 這個路由規則對應的 Envoy 配置如下所示:

- domains:
    - "*"
  includeRequestAttemptCount: true
  name: "*:8080"
  routes:
    - decorator:
        operation: productpage.default.svc.cluster.local:9080/productpage
      match:
        caseSensitive: true
        path: /productpage
      metadata:
        filterMetadata:
          istio:
            config: /apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/bookinfo
      route:
        cluster: outbound|9080||productpage.default.svc.cluster.local
        maxGrpcTimeout: 0s
        retryPolicy:
          hostSelectionRetryMaxAttempts: "5"
          numRetries: 2
          retriableStatusCodes:
            - 503
          retryHostPredicate:
            - name: envoy.retry_host_predicates.previous_hosts
              typedConfig:
                "@type": type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate
          retryOn: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes
        timeout: 0s

這個配置就是我們熟悉的 Envoy 的關于虛擬主機部分的配置,比如當我們請求的路徑為 /productpage 時,就會被這個路由規則匹配到,然后就用通過 route 字段來描述我們的路由目標了,針對這個目錄,可以看到有一些類似于 retry_policy、timeout等字段來配置這個目標的超時、重試策略等,不過最重要的還是 cluster 這個字段,它指定了這個路由目標對應著哪個上游集群,Envoy 最終將請求發送到這個 Cluster,比如我們這里的集群名稱為 outbound|9080||productpage.default.svc.cluster.local,關于其具體配置我們就要去查看 ClustersConfigDump 中的配置了。

ClustersConfigDump

該部分是用來存儲 Envoy 的集群配置的,同樣也分為 static_clusters 和 dynamic_active_clusters,分別對應著靜態配置和動態下發的配置。這里的 Cluster 集群是 Envoy 內部的概念,它是指 Envoy 連接的一組邏輯相同的上游主機,并不是說 K8s 集群,只是大多數情況下我們可以把這個集群理解為 K8s 集群中的一個 Service,一個 Service 通常對應著一組 Pod,由這組 Pod 響應請求并提供同一種服務,而 Envoy 的這個集群實際可以理解成這種Pod 集合。不過 Envoy 的一個集群也不一定就對應著一個 Service,因為集群是一組邏輯相同的上游主機,所以也有可能是別的符合定義的東西,比如說是服務的一個特定版本(如只是 v2 版本的 reviews 服務)。istio 的版本灰度能力就是基于這個做的,因為兩個版本的同一服務實際上可以分成兩個集群。

同樣我們可以使用 istioctl proxy-config cluster 命令來查看這部分配置:

istioctl proxy-config cluster istio-ingressgateway-9c8b9b586-s6s48 -n istio-system -o yaml

該配置文件會非常長,它會將 K8s 集群中的 Service 都轉換成 Envoy 的 Cluster,這里我們只看下 productpage 這個服務對應的 Cluster 配置,如下所示:

- circuitBreakers: #
    thresholds:
      - maxConnections: 4294967295
        maxPendingRequests: 4294967295
        maxRequests: 4294967295
        maxRetries: 4294967295
        trackRemaining: true
  commonLbConfig:
    localityWeightedLbConfig: {}
  connectTimeout: 10s
  edsClusterConfig:
    edsConfig:
      ads: {}
      initialFetchTimeout: 0s
      resourceApiVersion: V3
    serviceName: outbound|9080||productpage.default.svc.cluster.local
  filters:
    - name: istio.metadata_exchange
      typedConfig:
        "@type": type.googleapis.com/envoy.tcp.metadataexchange.config.MetadataExchange
        protocol: istio-peer-exchange
  lbPolicy: LEAST_REQUEST
  metadata:
    filterMetadata:
      istio:
        services:
          - host: productpage.default.svc.cluster.local
            name: productpage
            namespace: default
  name: outbound|9080||productpage.default.svc.cluster.local
  transportSocketMatches:
    - match:
        tlsMode: istio
      name: tlsMode-istio
      transportSocket:
        name: envoy.transport_sockets.tls
        typedConfig:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
          commonTlsContext:
            alpnProtocols:
              - istio-peer-exchange
              - istio
            combinedValidationContext:
              defaultValidationContext:
                matchSubjectAltNames:
                  - exact: spiffe://cluster.local/ns/default/sa/bookinfo-productpage
              validationContextSdsSecretConfig:
                name: ROOTCA
                sdsConfig:
                  apiConfigSource:
                    apiType: GRPC
                    grpcServices:
                      - envoyGrpc:
                          clusterName: sds-grpc
                    setNodeOnFirstMessageOnly: true
                    transportApiVersion: V3
                  initialFetchTimeout: 0s
                  resourceApiVersion: V3
            tlsCertificateSdsSecretConfigs:
              - name: default
                sdsConfig:
                  apiConfigSource:
                    apiType: GRPC
                    grpcServices:
                      - envoyGrpc:
                          clusterName: sds-grpc
                    setNodeOnFirstMessageOnly: true
                    transportApiVersion: V3
                  initialFetchTimeout: 0s
                  resourceApiVersion: V3
            tlsParams:
              tlsMaximumProtocolVersion: TLSv1_3
              tlsMinimumProtocolVersion: TLSv1_2
          sni: outbound_.9080_._.productpage.default.svc.cluster.local
    - match: {}
      name: tlsMode-disabled
      transportSocket:
        name: envoy.transport_sockets.raw_buffer
        typedConfig:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer
  type: EDS

我們可以看到這個 Envoy Cluster 的名稱為 outbound|9080||productpage.default.svc.cluster.local,和前面的路由配置中的 cluster 字段是一致的,名稱大多數會由 | 分成四個部分,分別是 inbound 或 outbound 代表入向流量或出向流量、端口號、subcluster 名稱(就是對應著 destination rule 里的 subset)、Service FQDN,由 istio 的服務發現進行配置,通過這個 name 我們很容易就能看出來這個集群對應的是 K8s 集群的哪個服務。

然后配置的負載均衡策略是 LEAST_REQUEST,另外比較重要的這里的配置的類型為 type: EDS,也就是會通過 EDS 來發現上游的主機服務,這個 EDS 的配置如下所示:

edsClusterConfig:
  edsConfig:
    ads: {}
    initialFetchTimeout: 0s
    resourceApiVersion: V3
  serviceName: outbound|9080||productpage.default.svc.cluster.local

基于 EDS 去動態發現上游主機的配置,其實在前面的 Envoy 章節我們已經介紹過了,和這里是不是幾乎是一致的,serviceName 其實就對應著 K8s 集群中的 productpage 這個 Service 對象的 9080 端口,而這個 Service 對象對應著一組 Pod,這組 Pod 就是我們的上游主機了。當然這是通過 xDS 協議下發的,我們可以通過 istioctl proxy-config endpoint 命令來查看這部分配置:

istioctl proxy-config endpoint istio-ingressgateway-9c8b9b586-s6s48 -n istio-system -o yaml

該部分數據非常多,下面只截取 productpage 相關的數據,如下所示:

- addedViaApi: true
  circuitBreakers:
    thresholds:
    - maxConnections: 4294967295
      maxPendingRequests: 4294967295
      maxRequests: 4294967295
      maxRetries: 4294967295
    - maxConnections: 1024
      maxPendingRequests: 1024
      maxRequests: 1024
      maxRetries: 3
      priority: HIGH
  edsServiceName: outbound|9080||productpage.default.svc.cluster.local
  hostStatuses:
  - address:
      socketAddress:
        address: 10.244.2.62
        portValue: 9080
    healthStatus:
      edsHealthStatus: HEALTHY
    locality: {}
    stats:
    - name: cx_connect_fail
    - name: cx_total
      value: "1"
    - name: rq_error
    - name: rq_success
      value: "4"
    - name: rq_timeout
    - name: rq_total
      value: "4"
    - name: cx_active
      type: GAUGE
    - name: rq_active
      type: GAUGE
    weight: 1
  name: outbound|9080||productpage.default.svc.cluster.local
  observabilityName: outbound|9080||productpage.default.svc.cluster.local

可以看到上面的配置中就包含一個真正的后端服務地址:

address:
  socketAddress:
    address: 10.244.2.62
    portValue: 9080

這個地址其實就是 productpage 這個 K8s Service 關聯的 Pod 的地址。這樣一個請求從進入到 Envoy 到最終轉發到后端服務的過程就清楚了。

SecretsConfigDump

由于網格中的 Envoy 之間互相通信會使用 mTLS 模式,因此每個 Envoy 通信時都需要提供本工作負載的證書,同時為了簽發證書還需要 istio ca 的根證書,這些證書的信息保存在該配置項之下。

總結

到這里我們就把 Envoy 的整個配置文件都理解了一遍,它們分別是 Bootstrap、Listeners、Routes、Clusters、Secrets 幾個配置,其中又涉及到 VirtualHost 等細分概念。

Istio Envoy 配置解讀,看這篇就夠了

整體上一個請求在 Envoy 內部的處理與轉發過程中,listener、route、cluster 這幾個配置是緊密相連的,它們通過配置的 name 一層又一層地向下引用(listener 內的 filter 引用 route、route 內的 virtual_host 引用 cluster),形成了一條引用鏈,最終將請求從 listener 遞交到具體的 cluster。

我們可以使用 envoyui.solo.io 這個在線的 Envoy 配置可視化工具來查看 Envoy 的配置,只需要將我們的 Envoy 配置 dump 出來上傳上來即可:

Istio Envoy 配置解讀,看這篇就夠了
Envoy config dump

經過上面的分析我們也明白了其實 Istio 并沒有實現很多復雜的邏輯,服務治理相關的功能比如負載均衡、故障注入、權重路由等都是 Envoy 本身就有的能力,Istio 只是將這些能力抽象成了一個個資源對象,然后通過 Envoy 的 xDS 協議下發到 Envoy 中,這樣就能夠實現對 Envoy 的流量治理了。所以重點還是需要我們先理解 Envoy 的配置,然后再去理解 Istio 的配置,這樣才能更好的理解 Istio,不然你就不清楚 Gateway、VirtualService 等這些資源對象到底是干什么的,它們是如何影響 Envoy 的配置的。

當然我們這里還只是分析的 Istio Ingress Gateway 的配置,而對于 Sidecar 模式的 Envoy 代理又是如何去配置的呢?它又是如何將 Pod 的流量進行攔截的呢?這些我們后面會繼續分析。

分享到:
標簽:Istio Envoy
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定