Listing IP addresses of instances for application load balancer in aws sdk for js - amazon-elb

For a classic ELB I used to call
elb.describeLoadBalancers
and received list of instances with IP addresses embedded in loadBalancerDescription
following this from sdk docs http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/ELB.html#describeLoadBalancers-property
Now we are switching to application load balancer so we need to switch to api version 2 http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/ELBv2.html
There is the same method there describeLoadBalancers - however, for application loadbalancer there is a concept of targetGroups which includes instances.
In the response of elb.describeLoadBalancers from API version 2 there is no field like that.
How/what should I call to receive the same information like for classic loadbalancer?

For those who found this question years later (like me). I discovered out a way to get the instances of an Application LoadBalancer. I used the describeTargetHealth passing the LoadBalancer arn and from that i got the informations that i needed to get to my EC2 instances such as the instance Id.
Docs:
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/ELBv2.html#describeTargetHealth-property
Git that i stumbled upon and helped me a lot:
https://gist.github.com/miguelmota/d748d507e18bb8d365a4948aa7187fec
One more thing be sure that you are using the ELB V2 if you are using an Application LoadBalancer.

After few hours of browsing through a documentation I am pretty sure that is is not possible to retrieve instances of Application Loadbalancer by loadbalancer name. Luckily, I had also tags on my instances so I was able to use method from EC2 API describeInstances including suitable tags as filters. There is also alternative option without tags - using healthchecks.

Related

Routing a clients connection to a specific instance of a SignalR backend within a Kubernetes cluster

While trying to create a web application for shared drawing I got stuck on a problem regarding Kubernetes and scaling. The application uses an ASP.NET Core backend with SignalR for sharing the drawing data across its users. For scaling out the application I am using a deployment for each microservice of the system. For the SignalR part though, additional configuration is required.
After some research I have found out about the possibility to sync all instances of the SignalR backend either through the use of Azures SignalR Service or the use of a Redis backplane. The latter of which I have gotten to work on my local minikube environment. I am not really happy with this solution because of the following reasons:
My main concern is that like this I have created a hard bottleneck in
the system. Unlike in a chat application where data is sent only once
in a while, messages are sent for every few points drawn in the
shared drawing experience by any client. Simply put, a lot of traffic
can occur and all of it has to pass through the single Redis backplane.
Additionally to me it seems unneccessary to make all instances of the SignalR backend talk to each
other. In this application shared drawing does only occur in small groups of up to 10 clients lets
say. Groups of this size can easily be hosted on a single instance.
So without syncing all instances of the SignalR backend I would have to route the clients connection based on the SignalR group name to the right instance of the SignalR backend when the client is trying to join a group.
I have found out about StatefulSets which allow me to have a persistent address for each backend pod in the cluster. I then could somehow associate the SignalR group IDs with the pod addresses they are running on in lets say another look up microservice. The problem with this is that the client needs to be able to access the right pod from outside of the cluster where that cluster internal address does not really help.
Also I am wondering if there isnt a whole better approach to the problem since I am very new to the world of kubernetes. I would be very greatful for your thoughts on this issue and any hint towards a (better) solution.

How to bring two Cloud Run Apps under one domain to avoid CORS

I have two apps I wanted to have "fully managed" by Cloud Run. One is a pure Vue.js SPA and the other is the belonging backend server for it that is connected to a MySQL and also fetches some other API endpoints.
Now I have deployed both apps but am totally unaware on how I can give the frontend app access to the backend app. They should be both running on the same domain to avoid the frontend from.
Current URL of the frontend app: https://myapp-xl23p3zuiq-ew.a.run.app
So I'd love to have the server accessible by: https://myapp-xl23p3zuiq-ew.a.run.app/api
Is this somewhat possible to achieve with Cloud Run?
I was having the same issue. The general idea that one usually has is to use path mapping and map / to your client and /server to your backend. After googling for a while I found this:
https://cloud.google.com/run/docs/mapping-custom-domains
Base path mapping: not supported
The term base path refers to the URL
path name that is after the domain name. For example, users is the
base path of example.com/users. Cloud Run only allows you to map a
domain to /, not to a specific base path. So any path routing has to
be handled by using a router inside the service's container or by
using Firebase Hosting.
Option1:
I ended up creating an "all in one" docker image with an nginx as reverse proxy and the client (some static files) and server (in my case a python application powered by uwsgi).
If you are looking for inspiration, you can check out the public repository here: https://gitlab.com/psono/psono-combo
Opttion2:
An alternative would be to host your client on client.example.com, your server on server.example.com and then create a third docker run instance with a reverse proxy under example.com.
All requestes would be "proxied" to the client and server. Your users will only interact with example.com so CORS won't be an issue.
Option3:
Configure CORS, so people accessing example.com can also connect to server.example.com
Currently this is not possible in Cloud Run, as already said on the comments to your question.
You could check if there are any Feature Request for this functionality on Buganizer (Google Issue Tracker), currently there seems to be none, and if that is indeed the case, you can create a new Feature Request by changing the request type from Bug to Feature Request and as Google develops it on their road map, you will be informed.
Hope this helped you.

How to collect all ip's of pods by specific name filter

I have some legacy application, which deployed on clustered environment. When one of the application nodes receives call it gets from some configuration file static list of all application nodes where application is deployed.
When all ip's collected it communicates with each app node over jmx.
Current aim is to migrate to k8s, so in this case list of application pods is dynamic and can be just stored as is. Need to implement something like service discovery.
Current thoughts is to implement some simple rest service that will run in separate pod, main aim of which is always return some list of ips (entrypoints) of application pods filtered by some predicate.
So I have few questions:
Is it correct way to work? Any other options? (without changing legacy code)
Is there any ready solution for this? If not, how can I get information about needed pods inside my rest service?
Define a service with a scope selector so all your special pods are included then you can list all your endpoints IP's asking the apiservice.
You can check it's working with the command.
kubectl get endpoints
After that remains how to execute this command inside your pod. That's another story.
This link explain that matter
https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-api/#accessing-the-api-from-a-pod
Looks you're running a clustered application, so probably you need a Headless Service combined with a StatefulSet.
With this, you will be able to reach your replicas using simple DNS like replicas-[0-9].namespace.svc without need to extract IP addresses from endpoints query.

How can I implement a sub-api gateway that can be replicated?

Preface
I am currently trying to learn how micro-services work and how to implement container replication and API gateways. I've hit a block though.
My Application
I have three main services for my application.
API Gateway
Crawler Manager
User
I will be focusing on the API Gateway and Crawler Manager services for this question.
API Gateway
This is a docker container running a Go server. The communication is all done with GraphQL.
I am using an API Gateway because I expect to have different services in my application each having their own specialized API. This is to unify everything.
All it does is proxy requests to their appropriate service and return a response back to the client.
Crawler Manager
This is another docker container running a Go server. The communication is done with GraphQL.
More or less, this behaves similar to another API gateway. Let me explain.
This service expects the client to send a request like this:
{
# In production 'url' will be encoded in base64
example(url: "https://apple.example/") {
test
}
}
The url can only link to one of these three sites:
https://apple.example/
https://peach.example/
https://mango.example/
Any other site is strictly prohibited.
Once the Crawler Manager service receives a request and the link is one of those three it decides which other service to have the request fulfilled. So in that way, it behaves much like another API gateway, but specialized.
Each URL domain gets its own dedicated service for processing it. Why? Because each site varies quite a bit in markup and each site needs to be crawled for information. Because their markup is varied, I'd like a service for each of them so in case a site is updated the whole Crawler Manager service doesn't go down.
As far as the querying goes, each site will return a response formatted identical to other sites.
Visual Outline
Problem
Now that we have a bit of an idea of how my application works I want to discuss my actual issues here.
Is having a sort of secondary API gateway standard and good practice? Is there a better way?
How can I replicate this system and have multiple Crawler Manager service family instances?
I'm really confused on how I'd actually create this setup. I looked at clusters in Docker Swarm / Kubernetes, but with the way I have it setup it seems like I'd need to make clusters of clusters. That makes me question my design overall. Maybe I need to not think about keeping them so structured?
At a very generic level, if service A calls service B that has multiple replicas B1, B2, B3, ... then it needs to know how to call them. The two basic options are to have some sort of service registry that can return all of the replicas, and then pick one, or to put a load balancer in front of the second service and just directly reach that. Usually setting up the load balancer is a little bit easier: the service call can be a plain HTTP (GraphQL) call, and in a development environment you can just omit the load balancer and directly have one service call the other.
/-> service-1-a
Crawler Manager --> Service 1 LB --> service-1-b
\-> service-1-c
If you're willing to commit to Kubernetes, it essentially has built-in support for this pattern. A Deployment is some number of replicas of identical pods (containers), so it would manage the service-1-a, -b, -c in my diagram. A Service provides the load balancer (its default ClusterIP type provides a load balancer accessible only within the cluster) and also a DNS name. You'd configure your crawler-manager pods with perhaps an environment variable SERVICE_1_URL=http://service-1.default.svc.cluster.local/graphql to connect everything together.
(In your original diagram, each "box" that has multiple replicas of some service would be a Deployment, and the point at the top of the box where inbound connections are received would be a Service.)
In plain Docker you'd have to do a bit more work to replicate this, including manually launching the replicas and load balancers.
Architecturally what you've shown seems fine. The big "if" to me is that you've designed it so that each site you're crawling potentially gets multiple independent crawling containers and a different code base. If that's really justified in your scenario, then splitting up the services this way makes sense, and having a "second routing service" isn't really a problem.

How to orchestrate different version of apps in Docker or Kubernetes

I have three versions of the app that I need to serve to the user based on selection (for now assume it's a drop-down)
I have 3 containers running v1, v2, v3 of the app.
How do we route the app to the right container in Kubernetes based on the selection? How do I separate my versions?
Create 3 different Kubernetes deployments with pods using containers v1, v2, and v3 respectively. Also, create 3 Kubernetes services to forward traffic to those 3 deployments.
Actually, this is a classical problem. Imagine you created any application which is providing any service for clients. Imagine your clients communicate with your service via client app using your API. The first version of your application was having API with 1 supported method. Imagine, your application went viral and you decided to improve functionality of you application by adding 2 newly created methods to your API. So you had decided to upgrade you API and client app. New clients can use 3 methods and everything is ok, but what about clients, who use old version of the client app? That's why most part of the API's have got a versioning, e.g v1/v2/v3. Old clients communicate via APIv1 and new clients via APIv2 and so on.
Since you have got a different versions of the same app it is clear, that some newer versions of the app support more functionality. Maybe it will be better to handle request via web server like Nginx or something else (including Ingress) by redirecting them depending on URL. For example, if URL has got v1, then route it to the app's deployment with version 1 and so on.
I'm not sure this is your case, but I hope it turns out to be useful.

Resources