Setting up a GitLab environment with the GitLab Environment Toolkit

This post is a notebook. It contains instructions to set up and create a GitLab environment in Google Cloud Platform (GCP) using the GitLab Environment Toolkit (GET), installed into a VS Code Dev Container.

The idea is that it's a literate sysadmin runbook, which can be copied and repeated within my get-container.

Notebook instructions

To use this, you must be running Jupyter Notebook with the Bash kernel installed. This is explored in detail on my earlier blog post. Jupyter and the extension should already have been installed when the GET Dev Container was provisioned. If not, then re-run the playbook:

ansible-playbook $WORKSPACE/.devcontainer/get/setup.yaml

Then start jupyter:

jupyter notebook --no-browser --allow-root

(this is aliased to notebook)

Select Kernel

Once jupyter is running in the dev container, you can open this notebook and select the Bash kernel from the Select Kernel button at the top of the buffer. The Bash kernel directly runs bash shell commands, rather than python.


Authenticate to GCP

Each notebook starts with a fresh environment, so set it up first. This loads the shell functions and aliases — which are used throught the notebook — and authenticates to GCP.

In [ ]:
source ~/.bashrc
$WORKSPACE/.devcontainer/get/gcloud-auth.sh
▹ Toggle output

🛜  Connecting to the Googleplex


GCP_AUTH_KIND:  application
GCP_PROJECT:    mlockhart-56581c10
GCP_REGION: us-west1
GCP_SA_SSH: /workspaces/get/keys/service-account_rsa.pub
GCP_SA_SSH_PRIV:    /workspaces/get/keys/service-account_rsa
GCP_SA_USER:    sa_REDACTED
GCP_TF_STATE_BUCKET:    mjl-get-terraform-state
GCP_ZONE:   us-west1-c
GET_ARCH:   /workspaces/get/.devcontainer/arch
GET_CONT:   /workspaces/get/_CONFIG
GET_HOME:   /workspaces/get
GET_KEYS:   /workspaces/get/keys
GET_LICENSE:    /workspaces/get/licenses/gitlab-premium
GET_ROOT_PASSWORD:  defaultpasswordchangeme
GET_ULTIMATE:   /workspaces/get/licenses/gitlab-ultimate
GOOGLE_APPLICATION_CREDENTIALS: /workspaces/get/keys/mlockhart-56581c10-8bc0e30dd679.json
GOOGLE_CREDENTIALS: /workspaces/get/keys/mlockhart-56581c10-8bc0e30dd679.json

Updated property [core/project].
Activated service account credentials for: [gitlab-mjl-mac@mlockhart-56581c10.iam.gserviceaccount.com]
loginProfile:
    REDACTED
    WARNING: Property validation for compute/region was skipped.
Updated property [compute/region].
WARNING: Property validation for compute/zone was skipped.
Updated property [compute/zone].

1. Reserve an external IP address

The new environment must have an external IP address. I usually reserve one for each environment, and make the environment's prefix match the name of the IP address.

It's good to list the current addresses that are reserved and in use, first. Here's the first shell alias. In this notebook I'll describe the aliases and functions so you can see what they mean. Normally you don't need to do that in order to just use them:

In [ ]:
alias gaddress
gaddress list
▹ Toggle output


alias gaddress='gcloud compute addresses'
NAME                              ADDRESS/RANGE   TYPE      PURPOSE  NETWORK  REGION    SUBNET  STATUS
gitlab-pages-ip                   104.198.10.38   EXTERNAL                    us-west1          RESERVED
gitlab-suse                       34.83.25.79     EXTERNAL                    us-west1          IN_USE
gl0                               34.19.85.189    EXTERNAL                    us-west1          RESERVED
gl1                               35.247.117.44   EXTERNAL                    us-west1          IN_USE
gl2                               34.127.19.111   EXTERNAL                    us-west1          IN_USE
gl3                               34.127.83.216   EXTERNAL                    us-west1          RESERVED
gl4                               34.83.247.87    EXTERNAL                    us-west1          RESERVED
gl4u                              34.83.115.41    EXTERNAL                    us-west1          RESERVED
gl5                               34.169.19.81    EXTERNAL                    us-west1          IN_USE
gl6-a                             34.168.235.194  EXTERNAL                    us-west1          IN_USE
gl6-s                             34.105.121.54   EXTERNAL                    us-west1          IN_USE
gl7                               34.145.108.180  EXTERNAL                    us-west1          RESERVED
interview-static-ip               34.169.52.156   EXTERNAL                    us-west1          RESERVED
mjl5658-gl2-2k-gitaly-ip-1        35.197.37.23    EXTERNAL                    us-west1          IN_USE
mjl5658-gl2-2k-gitlab-rails-ip-1  34.19.3.76      EXTERNAL                    us-west1          IN_USE
mjl5658-gl2-2k-gitlab-rails-ip-2  34.105.50.40    EXTERNAL                    us-west1          IN_USE
mjl5658-gl2-2k-monitor-ip-1       34.82.163.222   EXTERNAL                    us-west1          IN_USE
mjl5658-gl2-2k-postgres-ip-1      104.198.109.85  EXTERNAL                    us-west1          IN_USE
mjl5658-gl2-2k-redis-ip-1         34.168.118.24   EXTERNAL                    us-west1          IN_USE
mjl5658-gl2-2k-sidekiq-ip-1       34.82.105.251   EXTERNAL                    us-west1          IN_USE
new-p                             35.197.120.186  EXTERNAL                    us-west1          IN_USE
new-s                             34.82.12.174    EXTERNAL                    us-west1          IN_USE
old-p                             34.105.64.192   EXTERNAL                    us-west1          RESERVED
runner-static-ip                  35.199.147.59   EXTERNAL                    us-west1          IN_USE

1.1 Create an address if needed

Reserve a new address if necessary. Give it a short name that will be used for the environment. Here I create a new gl8 address:

In [7]:
gaddress create gl8
Created [https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/regions/us-west1/addresses/gl8].

The command does not report what the new address is. We can retrieve the generated IP address using another function:

type gaddress-ip
gaddress-ip is a function
gaddress-ip () 
{ 
    local FUNCDESC='Print the IP addresses for matching GCP server names';
    if [[ -z ${1} ]]; then
        echo "Usage: ${FUNCNAME} «name_pattern»" ${FUNCDESC};
        return 1;
    fi;
    gcloud compute addresses list --filter="name~'${1}'" --format="value(address)"
}

2. Generate a GET configuration

Use the gcp-environment script included in get-container, to create a new enironment from the GET configuration templates.

Below are the required script arguments, in long form. You can also run gcp-environment --help to see all of the options. The --economic option will configure Terraform to use less powerful compute instances with smaller volumes, which is fine and saves cost for a single-engineer test environment, but will not meet the performance specs for a reference architecture.

Change the values as necessary, and then run the cell:

In [8]:
cd $WORKSPACE
gcp-environment \
  --prefix gl8 \
  --external_ip $(gaddress-ip gl8) \
  --arch 1k \
  --glver 17.4.1 \
  --password $(pwgen 16) \
  --economic
Namespace(prefix='gl8', external_ip='34.168.4.189', url=None, arch='1k', glver='17.4.1', password='ur5iY5Cea8yez9Oo', license='/workspaces/get/licenses/gitlab-premium', economic=True, disk_size=20, ident='mjl5658', project='mlockhart-56581c10', region='us-west1', zone='us-west1-c', bucket='mjl-get-terraform-state', ssh_username='sa_104481838115385290889', ssh_key_path='/workspaces/get/keys/service-account_rsa', ansible='/workspaces/get/ansible/environments', terraform='/workspaces/get/terraform/environments', templates='/workspaces/get/.devcontainer/arch')
Generated /workspaces/get/terraform/environments/gl8_1k_v170401/environment.tf
Generated /workspaces/get/terraform/environments/gl8_1k_v170401/main.tf
Generated /workspaces/get/terraform/environments/gl8_1k_v170401/variables.tf
Generated /workspaces/get/ansible/environments/gl8_1k_v170401/inventory/1k.gcp.yml
Generated /workspaces/get/ansible/environments/gl8_1k_v170401/inventory/vars.yml

The script created new directories in GET's terraform/environments and ansible/environments, and added the necessary GET configuration settings.

You can inspect and fine-tune the settings in these files before applying them in Terraform and Ansible. If you are viewing this notebook in VSCode, you can click on the files above to open them.

3. Terraform

This step creates the necessary infrastructure in GCP for the new GitLab environment. It uses the Terraform files we just created.

The terraform settings need to be run from the terraform environment directory. Here are shortcuts to get there

In [9]:
alias cdte
cdte
alias cdte='cd ${GET_HOME}/terraform/environments/'

Now we're in the terraform environment base directory for GET. Switch to the specific environment's directory next. Doing it this way in two steps facilitates TAB-key completion.

In [11]:
cd gl8_1k_v170401
/workspaces/get/terraform/environments/gl8_1k_v170401

3.1 Terraform init

Terraform must be initialized before we can plan the infrastructure changes, or apply them. Use another alias for terraform:

In [ ]:
alias tf
tf init
▹ Toggle output


alias tf='time terraform'
Initializing the backend...

Successfully configured the backend "gcs"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing modules...
- gitlab_ref_arch_gcp in ../../modules/gitlab_ref_arch_gcp
- gitlab_ref_arch_gcp.consul in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.consul.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.gitaly in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.gitaly.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.gitlab_gke_gitaly_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.gitlab_gke_node_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.gitlab_gke_registry_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.gitlab_gke_sidekiq_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.gitlab_gke_supporting_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.gitlab_gke_toolbox_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.gitlab_gke_webservice_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.gitlab_nfs in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.gitlab_nfs.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.gitlab_rails in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.gitlab_rails.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.haproxy_external in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.haproxy_external.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.haproxy_internal in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.haproxy_internal.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.monitor in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.monitor.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.opensearch_vm in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.opensearch_vm.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.pgbouncer in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.pgbouncer.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.postgres in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.postgres.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.praefect in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.praefect.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.praefect_postgres in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.praefect_postgres.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.redis in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.redis.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.redis_cache in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.redis_cache.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.redis_persistent in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.redis_persistent.google_service_account in ../../modules/gitlab_gcp_service_account
- gitlab_ref_arch_gcp.sidekiq in ../../modules/gitlab_gcp_instance
- gitlab_ref_arch_gcp.sidekiq.google_service_account in ../../modules/gitlab_gcp_service_account
Initializing provider plugins...
- Finding hashicorp/google versions matching "~> 6.0"...
- Installing hashicorp/google v6.30.0...
- Installed hashicorp/google v6.30.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

real    0m11.086s
user    0m0.861s
sys 0m0.482s

3.2 Terraform apply

You should plan first.¯\_(ツ)_/¯ You can do that with the plan action:

tf plan

For testing, I usually skip the plan.

Here is another alias, to automatically approve and apply the terraform plan:

In [ ]:
alias tfap
tfap
▹ Toggle output


alias tfap='time terraform apply --auto-approve=true'
Acquiring state lock. This may take a few moments...
module.gitlab_ref_arch_gcp.data.google_compute_network.gitlab_network[0]: Reading...
module.gitlab_ref_arch_gcp.data.google_compute_subnetwork.gitlab_subnet[0]: Reading...
module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].data.google_client_openid_userinfo.current_userinfo[0]: Reading...
module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].data.google_client_openid_userinfo.current_userinfo[0]: Read complete after 1s [id=gitlab-mjl-mac@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.data.google_compute_network.gitlab_network[0]: Read complete after 1s [id=projects/mlockhart-56581c10/global/networks/default]
module.gitlab_ref_arch_gcp.data.google_compute_subnetwork.gitlab_subnet[0]: Read complete after 1s [id=projects/mlockhart-56581c10/regions/us-west1/subnetworks/default]

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_http_https_access[0] will be created
  + resource "google_compute_firewall" "gitlab_http_https_access" {
      + creation_timestamp = (known after apply)
      + description        = "Enable HTTP / HTTPS access for GitLab environment 'mjl5658-gl8-1k-v170401' on the default network"
      + destination_ranges = (known after apply)
      + direction          = (known after apply)
      + enable_logging     = (known after apply)
      + id                 = (known after apply)
      + name               = "mjl5658-gl8-1k-v170401-http-https-access"
      + network            = "https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/global/networks/default"
      + priority           = 1000
      + project            = "mlockhart-56581c10"
      + self_link          = (known after apply)
      + source_ranges      = [
          + "0.0.0.0/0",
        ]
      + target_tags        = [
          + "mjl5658-gl8-1k-v170401-web",
        ]

      + allow {
          + ports    = [
              + "80",
              + "443",
            ]
          + protocol = "tcp"
        }
    }

  # module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_icmp_access[0] will be created
  + resource "google_compute_firewall" "gitlab_icmp_access" {
      + creation_timestamp = (known after apply)
      + description        = "Enable ICMP access for GitLab environment 'mjl5658-gl8-1k-v170401' on the default network"
      + destination_ranges = (known after apply)
      + direction          = (known after apply)
      + enable_logging     = (known after apply)
      + id                 = (known after apply)
      + name               = "mjl5658-gl8-1k-v170401-icmp-access"
      + network            = "https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/global/networks/default"
      + priority           = 1000
      + project            = "mlockhart-56581c10"
      + self_link          = (known after apply)
      + source_ranges      = [
          + "0.0.0.0/0",
        ]
      + target_tags        = [
          + "mjl5658-gl8-1k-v170401",
        ]

      + allow {
          + ports    = []
          + protocol = "icmp"
        }
    }

  # module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_vm_ssh_access[0] will be created
  + resource "google_compute_firewall" "gitlab_vm_ssh_access" {
      + creation_timestamp = (known after apply)
      + description        = "Enable SSH access to VMs for GitLab environment 'mjl5658-gl8-1k-v170401' on the default network"
      + destination_ranges = (known after apply)
      + direction          = (known after apply)
      + enable_logging     = (known after apply)
      + id                 = (known after apply)
      + name               = "mjl5658-gl8-1k-v170401-vm-ssh-access"
      + network            = "https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/global/networks/default"
      + priority           = 1000
      + project            = "mlockhart-56581c10"
      + self_link          = (known after apply)
      + source_ranges      = [
          + "0.0.0.0/0",
        ]
      + target_tags        = [
          + "mjl5658-gl8-1k-v170401",
        ]

      + allow {
          + ports    = [
              + "22",
            ]
          + protocol = "tcp"
        }
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["artifacts"] will be created
  + resource "google_storage_bucket" "gitlab_object_storage_buckets" {
      + effective_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "mjl5658-gl8-1k-v170401-artifacts"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning {
          + enabled = false
        }

      + website (known after apply)
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["backups"] will be created
  + resource "google_storage_bucket" "gitlab_object_storage_buckets" {
      + effective_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "mjl5658-gl8-1k-v170401-backups"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning {
          + enabled = false
        }

      + website (known after apply)
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["ci-secure-files"] will be created
  + resource "google_storage_bucket" "gitlab_object_storage_buckets" {
      + effective_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "mjl5658-gl8-1k-v170401-ci-secure-files"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning {
          + enabled = false
        }

      + website (known after apply)
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["dependency-proxy"] will be created
  + resource "google_storage_bucket" "gitlab_object_storage_buckets" {
      + effective_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "mjl5658-gl8-1k-v170401-dependency-proxy"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning {
          + enabled = false
        }

      + website (known after apply)
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["lfs"] will be created
  + resource "google_storage_bucket" "gitlab_object_storage_buckets" {
      + effective_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "mjl5658-gl8-1k-v170401-lfs"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning {
          + enabled = false
        }

      + website (known after apply)
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["mr-diffs"] will be created
  + resource "google_storage_bucket" "gitlab_object_storage_buckets" {
      + effective_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "mjl5658-gl8-1k-v170401-mr-diffs"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning {
          + enabled = false
        }

      + website (known after apply)
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["packages"] will be created
  + resource "google_storage_bucket" "gitlab_object_storage_buckets" {
      + effective_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "mjl5658-gl8-1k-v170401-packages"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning {
          + enabled = false
        }

      + website (known after apply)
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["pages"] will be created
  + resource "google_storage_bucket" "gitlab_object_storage_buckets" {
      + effective_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "mjl5658-gl8-1k-v170401-pages"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning {
          + enabled = false
        }

      + website (known after apply)
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["registry"] will be created
  + resource "google_storage_bucket" "gitlab_object_storage_buckets" {
      + effective_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "mjl5658-gl8-1k-v170401-registry"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning {
          + enabled = false
        }

      + website (known after apply)
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["terraform-state"] will be created
  + resource "google_storage_bucket" "gitlab_object_storage_buckets" {
      + effective_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "mjl5658-gl8-1k-v170401-terraform-state"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning {
          + enabled = false
        }

      + website (known after apply)
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["uploads"] will be created
  + resource "google_storage_bucket" "gitlab_object_storage_buckets" {
      + effective_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "mjl5658-gl8-1k-v170401-uploads"
      + project                     = (known after apply)
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = {
          + "goog-terraform-provisioned" = "true"
        }
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning {
          + enabled = false
        }

      + website (known after apply)
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["artifacts"] will be created
  + resource "google_storage_bucket_iam_member" "gitlab_rails_object_storage_buckets_member" {
      + bucket = "mjl5658-gl8-1k-v170401-artifacts"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role   = "roles/storage.objectAdmin"
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["backups"] will be created
  + resource "google_storage_bucket_iam_member" "gitlab_rails_object_storage_buckets_member" {
      + bucket = "mjl5658-gl8-1k-v170401-backups"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role   = "roles/storage.objectAdmin"
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["ci-secure-files"] will be created
  + resource "google_storage_bucket_iam_member" "gitlab_rails_object_storage_buckets_member" {
      + bucket = "mjl5658-gl8-1k-v170401-ci-secure-files"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role   = "roles/storage.objectAdmin"
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["dependency-proxy"] will be created
  + resource "google_storage_bucket_iam_member" "gitlab_rails_object_storage_buckets_member" {
      + bucket = "mjl5658-gl8-1k-v170401-dependency-proxy"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role   = "roles/storage.objectAdmin"
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["lfs"] will be created
  + resource "google_storage_bucket_iam_member" "gitlab_rails_object_storage_buckets_member" {
      + bucket = "mjl5658-gl8-1k-v170401-lfs"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role   = "roles/storage.objectAdmin"
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["mr-diffs"] will be created
  + resource "google_storage_bucket_iam_member" "gitlab_rails_object_storage_buckets_member" {
      + bucket = "mjl5658-gl8-1k-v170401-mr-diffs"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role   = "roles/storage.objectAdmin"
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["packages"] will be created
  + resource "google_storage_bucket_iam_member" "gitlab_rails_object_storage_buckets_member" {
      + bucket = "mjl5658-gl8-1k-v170401-packages"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role   = "roles/storage.objectAdmin"
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["pages"] will be created
  + resource "google_storage_bucket_iam_member" "gitlab_rails_object_storage_buckets_member" {
      + bucket = "mjl5658-gl8-1k-v170401-pages"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role   = "roles/storage.objectAdmin"
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["registry"] will be created
  + resource "google_storage_bucket_iam_member" "gitlab_rails_object_storage_buckets_member" {
      + bucket = "mjl5658-gl8-1k-v170401-registry"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role   = "roles/storage.objectAdmin"
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["terraform-state"] will be created
  + resource "google_storage_bucket_iam_member" "gitlab_rails_object_storage_buckets_member" {
      + bucket = "mjl5658-gl8-1k-v170401-terraform-state"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role   = "roles/storage.objectAdmin"
    }

  # module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["uploads"] will be created
  + resource "google_storage_bucket_iam_member" "gitlab_rails_object_storage_buckets_member" {
      + bucket = "mjl5658-gl8-1k-v170401-uploads"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role   = "roles/storage.objectAdmin"
    }

  # module.gitlab_ref_arch_gcp.module.gitlab_rails.google_compute_instance.gitlab[0] will be created
  + resource "google_compute_instance" "gitlab" {
      + allow_stopping_for_update = true
      + can_ip_forward            = false
      + cpu_platform              = (known after apply)
      + creation_timestamp        = (known after apply)
      + current_status            = (known after apply)
      + deletion_protection       = false
      + effective_labels          = {
          + "gitlab_node_level"          = "gitlab-rails-primary"
          + "gitlab_node_prefix"         = "mjl5658-gl8-1k-v170401"
          + "gitlab_node_type"           = "gitlab-rails"
          + "goog-terraform-provisioned" = "true"
        }
      + id                        = (known after apply)
      + instance_id               = (known after apply)
      + label_fingerprint         = (known after apply)
      + labels                    = {
          + "gitlab_node_level"  = "gitlab-rails-primary"
          + "gitlab_node_prefix" = "mjl5658-gl8-1k-v170401"
          + "gitlab_node_type"   = "gitlab-rails"
        }
      + machine_type              = "e2-standard-2"
      + metadata                  = {
          + "enable-oslogin" = "TRUE"
        }
      + metadata_fingerprint      = (known after apply)
      + min_cpu_platform          = (known after apply)
      + name                      = "mjl5658-gl8-1k-v170401-gitlab-rails-1"
      + project                   = "mlockhart-56581c10"
      + self_link                 = (known after apply)
      + tags                      = [
          + "gitlab-rails",
          + "mjl5658-gl8-1k-v170401",
          + "mjl5658-gl8-1k-v170401-gitlab-rails",
          + "mjl5658-gl8-1k-v170401-ssh",
          + "mjl5658-gl8-1k-v170401-web",
        ]
      + tags_fingerprint          = (known after apply)
      + terraform_labels          = {
          + "gitlab_node_level"          = "gitlab-rails-primary"
          + "gitlab_node_prefix"         = "mjl5658-gl8-1k-v170401"
          + "gitlab_node_type"           = "gitlab-rails"
          + "goog-terraform-provisioned" = "true"
        }
      + zone                      = "us-west1-c"

      + boot_disk {
          + auto_delete                = true
          + device_name                = (known after apply)
          + disk_encryption_key_sha256 = (known after apply)
          + guest_os_features          = (known after apply)
          + kms_key_self_link          = (known after apply)
          + mode                       = "READ_WRITE"
          + source                     = (known after apply)

          + initialize_params {
              + architecture           = (known after apply)
              + image                  = "ubuntu-2404-lts-amd64"
              + labels                 = (known after apply)
              + provisioned_iops       = (known after apply)
              + provisioned_throughput = (known after apply)
              + resource_policies      = (known after apply)
              + size                   = 20
              + snapshot               = (known after apply)
              + type                   = "pd-standard"
            }
        }

      + confidential_instance_config (known after apply)

      + guest_accelerator (known after apply)

      + network_interface {
          + internal_ipv6_prefix_length = (known after apply)
          + ipv6_access_type            = (known after apply)
          + ipv6_address                = (known after apply)
          + name                        = (known after apply)
          + network                     = "https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/global/networks/default"
          + network_attachment          = (known after apply)
          + network_ip                  = (known after apply)
          + stack_type                  = (known after apply)
          + subnetwork                  = "https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/regions/us-west1/subnetworks/default"
          + subnetwork_project          = (known after apply)

          + access_config {
              + nat_ip       = "34.168.4.189"
              + network_tier = (known after apply)
            }
        }

      + reservation_affinity (known after apply)

      + scheduling (known after apply)

      + service_account {
          + email  = "gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
          + scopes = [
              + "https://www.googleapis.com/auth/cloud-platform",
            ]
        }

      + shielded_instance_config {
          + enable_integrity_monitoring = true
          + enable_secure_boot          = false
          + enable_vtpm                 = true
        }
    }

  # module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].google_service_account.gitlab[0] will be created
  + resource "google_service_account" "gitlab" {
      + account_id   = "gl8-gitlab-rails"
      + disabled     = false
      + display_name = "mjl5658-gl8-1k-v170401-gitlab-rails"
      + email        = "gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + id           = (known after apply)
      + member       = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + name         = (known after apply)
      + project      = "mlockhart-56581c10"
      + unique_id    = (known after apply)
    }

  # module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].google_service_account_iam_member.gitlab_user_members["serviceAccount:gitlab-mjl-mac@mlockhart-56581c10.iam.gserviceaccount.com"] will be created
  + resource "google_service_account_iam_member" "gitlab_user_members" {
      + etag               = (known after apply)
      + id                 = (known after apply)
      + member             = "serviceAccount:gitlab-mjl-mac@mlockhart-56581c10.iam.gserviceaccount.com"
      + role               = "roles/iam.serviceAccountUser"
      + service_account_id = (known after apply)
    }

  # module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].google_service_account_iam_member.object_storage_profile_token_creator[0] will be created
  + resource "google_service_account_iam_member" "object_storage_profile_token_creator" {
      + etag               = (known after apply)
      + id                 = (known after apply)
      + member             = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      + role               = "roles/iam.serviceAccountTokenCreator"
      + service_account_id = (known after apply)
    }

Plan: 29 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + gitlab_ref_arch_gcp = {
      + cloud_sql_geo_tracking_postgres_connection = {
          + cloud_sql_host    = ""
          + cloud_sql_name    = ""
          + cloud_sql_version = ""
        }
      + cloud_sql_postgres_connection              = {
          + cloud_sql_host               = ""
          + cloud_sql_name               = ""
          + cloud_sql_read_replica_hosts = []
          + cloud_sql_version            = ""
        }
      + cloud_sql_praefect_postgres_connection     = {
          + cloud_sql_host    = ""
          + cloud_sql_name    = ""
          + cloud_sql_version = ""
        }
      + consul                                     = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + gitaly                                     = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + gitlab_nfs                                 = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + gitlab_rails                               = {
          + data_disk_device_names = []
          + external_addresses     = [
              + "34.168.4.189",
            ]
          + internal_addresses     = {
              + "mjl5658-gl8-1k-v170401-gitlab-rails-1.c.mlockhart-56581c10.internal" = (known after apply)
            }
          + machine_names          = [
              + "mjl5658-gl8-1k-v170401-gitlab-rails-1",
            ]
          + self_links             = [
              + (known after apply),
            ]
          + service_account        = {
              + email     = "gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
              + member    = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
              + name      = (known after apply)
              + unique_id = (known after apply)
            }
          + zones                  = [
              + "us-west1-c",
            ]
        }
      + haproxy_external                           = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + haproxy_internal                           = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + kubernetes                                 = {
          + kubernetes_cluster_id                                  = ""
          + kubernetes_cluster_name                                = ""
          + kubernetes_cluster_version                             = ""
          + kubernetes_gitaly_node_group_service_account_email     = ""
          + kubernetes_gitaly_node_group_version                   = ""
          + kubernetes_node_group_service_account_email            = ""
          + kubernetes_registry_service_account_email              = ""
          + kubernetes_sidekiq_node_group_service_account_email    = ""
          + kubernetes_sidekiq_node_group_version                  = ""
          + kubernetes_sidekiq_service_account_email               = ""
          + kubernetes_supporting_node_group_service_account_email = ""
          + kubernetes_supporting_node_group_version               = ""
          + kubernetes_toolbox_service_account_email               = ""
          + kubernetes_webservice_node_group_service_account_email = ""
          + kubernetes_webservice_node_group_version               = ""
          + kubernetes_webservice_service_account_email            = ""
        }
      + memorystore_redis_cache_connection         = {
          + memorystore_redis_cache_address = ""
          + memorystore_redis_cache_port    = ""
        }
      + memorystore_redis_connection               = {
          + memorystore_redis_address = ""
          + memorystore_redis_port    = ""
        }
      + memorystore_redis_persistent_connection    = {
          + memorystore_redis_persistent_address = ""
          + memorystore_redis_persistent_port    = ""
        }
      + monitor                                    = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + network                                    = {
          + vpc_id                = "projects/mlockhart-56581c10/global/networks/default"
          + vpc_name              = "default"
          + vpc_self_link         = "https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/global/networks/default"
          + vpc_subnet_cidr_block = "10.138.0.0/20"
          + vpc_subnet_id         = "projects/mlockhart-56581c10/regions/us-west1/subnetworks/default"
          + vpc_subnet_name       = "default"
          + vpc_subnet_self_link  = "https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/regions/us-west1/subnetworks/default"
        }
      + opensearch_vm                              = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + pgbouncer                                  = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + postgres                                   = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + praefect                                   = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + praefect_postgres                          = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + redis                                      = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + redis_cache                                = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + redis_persistent                           = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
      + sidekiq                                    = {
          + data_disk_device_names = []
          + external_addresses     = []
          + internal_addresses     = {}
          + machine_names          = []
          + self_links             = []
          + service_account        = null
          + zones                  = []
        }
    }
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["artifacts"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["ci-secure-files"]: Creating...
module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].google_service_account.gitlab[0]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["uploads"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["terraform-state"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["packages"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["lfs"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["dependency-proxy"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["mr-diffs"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["pages"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["lfs"]: Creation complete after 4s [id=mjl5658-gl8-1k-v170401-lfs]
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["backups"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["packages"]: Creation complete after 4s [id=mjl5658-gl8-1k-v170401-packages]
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["registry"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["dependency-proxy"]: Creation complete after 5s [id=mjl5658-gl8-1k-v170401-dependency-proxy]
module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_vm_ssh_access[0]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["artifacts"]: Creation complete after 6s [id=mjl5658-gl8-1k-v170401-artifacts]
module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_http_https_access[0]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["mr-diffs"]: Creation complete after 6s [id=mjl5658-gl8-1k-v170401-mr-diffs]
module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_icmp_access[0]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["backups"]: Creation complete after 3s [id=mjl5658-gl8-1k-v170401-backups]
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["terraform-state"]: Creation complete after 7s [id=mjl5658-gl8-1k-v170401-terraform-state]
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["uploads"]: Creation complete after 7s [id=mjl5658-gl8-1k-v170401-uploads]
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["ci-secure-files"]: Creation complete after 7s [id=mjl5658-gl8-1k-v170401-ci-secure-files]
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["pages"]: Creation complete after 8s [id=mjl5658-gl8-1k-v170401-pages]
module.gitlab_ref_arch_gcp.google_storage_bucket.gitlab_object_storage_buckets["registry"]: Creation complete after 4s [id=mjl5658-gl8-1k-v170401-registry]
module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].google_service_account.gitlab[0]: Still creating... [10s elapsed]
module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].google_service_account.gitlab[0]: Creation complete after 15s [id=projects/mlockhart-56581c10/serviceAccounts/gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].google_service_account_iam_member.object_storage_profile_token_creator[0]: Creating...
module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].google_service_account_iam_member.gitlab_user_members["serviceAccount:gitlab-mjl-mac@mlockhart-56581c10.iam.gserviceaccount.com"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["ci-secure-files"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["backups"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["uploads"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["pages"]: Creating...
module.gitlab_ref_arch_gcp.module.gitlab_rails.google_compute_instance.gitlab[0]: Creating...
module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_vm_ssh_access[0]: Still creating... [10s elapsed]
module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_http_https_access[0]: Still creating... [10s elapsed]
module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_icmp_access[0]: Still creating... [10s elapsed]
module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_vm_ssh_access[0]: Creation complete after 13s [id=projects/mlockhart-56581c10/global/firewalls/mjl5658-gl8-1k-v170401-vm-ssh-access]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["packages"]: Creating...
module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_http_https_access[0]: Creation complete after 12s [id=projects/mlockhart-56581c10/global/firewalls/mjl5658-gl8-1k-v170401-http-https-access]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["mr-diffs"]: Creating...
module.gitlab_ref_arch_gcp.google_compute_firewall.gitlab_icmp_access[0]: Creation complete after 12s [id=projects/mlockhart-56581c10/global/firewalls/mjl5658-gl8-1k-v170401-icmp-access]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["artifacts"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["backups"]: Creation complete after 5s [id=b/mjl5658-gl8-1k-v170401-backups/roles/storage.objectAdmin/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["pages"]: Creation complete after 5s [id=b/mjl5658-gl8-1k-v170401-pages/roles/storage.objectAdmin/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["terraform-state"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["dependency-proxy"]: Creating...
module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].google_service_account_iam_member.object_storage_profile_token_creator[0]: Creation complete after 5s [id=projects/mlockhart-56581c10/serviceAccounts/gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com/roles/iam.serviceAccountTokenCreator/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["ci-secure-files"]: Creation complete after 5s [id=b/mjl5658-gl8-1k-v170401-ci-secure-files/roles/storage.objectAdmin/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["uploads"]: Creation complete after 5s [id=b/mjl5658-gl8-1k-v170401-uploads/roles/storage.objectAdmin/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["registry"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["lfs"]: Creating...
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["packages"]: Creation complete after 5s [id=b/mjl5658-gl8-1k-v170401-packages/roles/storage.objectAdmin/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["mr-diffs"]: Creation complete after 6s [id=b/mjl5658-gl8-1k-v170401-mr-diffs/roles/storage.objectAdmin/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["artifacts"]: Creation complete after 6s [id=b/mjl5658-gl8-1k-v170401-artifacts/roles/storage.objectAdmin/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].google_service_account_iam_member.gitlab_user_members["serviceAccount:gitlab-mjl-mac@mlockhart-56581c10.iam.gserviceaccount.com"]: Still creating... [10s elapsed]
module.gitlab_ref_arch_gcp.module.gitlab_rails.google_compute_instance.gitlab[0]: Still creating... [10s elapsed]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["dependency-proxy"]: Creation complete after 5s [id=b/mjl5658-gl8-1k-v170401-dependency-proxy/roles/storage.objectAdmin/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.module.gitlab_rails.module.google_service_account[0].google_service_account_iam_member.gitlab_user_members["serviceAccount:gitlab-mjl-mac@mlockhart-56581c10.iam.gserviceaccount.com"]: Creation complete after 10s [id=projects/mlockhart-56581c10/serviceAccounts/gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com/roles/iam.serviceAccountUser/serviceAccount:gitlab-mjl-mac@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["terraform-state"]: Creation complete after 5s [id=b/mjl5658-gl8-1k-v170401-terraform-state/roles/storage.objectAdmin/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["registry"]: Creation complete after 6s [id=b/mjl5658-gl8-1k-v170401-registry/roles/storage.objectAdmin/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.google_storage_bucket_iam_member.gitlab_rails_object_storage_buckets_member["lfs"]: Creation complete after 6s [id=b/mjl5658-gl8-1k-v170401-lfs/roles/storage.objectAdmin/serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com]
module.gitlab_ref_arch_gcp.module.gitlab_rails.google_compute_instance.gitlab[0]: Still creating... [20s elapsed]
module.gitlab_ref_arch_gcp.module.gitlab_rails.google_compute_instance.gitlab[0]: Creation complete after 23s [id=projects/mlockhart-56581c10/zones/us-west1-c/instances/mjl5658-gl8-1k-v170401-gitlab-rails-1]

Apply complete! Resources: 29 added, 0 changed, 0 destroyed.

Outputs:

gitlab_ref_arch_gcp = {
  "cloud_sql_geo_tracking_postgres_connection" = {
    "cloud_sql_host" = ""
    "cloud_sql_name" = ""
    "cloud_sql_version" = ""
  }
  "cloud_sql_postgres_connection" = {
    "cloud_sql_host" = ""
    "cloud_sql_name" = ""
    "cloud_sql_read_replica_hosts" = []
    "cloud_sql_version" = ""
  }
  "cloud_sql_praefect_postgres_connection" = {
    "cloud_sql_host" = ""
    "cloud_sql_name" = ""
    "cloud_sql_version" = ""
  }
  "consul" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "gitaly" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "gitlab_nfs" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "gitlab_rails" = {
    "data_disk_device_names" = []
    "external_addresses" = tolist([
      "34.168.4.189",
    ])
    "internal_addresses" = {
      "mjl5658-gl8-1k-v170401-gitlab-rails-1.c.mlockhart-56581c10.internal" = "10.138.0.78"
    }
    "machine_names" = [
      "mjl5658-gl8-1k-v170401-gitlab-rails-1",
    ]
    "self_links" = [
      "https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/zones/us-west1-c/instances/mjl5658-gl8-1k-v170401-gitlab-rails-1",
    ]
    "service_account" = {
      "email" = "gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      "member" = "serviceAccount:gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      "name" = "projects/mlockhart-56581c10/serviceAccounts/gl8-gitlab-rails@mlockhart-56581c10.iam.gserviceaccount.com"
      "unique_id" = "111971693028345180408"
    }
    "zones" = [
      "us-west1-c",
    ]
  }
  "haproxy_external" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "haproxy_internal" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "kubernetes" = {
    "kubernetes_cluster_id" = ""
    "kubernetes_cluster_name" = ""
    "kubernetes_cluster_version" = ""
    "kubernetes_gitaly_node_group_service_account_email" = ""
    "kubernetes_gitaly_node_group_version" = ""
    "kubernetes_node_group_service_account_email" = ""
    "kubernetes_registry_service_account_email" = ""
    "kubernetes_sidekiq_node_group_service_account_email" = ""
    "kubernetes_sidekiq_node_group_version" = ""
    "kubernetes_sidekiq_service_account_email" = ""
    "kubernetes_supporting_node_group_service_account_email" = ""
    "kubernetes_supporting_node_group_version" = ""
    "kubernetes_toolbox_service_account_email" = ""
    "kubernetes_webservice_node_group_service_account_email" = ""
    "kubernetes_webservice_node_group_version" = ""
    "kubernetes_webservice_service_account_email" = ""
  }
  "memorystore_redis_cache_connection" = {
    "memorystore_redis_cache_address" = ""
    "memorystore_redis_cache_port" = ""
  }
  "memorystore_redis_connection" = {
    "memorystore_redis_address" = ""
    "memorystore_redis_port" = ""
  }
  "memorystore_redis_persistent_connection" = {
    "memorystore_redis_persistent_address" = ""
    "memorystore_redis_persistent_port" = ""
  }
  "monitor" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "network" = {
    "vpc_id" = "projects/mlockhart-56581c10/global/networks/default"
    "vpc_name" = "default"
    "vpc_self_link" = "https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/global/networks/default"
    "vpc_subnet_cidr_block" = "10.138.0.0/20"
    "vpc_subnet_id" = "projects/mlockhart-56581c10/regions/us-west1/subnetworks/default"
    "vpc_subnet_name" = "default"
    "vpc_subnet_self_link" = "https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/regions/us-west1/subnetworks/default"
  }
  "opensearch_vm" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "pgbouncer" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "postgres" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "praefect" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "praefect_postgres" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "redis" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "redis_cache" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "redis_persistent" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
  "sidekiq" = {
    "data_disk_device_names" = []
    "external_addresses" = []
    "internal_addresses" = {}
    "machine_names" = []
    "self_links" = []
    "service_account" = null
    "zones" = []
  }
}

real    0m52.330s
user    0m3.575s
sys 0m0.862s


4. Ansible Playbooks

After provisioning the GCP infrastructure, we use Ansible to deploy GitLab into it. The aliases are similar but we run the Ansible playbooks from the main ansible directory, not the environment directory for the individual configurations.

In [14]:
alias cdae
cdae
alias cdae='cd ${GET_HOME}/ansible/environments/'

The ansible command to run the playbook with the right inventory is quite long. I have a shell function to do it. It also takes care to start in the correct directory, so we didn't need to use cdae first, but it does make it easier to get your bearings.

In [19]:
type aplayall
aplayall is a function
aplayall () 
{ 
    local FUNCDESC='Play all ansible playbooks for specified environment';
    [[ -z ${1} ]] && { 
        error "${FUNCNAME}: error: must specify an environment from ${GET_HOME}/ansible/environments/";
        return 1
    };
    E=$(echo "${1}"|tr -d '/');
    pushd ${GET_HOME}/ansible/;
    time ansible-playbook -i environments/${E}/inventory/ playbooks/all.yml;
    popd
}

4.1 Ansible playall

Let's run it to deploy GitLab! This step takes the longest time — about 20 minutes for a single-server "1k" reference architecture, and an hour or more for larger environments. Now is a good time to make a coffee or find another task to do.

The output will be saved into the notebook, so any problems can be reviewed and then fixed and retried.

In [ ]:
aplayall gl8_1k_v170401
▹ Toggle output


/workspaces/get/ansible /workspaces/get/ansible/environments

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************
[WARNING]: Found variable using reserved name: tags
[WARNING]: Found variable using reserved name: name

TASK [common : Gather facts (common)] ******************************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Mark facts gathered] ********************************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Gather package facts (common)] **********************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Check if GitLab repository exists] ******************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Install system packages (Ubuntu / Debian)] **********************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Install Python packages] ****************************************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Configure TCP keepalive settings] *******************************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Get Group Data Disks Config] ************************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Create select GitLab dirs if missing] ***************************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1] => (item={'path': '/etc/gitlab', 'mode': '0775'})
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1] => (item={'path': '/etc/gitlab/ssl', 'mode': '0755'})
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1] => (item={'path': '/etc/gitlab/trusted-certs', 'mode': '0755'})

TASK [common : Create skip-unmigrated-data-check file] *************************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Get GitLab json config file stats if it exists] *****************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Download GitLab repository installation script] *****************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Install GitLab repository] **************************************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Install GitLab repo package (deb)] ******************************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Lock GitLab package updates] ************************************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Install unattended-upgrades package] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Run Automatic Security Upgrades directly (Ubuntu / Debian)] *****
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Check if custom config exists] **********************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1 -> localhost]

TASK [common : Remove old Custom Config if not configured] *********************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Check if Custom Tasks file exists] ******************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1 -> localhost]

TASK [common : Mark common has run] ********************************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

TASK [Load Secrets if existing] ************************************************
included: common for mjl5658-gl8-1k-v170401-gitlab-rails-1

TASK [common : Check if GitLab Secrets file exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

PLAY [haproxy_*] ***************************************************************
skipping: no hosts matched

PLAY [gitlab_nfs] **************************************************************
skipping: no hosts matched

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

TASK [Load Secrets if existing] ************************************************
included: common for mjl5658-gl8-1k-v170401-gitlab-rails-1

TASK [common : Check if GitLab Secrets file exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

PLAY [consul] ******************************************************************
skipping: no hosts matched

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

TASK [Load Secrets if existing] ************************************************
included: common for mjl5658-gl8-1k-v170401-gitlab-rails-1

TASK [common : Check if GitLab Secrets file exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

PLAY [postgres] ****************************************************************
skipping: no hosts matched

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

TASK [Load Secrets if existing] ************************************************
included: common for mjl5658-gl8-1k-v170401-gitlab-rails-1

TASK [common : Check if GitLab Secrets file exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

PLAY [pgbouncer] ***************************************************************
skipping: no hosts matched

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

TASK [Load Secrets if existing] ************************************************
included: common for mjl5658-gl8-1k-v170401-gitlab-rails-1

TASK [common : Check if GitLab Secrets file exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

PLAY [redis,redis_cache_*,redis_persistent_*] **********************************
skipping: no hosts matched

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

TASK [Load Secrets if existing] ************************************************
included: common for mjl5658-gl8-1k-v170401-gitlab-rails-1

TASK [common : Check if GitLab Secrets file exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

PLAY [gitaly] ******************************************************************
skipping: no hosts matched

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

TASK [Load Secrets if existing] ************************************************
included: common for mjl5658-gl8-1k-v170401-gitlab-rails-1

TASK [common : Check if GitLab Secrets file exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

PLAY [praefect_postgres] *******************************************************
skipping: no hosts matched

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

TASK [Load Secrets if existing] ************************************************
included: common for mjl5658-gl8-1k-v170401-gitlab-rails-1

TASK [common : Check if GitLab Secrets file exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

PLAY [praefect] ****************************************************************
skipping: no hosts matched

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

TASK [Load Secrets if existing] ************************************************
included: common for mjl5658-gl8-1k-v170401-gitlab-rails-1

TASK [common : Check if GitLab Secrets file exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

PLAY [gitlab_rails] ************************************************************

TASK [Propagate Secrets if existing] *******************************************
included: common for mjl5658-gl8-1k-v170401-gitlab-rails-1

TASK [common : Check if GitLab Secrets file exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [gitlab_rails : Check if custom config exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1 -> localhost]

TASK [gitlab_rails : Setup GitLab deploy node config file with DB Migrations] ***
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [gitlab_rails : Reconfigure GitLab deploy node] ***************************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [gitlab_rails : Setup all GitLab Rails config files] **********************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [gitlab_rails : Remove old Custom Config if not configured] ***************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [gitlab_rails : Reconfigure all GitLab Rails] *****************************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [Propagate Secrets if new or changed] *************************************
included: common for mjl5658-gl8-1k-v170401-gitlab-rails-1

TASK [common : Check if GitLab Secrets file exists] ****************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Lookup GitLab Secrets file from first node] *********************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [common : Save GitLab Secrets file contents] ******************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1 -> localhost]

TASK [common : Mark that secrets have been collected after first reconfigure] ***
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1 -> localhost]

TASK [common : Write GitLab Secrets file] **************************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [gitlab_rails : Configure SSH Fast Lookup if OpenSSH service being used] ***
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [gitlab_rails : Reload OpenSSH service if being used] *********************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [gitlab_rails : Restart GitLab] *******************************************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [gitlab_rails : Enable Incremental Logging (Object Storage)] **************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [gitlab_rails : Create skip-auto-reconfigure file] ************************
changed: [mjl5658-gl8-1k-v170401-gitlab-rails-1]

TASK [gitlab_rails : Check if Custom Tasks file exists] ************************
ok: [mjl5658-gl8-1k-v170401-gitlab-rails-1 -> localhost]

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

PLAY [sidekiq] *****************************************************************
skipping: no hosts matched

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

PLAY [monitor] *****************************************************************
skipping: no hosts matched

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

PLAY [localhost] ***************************************************************

PLAY [all:!gitlab_*_node_pool:!ungrouped] **************************************

PLAY [opensearch] **************************************************************
skipping: no hosts matched

PLAY [localhost] ***************************************************************
FAILED - RETRYING: [localhost]: Wait for GitLab to be available (30 retries left).
FAILED - RETRYING: [localhost]: Wait for GitLab to be available (29 retries left).
FAILED - RETRYING: [localhost]: Wait for GitLab to be available (28 retries left).
FAILED - RETRYING: [localhost]: Wait for GitLab to be available (27 retries left).
FAILED - RETRYING: [localhost]: Wait for GitLab to be available (26 retries left).

TASK [post_configure : Wait for GitLab to be available] ************************
ok: [localhost]

TASK [post_configure : Get and save Environment Settings and License plan via GitLab Rails] ***
changed: [localhost -> mjl5658-gl8-1k-v170401-gitlab-rails-1(34.168.4.189)]

TASK [post_configure : Save Environment Settings] ******************************
ok: [localhost]

TASK [post_configure : Check for existing license or configure new subscription / license via GitLab Rails] ***
changed: [localhost -> mjl5658-gl8-1k-v170401-gitlab-rails-1(34.168.4.189)]

TASK [post_configure : Save license plan] **************************************
ok: [localhost]

TASK [post_configure : Disable Write to "authorized_keys" file setting via GitLab Rails] ***
changed: [localhost -> mjl5658-gl8-1k-v170401-gitlab-rails-1(34.168.4.189)]

TASK [post_configure : Enable 'gitlab_environment_toolkit_instance' setting via GitLab Rails] ***
changed: [localhost -> mjl5658-gl8-1k-v170401-gitlab-rails-1(34.168.4.189)]

TASK [post_configure : Check if Custom Tasks file exists] **********************
ok: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=8    changed=4    unreachable=0    failed=0    skipped=152  rescued=0    ignored=0   
mjl5658-gl8-1k-v170401-gitlab-rails-1 : ok=59   changed=18   unreachable=0    failed=0    skipped=232  rescued=0    ignored=0   


real    20m17.253s
user    0m49.661s
sys 0m20.607s
/workspaces/get/ansible/environments

5. Confirm environment

After we have installed GitLab, let's confirm that it is up and okay, before moving on to using it (testing, experimenting, or replicating our customer's problem).

In [ ]:
curl -fssL http://$(gaddress-ip gl8)/-/health
curl -fssL http://$(gaddress-ip gl8)/-/readiness?all=1|jq '.'
▹ Toggle output


GitLab OK
{
  "status": "ok",
  "master_check": [
    {
      "status": "ok"
    }
  ],
  "db_check": [
    {
      "status": "ok"
    }
  ],
  "buffered_counter_check": [
    {
      "status": "ok"
    }
  ],
  "cache_check": [
    {
      "status": "ok"
    }
  ],
  "db_load_balancing_check": [
    {
      "status": "ok"
    }
  ],
  "feature_flag_check": [
    {
      "status": "ok"
    }
  ],
  "queues_check": [
    {
      "status": "ok"
    }
  ],
  "queues_metadata_check": [
    {
      "status": "ok"
    }
  ],
  "rate_limiting_check": [
    {
      "status": "ok"
    }
  ],
  "repository_cache_check": [
    {
      "status": "ok"
    }
  ],
  "sessions_check": [
    {
      "status": "ok"
    }
  ],
  "shared_state_check": [
    {
      "status": "ok"
    }
  ],
  "trace_chunks_check": [
    {
      "status": "ok"
    }
  ],
  "chat_check": [
    {
      "status": "ok"
    }
  ],
  "workhorse_check": [
    {
      "status": "ok"
    }
  ],
  "gitaly_check": [
    {
      "status": "ok",
      "labels": {
        "shard": "default"
      }
    }
  ]
}

5.1 Login details

We can logon to the instance at its external_url, which will be the IP address. There is a single GitLab root administrator account, and it will have the randomly generated password. These values are in the Ansible vars.yml. I also have a function which prints those details.


📝 Note: this is not a safe way to store the secrets. In future I will be looking into using Ansible Vault to encrypt the secrets. The shell function will have to be updated then as well, of course.


In [18]:
type gitlab-url
gitlab-url gl8_1k_v170401
gitlab-url is a function
gitlab-url () 
{ 
    local FUNCDESC='Print the URL and default root password for a GitLab instance';
    if [[ -z ${1} ]]; then
        echo "Usage: ${FUNCDESC} «name_pattern»" ${FUNCDESC};
        return 1;
    fi;
    E=$(echo "${1}"|tr -d '/');
    yq '.all.vars.external_url, .all.vars.gitlab_root_password' ${GET_CONT}/ANSIBLE/${E}/inventory/vars.yml
}
http://34.168.4.189
ur5iY5Cea8yez9Oo

6. Clean up environment

When you no longer need this GitLab environment, you can turn it off, or destroy it.

You can stop and start the environment using gcloud compute instances stop|start INSTANCE_NAME.

The full INSTANCE_NAME is the name as defined in the configuration, which will be the same as the directory name, preceded by your global ident string, and followed by the GET role. For my single-server test instance it is mjl5658-DIRECTORY_NAME-gitlab-rails-1.

gcloud compute instances stop mjl5658-gl8-1k-v170410-gitlab-rails-1

📝 Note for larger environments, there will be multiple GCP compute instances, and they must each be started or stopped. I have a ruby script that uses gcloud with pattern matching, so that I can just use the prefix to find all of the instances (e.g. all matching gl8). Usually I run this script directly from my MacBook, not within the container. Unfortunately, I still have an outstanding issue to migrate that into the GET container.


6.0 Fetch instances

Since my convenience script isn't available to this notebook in the container, here is an approximate equivalent in bash:

In [ ]:
PATTERN=gl8
STATUS=RUNNING # or TERMINATED
INSTANCES=$(gcloud compute instances list \
  --filter="(name~$PATTERN AND status=$STATUS)" \
  --zones="$GCP_ZONE" \
  --format="value[terminator=\" \"](name)")
echo $INSTANCES
mjl5658-gl8-1k-v170401-gitlab-rails-1

6.1 Stop instance

Use gcloud to stop each instance. It can take multiple arguments, so you don't need to loop it.

In [ ]:
gcloud compute instances stop $INSTANCES
Stopping instance(s) mjl5658-gl8-1k-v170401-gitlab-rails-1...done.             
Updated [https://compute.googleapis.com/compute/v1/projects/mlockhart-56581c10/zones/us-west1-c/instances/mjl5658-gl8-1k-v170401-gitlab-rails-1].

6.2 Destroy environment

(It's not necessary to stop it first, but I've included both steps so you can (re) run either one).

The terraform destroy command is interactive, requiring manual confirmation, so I can't run it from the notebook.

You would do the following:

  1. cdte
  2. cd gl6_1k_v170401 #or whichever environment
  3. tf destroy
  4. answer yes

6.3 Release the external IP address

You can also release the IP address at this point. This is also has an interactive confirmation prompt, so here is a transcript:

gaddress delete gl8
The following addresses will be deleted:
 - [gl8] in [us-west1]

Do you want to continue (Y/n)?  

Deleted [https://www.googleapis.com/compute/v1/projects/mlockhart-56581c10/regions/us-west1/addresses/gl8].

Summary

That's the end of this short demo. I hope you found this instructive for how to employ GET from a Dev Container, to install GitLab into GCP. We did the following:

  1. Reserve a GCP public IP address
  2. Create a GET configuration based on the 1k template
  3. Provision the GCP infrastructure using Terraform
  4. Install GitLab using Ansible
  5. Test that GitLab is running
  6. Clean up
    1. Stop the environment's GCP compute instances
    2. Destroy the environment using Terraform
    3. Release the GCP reserved IP address

Other, larger reference architectures are available too. For testing, I often use the 2k ref arch to have separate Sidekiq and Rails servers, or the 3k ref arch for Gitaly Cluster. It's important to remember to use --economic|-E option for the configure script to contain cost, as these are large environments!

You can use this blog's source code as a starting point. Just open it in the get-container VS Code dev container. It has been modified somewhat for presentation, so search for the cells that contain Toggle output, and remove them. Alternatively, create a new notebook in your get-container and follow along.

Happy Hacking.