After creating all the Java files and Dockerfile for the Movies Application, I now want to create a GKE cluster using Terraform

Installing Terraform and Creating the .tf files

Setup:

  1. Install Terraform

    brew tap hashicorp/tap
    brew install hashicorp/tap/terraform
    
  2. Run the following command to connect using Google CLI: gcloud auth application-default login

  3. Create a Service Account in GCP with sufficient permissions (Kubernetes Engine Admin, Viewer)

    1. Generate a key, and store this credentials.json file
  4. Create a delegate Service Account to impersonate the main service account

    1. Grant access to the main service account by clicking on Grant Access within the main service account and adding the delete service account as a member with role Service Account Token Creator
    2. Now, this delegate service account can create service account tokens for the main service account
    3. Generate a key for this delegate service account, and call this file delegate.json
    4. This creates short-lived credentials
  5. Ignore the above steps 3 and 4 because we will use Workload Identity Federation instead

  6. In main.tf , use this template:

    provider "google" {
      project     = "<your-google-cloud-project-id>"
      region      = "<your-region>"
    }
    
    resource "google_container_cluster" "primary" {
      name     = "<name>"
      location = var.region
    
      initial_node_count = 2
    
      node_config {
        machine_type = "e2-small"
      }
    }
    
    
  7. To set up Workload Identity Federation, the first step is to create a GCP service account and grant IAM roles to that service account:

    resource "google_service_account" "workload_identity_user_sa" {
      account_id = "terraform-service-account"
      display_name = "Service account for Workload Identity Federation"
    }
    
    # 
    resource "google_project_iam_member" "monitoring-role" {
      member  = "serviceAccount:${google_service_account.workload_identity_user_sa.email}"
      project = data.google_client_config.current.project
      role    = "roles/monitoring.viewer"
    }
    
  8. Next, enable Workload Identity on GKE

    data "google_client_config" "current" {}
    
    resource "google_container_cluster" "primary" {	 
    	Existing code ...
    	
    	
    	workload_identity_config {
    		workload_pool = "${data.google_client_config.current.project}.svc.id.goog"
    	}
    	 
    	workload_metadata_config {
    		mode = "GKE_METADATA"
    	}
    	
    	...
    }
    
  9. Create a Kubernetes Service Account in the default namespace

    resource "kubernetes_service_account" "ksa" {
      metadata {
        name = "ksa-workload"
        namespace = "default"
        annotations = {
          "iam.gke.io/gcp-service-account" = google_service_account.workload_identity_user_sa.email
        }
      }
    }
    
  10. Allow this KSA to impersonate the GCP service account, so give it the workloadIdentityUser role and bind it to the GCP service account

    resource "google_service_account_iam_member" "workload_identity_role" {
      member = "serviceAccount:${data.google_client_config.current.project}.svc.id.goog[default/ksa-workload]"
      role = "roles/iam.workloadIdentityUser"
      service_account_id = google_service_account.workload_identity_user_sa.name
    }
    
  11. Run terraform init to create the .terraform folder and download all the dependencies for your code

Using GitHub Actions with Terraform

  1. Create a Github Workflow file called terraform.yml under .github/workflows

    name: Terraform CI/CD
    
    on:
      push:
        branches:
          - main
    
    env:
      PROJECT_ID: service-project-dev-1a
      GAR_LOCATION: us-west2
      REGION: us-west2
      DOCKER_REPO: my-repository
    
    jobs:
      terraform:
        name: 'Terraform'
        runs-on: ubuntu-latest
    
        # Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
        defaults:
          run:
            shell: bash
            # Inform a working directory if .tf files are not in root folder
            working-directory: ./terraform
    
        steps:
          # Checkout the repository to the GitHub Actions runner
          - name: Checkout
            uses: actions/checkout@v3
    
          # Install the latest version of Terraform CLI and configure the Terraform CLI configuration file with a Terraform Cloud user API token
          - name: Setup Terraform
            uses: hashicorp/setup-terraform@v2
            with:
              terraform_version: 1.10.4
    
          # Initialize a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc.
          - name: Terraform Init
            run: terraform init
    
    #      # Checks that all Terraform configuration files adhere to a canonical format
    #      - name: Terraform Format
    #        run: terraform fmt -check
    
          # Generates an execution plan for Terraform
          - name: Terraform Plan
            run: terraform plan -input=false
    
            # On push to "main", build or change infrastructure according to Terraform configuration files
            # Note: It is recommended to set up a required "strict" status check in your repository for "Terraform Cloud". See the documentation on "strict" required status checks for more information: <https://help.github.com/en/github/administering-a-repository/types-of-required-status-checks>
          - name: Terraform Apply
            if: github.ref == 'refs/heads/"main"' && github.event_name == 'push'
            run: terraform apply -auto-approve -input=false
    
  2. Set up Workload Identity Federation to authenticate to GCP (Add the following code to your Github Workflow under steps)

    # Authenticate to Google Cloud using Workload Identity Federation
    - name: 'Google auth'
      id: 'auth'
      uses: 'google-github-actions/auth@v1'
      with:
        workload_identity_provider: 'projects/89346032191/locations/global/workloadIdentityPools/github-actions-cloud-run/providers/github'
        service_account: 'github-cloud-deploy-sa@service-project-dev-1a.iam.gserviceaccount.com'
        token_format: 'access_token'
    
    # Set up Google Cloud SDK
    - name: 'Set up Cloud SDK'
      uses: 'google-github-actions/setup-gcloud@v1'
      with:
        project_id: '${{ env.PROJECT_ID }}'
    
    - name: 'Use gcloud CLI'
      run: 'gcloud info'
    
  3. Go to the GCP console, and add a new Workload Identity Pool called GitHub Actions

    image.png