microsoft / azure-container-apps

Roadmap and issues for Azure Container Apps
MIT License
372 stars 29 forks source link

Feature Request: ability to expose multiple ports #546

Open ronikurnia1 opened 1 year ago

ronikurnia1 commented 1 year ago

Is your feature request related to a problem? Please describe.
No

Describe the solution you'd like.
I need to be able to deploy a container which exposes more than one port (e.g. 2 ports)

Describe alternatives you've considered.
It would be great if we can setup multiple ingress for a container

anthonychu commented 1 year ago

@ronikurnia1 Can you please provide details on one or more concrete scenarios you're hoping to support? Thanks.

amolenk commented 1 year ago

I have the same request as @ronikurnia1

Currently, I'm blocked in the following scenario's:

  1. Customer scenario running Mosquitto MQTT broker. In this scenario, Mosquitto requires two separate listeners. A web application publishes messages to Mosquitto using the web sockets protocol (port 9001). A back-end microservice handles the incoming messages by connecting to Mosquitto using the MQTT protocol (port 1883). So I'd need to be able to set up public ingress on port 9001 and internal ingress on port 1883.

  2. Dev/test scenario using maildev. Maildev is a simple container for testing sending e-mails. It uses two ports: one for SMTP and one for hosting a user interface. I'd like to have both ports publicly exposed.

ronikurnia1 commented 1 year ago

Hi @anthonychu,

The same scenarios as @amolenk describe - need more then 1 port get exposed in one container.

duglin commented 1 year ago

@amolenk just curious, on the first scenario (Mosquitto), do you scale the app beyond 1 instance?

amolenk commented 1 year ago

@duglin No, not at the moment. In this scenario the messages are really lightweight and a single instance is sufficient. The first thing that'd need scaling will probably be the backend microservice that's actually processing the incoming messages.

duglin commented 1 year ago

that's what I figured, and I'm in no way suggesting this as a long-term solution, but as a quick hack to unblock things you might be able to have the backend talk to the broker on port 1883 if you talk to the instance directly (via ip). I don't know for sure if any networking policy would block it, but if not, then it should work since you're avoiding the ACA envoy/proxy stuff. Meaning, just don't try to tell ACA about 1883, just setup a listener and do pod->pod communications - no networking magic involved. Just a thought and yes it's risky if the IP changes :-)

amolenk commented 1 year ago

That's interesting; is there some programmatic way to find out the internal IP adres of an ACA App?

duglin commented 1 year ago

hmm I thought the IP might appear in the "show" output but I guess not. @ahmelsayed is there a way to get this info?

Other options:

Not thrilled with the options, but perhaps adding the IP of each replica to the "show" output would be an easy change? @ahmelsayed

kovla commented 1 year ago

The service is called "Apps" not "Web Apps", which is somewhat misleading given that only standard http/https ports are exposed. There are many applications that expose multiple ports. In our case, Neo4j database exposes one port for http(s) and another for its own bolt:// protocol. A full blown AKS just for this seems like an overkill, yet not much due to this limitation.

MirzaMerdovic commented 1 year ago

I would say that quite common scenario could be to have an app that exposes some grpc and rest endpoints and for that scenario you need to expose 2 ports.

Actually we are hitting this problem right now and to work around it we will have to use 2 Container Apps where one will serve rest traffic and other grpc which is just wasteful and I could go as far as to say that this is costing us more money then it should.

Hopefully this will get prioritized and enabled, as it a bit strange that this is possible to do with Container Instances

amolenk commented 1 year ago

Any roadmap updates on this?

Phiph commented 1 year ago

Linking another ticket to this one here https://github.com/microsoft/azure-container-apps/issues/201

While also offering a bump, I'd love to see this too!

nguyenlamlll commented 1 year ago

@anthonychu Honestly, isn't the service called "Azure Container Apps"?? Container. It's a container!!?? I am sorry, but I honestly do not understand why this isn't one of the basic features. It is a container, after all. We can expose multiple ports (in other words, more than 1 port) of a container. Many applications, many containers in this world expose more than 1 port. An example? Orthanc.

In fact, this simple feature was turned down coldly with #201. Such a big disappointment, tbh. I guess we can just move on and use another service, maybe from google cloud or AWS. Lol...

duglin commented 1 year ago

Just some clarifying questions:

MirzaMerdovic commented 1 year ago

@duglin answers from my point of view at least:

dhilgarth commented 1 year ago

if an app exposes multiple port is the assumption that all of them might be exposed on the internet? I'm assuming "yes"

Not in our scenario. Just like now, with the single ingress where we can define whether it's external or not, e.g. for the Test SMTP server - we are using mailhog - we just would have the dashboard in the internet, the SMTP port should be reachable only from within our VNET

what level of control do people need over the port numbers? This is important because with ACA managing the ingress supporting all possible ports would be challenge, especially if one port is use by multiple apps. So, supporting a fixed number of ports on certain port numbers (rather than any number and any random port numbers) is a much easier issue

I'm not sure I follow here. Why not just give use the ability to define internal target port and the external port it is being mapped to? Just like with Docker --port "7878:80". There would be no necessity for you to solve anything, it would be our responsibility to make sure that an externally mapped port is being used only by a single containerapp

if multiple ports were supported would support for HTTP(s)-related protocol be sufficient (w/o a custom vnet) ?

TCP support would be needed, again, take the test SMTP server as an example. Or a FastCGI application.

duglin commented 1 year ago

I'm not sure I follow here. Why not just give use the ability to define internal target port and the external port it is being mapped to? Just like with Docker --port "7878:80"

That gets to the heart of my question... do you care what the external port # is? And it looks like, for you, you don't. I can imagine a scenario where someone might claim that they need their users to send requests to a very specific external port # (e.g. port 25 for SMTP) but for HTTP flows it might be less critical. And for those cases where the external port # matters, like smtp, to limit it to just one containerapp it might require a custom vnet.

dhilgarth commented 1 year ago

The perspective of my answer is that of a microservices based distributed application that runs inside a custom VNET. I would like the freedom to specify the external ports on my own. And with "external", I don't necessarily mean "internet external". It could still very well just be reachable from within the VNET

CocoDico78 commented 1 year ago

all of them might be exposed on the internet

yes. There should be option to expose any nymber of additional ports to the internet.

do you care what the external port # is?

In our use case, the external ports doesn't really matter as long as they never change after deployment and that it's queryable after creation. Of course I'd rather have those ports be configurable (some clients are strict about this) and support other than just TCP.

would support for HTTP(s)-related protocol be sufficient

No. At least TCP, and even that restriction should be lifted to allow UDP as well.

akillablitz commented 1 year ago

Watching this thread closely...

Our use case was productionized Docker container for Keycloak IdP... it uses Infinispan distributed caching for performance... we changed discovery protocol from multicast UDP to JDBC_PING so instances record themselves in the DB, but ultimately the instances needed to talk internally on port 7800/TCP (default) to invalidate caches etc. so adding -p 7800:7800 in the docker run would be great.

AKS seemed to be the only viable option, but a significant change from our current pipeline. ACI Container Group was another option that could support resiliency, but seemed like a lot of manual overhead. ACA documentation around targetPort and exposedPort led us to believe this was not an option either.

Short term, we're down to a single instance App Service, losing resiliency, while we re-think and re-tool. :(

dhilgarth commented 1 year ago

This is becoming more and more of an issue in my setup. I need to deploy the OpenTelemetry Collector and it has 5 important ports, one of which is UDP. The corresponding docker-compose for local tests looks like this:

version: '3'
services:
  collector:
    image: otel/opentelemetry-collector-contrib:0.69.0
    volumes:
    - ./otel-config.yaml:/otel-config.yaml
    command: ["--config=/otel-config.yaml", "${OTELCOL_ARGS}"]
    environment:
      LOG_EXPORTER_LOG_LEVEL: "DEBUG"
    ports:
      - "4317:4317"     # grpc
      - "4318:4318"     # http
      - "13133:13133"   # health
      - "8006:8006"     # fluentdforward
      - "8006:8006/udp" # fluentforward

I want to deploy it to my custom VNET and expose all 5 ports to the VNET and additionally expose the http port (4318) to the internet.

dhilgarth commented 1 year ago

For anyone coming across this thread: Looks like they are discussing it for the roadmap: https://github.com/microsoft/azure-container-apps/issues/763 👍🏼

itpropro commented 1 year ago

Just adding SFTP (port 22) as an example of a workload that I encountered a lot in the last months and which is blocked by the http/https limitation for external ports currently.

riccardopinosio commented 1 year ago

I have the same issue as all of the people above. There's like a ton of services that need this. In my case, dgraph requires me to expose at least two ports, one for rest (graphql) and one for grpc. I'm currently stuck so won't be able to use ACA, might have to go down the ACI route.

itpropro commented 1 year ago

Any news regarding the roadmap for this @anthonychu ?

cachai2 commented 1 year ago

Hi folks, the public preview announcement will be going out next week. The following documentation outlines the feature and how to use it:

If you can, please continue to provide feedback on the feature and whether it meets the requirements for your scenarios.

valkko commented 1 year ago

For more concrete use cases: hosting something like coturn.

Looks like that won't work even with the preview as only 5 TCP ports are allowed. Sure, ACI might work here, but as far as I can tell that doesn't support autoscaling the instances based on load.

This feels a lot like missing basic feature.

schokoHero commented 11 months ago

We are hosting a service for multiple companies and from design there runs one "Server" for each company - split up by ports. But each of them only uses nearly no CPU and not much memory. At this point we are hosting them in over 20 containers each with one port - each with a lot of free memory all the time and each one costing real Euros every day... Now with this new feature I think about putting them all in one container but to to this I would need about 25+ ports available. What is the purpose of the 5 ports limit? I really wish you could remove this limit.