summaryrefslogtreecommitdiff
path: root/doc/ci/environments/deployment_safety.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/ci/environments/deployment_safety.md')
-rw-r--r--doc/ci/environments/deployment_safety.md106
1 files changed, 106 insertions, 0 deletions
diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md
new file mode 100644
index 00000000000..055baa78743
--- /dev/null
+++ b/doc/ci/environments/deployment_safety.md
@@ -0,0 +1,106 @@
+# Deployment safety
+
+Deployment jobs can be more sensitive than other jobs in a pipeline,
+and might need to be treated with extra care. GitLab has several features
+that help maintain deployment security and stability.
+
+You can:
+
+- [Restrict write-access to a critical environment](#restrict-write-access-to-a-critical-environment)
+- [Restrict deployments for a particular period](#restrict-deployments-for-a-particular-period)
+
+If you are using a continuous deployment workflow and want to ensure that concurrent deployments to the same environment do not happen, you should enable the following options:
+
+- [Ensure only one deployment job runs at a time](#ensure-only-one-deployment-job-runs-at-a-time)
+- [Skip outdated deployment jobs](#skip-outdated-deployment-jobs)
+
+## Restrict write access to a critical environment
+
+By default, environments can be modified by any team member that has [Developer permission or higher](../../user/permissions.md#project-members-permissions).
+If you want to restrict write access to a critical environment (for example a `production` environment),
+you can set up [protected environments](protected_environments.md).
+
+## Ensure only one deployment job runs at a time
+
+Pipeline jobs in GitLab CI/CD run in parallel, so it's possible that two deployment
+jobs in two different pipelines attempt to deploy to the same environment at the same
+time. This is not desired behavior as deployments should happen sequentially.
+
+You can ensure only one deployment job runs at a time with the [`resource_group` keyword](../yaml/README.md#resource_group) keyword in your `.gitlab-ci.yml`.
+
+For example:
+
+```yaml
+deploy:
+ script: deploy-to-prod
+ resource_group: prod
+```
+
+Example of a problematic pipeline flow **before** using the resource group:
+
+1. `deploy` job in Pipeline-A starts running.
+1. `deploy` job in Pipeline-B starts running. *This is a concurrent deployment that could cause an unexpected result.*
+1. `deploy` job in Pipeline-A finished.
+1. `deploy` job in Pipeline-B finished.
+
+The improved pipeline flow **after** using the resource group:
+
+1. `deploy` job in Pipeline-A starts running.
+1. `deploy` job in Pipeline-B attempts to start, but waits for the first `deploy` job to finish.
+1. `deploy` job in Pipeline-A finishes.
+1. `deploy` job in Pipeline-B starts running.
+
+For more information, see [`resource_group` keyword in `.gitlab-ci.yml`](../yaml/README.md#resource_group).
+
+## Skip outdated deployment jobs
+
+The execution order of pipeline jobs can vary from run to run, which could cause
+undesired behavior. For example, a deployment job in a newer pipeline could
+finish before a deployment job in an older pipeline.
+This creates a race condition where the older deployment finished later,
+overwriting the "newer" deployment.
+
+You can ensure that older deployment jobs are cancelled automatically when a newer deployment
+runs by enabling the [Skip outdated deployment jobs](../pipelines/settings.md#skip-outdated-deployment-jobs) feature.
+
+Example of a problematic pipeline flow **before** enabling Skip outdated deployment jobs:
+
+1. Pipeline-A is created on the master branch.
+1. Later, Pipeline-B is created on the master branch (with a newer commit SHA).
+1. The `deploy` job in Pipeline-B finishes first, and deploys the newer code.
+1. The `deploy` job in Pipeline-A finished later, and deploys the older code, **overwriting** the newer (latest) deployment.
+
+The improved pipeline flow **after** enabling Skip outdated deployment jobs:
+
+1. Pipeline-A is created on the `master` branch.
+1. Later, Pipeline-B is created on the `master` branch (with a newer SHA).
+1. The `deploy` job in Pipeline-B finishes first, and deploys the newer code.
+1. The `deploy` job in Pipeline-A is automatically cancelled, so that it doesn't overwrite the deployment from the newer pipeline.
+
+## Restrict deployments for a particular period
+
+If you want to prevent deployments for a particular period, for example during a planned
+vacation period when most employees are out, you can set up a [Deploy Freeze](../../user/project/releases/index.md#set-a-deploy-freeze).
+During a deploy freeze period, no deployment can be executed. This is helpful to
+ensure that deployments do not happen unexpectedly.
+
+## Troubleshooting
+
+### Pipelines jobs fail with `The deployment job is older than the previously succeeded deployment job...`
+
+This is caused by the [Skip outdated deployment jobs](../pipelines/settings.md#skip-outdated-deployment-jobs) feature.
+If you have multiple jobs for the same environment (including non-deployment jobs), you might encounter this problem, for example:
+
+```yaml
+build:service-a:
+ environment:
+ name: production
+
+build:service-b:
+ environment:
+ name: production
+```
+
+The [Skip outdated deployment jobs](../pipelines/settings.md#skip-outdated-deployment-jobs) might not work well with this configuration, and will need to be disabled.
+
+There is a [plan to introduce a new annotation for environments](https://gitlab.com/gitlab-org/gitlab/-/issues/208655) to address this issue.