Skip to content

CI/CD Pipelines

Jenkins Pipeline Example

Jenkins pipelines automate Terraform workflows using a Jenkinsfile. Below is a sample pipeline that validates, plans, applies Terraform changes, and configures remote state backends (e.g., S3, Azure Blob Storage):

pipeline {
    agent any
    environment {
        AWS_ACCESS_KEY_ID = credentials('aws-access-key') // Inject AWS credentials via Jenkins credentials manager
        AWS_SECRET_ACCESS_KEY = credentials('aws-secret-key')
        TF_BACKEND_CONFIG = """{
            "backend": "s3",
            "config": {
                "bucket": "terraform-state-bucket",
                "key": "prod/terraform.tfstate",
                "region": "us-west-2",
                "encrypt": true
            }
        }"""
    }
    stages {
        stage('Initialize Terraform') {
            steps {
                sh 'terraform init -backend-config=${TF_BACKEND_CONFIG}'
            }
        }
        stage('Validate Terraform') {
            steps {
                sh 'terraform validate'
            }
        }
        stage('Plan Infrastructure Changes') {
            steps {
                sh 'terraform plan -out=tfplan'
            }
        }
        stage('Apply Infrastructure Changes') {
            steps {
                sh 'terraform apply tfplan --auto-approve'
            }
        }
    }
}

Notes:
- Use --auto-approve for automated pipelines to bypass manual confirmation.
- Store credentials in Jenkins credentials manager and reference them via environment variables (e.g., AWS_ACCESS_KEY_ID).
- For Azure Blob Storage, replace backend = "s3" with backend = "azurerm" and configure storage_account_name, container_name, and key in TF_BACKEND_CONFIG.


GitLab CI/CD Integration

GitLab CI uses a .gitlab-ci.yml file to define pipelines. Here’s an example with remote state backend configuration (e.g., S3, Azure Blob Storage):

stages: ["init", "validate", "plan", "apply"]

init:
  script:
    - echo "Initializing Terraform with remote state backend..."
    - terraform init -backend-config=${TF_BACKEND_CONFIG}
  only:
    - main

validate:
  script:
    - terraform validate
  only:
    - main

plan:
  script:
    - terraform plan -out=tfplan
  only:
    - main

apply:
  script:
    - terraform apply tfplan --auto-approve
  only:
    - main

Security Tip: Use GitLab’s secret variables (e.g., TF_VAR_AWS_ACCESS_KEY_ID, TF_VAR_AWS_SECRET_ACCESS_KEY) to pass sensitive data securely. For Azure, replace s3 with azurerm and configure storage_account_name, container_name, and key via secret variables.


GitHub Actions Workflow

GitHub Actions workflows are defined in a workflow.yml file. Here’s a Terraform automation example with remote state backend configuration (e.g., S3, Azure Blob Storage):

name: Terraform CI/CD
on: [push]
env:
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} # Inject AWS credentials via GitHub Secrets
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  TF_BACKEND_CONFIG: |
    {
      "backend": "s3",
      "config": {
        "bucket": "terraform-state-bucket",
        "key": "prod/terraform.tfstate",
        "region": "us-west-2",
        "encrypt": true
      }
    }
jobs:
  terraform-validate:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      - name: Initialize Terraform
        run: terraform init -backend-config=${{ env.TF_BACKEND_CONFIG }}
      - name: Terraform validate
        run: terraform validate
      - name: Terraform plan
        run: terraform plan -out=tfplan
      - name: Terraform apply
        run: terraform apply tfplan --auto-approve

Best Practice: Use GitHub Secrets (e.g., AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) to protect sensitive variables. For Azure, replace s3 with azurerm and configure storage_account_name, container_name, and key via secrets.


Best Practices for Terraform CI/CD

  • State Locking: Enable terraform state lock to prevent concurrent modifications.
  • Parallelism: Use terraform parallelism to optimize resource-intensive operations.
  • Testing: Integrate unit tests (e.g., terraform validate, terraform fmt) into pipelines.
  • Rollbacks: Implement rollback strategies for failed deployments using terraform destroy.

Key takeaways

  • Automating Terraform with CI/CD ensures consistent, auditable infrastructure changes.
  • Use remote state backends (e.g., S3, Azure Blob Storage) to manage Terraform state securely across teams.
  • Validate and plan changes before applying to avoid unintended modifications.
  • Leverage CI/CD tools’ secret management features to protect credentials.
  • Prioritize state locking and rollback mechanisms for production environments.