Service Fabric (On-premise) Routing to Multi-tenancy Containerized Application - url-routing

I'm trying to get a proof of concept going for a multi-tenancy containerized ASP.NET MVC application in Service Fabric. The idea is that each customer would get 1+ instances of the application spread across the cluster. One thing I'm having trouble getting mapped out is routing.
Each app would be partitioned similar to this SO answer. The plan so far is to have an external load balancer route each request to the SF Reverse Proxy service.
So for instance:
tenant1.myapp.com would get routed to the reverse proxy at <SF cluster node>:19081/myapp/tenant1 (19081 is the default port for SF Reverse Proxy), tenant2.myapp.com -> <SF Cluster Node>:19081/myapp/tenant2, etc and then the proxy would route it to the correct node:port where an instance of the application is listening.
Since each application has to be mapped to a different port, the plan is for SF to dynamically assign a port on creation of each app. This doesn't seem entirely scaleable since we could theoretically hit a port limit (~65k).
My questions then are, is this a valid/suggested approach? Are there better approaches? Are there things I'm missing/overlooking? I'm new to SF so any help/insight would be appreciated!

I don't think the Ephemeral Port Limit will be an issue for you, is likely that you will consume all server resources (CPU + Memory) even before you consume half of these ports.
To do what you need is possible, but it will require you to create a script or an application that will be responsible to create and manage configuration for the service instances deployed.
I would not use the built-in reverse proxy, it is very limited and for what you want will just add extra configuration with no benefit.
At moment I see traefik as the most suitable solution. Traefik enables you to route specific domains to specific services, and it is exactly what you want.
Because you will use multiple domains, it will require a dynamic configuration that is not provided out of the box, this is why I suggested you to create a separate application to deploy these instances. A very high level steps would be:
You define your service with the traefik default rules as shown here
From your application manager, you deploy a new named service of this service for the new tenant
After the instance is deployed you configure it to listen in a specific domain, setting the rule traefik.frontend.rule=Host:tenant1.myapp.com to the correct tenant name
You might have to add some extra configurations, but this will lead you to the right path.
Regarding the cluster architecture, you could do it in many ways, for starting, I would recommend you keep it simple, one FrontEnd node type containing the traefik services and another BackEnd node type for your services, from there you can decide how to plan the cluster properly, there is already many SO answers on how to define the cluster.
Please see more info on the following links:
https://blog.techfabric.io/using-traefik-reverse-proxy-for-securing-microservices-on-azure-service-fabric/
https://docs.traefik.io/configuration/backends/servicefabric/

Assuming you don't need an instance on every node, you can have up to (nodecount * 65K) services, which would make it scalable again.
Have a look at Azure API management and Traefik, which have some SF integration options. This works a lot nicer than the limited built-in reverse proxy. For example, they offer routing rules.

Related

Do I need a separate WAF if I want to use Azure Deployment Slot on production instance?

I'm looking to leverage Azure deployment slots for a production Web App (with Azure SQL DB).
I also use a Fortiweb WAF-as-a-Service for production app.
If I use deployment slots, will I need a separate Fortiweb WAF-as-a-Service instance to point to new name of "ProductionApp/Staging"?
I suspect I would need DNS entries as well for new Staging name, along with a separate WAF to have the client successfully connect to staging deployment slot.
Any comments, pointers or other would be most welcomed.
Regards,
Paul
Thank you to #PDorenberg for your question, and the subsequent solution that you provided in your comment.
For the sake of the community, I'm posting your comment as an answer, as it will benefit many others who are facing the same issue and are searching for a solution. Also, I've adding some points that I feel should be included and considered in the answer.
Deployment slots can’t swap custom client domain, associated private TLS/SSL certificates and scale settings as these settings are directly related to virtual network and private endpoints and these are ultimately related to the IP address space and DNS records created for them which are unique for every instance of resource that is routable, mappable and can be found over the internet through public IP addresses
Also, do keep in mind that only app settings, connection strings, language framework versions, web sockets, HTTP version, and platform bitness can be swapped between a deployment slot and a production slot. Please see the documentation for all the information regarding the deployment slot configuration and swapping.
Please also take note that you won’t need the Fortiweb WAF-as-a-service instance when pointing to the production slot of the app for a deployment that is already deployed in the staging slot of the App Service. But if the App Service instances are different for different apps in production, then you surely would need the Fortiweb WAF-as-a-service to route the traffic accordingly to each App Service instance separately.

Connect to multiple microservices using the same subdomain from React

I am having trouble understanding how to use a microservices model. The idea of a microservice is that I have multiple local servers, each serving a different port. Connecting to these local servers can be easily done locally (e.g., using an Express hosted website). But if I am using a frontend application, such as React, how am I supposed to call the different APIs.
The only solution I can seem to think is to create a subdomain per API, but this seems far-fetched and impractical since I would need to create a lot of entries inside the Names Server (e.g., Cloudflare).
If I am using an application like Apache or Nginx, is there a way to publicly access the APIs using a single domain? Or using subsubdomains such as api1.subdomain.domain.com, api2.subdomain.domain.com ... but without adding each of these subdomains to the name server?
An alternative I can think of is creating a public API whose job is to connect to local services, but this seems to defeat the purpose of microservices.
I can't find anything online and all tutorials always use localhost which does not work in production code.
Thanks in advance!
You should research API Gateways / Edge-Services.
Personally, I like hosting the containers for microservices in Kubernetes and forwarding all traffic to *.mydomain.tld to the kubernetes cluster and configuring the load balancing (in this case: which subdomain should be routed to which service) there.

Is it possible to use internal load balancer with backend on App Engine Flexible instances?

We need this to use non standard TCP port. From what I can see Load balancers need instance groups to be defined, and instance groups are compute engine thing. So I wonder if it's possible at all.
App Engine is a managed service, this means that it has it's own load balancer and manages the requests in a very specific way which you can check over here.
As mentioned by #guillaume blaquiere, you would be mixing 2 concepts completely different which are IaaS and PaaS. If you need to set up a specific load balancer with certain behaviour for your App to run, you may be better off using Managed instance groups rather than App Engine so you have more control on everything rather than relying on GCP's management.
I hope you find this information useful.

With AngularJS based single page apps hosted on premise, how to connect to AWS cloud servers

Maybe this is a really basic question, but how do you architect your system such that your single page application is hosted on premise with some hostname, say mydogs.com but you want to host your application services code in the cloud (as well as database). For example, let's say you spin up an Amazon EC2 Container Service using docker and it is running NodeJS server. The hostnames will all have ec2_some_id.amazon.com. What system sits in from of the Amazon EC2 instance where my angularjs app connects to? What architecture facilitate this type of app? Especially AWS based services.
One of the important aspects setting up the web application and the backend is to server it using a single domain avoiding cross origin requests (CORS). To do this, you can use AWS CloudFront as a proxy, where the routing happens based on URL paths.
For example, you can point the root domain to index.html while /api/* requests to the backend endpoint running in EC2. Sample diagram of the architecture is shown below.
Also its important for your angular application to have full url paths. One of the challenges having these are, for routes such as /home /about and etc., it will reload a page from the backend for that particular path. Since its a single page application you won't be having server pages for /home and /about & etc. This is where you can setup error pages in CloudFront so that, all the not found routes also can be forwarded to the index.html (Which serves the AngularJS app).
The only thing you need to care about is the CORS on whatever server you use to host your backend in AWS.
More Doc on CORS:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Hope it helps.
A good approach is to have two separated instances. It is, an instance to serve your API (Application Program Interface) and another one to serve your SPA (Single Page Application).
For the API server you may want more robust service because it's the one that will suffer the most receiving tons of requests from all client instances, so this one needs to have more performance, band, etc. In addition, you probably want your API server to be scalable when needed (depends on the load over it); maybe not, but is something to keep in mind if your application is supposed to grow fast. So you may invest a little bit more on this one.
The SPA server in the other hand, is the one that will only serve static resources (if you're not using server side rendering), so this one is supposed to be cheaper (if not free). Furthermore, all it does is to serve the application resources once and the application actually runs on client and most files will end up being cached by the browser. So you don't need to invest much on this one.
Anyhow, you question about which service will fit better for this type of application can't be answered because it doesn't define much about that you may find the one that sits for the requisites you want in terms of how your application will be consumed by the clients like: how many requests, downloads, or storage your app needs.
Amazon EC2 instance types

How does google container engines load balancer interact with replication controllers?

I've read through the google container engine and load balancer docs.
What I've understood:
I can encapsulated common pods into one replication controller
I can add network load balancing very easily to my container engine app
Given I have various services sitting behind a nginx reverse proxy.
What I want to say: This is my set of services behind nginx. Please push them to each node and connect nginx to the load balancer. Hence, when one node fails it can serve the others and so on.
Questions:
Do I understand the idea of load balancers and replication controllers in that context correctly?
If yes, do I assume right that only the frontend parts of the application go into the replication controller while non-replica services (such as the postgres database or the redis cache) are pushed into a service?
How would I set that up? I do not find a point in the docs where it actually connects a load balancer to my container entrypoints.
In general I'm a bit new to the concepts and may struggle with basics.
I don't really get your idea behind your first question. This is how I see this:
The loadbalancer is just used to open your service to the outside, to set a public IP to your nginx pods in your case. Here is how this works (also the answer to your question 3.): https://cloud.google.com/container-engine/docs/load-balancer
The replication controller is used to make sur you have always the right number of pods running for the associated pod. So the best way to make any pod run indefinitely is in this context. To answer your question 2., I would make sur that all your pods run with an associated replication controller, postgres db and redis included, just to be certain that you have always an instance of them running.
The service makes it easy to communicate between "internal" pods, and also has some kind of internal load balancing if the associated pod is replicated. In your case, your db and redis pods (each controlled by a replication controller) will indeed have to be managed also by a service to make them available to your nginx pods.
If you want an example of a complete "stack" running I would suggest this link: https://cloud.google.com/container-engine/docs/tutorials/guestbook even if it is quite simple you can get the main ideas behind all this.

Resources