Search code examples
google-cloud-platformpulumipulumi-python

Pulumi micro stacks with shared component


I manage a project on Google Cloud Platform which is composed by GKE and Cloud Run. I would like to achieve a flexible and independent deployment for each Cloud Run function: each function should extend the current infrastructure but be deployable independently using also CI/CD. I want to deploy the Cloud Run functions with a single load balancer (i.e., single domain), but different paths (see). I was able to achieve this goal with a single stack, but each new function or modification requires to always modify the main repo and the CI/CD needs to always use the main repo to deploy each function.

I would like to use micro-stacks approach, but pulumi does not seem to allow the modification of the "shared" component URLMap from each micro stack. I need this component to map the load balancer with the correct path and backend service.

Micro-stack repositories structures:

  • Infrastructure: main repo which creates shared resources (e.g., enable cloud run services, VPC access connector, Cloud NAT...)
  • Infrastructure library: Component Resources to be shared with other "micro-stacks" (e.g., cloud run)
  • Multiple repositories for each micro service (i.e., micro-stack).

Infra repo with initialization of main components (omitting useless parameters):


managed_ssl_certificate = gcp.compute.ManagedSslCertificate(...)

url_map = URLMap("cloud-run-url-map",
                      host_rules=[
                          URLMapHostRuleArgs(
                              hosts=["example.com"],
                              path_matcher="example"
                          )],
                      path_matchers=[
                          URLMapPathMatcherArgs(
                              name="example",
                              default_service=self.function_backend_service.self_link.apply(lambda self_link: self_link),
                        # Each Cloud Run function should add its path
                        path_rules=[]
                        ...
                          )])

http_load_balancer = gcp.compute.TargetHttpsProxy(url_map=url_map.id,
                                                  ssl_certificates=[managed_ssl_certificate.id],
                                                  ...)

forwarding_rule = gcp.compute.GlobalForwardingRule(target=http_load_balancer.id,
                                                    ...)

The infrastructure library which is used by each Cloud Run function and it needs to edit the "URL Map":


class MyCloudRun(ComponentResource):
    self.function = pulumi_gcp.cloudrunv2.Service(...)

    # Create a serverless network endpoint group (NEG) for the Cloud Run service
    cloud_run_neg = pulumi_gcp.compute.RegionNetworkEndpointGroup(...)

    # Create the backend service that points to the Cloud Run NEG
    self.function_backend_service = pulumi_gcp.compute.BackendService(...)

    # How to manage the URL Map? How to add the new URLMapPathMatcherPathRuleArgs ?
    # I tried to retrive the existing URL Map as follow but I got Duplicate resource URN; try giving it a unique name
    # Moreover, I am not sure how pulumi can delete the correct URLMapPathMatcherPathRuleArgs when removing the function

    original_path_matcher = URLMap.get(resource_name="my_name",id="my_id")
    new_path_rule = URLMapPathMatcherPathRuleArgs(
    paths=["/test"],
    service=self.function_backend_service)
    # The update logic is much more complex, but let's assume that original_path_matcher[0] exist and the operation of append does not create duplicate of URL Matcher.
    original_path_matcher[0].path_rules.append(new_path_rule)

What is wrong in my approach?


Solution

  • My approach to micro-stacks with a "shared" URLMap component (though it's not the most elegant solution, it functions well):

    • Micro-stack repositories: each Cloud Run function has its own repository. These repositories export information required for the URLMap, such as path and backend service.
    • Infrastructure library: library, shared among all Cloud Run functions, contains the code for deploying the functions and exporting the URLMap parameters.
    • Infrastructure repository: the infrastructure repository holds the configuration for each stack. This includes information on which function to deploy (referencing the stack and function name) to access the exported variables. This approach allows for managing the entire URLMap lifecycle, including deletion when a Cloud Run function is removed.

    Limitation: If changes to a Cloud Run function impact the URLMap (e.g., adding a new path), the infrastructure repository needs to be re-deployed to reflect those changes.