I'd like to have my Google Cloud Run services privately communicate with one another over non-HTTP and/or without having to add bearer authentication in my code.
I'm aware of this documentation from Google which describes how you can do authenticated access between services, although it's obviously only for HTTP.
I think I have a general idea of what's necessary:
Create a custom VPC for my project
Enable the Serverless VPC Connector
What I'm not totally clear on is:
Is any of this necessary? Can Cloud Run services within the same project already see each other?
How do services address one another after this?
Do I gain the ability to use simpler by-convention DNS names? For example, could I have each service in Cloud Run manifest on my VPC as a single first level DNS name like apione and apitwo rather than a larger DNS name that I'd then have to hint in through my deployments?
If not, is there any kind of mechanism for services to discover names?
If I put my managed Cloud SQL postgres database on this network, can I control its DNS name?
Finally, are there any other gotchas I might want to be aware of? You can assume my use case is very simple, two or more long lived services on Cloud Run, doing non-HTTP TCP/UDP communications.
I also found a potentially related Google Cloud Run feature request that is worth upvoting if this isn't currently possible.
Cloud Run services are only reachable through HTTP request. you can't use other network protocol (SSH to log into instances for example, or TCP/UDP communication).
However, Cloud Run can initiate these kind of connection to external services (for instance Compute Engine instances deployed in your VPC, thanks to the serverless VPC Connector).
the serverless VPC connector allow you to make a bridge between the Google Cloud managed environment (where live the Cloud Run (and Cloud Functions/App Engine) instances) and the VPC of your project where you have your own instances (Compute Engine, GKE node pools,...)
Thus you can have a Cloud Run service that reach a Kubernetes pods on GKE through a TCP connection, if it's your requirement.
About service discovery, it's not yet the case but Google work actively on that and Ahmet (Google Cloud Dev Advocate on Cloud Run) has released recently a tool for that. But nothing really build in.
Related
Currently, I have followed the google docs quick start docs for deploying a simple cloud run web server that is connected to AlloyDB. However, in the docs, it all seem to point towards of having to utilize VM for a postgreSQL client, which then is connected to my AlloyDB cluster instance. I believe a connection can only be made within the same VPC and/or a proxy service via the VM(? Please correct me if I'm wrong)
I was wondering, if I only want to give access to services within the same VPC, is having a VM a must? or is there another way?
You're correct. AlloyDB currently only allows connecting via Private IP, so the only way to talk directly to the instances is within the same VPC. The reason all the tutorials (e.g. https://cloud.google.com/alloydb/docs/quickstart/integrate-cloud-run, which is likely the quickstart you mention) talk about a VM is that in order to create your databases themselves within the AlloyDB cluster, set user grants, etc, you need to be able to talk to it from inside the VPC. Another option for example, would be to set up Cloud VPN to some local network to connect your LAN to the VPC directly. But that's slow, costly, and kind of a pain.
Cloud Run itself does not require the VM piece, the quickstart I linked to above walks through setting up the Serverless VPC Connector which is the required piece to connect Cloud Run to AlloyDB. The VM in those instructions is only for configuring the PG database itself. So once you've done all the configuration you need, you can shut down the VM so it's not costing you anything. If you needed to step back in to make configuration changes, you can spin the VM back up, but it's not something that needs to be running for the Cloud Run -> AlloyDB connection.
Providing public ip functionality for AlloyDB is on the roadmap, but I don't have any kind of timeframe for when it will be implemented.
Consider a scenario with two identical Cloud Run services ("Real Time App") deployed in two different regions, let's say EU and US. These services use Firestore for real time communication, and minimizing latency is important. Since Firestore only allows specifying one region per project, each Cloud Run service is deployed in its own project and uses its regional Firestore instance. It is not needed for a service in the US to access Firestore data in the EU and vice versa.
Is there a way to deploy a global HTTPS load balancer to route requests to Cloud Run service closest to the user when services are defined in different projects?
I attempted a setup with a shared VPC between a Host "Global" project (in the US) and 2 service projects (EU and US). I created a Cloud Run Service, Network Endpoint Group (NEG), and Backend Service in each regional project. I then attempted to create a Global forwarding rule, Target HTTPs proxy, and URL Map in the host project. However, the URL Map cannot be fed a backend service in another project, complaining that:
Cross-project references for this resource are not allowed.
Indeed, per the Shared VPC Architecture and Cross-project service referencing section of the documentation it seems that:
Cross-project service referencing is not supported for the global external HTTP(S) load balancer
and that, if I understood correctly, the following rules apply:
The NEG must be defined in the same project as the Cloud Run Service
The Backend Service must be in the same project as the NEG
The Target HTTP(s) Proxy and associating URL map must be in the same project as the Backend Service
The Forwarding Rule must be in the same project as the Backend Service
essentially requiring the entire chain to be defined in one project.
Are there recommended workarounds for this scenario?
One solution I can think of is to create a "Router" Cloud Run Service in the Host global project behind a load balancer, with multi region deployment. Its sole purpose is to respond to the client with the regional URL endpoint of the closest "Real Time App" Cloud Run service.
I am wondering whether there is a more elegant solution, though.
The current setup is as follows:
I have a Cloud Run service, which acts as "back-end", which needs to reach external services but wants to be reached ONLY by the second Cloud Run instance. which acts as a "front-end", which needs to reach auth0 and the "back-end" and be reached by any client with a browser.
I recognize that the setup is not optimal, but I've inherited as is and we cannot migrate to another solution (maybe k8n). I'm trying to make this work with the least amount of impact on the infrastructure and, ideally, without having to touch the services themselves.
What I've tried is to restrict the ingress of the back-end service to INTERNAL and place two serverless VPC connectors (one per service), so that the front-end service would be able to reach the back-end but no one else could.
But I've encountered a huge issue: if I set the egress of the front-end all on the VPC it works, but now the front-end cannot reach auth0 and therefore the users cannot authenticate. If I place the egress as "mixed" (only internal ip ranges go through the VPC) the Google Run URL (*.run.app) is resolved not through the VPC and therefore it returns a big bad 403.
What I tried so far:
Placing a load balancer in front of the back-end service. But the serverless NEG only supports the global http load balancer and I'd need an internal one if I wanted an internal ip to resolve against
Trying to see if the VPC accessor itself MAYBE provided an internal (static) ip, but it doesn't seem so
Someone in another question suggested a "MIG as a proxy" but I haven't managed to figure that out (Can I run Cloud Run applications on a private IP (inside dedicated VPC network)?)
Fooled around with the Gateway API, but it seems that I'd have to provide a openAPI specification for the back-end, and I'm still under the delusion that this might be resolved with a cheaper (in terms of effort) approach.
So, I get that the Cloud Run instance cannot possibly have an internal IP by itself, but is there any kind of GCP product that can act as a proxy? Can someone elaborate on the "MIG as a proxy" approach (Managed Instance Group? Of what, though?), which might be the solution I'm looking for? (Sadly, I do not have the reputation needed to comment on that question or I would have).
Any kind of pointer is, as always, deeply appreciated.
You are designing this wrong. Use Cloud Run's identity-based access control instead of trying to route traffic. Google IAP (Identity Aware Proxy) will block all traffic that is not authorized.
Authenticating service-to-service
I have read other questions about this that all mention enabling service discovery, but my issue is a little different as to how to go about setting this up for my current Fargate deployments.
I have four spring boot api containers built via Gradle, pushed to ECR, and deployed in ECS Fargate with Terraform IaC setting up the appropriate resources. Three of these containerized apis have environment variables set within them to reference the fourth container, thus making an external api call outside of the container to that one service. DNS and 443 load balancer is setup for these deployments.
I have created a new service in the cluster containing the api that needs to be discovered. I have enabled service discover and created a local CloudMap A record for the api and then set each environment variable in the other containzers to use that local A record url, e.g., ecsservicename.local. Additionally I have tried to dig the service that I am connecting to in the other apis and that returns an IP so I am sure that that is working.
My questions are as follows:
(1) Since really only one services should be picked up by the others, was it correct to set service discovery on that one api and not the others or should I set up service discovery on all the other apis?
(2) Even if route53 is setup should this be an A record or SRV? I was confused by the documentation as to when to use which on aws.
(3) Is there a better or easier approach to use for inter-container communication that I am missing?
That's correct. Discovery should be set only for the one service. Other discoveries are not needed, as you are not inter-connection to those other services.
SRV also gives port, so from docs:
if the task definition that your service task specifies uses the bridge or host network mode, an SRV record is the only supported DNS record type.
I think your architecture is well thought and can't think of anything "easier" or better.
I have tried to search relevant info but couldn't find anything relevant. Please point me to some links on this.
I would like to know what is the best way to:
Connect to on-premise SOAP services from AWS cloud
on-premise Java RMI services
on-premise FTP to exchange files
Thanks
Connecting to SOAP, Java RMI or FTP service on-premise is something that will part of your application logic implementation. Which infrastructure you choose to deploy your application is a matter of choice depending on factors like what knowledge you have, what other application requirements you have and so on. Provided that you have configured your on-premise servers so that they are available on the public internet, you can choose to deploy your application using any server hosting option. For AWS specifically, EC2, Elastic Beanstalk and container options EKS and ECS comes to mind in addition to Lambda.