easegress-io/easegress

[Question]: When using Easegress as an Ingress controller, how can I add a global filter to the default HTTP server?

tjqc0512 opened this issue · 8 comments

This is not Bug report or Feature request

  • I confirm that this is not bug report or feature request.

Is this question answered in the documentation?

  • I have searched the documentation

Is there an existing issue for this?

  • I have searched the existing issues

Your question

When using Easegress as an Ingress controller, I want to add a global filter to the default HTTP server created by the Easegress Ingress controller, to ensure all traffic first passes through the global filter before being forwarded to the backend services.
I have already configured a global filter for the HTTP server in the controller.yaml, but it does not take effect. All traffic is directly forwarded to the backend services without going through the global filter.

apiVersion: v1
data:
  easegress-server.yaml: |
    name: ingress-easegress
    cluster-name: easegress-ingress-controller
    cluster-role: primary
    api-addr: 0.0.0.0:2381
    data-dir: /opt/easegress/data
    log-dir: /opt/easegress/log
    debug: true
    log: info
  controller.yaml: |
    kind: IngressController
    name: easegress-ingress-controller
    namespaces:
    - ingress-easegress
    - gw-cscc
    - test
    ingressClass: easegress
    httpServer:
      globalFilter: global-filter
      port: 8080
      https: false
      keepAlive: true
      keepAliveTimeout: 60s
      maxConnections: 10240   

However, in a new HTTP server that I created within the Easegress ingress controller, the traffic can normally pass through the global filter. Is it because the default HTTP server created by the Easegress ingress controller does not support configuring global filters?

  pip.yaml: |
    kind: HTTPServer
    name: httpserver-test-rsa
    globalFilter: global-filter
    port: 8081
    rules:
      - paths:
        - pathPrefix: /service2
          backend: pipeline-demo
    ---    
    name: pipeline-demo
    kind: Pipeline
    flow:
      - filter: rsa
        jumpIf:
          invalid: END
      - filter: proxy         
    filters:
      - name: rsa
        kind: Validator 
        headers:
          Is-Valid:
            values: ["abc", "goodplan"] 
      - name: proxy
        kind: Proxy
        pools:
        - servers:
          - url: http://hello-service:60002
          loadBalance:
            policy: roundRobin
    ---
    name: global-filter
    kind: GlobalFilter
    beforePipeline:
      flow:
        - filter: rsaAuthFilter
      filters:
        - name: rsaAuthFilter
          kind: RsaAuthFilter   

Can you post the log of the ingress controller pod, and is there any error that occurred?

Hi, easegress ingress controller implements the standard of k8s ingress controller. So, the globalFilter is not support yet.

But i have just checked the code and find it seems simple to add this feature.

func newHTTPServerSpecBuilder(template *httpserver.Spec) *httpServerSpecBuilder {
	return &httpServerSpecBuilder{
		Kind: httpserver.Kind,
		Name: "http-server-ingress-controller",
		Spec: httpserver.Spec{
			Port:             template.Port,
			KeepAlive:        template.KeepAlive,
			HTTPS:            template.HTTPS,
			KeepAliveTimeout: template.KeepAliveTimeout,
			MaxConnections:   template.MaxConnections,
		},
	}
}

the problem is when create builder for httpserver in ingress controller, template.GlobalFilter is not copied. And since GlobalFilter is a business controller, httpserver in ingress controller namespace can get it.

What do you think @xxx7xxxx? I can't see why we not support this feature?

Can you post the log of the ingress controller pod, and is there any error that occurred?

The logs do not show any exceptions, but the traffic is not passing through the global filter.
2024-03-13T09:38:46.998Z DEBUG httpserver/mux.go:395 http-server-ingress-controller: the matched backend(Pipeline) for [POST /WF_BEIJING] is "pipeline-ingress-easegress-hello-service-60001"
[2024-03-13T09:38:46.998Z] [10.42.0.1:63350 10.42.0.1 POST /WF_BEIJING HTTP/1.1 200] [8.92ms rx:640B tx:186B] [status code: 200 | pipeline(pipeline-ingress-easegress-hello-service-60001): proxy(6.868ms) | proxy#proxy#main#duration: 8.383ms]

Sure, we could support it by adding the copy line, and a profound solution would be adding a general HTTPServerSpeBuilder for all of them. @tjqc0512 Do you want to address this issue?

➜  easegress  rg newHTTPServerSpecBuilder
pkg/object/gatewaycontroller/translator.go
289:func newHTTPServerSpecBuilder(name string) *httpServerSpecBuilder {
590:    sb := newHTTPServerSpecBuilder(fmt.Sprintf("http-server-%s-%s", g.Name, l.Name))

pkg/object/meshcontroller/worker/egress.go
101:func newHTTPServerSpecBuilder(httpServerName string, spec *httpserver.Spec) *httpServerSpecBuilder {
526:    builder := newHTTPServerSpecBuilder(egs.egressServerName, httpServerSpec)

pkg/object/function/worker/ingress.go
99:func newHTTPServerSpecBuilder(controllerName string) *httpServerSpecBuilder {
194:    builder := newHTTPServerSpecBuilder(ings.superSpec.Name())
212:    builder := newHTTPServerSpecBuilder(ings.superSpec.Name())

pkg/object/ingresscontroller/translator.go
174:func newHTTPServerSpecBuilder(template *httpserver.Spec) *httpServerSpecBuilder {
482:    b := newHTTPServerSpecBuilder(st.httpSvrCfg)

Hi, easegress ingress controller implements the standard of k8s ingress controller. So, the is not support yet.globalFilter

But i have just checked the code and find it seems simple to add this feature.

func newHTTPServerSpecBuilder(template *httpserver.Spec) *httpServerSpecBuilder {
	return &httpServerSpecBuilder{
		Kind: httpserver.Kind,
		Name: "http-server-ingress-controller",
		Spec: httpserver.Spec{
			Port:             template.Port,
			KeepAlive:        template.KeepAlive,
			HTTPS:            template.HTTPS,
			KeepAliveTimeout: template.KeepAliveTimeout,
			MaxConnections:   template.MaxConnections,
		},
	}
}

the problem is when create builder for httpserver in ingress controller, is not copied. And since is a business controller, httpserver in ingress controller namespace can get it.template.GlobalFilter``GlobalFilter

What do you think @xxx7xxxx? I can't see why we not support this feature?

Sure, I appreciate your guidance. I'll try modifying this feature and rebuild the easegress-server for testing. Additionally, I have a question regarding how to print logs or output logs to a file for a custom-developed filter. Currently, I'm using the github.com/megaease/easegress/pkg/logger library for logging, but it's not outputting logs as expected, for example, logger.Warnf("RsaAuthFilter: 'X-Custom-WF-Name' header is not a string"). I've also tried solutions I found through searching, but none have been successful.

but it's not outputting logs as expected

What's the detail? Does it print all logs except for the log you added? It can't be.

but it's not outputting logs as expected

What's the detail? Does it print all logs except for the log you added? It can't be.

I am unable to print and output logs for all operations within my custom filter. I don't know how to implement printing and outputting logs for debugging purposes.

I don't know the reason. If other filters can print logs, yours can not be the exception. Do you register your filter in source code and make it sure that it has run? Or Just panic in your code to assert that your code has been executed.