diff options
author | Jacob Vosmaer <jacob@gitlab.com> | 2020-03-20 17:56:03 +0300 |
---|---|---|
committer | Paul Okstad <pokstad@gitlab.com> | 2020-03-20 17:56:03 +0300 |
commit | 26bc162bf9c66eaf26b9453e744136d8e580aa18 (patch) | |
tree | 5ebb7f335a4b5b0e64e26846ee163d8e00133d80 | |
parent | 4bd9b1536b4776ae369b8e43388a25941e18a19e (diff) |
Automate some of the Gitaly HA demo setup
-rw-r--r-- | _support/terraform/.gitignore | 3 | ||||
-rw-r--r-- | _support/terraform/README.md | 60 | ||||
-rwxr-xr-x | _support/terraform/create-demo-cluster | 69 | ||||
-rwxr-xr-x | _support/terraform/destroy-demo-cluster | 12 | ||||
-rw-r--r-- | _support/terraform/helper.rb | 12 | ||||
-rw-r--r-- | _support/terraform/main.tf | 189 | ||||
-rwxr-xr-x | _support/terraform/print-info | 12 | ||||
-rw-r--r-- | _support/terraform/terraform.tfvars.erb | 5 |
8 files changed, 362 insertions, 0 deletions
diff --git a/_support/terraform/.gitignore b/_support/terraform/.gitignore new file mode 100644 index 000000000..5a6a4426c --- /dev/null +++ b/_support/terraform/.gitignore @@ -0,0 +1,3 @@ +/.terraform* +/*.tfstate* +/terraform.tfvars diff --git a/_support/terraform/README.md b/_support/terraform/README.md new file mode 100644 index 000000000..75aafe8fa --- /dev/null +++ b/_support/terraform/README.md @@ -0,0 +1,60 @@ +# terraform for gitaly ha demo + +## Creating a demo cluster + +### 1. Install Google Cloud SDK + +- For most platforms, including macOS, use the [official + guide](https://cloud.google.com/sdk/docs/quickstarts) +- For Arch Linux, go to [this + AUR](https://aur.archlinux.org/packages/google-cloud-sdk) + +### 2. Install Terraform + +On macOS with homebrew, use `brew install terraform`. For other +platforms see [the Terraform download +page](https://www.terraform.io/downloads.html). + +### 3. Run the script + +``` +./create-demo-cluster +``` + +This will open a browser to sign into GCP if necessary. Terraform will +print a plan and ask you to confirm it before it creates anything in +GCP. + +When the script is done, `apt-get install gitlab-ee` is still busy +running in the background on your new VM's. + +### 4. Manually create a CloudSQL instance + +In principle Terraform can also create a CloudSQL instance for +Praefect but this is still work in progress. In the meantime, please +use the GCP web UI to create a CloudSQL Postgres instance for +Praefect. + +### 5. Use SSH to manually configure the hosts + +Updating the config for all the demo cluster hosts is not yet +automated. Please follow the documentation at +https://docs.gitlab.com/ee/administration/gitaly/praefect.html. + +To see the list of IP's for your machines, run: + +``` +./print-info +``` + +## Destroying a demo cluster + +When you run the command below Terraform will print a plan of things +to destroy, that you then have to confirm (or abort with Ctrl-C). + +Be careful! Double check how many nodes are being destroyed, and what +their names are. + +``` +./destroy-demo-cluster +``` diff --git a/_support/terraform/create-demo-cluster b/_support/terraform/create-demo-cluster new file mode 100755 index 000000000..4c59c9163 --- /dev/null +++ b/_support/terraform/create-demo-cluster @@ -0,0 +1,69 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'erb' +require 'etc' + +require_relative 'helper.rb' + +TFVARS = 'terraform.tfvars' + +def main + unless gcloud_appliction_default_logged_in? + run!(%w[gcloud auth application-default login]) + end + + unless terraform_initialized? + run!(%w[terraform init]) + end + + unless File.exist?(TFVARS) + render!(TFVARS, 'terraform.tfvars.erb') + end + + run!(%w[terraform apply]) +end + +def praefect_demo_cluster_name + default_name = "#{username}-#{Time.now.utc.strftime('%Y%m%d')}" + get_input('Enter a name for your demo cluster', default_name) +end + +def username + Etc.getlogin +end + +def ssh_pubkey + default_path = File.join(Etc.getpwnam(username).dir, '.ssh/id_rsa.pub') + pubkey_path = get_input('Enter the path to your SSH public key', default_path) + pubkey = File.read(pubkey_path).chomp + + unless pubkey.start_with?('ssh-') + # Protect against accidentally using the private key + abort "contents of #{path} do not look like an SSH pubkey" + end + + pubkey +end + +def get_input(prompt, default) + puts "#{prompt} (default: #{default})." + print "> " + + input = gets.chomp + input.empty? ? default : input +end + +def render!(file, template_path) + IO.write(file, ERB.new(File.read(template_path)).result(binding)) +end + +def gcloud_appliction_default_logged_in? + system( + *%w[gcloud auth application-default print-access-token], + out: '/dev/null', + err: '/dev/null' + ) +end + +main diff --git a/_support/terraform/destroy-demo-cluster b/_support/terraform/destroy-demo-cluster new file mode 100755 index 000000000..88e7f81f7 --- /dev/null +++ b/_support/terraform/destroy-demo-cluster @@ -0,0 +1,12 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require_relative 'helper.rb' + +def main + return unless terraform_any_machines? + + run!(%w[terraform destroy]) +end + +main diff --git a/_support/terraform/helper.rb b/_support/terraform/helper.rb new file mode 100644 index 000000000..eddccbf33 --- /dev/null +++ b/_support/terraform/helper.rb @@ -0,0 +1,12 @@ +require 'json' + +require_relative '../run.rb' + +def terraform_initialized? + File.exist?('.terraform') +end + +def terraform_any_machines? + state = JSON.parse(capture!(%w[terraform show -json])) + state.has_key?('values') +end diff --git a/_support/terraform/main.tf b/_support/terraform/main.tf new file mode 100644 index 000000000..66c6b594f --- /dev/null +++ b/_support/terraform/main.tf @@ -0,0 +1,189 @@ +variable "demo_region" { default = "us-east4" } +variable "demo_zone" { default = "us-east4-c" } +variable "praefect_demo_cluster_name" { } +variable "ssh_user" {} +variable "ssh_pubkey" { } +variable "os_image" { default = "ubuntu-os-cloud/ubuntu-1804-lts" } +variable "startup_script" { + default = <<EOF + set -e + if [ -d /opt/gitlab ] ; then exit; fi + + curl -s https://packages.gitlab.com/install/repositories/gitlab/nightly-builds/script.deb.sh | sudo bash + sudo apt-get install -y gitlab-ee + EOF +} +variable "gitaly_machine_type" { default = "n1-standard-2" } +#variable "praefect_sql_password" {} + +provider "google" { + version = "~> 3.12" + + project = "gitlab-internal-153318" + region = var.demo_region + zone = var.demo_zone +} + +# resource "google_sql_database_instance" "praefect_sql" { +# name = format("%s-praefect-postgresql", var.praefect_demo_cluster_name) +# database_version = "POSTGRES_9_6" +# region = var.demo_region +# +# settings { +# # Second-generation instance tiers are based on the machine +# # type. See argument reference below. +# tier = "db-f1-micro" +# } +# } +# +# output "praefect_postgresql_ip" { +# value = google_sql_database_instance.praefect_sql.public_ip_address +# } + +# resource "google_sql_user" "users" { +# name = "praefect" +# instance = google_sql_database_instance.praefect_sql.name +# password = var.praefect_sql_password +# } + +resource "google_compute_instance" "gitlab" { + name = format("%s-gitlab", var.praefect_demo_cluster_name) + machine_type = "n1-standard-2" + + boot_disk { + initialize_params { + image = var.os_image + } + } + + network_interface { + subnetwork = "default" + access_config {} + } + + metadata = { + ssh-keys = format("%s:%s", var.ssh_user, var.ssh_pubkey) + startup-script = var.startup_script + } + + tags = ["http-server", "https-server"] +} + +output "gitlab_internal_ip" { + value = google_compute_instance.gitlab.network_interface[0].network_ip +} +output "gitlab_external_ip" { + value = google_compute_instance.gitlab.network_interface[0].access_config[0].nat_ip +} + +resource "google_compute_instance" "praefect" { + name = format("%s-praefect", var.praefect_demo_cluster_name) + machine_type = "n1-standard-1" + + boot_disk { + initialize_params { + image = var.os_image + } + } + + network_interface { + subnetwork = "default" + access_config {} + } + + metadata = { + ssh-keys = format("%s:%s", var.ssh_user, var.ssh_pubkey) + startup-script = var.startup_script + } +} + +output "praefect_internal_ip" { + value = google_compute_instance.praefect.network_interface[0].network_ip +} +output "praefect_ssh_ip" { + value = google_compute_instance.praefect.network_interface[0].access_config[0].nat_ip +} + +resource "google_compute_instance" "gitaly_1" { + name = format("%s-gitaly-1", var.praefect_demo_cluster_name) + machine_type = var.gitaly_machine_type + + boot_disk { + initialize_params { + image = var.os_image + } + } + + network_interface { + subnetwork = "default" + access_config {} + } + + metadata = { + ssh-keys = format("%s:%s", var.ssh_user, var.ssh_pubkey) + startup-script = var.startup_script + } +} + +output "gitaly_1_internal_ip" { + value = google_compute_instance.gitaly_1.network_interface[0].network_ip +} +output "gitaly_1_ssh_ip" { + value = google_compute_instance.gitaly_1.network_interface[0].access_config[0].nat_ip +} + +resource "google_compute_instance" "gitaly_2" { + name = format("%s-gitaly-2", var.praefect_demo_cluster_name) + machine_type = var.gitaly_machine_type + + boot_disk { + initialize_params { + image = var.os_image + } + } + + network_interface { + subnetwork = "default" + access_config {} + } + + metadata = { + ssh-keys = format("%s:%s", var.ssh_user, var.ssh_pubkey) + startup-script = var.startup_script + } +} + +output "gitaly_2_internal_ip" { + value = google_compute_instance.gitaly_2.network_interface[0].network_ip +} +output "gitaly_2_ssh_ip" { + value = google_compute_instance.gitaly_2.network_interface[0].access_config[0].nat_ip +} + +resource "google_compute_instance" "gitaly_3" { + name = format("%s-gitaly-3", var.praefect_demo_cluster_name) + machine_type = var.gitaly_machine_type + + boot_disk { + initialize_params { + image = var.os_image + } + } + + network_interface { + subnetwork = "default" + access_config {} + } + + metadata = { + ssh-keys = format("%s:%s", var.ssh_user, var.ssh_pubkey) + startup-script = var.startup_script + } +} + +output "gitaly_3_internal_ip" { + value = google_compute_instance.gitaly_3.network_interface[0].network_ip +} +output "gitaly_3_ssh_ip" { + value = google_compute_instance.gitaly_3.network_interface[0].access_config[0].nat_ip +} diff --git a/_support/terraform/print-info b/_support/terraform/print-info new file mode 100755 index 000000000..852404725 --- /dev/null +++ b/_support/terraform/print-info @@ -0,0 +1,12 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require_relative 'helper.rb' + +def main + return unless terraform_any_machines? + + run!(%w[terraform output]) +end + +main diff --git a/_support/terraform/terraform.tfvars.erb b/_support/terraform/terraform.tfvars.erb new file mode 100644 index 000000000..73bd7778b --- /dev/null +++ b/_support/terraform/terraform.tfvars.erb @@ -0,0 +1,5 @@ +# This variable will be prefixed to all machines created by terraform +praefect_demo_cluster_name = "<%= praefect_demo_cluster_name %>" + +ssh_user = "<%= username %>" +ssh_pubkey = "<%= ssh_pubkey %>" |