summaryrefslogtreecommitdiff
path: root/doc/ci/cloud_deployment/index.md
blob: bd9276275a709aa9c28d8c2a44fc91b07b38e73f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
---
stage: Release
group: Release
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---

# Deploy to AWS from GitLab CI/CD **(FREE)**

GitLab provides Docker images with the libraries and tools you need to deploy
to AWS. You can reference these images in your CI/CD pipeline.

If you're using GitLab.com and deploying to the [Amazon Elastic Container Service](https://aws.amazon.com/ecs/) (ECS),
read about [deploying to ECS](ecs/deploy_to_aws_ecs.md).

## Authenticate GitLab with AWS

To use GitLab CI/CD to connect to AWS, you must authenticate.
After you set up authentication, you can configure CI/CD to deploy.

1. Sign on to your AWS account.
1. Create [an IAM user](https://console.aws.amazon.com/iam/home#/home).
1. Select your user to access its details. Go to **Security credentials > Create a new access key**.
1. Note the **Access key ID** and **Secret access key**.
1. In your GitLab project, go to **Settings > CI/CD**. Set the following
   [CI/CD variables](../variables/index.md):

   | Environment variable name      | Value                   |
   |:-------------------------------|:------------------------|
   | `AWS_ACCESS_KEY_ID`            | Your Access key ID.     |
   | `AWS_SECRET_ACCESS_KEY`        | Your secret access key. |
   | `AWS_DEFAULT_REGION`           | Your region code. You might want to confirm that the AWS service you intend to use is [available in the chosen region](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/). |

1. Variables are [protected by default](../variables/index.md#protected-cicd-variables).
   To use GitLab CI/CD with branches or tags that are not protected,
   clear the **Protect variable** checkbox.

## Use an image to run AWS commands

If an image contains the [AWS Command Line Interface](https://aws.amazon.com/cli/),
you can reference the image in your project's `.gitlab-ci.yml` file. Then you can run
`aws` commands in your CI/CD jobs.

For example:

```yaml
deploy:
  stage: deploy
  image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest
  script:
   - aws s3 ...
   - aws create-deployment ...
  environment: production
```

GitLab provides a Docker image that includes the AWS CLI:

- Images are hosted in the GitLab Container Registry. The latest image is
  `registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest`.
- [Images are stored in a GitLab repository](https://gitlab.com/gitlab-org/cloud-deploy/-/tree/master/aws).

Alternately, you can use an [Amazon Elastic Container Registry (ECR)](https://aws.amazon.com/ecr/) image.
[Learn how to push an image to your ECR repository](https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-ecr-image.html).

You can also use an image from any third-party registry.

## Deploy your application to ECS

> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207962) in GitLab 12.9.
> - The `Deploy-ECS.gitlab-ci.yml` template was [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/220821) to `AWS/Deploy-ECS.gitlab-ci.yml` in GitLab 13.2.

You can automate deployments of your application to your [Amazon ECS](https://aws.amazon.com/ecs/)
cluster.

Prerequisites:

- [Authenticate AWS with GitLab](#authenticate-gitlab-with-aws).
- Create a cluster on Amazon ECS.
- Create related components, like an ECS service or a database on Amazon RDS.
- Create an ECS task definition, where the value for the `containerDefinitions[].name` attribute is
  the same as the `Container name` defined in your targeted ECS service. The task definition can be:
  - An existing task definition in ECS.
  - [In GitLab 13.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/222618),
    a JSON file in your GitLab project. Use the
    [template in the AWS documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-task-definition.html#task-definition-template)
    and save the file in your project. For example `<project-root>/ci/aws/task-definition.json`.

To deploy to your ECS cluster:

1. In your GitLab project, go to **Settings > CI/CD**. Set the following
   [CI/CD variables](../variables/index.md). You can find these names by
   selecting the targeted cluster on your [Amazon ECS dashboard](https://console.aws.amazon.com/ecs/home).

   | Environment variable name      | Value                   |
   |:-------------------------------|:------------------------|
   | `CI_AWS_ECS_CLUSTER`           | The name of the AWS ECS cluster that you're targeting for your deployments. |
   | `CI_AWS_ECS_SERVICE`           | The name of the targeted service tied to your AWS ECS cluster. Ensure that this variable is scoped to the appropriate environment (`production`, `staging`, `review/*`). |
   | `CI_AWS_ECS_TASK_DEFINITION`   | If the task definition is in ECS, the name of the task definition tied to the service. |
   | `CI_AWS_ECS_TASK_DEFINITION_FILE` | If the task definition is a JSON file in GitLab, the filename, including the path. For example, `ci/aws/my_task_definition.json`. If the name of the task definition in your JSON file is the same name as an existing task definition in ECS, then a new revision is created when CI/CD runs. Otherwise, a brand new task definition is created, starting at revision 1. |

   WARNING:
   If you define both `CI_AWS_ECS_TASK_DEFINITION_FILE` and `CI_AWS_ECS_TASK_DEFINITION`,
   `CI_AWS_ECS_TASK_DEFINITION_FILE` takes precedence.

1. Include this template in `.gitlab-ci.yml`:

   ```yaml
   include:
     - template: AWS/Deploy-ECS.gitlab-ci.yml
   ```

   The `AWS/Deploy-ECS` template ships with GitLab and is available
   [on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml).

1. Commit and push your updated `.gitlab-ci.yml` to your project's repository.

Your application Docker image is rebuilt and pushed to the GitLab Container Registry.
If your image is located in a private registry, make sure your task definition is
[configured with a `repositoryCredentials` attribute](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html).

The targeted task definition is updated with the location of the new
Docker image, and a new revision is created in ECS as result.

Finally, your AWS ECS service is updated with the new revision of the
task definition, making the cluster pull the newest version of your
application.

NOTE:
ECS deploy jobs wait for the rollout to complete before exiting. To disable this behavior,
set `CI_AWS_ECS_WAIT_FOR_ROLLOUT_COMPLETE_DISABLED` to a non-empty value.

WARNING:
The [`AWS/Deploy-ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml)
template includes two templates: [`Jobs/Build.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml)
and [`Jobs/Deploy/ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml). Do not include these templates on their own. Only include the
`AWS/Deploy-ECS.gitlab-ci.yml` template. These other templates are designed to be
used only with the main template. They may move or change unexpectedly. Also, the job names within
these templates may change. Do not override these job names in your own pipeline,
because the override stops working when the name changes.

## Deploy your application to EC2

> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201742) in GitLab 13.5.

GitLab provides a template, called `AWS/CF-Provision-and-Deploy-EC2`,
to assist you in deploying to Amazon EC2.

When you configure related JSON objects and use the template, the pipeline:

1. **Creates the stack**: Your infrastructure is provisioned by using
   the [AWS CloudFormation](https://aws.amazon.com/cloudformation/) API.
1. **Pushes to an S3 bucket**: When your build runs, it creates an artifact.
   The artifact is pushed to an [AWS S3](https://aws.amazon.com/s3/) bucket.
1. **Deploys to EC2**: The content is deployed on an [AWS EC2](https://aws.amazon.com/ec2/) instance.

![CF-Provision-and-Deploy-EC2 diagram](../img/cf_ec2_diagram_v13_5.png)

### Configure the template and JSON

To deploy to EC2, complete the following steps.

1. Create JSON for your stack. Use the [AWS template](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html).
1. Create JSON to push to S3. Include the following details.

   ```json
   {
     "applicationName": "string",
     "source": "string",
     "s3Location": "s3://your/bucket/project_built_file...]"
   }
   ```

   The `source` is the location where a `build` job built your application.
   The build is saved to [`artifacts:paths`](../yaml/index.md#artifactspaths).

1. Create JSON to deploy to EC2. Use the [AWS template](https://docs.aws.amazon.com/codedeploy/latest/APIReference/API_CreateDeployment.html).
1. Make the JSON objects accessible to your pipeline:
   - If you want these JSON objects saved in your repository, save the objects as three
     separate files.

     In your `.gitlab-ci.yml` file, add [CI/CD variables](../variables/index.md)
     that point to the file paths relative to the project root. For example,
     if your JSON files are in a `<project_root>/aws` folder:

     ```yaml
     variables:
       CI_AWS_CF_CREATE_STACK_FILE: 'aws/cf_create_stack.json'
       CI_AWS_S3_PUSH_FILE: 'aws/s3_push.json'
       CI_AWS_EC2_DEPLOYMENT_FILE: 'aws/create_deployment.json'
     ```

   - If you do not want these JSON objects saved in your repository, add each object
     as a separate [file type CI/CD variable](../variables/index.md#cicd-variable-types)
     in the project settings. Use the same variable names as above.

1. In your `.gitlab-ci.yml` file, create a CI/CD variable for the name of the stack. For example:

   ```yaml
   variables:
     CI_AWS_CF_STACK_NAME: 'YourStackName'
   ```

1. In your `.gitlab-ci.yml` file, add the CI template:

   ```yaml
   include:
     - template: AWS/CF-Provision-and-Deploy-EC2.gitlab-ci.yml
   ```

1. Run the pipeline.

   - Your AWS CloudFormation stack is created based on the content of your
     `CI_AWS_CF_CREATE_STACK_FILE` variable.
     If your stack already exists, this step is skipped, but the `provision`
     job it belongs to still runs.
   - Your built application is pushed to your S3 bucket then and deployed to your EC2 instance, based
     on the related JSON object's content. The deployment job finishes when the deployment to EC2
     is done or has failed.

## Troubleshooting

### Error `'ascii' codec can't encode character '\uxxxx'`

This error can occur when the response from the `aws-cli` utility used by the Cloud Deploy images contains a Unicode character. The Cloud Deploy images we provide do not have a defined locale and default to using ASCII. To resolve this error, add the following CI/CD variable:

```yaml
variables:
  LANG: "UTF-8"
```