зеркало из https://github.com/microsoft/bedrock.git
Adding Terraform CICD reference for Gitlab and related README (#1450)
This commit is contained in:
Родитель
c9f9591f6b
Коммит
a2ef0541d7
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euox pipefail
|
||||
|
||||
az login --service-principal -u "$ARM_CLIENT_ID" -p "$ARM_CLIENT_SECRET" --tenant "$ARM_TENANT_ID"
|
|
@ -0,0 +1,34 @@
|
|||
# This file contains the variables and jobs for the dev stage
|
||||
|
||||
.dev-vars: &dev-vars
|
||||
ARM_CLIENT_ID: $DEV_ARM_CLIENT_ID
|
||||
ARM_CLIENT_SECRET: $DEV_ARM_CLIENT_SECRET
|
||||
AZURE_STORAGE_ACCOUNT_NAME: $DEV_AZURE_STORAGE_ACCOUNT_NAME
|
||||
AZURE_STORAGE_ACCOUNT_CONTAINER: $DEV_AZURE_STORAGE_ACCOUNT_CONTAINER
|
||||
AZURE_STORAGE_ACCOUNT_SUBSCRIPTION: $DEV_AZURE_STORAGE_ACCOUNT_SUBSCRIPTION
|
||||
VAR_FILE_NAME: 'DEV_TF_VARS'
|
||||
ENVIRONMENT: 'dev'
|
||||
|
||||
DevBuild:
|
||||
extends: .build
|
||||
stage: Dev-Build
|
||||
variables:
|
||||
<<: *dev-vars
|
||||
only:
|
||||
- master
|
||||
- merge_requests
|
||||
- web
|
||||
|
||||
DevRelease:
|
||||
extends: .release
|
||||
stage: Dev-Release
|
||||
variables:
|
||||
<<: *dev-vars
|
||||
needs:
|
||||
- job: DevBuild
|
||||
artifacts: true
|
||||
when: on_success
|
||||
only:
|
||||
- master
|
||||
- merge_requests
|
||||
- web
|
|
@ -0,0 +1,34 @@
|
|||
# This file contains the variables and jobs for the integration stage
|
||||
|
||||
.integration-vars: &integration-vars
|
||||
ARM_CLIENT_ID: $INTEGRATION_ARM_CLIENT_ID
|
||||
ARM_CLIENT_SECRET: $INTEGRATION_ARM_CLIENT_SECRET
|
||||
AZURE_STORAGE_ACCOUNT_NAME: $INTEGRATION_AZURE_STORAGE_ACCOUNT_NAME
|
||||
AZURE_STORAGE_ACCOUNT_CONTAINER: $INTEGRATION_AZURE_STORAGE_ACCOUNT_CONTAINER
|
||||
AZURE_STORAGE_ACCOUNT_SUBSCRIPTION: $INTEGRATION_AZURE_STORAGE_ACCOUNT_SUBSCRIPTION
|
||||
VAR_FILE_NAME: 'INTEGRATION_TF_VARS'
|
||||
ENVIRONMENT: 'integration'
|
||||
|
||||
IntegrationBuild:
|
||||
extends: .build
|
||||
stage: Integration-Build
|
||||
variables:
|
||||
<<: *integration-vars
|
||||
only:
|
||||
- master
|
||||
needs:
|
||||
- job: DevRelease
|
||||
artifacts: false
|
||||
|
||||
IntegrationRelease:
|
||||
extends: .release
|
||||
stage: Integration-Release
|
||||
variables:
|
||||
<<: *integration-vars
|
||||
needs:
|
||||
- job: IntegrationBuild
|
||||
artifacts: true
|
||||
when: manual
|
||||
allow_failure: false
|
||||
only:
|
||||
- master
|
|
@ -0,0 +1,43 @@
|
|||
# This file contains all of the checks that need to happen
|
||||
# before a build and release.
|
||||
|
||||
# Cache dependent modules + proviers and upload an artifact. We need to
|
||||
# make sure that the backend configuration is not configured, since it will
|
||||
# need to be done for each stage. The configuration per stage may differ, so
|
||||
# it makes sense to defer the initialization.
|
||||
InitTF:
|
||||
stage: Init
|
||||
script: .ci/tf-init-without-backend.sh
|
||||
artifacts:
|
||||
paths:
|
||||
- .terraform/
|
||||
only:
|
||||
- master
|
||||
- merge_requests
|
||||
|
||||
# Lint check terraform files
|
||||
LintTF:
|
||||
stage: Pre-Build
|
||||
script: .ci/tf-lint.sh
|
||||
only:
|
||||
- master
|
||||
- merge_requests
|
||||
|
||||
# Validate terraform configuration
|
||||
ValidateTF:
|
||||
stage: Pre-Build
|
||||
script: .ci/tf-validate.sh
|
||||
needs:
|
||||
- job: InitTF
|
||||
artifacts: true
|
||||
only:
|
||||
- master
|
||||
- merge_requests
|
||||
|
||||
# Lint check go files
|
||||
lintGo:
|
||||
stage: Pre-Build
|
||||
script: .ci/go-lint.sh
|
||||
only:
|
||||
- master
|
||||
- merge_requests
|
|
@ -0,0 +1,34 @@
|
|||
# This file contains the variables and jobs for the prod stage
|
||||
|
||||
.prod-vars: &prod-vars
|
||||
ARM_CLIENT_ID: $PROD_ARM_CLIENT_ID
|
||||
ARM_CLIENT_SECRET: $PROD_ARM_CLIENT_SECRET
|
||||
AZURE_STORAGE_ACCOUNT_NAME: $PROD_AZURE_STORAGE_ACCOUNT_NAME
|
||||
AZURE_STORAGE_ACCOUNT_CONTAINER: $PROD_AZURE_STORAGE_ACCOUNT_CONTAINER
|
||||
AZURE_STORAGE_ACCOUNT_SUBSCRIPTION: $PROD_AZURE_STORAGE_ACCOUNT_SUBSCRIPTION
|
||||
VAR_FILE_NAME: 'PROD_TF_VARS'
|
||||
ENVIRONMENT: 'prod'
|
||||
|
||||
ProdBuild:
|
||||
extends: .build
|
||||
stage: Prod-Build
|
||||
variables:
|
||||
<<: *prod-vars
|
||||
only:
|
||||
- master
|
||||
needs:
|
||||
- job: IntegrationRelease
|
||||
artifacts: false
|
||||
|
||||
ProdRelease:
|
||||
extends: .release
|
||||
stage: Prod-Release
|
||||
variables:
|
||||
<<: *prod-vars
|
||||
needs:
|
||||
- job: ProdBuild
|
||||
artifacts: true
|
||||
when: manual
|
||||
allow_failure: false
|
||||
only:
|
||||
- master
|
|
@ -0,0 +1,27 @@
|
|||
# This file contains jobs that can be extended by stage-specific
|
||||
# build and release steps
|
||||
|
||||
# Generic terraform build job
|
||||
.build:
|
||||
environment:
|
||||
name: $ENVIRONMENT
|
||||
artifacts:
|
||||
paths:
|
||||
- .terraform/
|
||||
- "$PLAN_FILE"
|
||||
script:
|
||||
- .ci/az-login.sh
|
||||
- .ci/tf-init-for-stage.sh
|
||||
- .ci/tf-workspace-select.sh
|
||||
- .ci/tf-plan.sh
|
||||
|
||||
# Generic terraform release job
|
||||
.release:
|
||||
environment:
|
||||
name: $ENVIRONMENT
|
||||
allow_failure: false
|
||||
script:
|
||||
- .ci/az-login.sh
|
||||
- .ci/tf-init-for-stage.sh
|
||||
- .ci/tf-workspace-select.sh
|
||||
- .ci/tf-apply.sh
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Note: the omission of the `pipefail` flag is intentional. It allows this
|
||||
# step to succeede in the case that there are no `*.go` files in the
|
||||
# infrastructure repository.
|
||||
set -euox
|
||||
|
||||
echo "Linting Go Files... If this fails, run 'go fmt ./...' to fix"
|
||||
|
||||
# This runs a go fmt on each file without using the 'go fmt ./...' syntax.
|
||||
# This is advantageous because it avoids having to download all of the go
|
||||
# dependencies that would have been triggered by using the './...' syntax.
|
||||
FILES_WITH_FMT_ISSUES=$(find . -name "*.go" | grep -v '.terraform' | xargs gofmt -l | wc -l)
|
||||
|
||||
# convert to integer...
|
||||
FILES_WITH_FMT_ISSUES=$(($FILES_WITH_FMT_ISSUES + 0))
|
||||
|
||||
# set exit code accordingly
|
||||
exit $FILES_WITH_FMT_ISSUES
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euox pipefail
|
||||
|
||||
terraform apply -input=false -auto-approve $PLAN_FILE
|
|
@ -0,0 +1,4 @@
|
|||
# #!/usr/bin/env bash
|
||||
set -euox pipefail
|
||||
|
||||
terraform init -backend-config "storage_account_name=$AZURE_STORAGE_ACCOUNT_NAME" -backend-config "container_name=$AZURE_STORAGE_ACCOUNT_CONTAINER"
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euox pipefail
|
||||
|
||||
terraform init -backend=false
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euox pipefail
|
||||
|
||||
echo "Linting Terraform Files... If this fails, run 'terraform fmt -recursive' to fix"
|
||||
terraform fmt -recursive -check
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euox pipefail
|
||||
|
||||
# workaround for https://gitlab.com/gitlab-org/gitlab-foss/-/issues/65763
|
||||
terraform plan -var-file="${!VAR_FILE_NAME}" -out "$PLAN_FILE"
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euox pipefail
|
||||
|
||||
terraform validate
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euox pipefail
|
||||
|
||||
terraform workspace new $ENVIRONMENT || terraform workspace select $ENVIRONMENT
|
|
@ -0,0 +1,40 @@
|
|||
# Extension points not yet implemented:
|
||||
# (1) Run infrastructure unit tests in precheck stage
|
||||
# (2) Run infrastructure integration tests
|
||||
|
||||
# Configure the base image for CI jobs here.
|
||||
#
|
||||
# To override the entrypoint see the documentation here:
|
||||
# https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#overriding-the-entrypoint-of-an-image
|
||||
#
|
||||
# To use a custom image, use the following syntax:
|
||||
# name: "$CI_REGISTRY/<your image here>:<your tag here>"
|
||||
image:
|
||||
name: "{{IMAGE_SLUG}}"
|
||||
entrypoint:
|
||||
- '/usr/bin/env'
|
||||
- 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
|
||||
|
||||
include:
|
||||
- '/.ci/ci-stages.yml'
|
||||
- '/.ci/ci-prechecks.yml'
|
||||
- '/.ci/ci-dev.yml'
|
||||
- '/.ci/ci-integration.yml'
|
||||
- '/.ci/ci-prod.yml'
|
||||
|
||||
before_script:
|
||||
- terraform version
|
||||
|
||||
stages:
|
||||
- Init
|
||||
- Pre-Build
|
||||
- Dev-Build
|
||||
- Dev-Release
|
||||
- Integration-Build
|
||||
- Integration-Release
|
||||
- Prod-Build
|
||||
- Prod-Release
|
||||
|
||||
variables:
|
||||
TF_IN_AUTOMATION: "true"
|
||||
PLAN_FILE: tfplan.out
|
|
@ -0,0 +1,13 @@
|
|||
FROM hashicorp/terraform:0.12.29
|
||||
|
||||
# Add common dependencies
|
||||
RUN apk update && \
|
||||
apk add openssl curl tar gzip bash ca-certificates coreutils
|
||||
|
||||
# Add Azure CLI
|
||||
RUN \
|
||||
apk add py3-pip && \
|
||||
apk add --virtual=build gcc libffi-dev musl-dev openssl-dev python3-dev make && \
|
||||
pip3 --no-cache-dir install -U pip && \
|
||||
pip3 --no-cache-dir install azure-cli && \
|
||||
apk del --purge build
|
|
@ -0,0 +1,72 @@
|
|||
# Terraform Deployments on Gitlab
|
||||
|
||||
This repository contains CICD templates that can deploy [Terraform](https://www.terraform.io/) templates for production systems into Azure using Gitlab.
|
||||
|
||||
## Automated CICD
|
||||
|
||||
Deployment of Terraform Templates are fully automated via the [GitLab Pipeline](./.gitlab-ci.yml).
|
||||
|
||||
**Terminology**
|
||||
|
||||
* `init` causes Terraform modules to be downloaded/cached
|
||||
* `lint` applies lint checks to the IAC templates and any Go files
|
||||
* `build` is a Terraform plan
|
||||
* `release` is a Terraform apply
|
||||
|
||||
The table below outlines when a deployment will happen to each stage:
|
||||
|
||||
> **Note**: Manual approvals are **always required** before deploying to non-`dev` environments
|
||||
|
||||
| Action | Pipeline Stages (sequential) |
|
||||
| --- | --- |
|
||||
| Manual branch build | `dev::build`, `dev::release` |
|
||||
| Create/Update PR | `init`, `lint`, `dev::build`, `dev::release` |
|
||||
| Merge PR | `init`, `lint`, `dev::build`, `dev::release`, `integration::build`, `integration::release`, `prod::build`, `prod::release` |
|
||||
| Master Branch Build | Same as above |
|
||||
|
||||
## Infrastructure Rollbacks
|
||||
|
||||
It is possible that Terraform deployments will need to be rolled back. To rollback use `git revert` commands or simply make another commit to return your configuration to a previous state in the infrastructure as code repository.
|
||||
|
||||
Be sure to create a local git branch, then commit, push, and generate a pull request on GitLab.
|
||||
|
||||
## Usage
|
||||
|
||||
**Step 1: Azure & Gitlab Configuration**
|
||||
|
||||
All Azure and Gitlab configuration required to use these templates should be provisioned using the [`gitlab-bootstrap-iac-cicd`](https://github.com/microsoft/cobalt/tree/master/infra/templates/gitlab-bootstrap-iac-cicd) template from project [Cobalt](https://github.com/microsoft/cobalt). No other manual configuration is necessary.
|
||||
|
||||
**Step 2: Build and Push Gitlab Runner Base Image**
|
||||
|
||||
The CICD templates in this folder assume the following tools are installed.
|
||||
* Terraform v0.12.x
|
||||
* Golang
|
||||
* Azure CLI
|
||||
|
||||
The included [`Dockerfile.sample`](Dockerfile.sample) can be used as a starting point. Use these commands to push the base image to the ACR:
|
||||
|
||||
```bash
|
||||
# Configure environment
|
||||
$ ACR_NAME="..."
|
||||
$ IMAGE="..."
|
||||
$ TAG="latest"
|
||||
|
||||
# Build and push image
|
||||
$ az acr login -n "$ACR_NAME"
|
||||
$ docker build -f Dockerfile.sample . -t "$ACR_NAME.azurecr.io/$IMAGE:$TAG"
|
||||
$ docker push "$ACR_NAME.azurecr.io/$IMAGE:$TAG"
|
||||
```
|
||||
|
||||
**Step 3: Configure Gitlab Pipeline to Use Base Image**
|
||||
|
||||
Now insert a custom value for the base image reference/property in `.gitlab-ci.yml`:
|
||||
|
||||
> **Note**: The use of `\$CI_REGISTRY` in the command below is intentional. When this pipeline is exercised, the value of `CI_REGISTRY` will be resolved because the [`gitlab-bootstrap-iac-cicd`](https://github.com/microsoft/cobalt/tree/master/infra/templates/gitlab-bootstrap-iac-cicd) template from step 1 configured it to point to the correct container registry.
|
||||
|
||||
```bash
|
||||
$ sed -i '' "s/{{IMAGE_SLUG}}/\$CI_REGISTRY\/$IMAGE:$TAG/g" .gitlab-ci.yml
|
||||
```
|
||||
|
||||
**Step 4: Write Some Terraform!**
|
||||
|
||||
At this point, you can begin writing a Terraform template for your deployment. The [`sample.tf`](./sample.tf) file is a sample Terraform template that shows a simple but working Terraform file that uses the backend state and variables configured through the Gitlab/Azure bootstrapping process referenced above.
|
|
@ -0,0 +1,44 @@
|
|||
# This file in intended to show how to leverage the following, which are provisioned
|
||||
# through the Azure/Gitlab bootstrapping process.
|
||||
# (1) Backend State
|
||||
# (2) TF Vars
|
||||
#
|
||||
# See README.me for more
|
||||
|
||||
provider "azurerm" {
|
||||
version = "=2.22"
|
||||
features {}
|
||||
}
|
||||
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
key = "terraform.tfstate"
|
||||
}
|
||||
}
|
||||
|
||||
variable "env" {
|
||||
type = string
|
||||
description = "The name of the environment to provision. Examples: dev, qa, prod"
|
||||
}
|
||||
|
||||
variable "resource_group" {
|
||||
type = string
|
||||
description = "The resource group to deploy into"
|
||||
}
|
||||
|
||||
variable "acr_id" {
|
||||
type = string
|
||||
description = "The resource identifier for AKS to attach to"
|
||||
}
|
||||
|
||||
output "echo_env" {
|
||||
value = var.env
|
||||
}
|
||||
|
||||
output "echo_resource_group" {
|
||||
value = var.resource_group
|
||||
}
|
||||
|
||||
output "echo_acr_id" {
|
||||
value = var.acr_id
|
||||
}
|
Загрузка…
Ссылка в новой задаче