Closed chrissainty closed 1 month ago
@chrissainty absolutely would like to get a sample in place. The Readme documents the usage obviously but I was thinking of a simple demo aspire project that maybe shows how it can be setup to validate JWT tokens in KrakenD at the perimeter for APIs. I am doing this in a private repo at the moment.
That said PRs are certainly welcome ;-)
Hope to get to this soon though. Thanks for the interest!
Thanks for the response. I'd be happy to help with a PR, but I can't get a working configuration right now, hence wanting a sample myself.
I've got KrakenD setup with your package as you've stated in the README. I"m struggling with the endpoint configuration. For example:
"endpoints": [
{
"endpoint": "/v1/accounts",
"backend": [
{
"url_pattern": "/v1/accounts",
"method": "GET",
"host": ["http://localhost:5376"]
}
]
}
],
How do I provide the Aspire service discovery domain instead of hard coding localhost and port number? Also hardcoding localhost and port number doesn't work either, the connection gets refused. Not sure why yet.
This is what I think I should be able to do:
"endpoints": [
{
"endpoint": "/v1/accounts",
"backend": [
{
"url_pattern": "/v1/accounts",
"method": "GET",
"host": ["http://accountsapi"]
}
]
}
],
This should then use the Aspire service discovery. But the logs just show the following error:
KRAKEND ERROR: [ENDPOINT: /v1/accounts] Get "[http://accountsapi/v1/accounts"](http://accountsapi/v1/accounts%22);: dial tcp: lookup accountsapi on 192.168.65.7:53: no such host
Am I way off on this? Documentation on using any API Gateways with Aspire seem almost non-existent which seems really strange as to me, any real distributed system would need a gateway. Maybe Aspire just isn't intended for real world use yet or I'm misunderstanding it's purpose.
Any help would be appreciated.
If I get a chance to make up an example this weekend I'll try. In the meantime, service discovery as I understand it requires http client awareness. So KrakenD is not going to work that way.
However, here is a snippet (haven't had the chance to make it dynamic yet with aspire env vars) to help in the short term. You have to use the docker (or podman) url since it's inside the cluster (without external endpoint/ingress). This works the same way the OTEL collector running in cluster is communicated with.
"endpoints": [
{
"endpoint": "/v1/test",
"method": "GET",
"input_query_strings": ["*"],
"output_encoding": "json-collection",
"backend": [
{
"host": [ "http://host.docker.internal:5118" ],
"url_pattern": "/test",
"is_collection": true
}
],
Hope this helps! I would use the env vars (like the OTEL example) to pass all the host values to the array.
@chrissainty I have added an example project https://github.com/NapalmCodes/Aspire.Hosting.Krakend/tree/main/examples
This covers using KrakenD flexible configuration to bring env vars over from Aspire into the configuration. One thing to note is this will only work currently (locally) with one replica of an API Service unless a YARP proxy is defined between the gateway and API instances (maybe as a sidecar). Not ideal but YARP is service discovery aware. I think the Aspire team is planning and designing a better story for this but seems to be what we have now. You could codify the backend host urls manually, that is certainly an alternative that will work (i.e.: providing each replica's host values and ports) as well.
Let me know if you have any questions and if this meets your needs.
I am debating the possibility of having a "sub resource" or sidecar as part of this project that just forwards to service discovery. That would make KrakenD a lot more user friendly in Aspire and having it work as expected out of the box.
I think you could do this and have it be a resource that is not deployed by azd
. If K8S was the deployment target it could just use DNS SRV to resolve service replicas. Thoughts?
Thanks for the example project, it's really appreciated. I've got everything working and debugging through has allowed me to understand a bit more about what is going on.
I think the addition of a sub resource/side-car would be extremely valuable. Having to do what's in the example project isn't a great experience for developers. I spent a few hours wrestling with it just to delete all the Go script from my krakend.json and re-add it and everything just work. I must have had a slight typo or extra space or something really small wrong somewhere. But my point is it's really fiddly.
Part of that is KrakenD's flexible config model. It's not valid JSON and editing in a json editor gets really fiddly. Not much I can do there. But with the sidecar theoretically this becomes a set and forget. The developer would never need to touch it.
Oh yeah, I totally understand. Sorry that wasn't meant as a criticism of what you've built. But if we can find a way to minimise that, then it can only be a good thing.
For now going to close this and create an issue for sidecar referencing this.
@chrissainty I could use an opinion.
I think this might be a dead end with the sidecar. I was thinking about this. The goal of the sidecar in my mind was to enable service discovery for KrakenD. However, service discovery is an HTTP Client feature in .NET/Aspire. This only works if it is resolvable via env vars (as it works locally with Aspire) OR via DNS as a cluster environment would have available.
Long story short, there is no DNS SRV in the DCP network that we can interact with to my knowledge. Therefore, the only way to do this from what I have seen so far is to bind the endpoint (i.e.: host.docker.internal address(es)) OR it does work if you run the YARP proxy from a project within your solution locally (not via container).
So I think what I plan on doing is making the example utilize the lightweight proxy project I have been testing with and recommending to consumers of this package that to handle advanced scenarios like this you can either not worry about running multiple replicas locally or if you want here is a YARP project you can drop in to wire up KrakenD to.
Thoughts/ideas etc are welcome.
Update: I have this working statically. I need to figure out how to make things more dynamic.
Hey @NapalmCodes, great work on the component. It would be fantastic if there was an example solution to see everything running. Are there any plans for something like that?
Cheers