亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線(xiàn)咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

前面我們創(chuàng)建了一個(gè) Gateway 和 VirtualService 對(duì)象,用來(lái)對(duì)外暴露應(yīng)用,然后我們就可以通過(guò) ingressgateway 來(lái)訪(fǎng)問(wèn) Bookinfo 應(yīng)用了。那么這兩個(gè)資源對(duì)象是如何實(shí)現(xiàn)的呢?

Gateway 資源是用來(lái)配置允許外部流量進(jìn)入 Istio 服務(wù)網(wǎng)格的流量入口,用于接收傳入的 HTTP/TCP 連接。它會(huì)配置暴露的端口、協(xié)議等,但與 Kube.NETes Ingress 資源不同,不會(huì)包括任何流量路由配置,真正的路由規(guī)則是通過(guò) VirtualService 來(lái)配置的。

我們?cè)俨榭匆幌虑懊鎰?chuàng)建的 Gateway 對(duì)象的定義:

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

這里定義的 Gateway 對(duì)象中有一個(gè) selector 標(biāo)簽選擇器,它會(huì)匹配 istio=ingressgateway 標(biāo)簽的 Pod,其實(shí)就是 istio-ingressgateway 這個(gè)組件。

其實(shí)本質(zhì)上 istio-ingressgateway 也是一個(gè) Envoy 代理,用來(lái)作為 Istio 的統(tǒng)一入口網(wǎng)關(guān),它會(huì)接收外部流量,然后根據(jù) VirtualService 中定義的路由規(guī)則來(lái)進(jìn)行流量的轉(zhuǎn)發(fā)。

我們可以查看下 istio-ingressgateway 的 Envoy 配置來(lái)驗(yàn)證下:

# 進(jìn)入 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 目錄中有一個(gè)配置文件 envoy-rev.json,這個(gè)文件就是 Envoy 的配置文件,該文件通過(guò) istio 為 sidecar 注入的參數(shù)在啟動(dòng)的時(shí)候修改或生成,由于這里采用的是 xDS 動(dòng)態(tài)配置的方式,所以直接看不到前面我們添加的 Gateway 相關(guān)信息的,但是我們可以利用 Envoy 的 Admin 提供的 config_dump 來(lái)查看下配置文件:

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

istio envoy 默認(rèn)配置為 json 格式,導(dǎo)出來(lái)的配置文件非常長(zhǎng)(有 10000+行),我們可以先只看上層內(nèi)容:

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

我們可以看到這個(gè)配置文件中其實(shí)就一個(gè) configs 數(shù)組,每個(gè)元素都是一項(xiàng)配置,每個(gè)配置都指定了一個(gè)獨(dú)特的 @type 字段,來(lái)指定該配置是是干嘛的。接下來(lái)我們就來(lái)看下這個(gè)配置文件中的每個(gè)配置項(xiàng)都是干嘛的。

BootStrapConfigDump

用于在 Envoy 啟動(dòng)時(shí)加載的一些靜態(tài)配置,包括類(lèi)似 Sidecar 的環(huán)境變量等信息。我們也可以使用 istioctl proxy-config bootstrap 命令來(lái)查看這部分配置:

$ 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:  # 動(dòng)態(tài)配置發(fā)現(xiàn)服務(wù)信息
    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:  # 節(jié)點(diǎn)信息
    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 配置基本一致,在上面配置中定義了一個(gè) Prometheus 監(jiān)聽(tīng)器,用來(lái)暴露 Prometheus 監(jiān)控指標(biāo),還定義了一個(gè) Agent 監(jiān)聽(tīng)器,用來(lái)暴露健康檢查接口,另外還定義了一個(gè) zipkin 集群,用來(lái)定義鏈路追蹤的配置。另外通過(guò) dynamicResources 定義了動(dòng)態(tài)配置發(fā)現(xiàn)服務(wù)信息,xds-grpc 就是用來(lái)定義 Envoy 與 Pilot 之間的 xDS 通信的。

ListenersConfigDump

這里存儲(chǔ)著 Envoy 的 listeners 配置,也就是 Envoy 的監(jiān)聽(tīng)器。Envoy 在攔截到請(qǐng)求后,會(huì)根據(jù)請(qǐng)求的地址與端口,將請(qǐng)求交給匹配的 listener 處理。

我們看到這個(gè) ListenersConfigDump 中的 listener 配置分成了 static_listners 和 dynamic_listeners,分別對(duì)應(yīng) Envoy 的靜態(tài)配置和動(dòng)態(tài)配置,靜態(tài)配置,是 Envoy 配置文件中直接指定的,而 dynamic_listeners的 listener 則是 istiod 通過(guò) xDS 協(xié)議為 Envoy 下發(fā)的。

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

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

對(duì)應(yīng)的配置文件如下所示:

- 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 配置還是很長(zhǎng),但是我們應(yīng)該也還是非常熟悉的,本質(zhì)就是 Envoy 的配置文件中的 listener 配置。我們這里重點(diǎn)看下動(dòng)態(tài)配置對(duì)應(yīng)的配置,靜態(tài)的就是前面指定 prometheus 和 agent 對(duì)應(yīng)的監(jiān)聽(tīng)器配置。

我們可以看到上面的動(dòng)態(tài)配置對(duì)應(yīng)的監(jiān)聽(tīng)器名稱(chēng)為 0.0.0.0_8080,對(duì)應(yīng)的監(jiān)聽(tīng)地址為 0.0.0.0:8080,也就是說(shuō)在 Envoy 中監(jiān)聽(tīng)了 8080 端口:

address:
  socketAddress:
    address: 0.0.0.0
    portValue: 8080

而前面我們是不是創(chuàng)建了一個(gè) Gateway 資源對(duì)象,并指定了 8080 端口,其實(shí)這個(gè)端口就是我們前面創(chuàng)建的 Gateway 對(duì)象中定義的端口,這個(gè)監(jiān)聽(tīng)器的配置就是通過(guò) istiod 通過(guò) xDS 協(xié)議下發(fā)的。

那么請(qǐng)求是如何到達(dá)這個(gè)監(jiān)聽(tīng)器的呢?我們可以查看下 istio-ingressgateway 組建的 Service 數(shù)據(jù):

$ 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 個(gè)端口,還記得前面我們?nèi)ピL(fǎng)問(wèn) Productpage 的時(shí)候是如何訪(fǎng)問(wèn)的嗎?是不是通過(guò) http://$GATEWAY_URL/productpage 訪(fǎng)問(wèn)的,而我們這里沒(méi)有 LoadBalancer,所以直接使用 NodePort 形式訪(fǎng)問(wèn)就行,最終我們是通過(guò) http://NodeIP:31896/productpage 來(lái)訪(fǎng)問(wèn)應(yīng)用的,而這個(gè) 31896 端口對(duì)應(yīng) istio-ingressgateway 組件的 Service 中定義的 80 端口,也就是說(shuō)我們的請(qǐng)求是通過(guò) 80 端口到達(dá) istio-ingressgateway 組件的,那么這個(gè) 80 端口是如何到達(dá) 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 的定義就明白了,實(shí)際上 istio-ingressgateway 這個(gè) Service 定義的 80 端口對(duì)應(yīng)的是 istio-ingressgateway 組件 Pod 的 8080 端口,也就是說(shuō)我們的請(qǐng)求是通過(guò) 80 端口到達(dá) istio-ingressgateway 組件的 8080 端口的,而這個(gè) 8080 端口就是我們前面在 Envoy 配置中看到的監(jiān)聽(tīng)器的端口了,所以當(dāng)我們?cè)L問(wèn) http://$GATEWAY_URL/productpage 的時(shí)候請(qǐng)求到達(dá)了 istio-ingressgateway 這個(gè)組件的 8080 端口了。

當(dāng)請(qǐng)求到達(dá) istio-ingressgateway 組件時(shí),就會(huì)被這個(gè)監(jiān)聽(tīng)器所匹配,然后將請(qǐng)求交給 http_connection_manager 這個(gè) filter 來(lái)處理,當(dāng)然后面就是用各種具體的 filter 來(lái)處理請(qǐng)求了,比如 envoy.filters.http.fault 這個(gè) filter 就是用來(lái)處理故障注入的,envoy.filters.http.router 則是用來(lái)處理路由轉(zhuǎn)發(fā)的、envoy.filters.http.cors 則是用來(lái)處理跨域請(qǐng)求的等等。

但是我們的請(qǐng)求進(jìn)到 Envoy 后是又該如何路由呢?我應(yīng)該將請(qǐng)求轉(zhuǎn)發(fā)到哪里去呢?這個(gè)是不是就是 Envoy 中的路由配置來(lái)決定的了,對(duì)于靜態(tài)配置我們清楚直接在 Envoy 配置文件中就可以看到,比如:

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

但是我們這里的路由配置是動(dòng)態(tài)配置的,我們看到對(duì)應(yīng)的配置中有一個(gè) rds 字段,這個(gè)字段就是用來(lái)指定動(dòng)態(tài)路由配置的,其中的 routeConfigName 字段就是用來(lái)指定對(duì)應(yīng)的路由配置名稱(chēng)的:

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

RoutesConfigDump

這里面保存著 Envoy 的路由配置,和 listeners 一樣,RoutesConfigDump 也分為 static_route_configs 和 dynamic_route_configs,分別對(duì)應(yīng)著靜態(tài)的路由配置和動(dòng)態(tài)下發(fā)的路由配置。

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

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

對(duì)應(yīng)的配置如下所示:

- 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

后面的兩個(gè) virtualHosts 就是我們的靜態(tài)路由配置,第一個(gè)是動(dòng)態(tài)的路由配置,我們可以看到該配置的名稱(chēng)就是 http.8080,是不是和前面的 routeConfigName 是一致的。那么這個(gè)配置又是什么地方定義的呢?

其實(shí)仔細(xì)看這里面的配置和前面我們創(chuàng)建的 VirtualService 這個(gè)資源對(duì)象是不是很像,我們?cè)倏聪虑懊鎰?chuàng)建的 VirtualService 對(duì)象的定義:

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 對(duì)象中定義了 5 個(gè)路由規(guī)則,而這里的 RoutesConfigDump 中也定義了 5 個(gè)路由規(guī)則,VirtualService 中定義的 5 個(gè)路由分別為 /productpage/static/login/logout/api/v1/products,而 RoutesConfigDump 中定義的 5 個(gè)路由分別為 /productpage/static/login/logout/api/v1/products,是不是一一對(duì)應(yīng)的。最終匹配這些路由規(guī)則的請(qǐng)求是被轉(zhuǎn)發(fā)到 productpage 這個(gè)服務(wù)的 9080 端口的。

比如 /productpage 這個(gè)路由規(guī)則對(duì)應(yīng)的 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

這個(gè)配置就是我們熟悉的 Envoy 的關(guān)于虛擬主機(jī)部分的配置,比如當(dāng)我們請(qǐng)求的路徑為 /productpage 時(shí),就會(huì)被這個(gè)路由規(guī)則匹配到,然后就用通過(guò) route 字段來(lái)描述我們的路由目標(biāo)了,針對(duì)這個(gè)目錄,可以看到有一些類(lèi)似于 retry_policytimeout等字段來(lái)配置這個(gè)目標(biāo)的超時(shí)、重試策略等,不過(guò)最重要的還是 cluster 這個(gè)字段,它指定了這個(gè)路由目標(biāo)對(duì)應(yīng)著哪個(gè)上游集群,Envoy 最終將請(qǐng)求發(fā)送到這個(gè) Cluster,比如我們這里的集群名稱(chēng)為 outbound|9080||productpage.default.svc.cluster.local,關(guān)于其具體配置我們就要去查看 ClustersConfigDump 中的配置了。

ClustersConfigDump

該部分是用來(lái)存儲(chǔ) Envoy 的集群配置的,同樣也分為 static_clusters 和 dynamic_active_clusters,分別對(duì)應(yīng)著靜態(tài)配置和動(dòng)態(tài)下發(fā)的配置。這里的 Cluster 集群是 Envoy 內(nèi)部的概念,它是指 Envoy 連接的一組邏輯相同的上游主機(jī),并不是說(shuō) K8s 集群,只是大多數(shù)情況下我們可以把這個(gè)集群理解為 K8s 集群中的一個(gè) Service,一個(gè) Service 通常對(duì)應(yīng)著一組 Pod,由這組 Pod 響應(yīng)請(qǐng)求并提供同一種服務(wù),而 Envoy 的這個(gè)集群實(shí)際可以理解成這種Pod 集合。不過(guò) Envoy 的一個(gè)集群也不一定就對(duì)應(yīng)著一個(gè) Service,因?yàn)榧菏?strong>一組邏輯相同的上游主機(jī),所以也有可能是別的符合定義的東西,比如說(shuō)是服務(wù)的一個(gè)特定版本(如只是 v2 版本的 reviews 服務(wù))。istio 的版本灰度能力就是基于這個(gè)做的,因?yàn)閮蓚€(gè)版本的同一服務(wù)實(shí)際上可以分成兩個(gè)集群。

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

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

該配置文件會(huì)非常長(zhǎng),它會(huì)將 K8s 集群中的 Service 都轉(zhuǎn)換成 Envoy 的 Cluster,這里我們只看下 productpage 這個(gè)服務(wù)對(duì)應(yīng)的 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

我們可以看到這個(gè) Envoy Cluster 的名稱(chēng)為 outbound|9080||productpage.default.svc.cluster.local,和前面的路由配置中的 cluster 字段是一致的,名稱(chēng)大多數(shù)會(huì)由 | 分成四個(gè)部分,分別是 inbound 或 outbound 代表入向流量或出向流量、端口號(hào)、subcluster 名稱(chēng)(就是對(duì)應(yīng)著 destination rule 里的 subset)、Service FQDN,由 istio 的服務(wù)發(fā)現(xiàn)進(jìn)行配置,通過(guò)這個(gè) name 我們很容易就能看出來(lái)這個(gè)集群對(duì)應(yīng)的是 K8s 集群的哪個(gè)服務(wù)。

然后配置的負(fù)載均衡策略是 LEAST_REQUEST,另外比較重要的這里的配置的類(lèi)型為 type: EDS,也就是會(huì)通過(guò) EDS 來(lái)發(fā)現(xiàn)上游的主機(jī)服務(wù),這個(gè) EDS 的配置如下所示:

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

基于 EDS 去動(dòng)態(tài)發(fā)現(xiàn)上游主機(jī)的配置,其實(shí)在前面的 Envoy 章節(jié)我們已經(jīng)介紹過(guò)了,和這里是不是幾乎是一致的,serviceName 其實(shí)就對(duì)應(yīng)著 K8s 集群中的 productpage 這個(gè) Service 對(duì)象的 9080 端口,而這個(gè) Service 對(duì)象對(duì)應(yīng)著一組 Pod,這組 Pod 就是我們的上游主機(jī)了。當(dāng)然這是通過(guò) xDS 協(xié)議下發(fā)的,我們可以通過(guò) istioctl proxy-config endpoint 命令來(lái)查看這部分配置:

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

該部分?jǐn)?shù)據(jù)非常多,下面只截取 productpage 相關(guān)的數(shù)據(jù),如下所示:

- 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

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

address:
  socketAddress:
    address: 10.244.2.62
    portValue: 9080

這個(gè)地址其實(shí)就是 productpage 這個(gè) K8s Service 關(guān)聯(lián)的 Pod 的地址。這樣一個(gè)請(qǐng)求從進(jìn)入到 Envoy 到最終轉(zhuǎn)發(fā)到后端服務(wù)的過(guò)程就清楚了。

SecretsConfigDump

由于網(wǎng)格中的 Envoy 之間互相通信會(huì)使用 mTLS 模式,因此每個(gè) Envoy 通信時(shí)都需要提供本工作負(fù)載的證書(shū),同時(shí)為了簽發(fā)證書(shū)還需要 istio ca 的根證書(shū),這些證書(shū)的信息保存在該配置項(xiàng)之下。

總結(jié)

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

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

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

我們可以使用 envoyui.solo.io 這個(gè)在線(xiàn)的 Envoy 配置可視化工具來(lái)查看 Envoy 的配置,只需要將我們的 Envoy 配置 dump 出來(lái)上傳上來(lái)即可:

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

經(jīng)過(guò)上面的分析我們也明白了其實(shí) Istio 并沒(méi)有實(shí)現(xiàn)很多復(fù)雜的邏輯,服務(wù)治理相關(guān)的功能比如負(fù)載均衡、故障注入、權(quán)重路由等都是 Envoy 本身就有的能力,Istio 只是將這些能力抽象成了一個(gè)個(gè)資源對(duì)象,然后通過(guò) Envoy 的 xDS 協(xié)議下發(fā)到 Envoy 中,這樣就能夠?qū)崿F(xiàn)對(duì) Envoy 的流量治理了。所以重點(diǎn)還是需要我們先理解 Envoy 的配置,然后再去理解 Istio 的配置,這樣才能更好的理解 Istio,不然你就不清楚 Gateway、VirtualService 等這些資源對(duì)象到底是干什么的,它們是如何影響 Envoy 的配置的。

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

分享到:
標(biāo)簽:Istio Envoy
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定