How to use multiple environments and clusters

Multiple environments

The purpose of using multiple environments is to be able to make changes and experiment (development) or review latest
changes before going live (staging) on your production cluster.

You can have as many environments as you need and name them however you want, but the suggested default way is having
the 3 following environments: development, staging, production.

Multiple clusters

The suggested way to use environments with MetaKube Accelerator is to have a dedicated cluster for each environment. That way the workload of each environment is distributed to different clusters as well.

In order to do this, you need to create multiple MetaKube clusters and control their Building Blocks through one central control repository.

In this case, all you have to do to let the central repository have access to them is to configure the multiple kubeconfig files of each cluster as CI variables, as described here. The environment scope for each kubeconfig would be development, staging and production respectively.

On the gitlab-ci.yml of each Building Block, you can now have multiple environments like the following example:

include:
    - project: syseleven/building-blocks/helmfiles/ingress-nginx
      file: JobDevelopment.yaml
      ref: 5.34.0
    - project: syseleven/building-blocks/helmfiles/ingress-nginx
      file: JobStaging.yaml
      ref: 5.34.0
    - project: syseleven/building-blocks/helmfiles/ingress-nginx
      file: JobProduction.yaml
      ref: 5.34.0

You can use a central configuration of the Building Block on all the environments by using a generic values file - in this case that would be values-ingress-nginx.yaml.

To make unique changes on the configuration of the Building Block for each environment, use the values yaml followed by the name of the environment, like values-ingress-nginx-development.yaml, values-ingress-nginx-staging.yaml and values-ingress-nginx-production.yaml.

Rename environments

Apart from the default names for the environments, you can as well use your own names.

In this case, you need to use the job template of one of the default environments (e.g. JobDevelopment.yaml) and extend the jobs so that you change the environment name. If you wish the default environment jobs not to run, make sure you use the correct rules to prevent them from running, like we do on the following example:

include:
    - project: syseleven/building-blocks/helmfiles/ingress-nginx
      file: JobDevelopment.yaml
      ref: 5.34.0

syseleven-deploy-crds-<environment-name>:
  extends: .syseleven-deploy-crds
  environment:
    name: <environment-name>

syseleven-ingress-nginx-diff-<environment-name>:
  extends: syseleven-ingress-nginx-diff-development
  environment:
    name: <environment-name>
  rules:
    - when: always

syseleven-ingress-nginx-deploy-<environment-name>:
  extends: syseleven-ingress-nginx-deploy-development
  environment:
    name: <environment-name>
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  needs:
    - job: syseleven-deploy-crds-<environment-name>

syseleven-deploy-crds-development:
  rules:
    - when: never

syseleven-ingress-nginx-diff-development:
  rules:
    - when: never

syseleven-ingress-nginx-deploy-development:
  rules:
    - when: never

The same process applies for the values yaml as well, which would be values-ingress-nginx-<environment-name>.yaml.

Trigger single environment jobs

With the above pipeline, a change in any environment will trigger all environments' jobs to run. This way is totally efficient and no unwanted changes will happen to environments. However if you need your pipeline to run faster, you can modify a Building Block's pipeline as described below.

Let's suppose you're using environments development and production. You have to overwrite the rules of the corresponding jobs, so that they will only run when there is a change on the dedicated values file or the global values file.

include:
    - project: syseleven/building-blocks/helmfiles/ingress-nginx
      file: JobDevelopment.yaml
      ref: 5.34.0
    - project: syseleven/building-blocks/helmfiles/ingress-nginx
      file: JobProduction.yaml
      ref: 5.34.0

syseleven-ingress-nginx-deploy-development:
  rules:
    - if: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH"
      changes:
        - syseleven-ingress-nginx/values-ingress-nginx-development.yaml
        - syseleven-ingress-nginx/values-ingress-nginx.yaml
        - syseleven-ingress-nginx/values-ingress-nginx-extension-development.yaml
        - syseleven-ingress-nginx/values-ingress-nginx-extension.yaml

syseleven-ingress-nginx-deploy-production:
  rules:
    - if: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH"
      changes:
        - syseleven-ingress-nginx/values-ingress-nginx-production.yaml
        - syseleven-ingress-nginx/values-ingress-nginx.yaml
        - syseleven-ingress-nginx/values-ingress-nginx-extension-production.yaml
        - syseleven-ingress-nginx/values-ingress-nginx-extension.yaml

In the above example, development environment's job will only run if there is a change on values-ingress-nginx-development.yaml or if there is a global change of settings on file values-ingress-nginx.yaml, as well as the extension environment or global values, and so will production respectively.

Also, note that only the deploy jobs were modified and not the diff ones. This is because it's always useful to have the diff on the output at any time to review.