Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#5641: add fastcgi support for kong #5642

Closed
wants to merge 3 commits into from
Closed

Conversation

roodkcab
Copy link

@roodkcab roodkcab commented Mar 6, 2020

Summary

we use kong as our api-gateway, while we have quite a lot php-fpm running with nginx as service using fastcgi protocol. As u can see, the only purpose of nginx is to transform http to fastcgi, and I'd like to remove such middle layer via moving such function into kong, since resty can easily proxy fastcgi program using fastcgi_pass

Full changelog

  • [Implement]
    support for service using fastcgi protocol

  • [Unit Test]
    pass all unit test

add service via
curl -i -X POST --url http://localhost:8001/services/ --data 'name=example-service' --data 'url=fcgi://{fcgi_host}:{fcgi_port}/{fcgi_script_filename}'

Issues resolved

Fix #5641

@CLAassistant
Copy link

CLAassistant commented Mar 6, 2020

CLA assistant check
All committers have signed the CLA.

@roodkcab
Copy link
Author

roodkcab commented Mar 6, 2020

how to trigger ci? retest

@hishamhm
Copy link
Contributor

hishamhm commented Mar 9, 2020

Hi @roodkcab! Thank you for the pull request, that is an intriguing idea and it spurred a lot of conversation within our development team!

Ultimately, though, we concluded that hardcoding fcgi as a supported "protocol" is not the way to go. In spite of the surface similarity with the gRPC implementation in this PR, fcgi would work more like a local content producer within the same server (as evidenced by its configuration via environment variables) than a proper proxying protocol. Implementation-wise, the PHP-specific configurations would also be a blocker, but generally the conclusion is that this strays a bit too much from Kong's main focus as an API gateway to be a core feature.

Having said that, we have always supported customizing Kong's nginx template so that additional location blocks can be added to allow the Kong process to perform double-duty as both a reverse proxy and serving other kinds of data (made especially easy via include injection rules).

We do have thoughts in mind about making protocol support more extensible, which could possibly open the door for implementing this in different ways, though, so stay tuned!

@hishamhm hishamhm closed this Mar 9, 2020
@guanlan guanlan mentioned this pull request Mar 9, 2020
@roodkcab
Copy link
Author

roodkcab commented Mar 10, 2020

@hishamhm thank u for telling me your conversation on this pr, really appreciate. Please let me explain a little bit of this pull request

fcgi would work more like a local content producer within the same server

I think it's a mistake due to a lot environment set in @fcgi configuration, actually I use kong-ingress with kong as api-gateway on our k8s cluster, while php-fpm is running on a totally different node. I think the only useful environment here is upstream_path which is get from service entity of Kong.

as u can see here, upstream_path is set as {fcgi_script_filename}
curl -i -X POST --url http://localhost:8001/services/ --data 'name=example-service' --data 'url=fcgi://{fcgi_host}:{fcgi_port}/{fcgi_script_filename}'

image

I have to get protocol and path from service entity, so that I can delegate multiple php-fpm service using kong gateway.

we have always supported customizing Kong's nginx template

I don't think nginx template is a right way to solve my problem. Let me give u an example, and I'd like to have a discussion here.

As u know, Kong ingress will automatically recognize service using Ingress configuration in k8s

kind: Service
metadata:
  name: demo
  namespace: qa
spec:
  type: ClusterIP
  ports:
  - name: demo-fpm
    port: 9000
  selector:
    app: demo
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: demo
  namespace: demo
spec:
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          serviceName: demo
          servicePort: 9000

here we have an Ingress which point example.com to service demo:9000, and kong will automatically recognize it as a service, with @fcgi support, kong cloud proxy such request directly to fastcgi protocol on port 9000.

a customizing nginx template will surely get the job done, but that would be a lot of work, I have to write such template for each service manually, and I'm warring about such template may broke configuration generated by ingress itself, due to duplicate server name.

if I remove all environment set in @fcgi except for upstream_path, it still work, cause it only a proxy not a Nginx running with php-fpm. I don't think it breaks the the main focus of Kong, i.e. being an api gateway, php-fpm is just like go program using grpc protocol or other program using http protocol as a service.

Though I'm glad to hear u are thinking about extending protocol in an easy way, looking forward on that feature.

@kasnet
Copy link

kasnet commented Apr 21, 2020

@roodkcab Hello, when dose this pr release? Thanks

@roodkcab
Copy link
Author

@kasnet it seems kong team will not merge this pr, I'm planning to maintain a fork myself, I'll rebase to 2.0 of kong asap, and release on my own branch, i.e. roodkcab:fastcgi.

@roodkcab
Copy link
Author

roodkcab commented Apr 23, 2020

this feature is fully tested and been deployed to our kubernetes production cluster, we also modify kong-ingress a little bit so that it will automatically set path from service discovering. Again we do hope kong dev team to consider merge this pr, since there's a lot's of PHP/Python/Perl projects using fastcgi protocol, without kong, all of such project have to add a nginx container in Pod to delegate http request. I think kong dev team is focusing on something more important, so currently I'll try to maintain such feature, i.e. rebase to latest release branch, till they have more time to discuss this pr again.

To anyone who like this pr, please vote for it, cheers.

@kasnet
Copy link

kasnet commented Apr 24, 2020

I agree with your idea, vote for this, thank you @roodkcab

@roodkcab
Copy link
Author

code has been rebased to the latest master branch for both

https://github.com/roodkcab/kong
https://github.com/roodkcab/kubernetes-ingress-controller

on fastcgi branch.

@samhuss
Copy link

samhuss commented Mar 11, 2021

Thank you @roodkcab, I'm trying to use your implementation on your branch, however I'm struggling with setting up the ingress correctly so kong can recognize it as fcgi, would you please give a sample description for a [deployment, service, ingress] files.
Thanks again

@roodkcab
Copy link
Author

@samhuss you can add such annotations into your service and kong-ingress should automatically configure a @FCGI ingress

apiVersion: v1
kind: Service
metadata:
  name: byte
  namespace: online
  annotations:
    configuration.konghq.com/protocol: "fcgi"
    configuration.konghq.com/port: "9000"
    configuration.konghq.com/path: "/var/www/byte/public/index.php"

@samhuss
Copy link

samhuss commented Mar 13, 2021

@roodkcab thanks for your reply, it works now on my local kong setup using the service configuration below. My local php service is running in docker-compose under /app/public folder so I changed the path to the target service.

curl -XPATCH localhost:8001/services/fcgi \
  --data name=fcgi \
  --data protocol=fcgi \
  --data host=127.0.0.1 \
  --data port=9000 \
  --data path=/app/public/fcgi/index.php

With this setup, the php file path is always defined through the annotation path value, however if I want to call another sub-folder with another file name, I have to create another igress or route with the new file.

I was thinking of creating a new version of the service with 2 modifications:

  • a root annotation parameter that is always fixed for the specific backend php services: ex: /app/public/
  • instead of passing fastcgi_pass $kong_upstream, I will use the normal route URI that is coming from the route call like: http://localhost/fcgi/ and then form a new fastcgi_pass like this: $root/fcgi/index.php:$port

This way I will use one ingress per backend php server (micro service) and forward to the targeted folders under this service root directly from the url.

@roodkcab
Copy link
Author

@samhuss

With this setup, the php file path is always defined through the annotation path value, however if I want to call another sub-folder with another file name, I have to create another igress or route with the new file.

right, my modification doesn't support for multiple routes. since almost all of our PHP services handle route themselves. the only thing we need to define in ingress is the location of the project's index.php.

for those services with extra php file to use, we simply define an extra service, and make different ingress rules point to each service respectively.

@deehidayat
Copy link

Imagine having many microservices based on fastcgi and each service still requiring nginx before Kong could access it. I voted for this feature so that we can eliminate one layer and quickly publish fastcgi (and similar protocol) apps directly from Kong.

@muhammad-rizwan
Copy link

This would be something really nice to have, as we move more towards event driven architecture with more apis in place, having an extra layer of Nginx just for fast-cgi params, is waste of resources.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants