slime-io / slime

An intelligent ServiceMesh manager based on Istio
https://slime-io.github.io/
Other
424 stars 78 forks source link

Proposal: Lazyload use envoy as a global sidecar for supporting multi protocol #373

Closed Patrick0308 closed 1 year ago

Patrick0308 commented 1 year ago

影响的子模块(在下面列表中打'X')

问题背景 lazy load not support grpc 您的提案内容

Using envoy as global sidecar because its pluginability and updating configuration dynamically.

Architecture

image

H1/H2

envoy configuration example:

static_resources:
  listeners:
  - address:
      socket_address:
        address: 0.0.0.0
        port_value: 20000
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          access_log:
          - name: envoy.access_loggers.stdout
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
          codec_type: AUTO
          stat_prefix: health 
          use_remote_address: true
          route_config:
            name: health 
            virtual_hosts:
            - name: all
              domains:
              - "*"
              routes:
              - match:
                  prefix: "/"
                direct_response:
                  status: 200
                  body:
                    inline_string: "success"
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  - address:
      socket_address:
        address: 0.0.0.0
        port_value: 80
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          codec_type: AUTO
          access_log:
          - name: envoy.access_loggers.stdout
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
          stat_prefix: egress_http
          common_http_protocol_options:
            idle_timeout: 840s
          use_remote_address: true
          route_config:
            name: proxy 
            virtual_hosts:
            - name: all
              domains:
              - "*"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: original_dst_cluster 
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
  - cleanupInterval: 8640000s
    connectTimeout: 10s
    lbPolicy: CLUSTER_PROVIDED
    name: original_dst_cluster 
    type: ORIGINAL_DST
    original_dst_lb_config:
      use_http_header: true
      http_header_name: "Slime-Orig-Dest"
    typedExtensionProtocolOptions:
      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
        '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
        useDownstreamProtocolConfig:
          http2ProtocolOptions:
            maxConcurrentStreams: 1073741824
          httpProtocolOptions: {}

h1/h2 On Same Svc's Same Port

Now global sidecar svc port protocol is http. Istio inbound sidecar will downgrade http2 to http1. This a way to support it. Configure:

apiVersion: v1
kind: Service
metadata:
  annotations:
    meta.helm.sh/release-name: lazyload
    meta.helm.sh/release-namespace: mesh-operator
  labels:
    app: global-sidecar
    app.kubernetes.io/managed-by: Helm
    service: global-sidecar
  name: global-sidecar
  namespace: mesh-operator
spec:
  ports:
  - name: http2-80
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: global-sidecar
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: global-sidecar
  namespace: mesh-operator
spec:
  host: global-sidecar.mesh-operator.svc.cluster.local
  trafficPolicy:
    connectionPool:
      http:
        useClientProtocol: true

Other protocol

Lazyload create svc for each other protocol and update to-global-sidecar envoy filter.

YonkaFang commented 1 year ago

感谢。 grpc的支持确实是比较关注的点。

请问有没有相关信息能提供一下,比如用于验证功能的grpc(consumer、provider)demo、global sidecar 镜像 等?

Patrick0308 commented 1 year ago

@YonkaFang global sidecar 镜像:https://hub.docker.com/r/patrick0308/slime-envoy grpc demo: https://github.com/h3poteto/istio-grpc-example

MouceL commented 1 year ago

用envoy替代global-sidecar需要注意以下几点

  1. 目前没有纳管http外的port (TODO)

导致grpc server相关listener未下发,grpc client请求根本走不到兜底逻辑,需要将http/http2/grpc类型的端口都纳管进来

  1. 共用80端口问题

http1.1请求和grpc请求都被兜底到 outbound|80||global-sidecar.mesh-operator.svc.cluster.local

  - name: http-80
    port: 80
    protocol: TCP
    targetPort: 80

那么http1.1请求可以正常转发,而grpc请求在global-sidecar中会被降级成http1.1

  - name: http2-80
    port: 80
    protocol: TCP
    targetPort: 80

那么grpc请求可以正常转发,而http1.1请求会被升级成http2.0


为了解决这个第2点,我们需要指定 useClientProtocol:true

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: global-sidecar
  namespace: mesh-operator
spec:
  host: global-sidecar.mesh-operator.svc.cluster.local
  trafficPolicy:
    connectionPool:
      http:
        useClientProtocol: true

最后形态是:指定http2端口 + 下发useClientProtocol:true

结果:grpc请求由于指定了http2而正常转发,http1.1请求也因为指定了useClientProtocol:true而按照客户端协议转发

  1. 目前还存在一个问题 (TODO)

短域名请求,在global-sidecar转发中,只能走passthrough

believening commented 1 year ago

用envoy替代global-sidecar需要注意以下几点

  1. 目前没有纳管http外的port (TODO)

导致grpc server相关listener未下发,grpc client请求根本走不到兜底逻辑,需要将http/http2/grpc类型的端口都纳管进来

  1. 共用80端口问题

http1.1请求和grpc请求都被兜底到 outbound|80||global-sidecar.mesh-operator.svc.cluster.local

  • 如果global-sidecar端口写成http
  - name: http-80
    port: 80
    protocol: TCP
    targetPort: 80

那么http1.1请求可以正常转发,而grpc请求在global-sidecar中会被降级成http1.1

  • 如果global-sidecar端口写成http2
  - name: http2-80
    port: 80
    protocol: TCP
    targetPort: 80

那么grpc请求可以正常转发,而http1.1请求会被升级成http2.0

为了解决这个第2点,我们需要指定 useClientProtocol:true

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: global-sidecar
  namespace: mesh-operator
spec:
  host: global-sidecar.mesh-operator.svc.cluster.local
  trafficPolicy:
    connectionPool:
      http:
        useClientProtocol: true

最后形态是:指定http2端口 + 下发useClientProtocol:true

结果:grpc请求由于指定了http2而正常转发,http1.1请求也因为指定了useClientProtocol:true而按照客户端协议转发

  1. 目前还存在一个问题 (TODO)

短域名请求,在global-sidecar转发中,只能走passthrough

使用 envoy 作为 global sidecar 的 proxy,还存在如下问题需要评估:

ZPerling commented 1 year ago

这个问题是说当前的实现是不支持grpc或者triple协议的吗?

MouceL commented 1 year ago

这个问题是说当前的实现是不支持grpc或者triple协议的吗?

不支持grpc,更不支持triple

最近想推进grpc懒加载的支持

MouceL commented 1 year ago
  • proxy 演进维护的成本,后续对于代理本身的特性需求需要转化对 envoy 的需求

proxy 演进维护的成本,后续对于代理本身的特性需求需要转化对 envoy 的需求

这个确实是这样,如果slime自身维护,想怎么加功能都行

如果依赖envoy,就不是很好的推进

Patrick0308 commented 1 year ago

@MouceL triple 是基于 http2 的,支持 http2 应该就支持 triple 了。

proxy 演进维护的成本,后续对于代理本身的特性需求需要转化对 envoy 的需求

关于这点的话 envoy 有很好的扩展性,大部分需求都能通过自定义 filter 实现。