Microservices Architecture

Creating Applications from Multiple Repositories

Release works well with both large complex applications and many smaller applications all talking to each other. If you fall into the latter category, our solution to a microservices architecture is the App Imports feature. App Imports creates single-direction dependencies from one application to another with all services being brought up in the same namespace. This means there is one hard requirement for using App Imports: you cannot have two services with the same name. See Unique Service Names for further explanation.

A step by step example of using App Imports can be found at App Imports - Connecting Two Apps Together.

Setting up App Imports

app_imports:
- name: backend
branch: new-branch
service_excludes:
- name: redis

App Import Example in the Application Template

An example is shown above; the documentation for the schema can be viewed in the Application Template docs. Moving forward we will discuss this where an application frontend is using App Imports with an application named backend.

Single-Direction

If frontend adds an app_imports section to its template to import backend, that means that whenever an environment for frontend is created, an environment for backend will also be created. This is the single-direction of the import. If someone were to create an environment for backend, only the environment for backend would be created.

To create bi-directional imports, both applications need to have an app_imports section in their template.

App Imports are also not recursive. If bi-directional imports are set up, you will not create an infinite loop. You might think that frontend would import backend which would import frontend and create an infinite loop, but the import will only occur once with frontend importing backend and finishing.

Branch Selection

Branch selection has a fallback order that includes three different options. They are

  1. The branch set in the Application Template. If set, all environments will always use this branch. Remember that the branch attribute is optional in the template.

  2. A matching branch on Github. If frontend is on branch example then Release will query Github and see if the repository used for backend also has a branch named example. If there is a match, that branch will be used.

  3. The final option uses the default (or "main") branch that is set for the repository on Github.

Ingress Environment Variables

Release auto generates environment variables in the form of <SERVICE_NAME>_INGRESS_URL when the service is exposed to the internet. If, for example, backend has a service named api, then this means Release will generate an environment variable named API_INGRESS_URL. For this example, image that frontend has a service named web and Release will have generated the WEB_INGRESSR_URL environment variable also.

When using App Imports, the ingress environment variables are shared between between all environments. This means that frontend will have access to API_INGRESS_VARIABLE and its own WEB_INGRESS_URL and the same will apply for backend. Release shares all the environment variables because you may have multiple apps that imported, but two or more of those imported apps need to be able to communicate.

Mapping Environment Variables

Given that the ingress environment variables are available, you may need to map those to another environment variable your application is expecting. If frontend was using the environment variable REACT_APP_BACKEND_APIto talk to its API, then we would want to map the API_INGRESS_URLto it. This can be achieved using Environment Variable Mapping.

Environment Variable Mapping Example

Unique Service Names

Warning: Unexpected behavior caused by using services with the same name

If frontend had a service named api and backend had a service named api, Release would try to deploy two services named api into the same namespace. Kubernetes would remove the first, replacing it with the second; this is a function of how Kubernetes works and is not Release specific. We suggest adding the name of the application as a prefix to the service if there actually is a naming collision so you would have ${app_name}-api to differentiate between both services in each app.

Viewing Services in the Namespace

When using App Imports, all the services are placed into the same namespace. This means that when viewing the Instances table on an Environment Details page, you will be able to see the services from all the applications.

If you look under the Namespace section in the top left, you'll see that the environment jer-k-main from the application backend is imported into this namespace. The backend application defines the api, db, redis, and sidekiq services, which can see seen in the Instances table. The frontend application defines the app service, which can also seen.