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

Feature Request: Support service discovery via app name #473

Closed
ezYakaEagle442 opened this issue Oct 31, 2022 · 11 comments
Closed

Feature Request: Support service discovery via app name #473

ezYakaEagle442 opened this issue Oct 31, 2022 · 11 comments
Assignees
Labels
enhancement New feature or request Networking Related to ACA networking

Comments

@ezYakaEagle442
Copy link

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

The doc https://learn.microsoft.com/en-us/azure/container-apps/connect-apps?source=recommendations&tabs=bash describes that the only way connect microservices without Dapr is to get the App FQDN which breaks Apps migration when migrating an existing App to ACA.

see at https://github.com/ezYakaEagle442/aca-java-petclinic-mic-srv#understanding-the-spring-petclinic-application

Specifically required when deploying the Petclinic App to ACA ${} ${VETS_SVC_URL} ${} , ${VISITS_SVC_URL} , ${CUSTOMERS_SVC_URL} Environment variables have been configured in :

original code :

spring:
  cloud:
    gateway:
      discovery:
        # make sure a DiscoveryClient implementation (such as Netflix Eureka) is on the classpath and enabled
        locator: # https://cloud.spring.io/spring-cloud-gateway/reference/html/#the-discoveryclient-route-definition-locator
          enabled: true #  to configure Spring Cloud Gateway to use the Spring Cloud Service Registry to discover the available microservices.    
      routes:
        - id: vets-service
          uri: http://vets-service
          predicates:
            - Path=/api/vet/**
          filters:
            - StripPrefix=2
        - id: visits-service
          uri: http://visits-service
          predicates:
            - Path=/api/visit/**
          filters:
            - StripPrefix=2
        - id: customers-service
          uri: http://customers-service
          predicates:
            - Path=/api/customer/**
          filters:
            - StripPrefix=2

code update required to deploy Petclinic to ACA :

spring:      
  cloud:
    gateway:
      routes:
        - id: vets-service
          uri: https://${VETS_SVC_URL}
          predicates:
            - Path=/api/vet/**
          filters:
            - StripPrefix=2
        - id: visits-service
          uri: https://${VISITS_SVC_URL}
          predicates:
            - Path=/api/visit/**
          filters:
            - StripPrefix=2
        - id: customers-service
          uri: https://${CUSTOMERS_SVC_URL}
          predicates:
            - Path=/api/customer/**
          filters:
            - StripPrefix=2

original code :

public Mono<OwnerDetails> getOwner(final int ownerId) {
    return webClientBuilder.build().get()
        .uri("http://customers-service/owners/{ownerId}", ownerId)
        .retrieve()
        .bodyToMono(OwnerDetails.class);
}

code update required to deploy Petclinic to ACA :

public Mono<OwnerDetails> getOwner(final int ownerId) {
    return webClientBuilder.build().get()
        .uri("https://${CUSTOMERS_SVC_URL}/owners/{ownerId}", ownerId)
        .retrieve()
        .bodyToMono(OwnerDetails.class);
    }

original code :

private String hostname = "http://visits-service/";

code update required to deploy Petclinic to ACA :

private String hostname = "https://${VISITS_SVC_URL}/";

Those back-end URL have been set in the App through Bicep

    template: {
      containers: [
        { 
          command: [
            'java', '-javaagent:${applicationInsightsAgentJarFilePath}', 'org.springframework.boot.loader.JarLauncher', '--server.port=8080', '-Xms512m -Xmx1024m', '--spring.cloud.azure.keyvault.secret.enabled=false', '--spring.cloud.azure.keyvault.secret.property-source-enabled=false'
          ]
          env: [
            {
              // https://docs.microsoft.com/en-us/azure/azure-monitor/app/java-in-process-agent#set-the-application-insights-connection-string
              name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
              secretRef: 'appinscon'
            }
            {
              name: 'SPRING_CLOUD_AZURE_TENANT_ID'
              secretRef: 'springcloudazuretenantid'
            }   
            {
              name: 'SPRING_CLOUD_AZURE_KEY_VAULT_ENDPOINT'
              secretRef: 'springcloudazurekvendpoint'
            }           
            {
              name: 'CFG_SRV_URL'
              value: ConfigServerContainerApp.properties.configuration.ingress.fqdn
            }
            {
              name: 'CUSTOMERS_SVC_URL'
              value: CustomersServiceContainerApp.properties.configuration.ingress.fqdn
            }    
            {
              name: 'VETS_SVC_URL'
              value: VetsServiceContainerApp.properties.configuration.ingress.fqdn
            } 
            {
              name: 'VISITS_SVC_URL'
              value: VisitsServiceContainerApp.properties.configuration.ingress.fqdn
            }                                          
          ]

Describe the solution you'd like.
To support App portability, ACA should expose the interna service through this URL pattern : http://${ACA_APP_NAME}

Describe alternatives you've considered.
The only option was to replace the URL http://mybackend by the https://${ACA endpoint}

Additional context.
this breaks the portability of any spring boot Apps, any other App using K8S internal service pattern when configuring URL through http://mybackend-service

@kendallroden @dariagrigoriu @torosent

@ezYakaEagle442 ezYakaEagle442 added the enhancement New feature or request label Oct 31, 2022
@ghost ghost added the Needs: triage 🔍 Pending a first pass to read, tag, and assign label Oct 31, 2022
@kendallroden
Copy link
Contributor

kendallroden commented Nov 1, 2022

We are investigating the implementation and have plans to enable shortly. Thanks for the issue we have marked as roadmap

@kendallroden kendallroden added Networking Related to ACA networking and removed Needs: triage 🔍 Pending a first pass to read, tag, and assign labels Nov 1, 2022
@kendallroden kendallroden self-assigned this Nov 1, 2022
@kendallroden kendallroden added investigating currently looking into the issue roadmap This feature is on the roadmap and removed investigating currently looking into the issue labels Nov 1, 2022
@benc-uk
Copy link

benc-uk commented Nov 4, 2022

Would be great to see some improvements here. For many coming from Kubernetes, it seems super strange needing to put an ingress in front of each container app, even for internal "pod to pod" calls. For most Kubernetes people, ingress means - exposing traffic outside the cluster

I totally get that the deployment model for ACA is very different from true Kubernetes, perhaps it's just overloading on the term "ingress"

@ezYakaEagle442
Copy link
Author

see also ezYakaEagle442/aca-java-petclinic-mic-srv#1, it looks worse than what I thought : even using the FQDN as workaround, the UI is broken.

ezYakaEagle442 added a commit to ezYakaEagle442/aca-java-petclinic-mic-srv that referenced this issue Nov 9, 2022
ezYakaEagle442 added a commit to ezYakaEagle442/aca-java-petclinic-mic-srv that referenced this issue Nov 9, 2022
@ezYakaEagle442
Copy link
Author

finally fixed the routing using internal service with:

String internalK8Ssvc2svcRoute = "http://" + System.getenv("CUSTOMERS_SVC_APP_NAME") + ".internal." + System.getenv("CONTAINER_APP_ENV_DNS_SUFFIX");

@mburumaxwell
Copy link

My 2 cents on this having migrated mostly from AKS to ACA in the last 30 days.

The problem with building the URL using the name of the Container App is the {APP_NAME}.internal.{ENV_DNS_SUFFIX} domain is only mapped when the ingress is internal. Should you change the target application to external you will need to rebuild your code to change how the URL is built by removing the .internal. part, otherwise it will always return a 404.

Using the name of the app (analogous to the name of the service in AKS) would be okay but complicate TLS setup and also makes the assumption that all the apps are in the same Kubernetes namespace?

I would much rather prefer (maybe it is just wish), that Azure made the internal domain name always functional so long as the ingress is enabled (internal or external) while the one without the .internal section be functional only when the ingress is external.

@ahmelsayed
Copy link
Member

the .internal. domain should always work, i.e: for both internal and external apps. Only the external domain is conditional on the app being external.

example:

# 1. Create an external proxy app 
$ az containerapp create \
  --name squid-proxy \
  --resource-group $RESOURCE_GROUP \
  --environment $CONTAINERAPPS_ENVIRONMENT  \
  --image docker.io/ubuntu/squid:5.2-22.04_beta \
  --transport tcp \
  --target-port 3128 \
  --exposed-port 3128 \
  --ingress external \
  --query properties.configuration.ingress.fqdn

> squid-proxy.bluesand-424eb2fe.westeu.azurecontainerapps.io

# 2. Create an external nginx app
$ az containerapp create \
  --name nginx\
  --resource-group $RESOURCE_GROUP \
  --environment $CONTAINERAPPS_ENVIRONMENT  \
  --image nginx \
  --target-port 80 \
  --ingress external \
  --query properties.configuration.ingress.fqdn

> nginx.bluesand-424eb2fe.westeu.azurecontainerapps.io

# through the proxy, both external and internal endpoints should be accessible
# external
$ curl -I --proxy squid-proxy.bluesand-424eb2fe.westeu.azurecontainerapps.io:3128 \
    https://nginx.bluesand-424eb2fe.westeu.azurecontainerapps.io 

> HTTP/1.1 200 Connection established

> HTTP/2 200 
> server: nginx/1.23.2
> date: Thu, 10 Nov 2022 17:29:27 GMT
> content-type: text/html
> content-length: 615
> last-modified: Wed, 19 Oct 2022 07:56:21 GMT
> etag: "634fada5-267"
> accept-ranges: bytes

# internal
$ curl -I --proxy squid-proxy.bluesand-424eb2fe.westeu.azurecontainerapps.io:3128 \
    https://nginx.internal.bluesand-424eb2fe.westeu.azurecontainerapps.io 

> HTTP/1.1 200 Connection established

> HTTP/2 200 
> server: nginx/1.23.2
> date: Thu, 10 Nov 2022 17:29:43 GMT
> content-type: text/html
> content-length: 615
> last-modified: Wed, 19 Oct 2022 07:56:21 GMT
> etag: "634fada5-267"
> accept-ranges: bytes

Using the name of the app (analogous to the name of the service in AKS) would be okay but complicate TLS setup and also makes the assumption that all the apps are in the same Kubernetes namespace?

I would much rather prefer (maybe it is just wish), that Azure made the internal domain name always functional so long as the ingress is enabled (internal or external) while the one without the .internal section be functional only when the ingress is external.

This is coming soon. Though you're right about the TLS issue. It'll be http:// only to start.

@kendallroden kendallroden changed the title Feature Request: supports K8S internal service to enable Apps portability Feature Request: Support service discovery via app name Dec 13, 2022
@kendallroden kendallroden removed the roadmap This feature is on the roadmap label Dec 13, 2022
@kendallroden kendallroden moved this to Planned (Committed) in Azure Container Apps Roadmap Dec 13, 2022
@anthonychu anthonychu self-assigned this Dec 14, 2022
@SophCarp SophCarp moved this from Planned (Committed) to In-Progress (Development) in Azure Container Apps Roadmap Jan 20, 2023
@SophCarp
Copy link

Roadmap issue: #605

@calleo
Copy link

calleo commented Feb 10, 2023

This was very helpful. Perhaps this could be added to the docs: https://learn.microsoft.com/en-us/azure/container-apps/connect-apps?

I had no idea I had to use ".internal" to reach an internal service which is not externally exposed.

@cachai2 cachai2 self-assigned this Mar 6, 2023
@ahmelsayed
Copy link
Member

This should work now as expected. You can call http apps over http://{appName} or http://{revisionName}.

@marinasundstrom
Copy link

I have been working on the developer experience in my own app. I use Steeltoe with Consul locally.

The convention https://<app-name> will work great for both development, and production!

@marinasundstrom
Copy link

marinasundstrom commented Oct 20, 2023

I was expecting this to work, but it does not: https://<app-name>, or is it just for HTTP?

Yes, they are internal. So is it about the .internal. Kind of ruins it for me with the conventions.

Where is the documentation?

Update: http is important. http://<app-name>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Networking Related to ACA networking
Projects
None yet
Development

No branches or pull requests

10 participants