mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
feat: add new scaletest infrastructure (#15573)
Closes https://github.com/coder/internal/issues/148 This has been validated to have working proxies with the `small` scenario. - [x] multi-region gcp infrastructure - [x] use cloudflare provider to automate dns entries - [x] automate proxy registration - [x] multi-regional proxies - [x] move scenarios into locals This excludes the infrastructure for `cert-manager` and `otel-collector` and those will be included in followup PRs.
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
resource "cloudflare_record" "coder" {
|
||||
for_each = local.deployments
|
||||
zone_id = var.cloudflare_zone_id
|
||||
name = each.value.subdomain
|
||||
content = google_compute_address.coder[each.key].address
|
||||
type = "A"
|
||||
ttl = 3600
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
coder:
|
||||
workspaceProxy: ${workspace_proxy}
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: "cloud.google.com/gke-nodepool"
|
||||
operator: "In"
|
||||
values: ["${node_pool}"]
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 1
|
||||
podAffinityTerm:
|
||||
topologyKey: "kubernetes.io/hostname"
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: "app.kubernetes.io/instance"
|
||||
operator: "In"
|
||||
values: ["${release_name}"]
|
||||
env:
|
||||
%{~ if workspace_proxy ~}
|
||||
- name: "CODER_ACCESS_URL"
|
||||
value: "${access_url}"
|
||||
- name: CODER_PRIMARY_ACCESS_URL
|
||||
value: "${primary_url}"
|
||||
- name: CODER_PROXY_SESSION_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: token
|
||||
name: "${proxy_token}"
|
||||
%{~ endif ~}
|
||||
%{~ if provisionerd ~}
|
||||
- name: "CODER_URL"
|
||||
value: "${access_url}"
|
||||
- name: "CODER_PROVISIONERD_TAGS"
|
||||
value: "scope=organization"
|
||||
- name: "CODER_CONFIG_DIR"
|
||||
value: "/tmp/config"
|
||||
%{~ endif ~}
|
||||
%{~ if !workspace_proxy && !provisionerd ~}
|
||||
- name: "CODER_ACCESS_URL"
|
||||
value: "${access_url}"
|
||||
- name: "CODER_PG_CONNECTION_URL"
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: "${db_secret}"
|
||||
key: url
|
||||
- name: "CODER_PROVISIONER_DAEMONS"
|
||||
value: "0"
|
||||
- name: CODER_PROVISIONER_DAEMON_PSK
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: psk
|
||||
name: "${provisionerd_psk}"
|
||||
- name: "CODER_PROMETHEUS_COLLECT_AGENT_STATS"
|
||||
value: "true"
|
||||
- name: "CODER_PROMETHEUS_COLLECT_DB_METRICS"
|
||||
value: "true"
|
||||
- name: "CODER_PPROF_ENABLE"
|
||||
value: "true"
|
||||
%{~ endif ~}
|
||||
- name: "CODER_CACHE_DIRECTORY"
|
||||
value: "/tmp/coder"
|
||||
- name: "CODER_TELEMETRY_ENABLE"
|
||||
value: "false"
|
||||
- name: "CODER_LOGGING_HUMAN"
|
||||
value: "/dev/null"
|
||||
- name: "CODER_LOGGING_STACKDRIVER"
|
||||
value: "/dev/stderr"
|
||||
- name: "CODER_PROMETHEUS_ENABLE"
|
||||
value: "true"
|
||||
- name: "CODER_VERBOSE"
|
||||
value: "true"
|
||||
- name: "CODER_EXPERIMENTS"
|
||||
value: "${experiments}"
|
||||
- name: "CODER_DANGEROUS_DISABLE_RATE_LIMITS"
|
||||
value: "true"
|
||||
image:
|
||||
repo: ${image_repo}
|
||||
tag: ${image_tag}
|
||||
replicaCount: "${replicas}"
|
||||
resources:
|
||||
requests:
|
||||
cpu: "${cpu_request}"
|
||||
memory: "${mem_request}"
|
||||
limits:
|
||||
cpu: "${cpu_limit}"
|
||||
memory: "${mem_limit}"
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
%{~ if !provisionerd ~}
|
||||
service:
|
||||
enable: true
|
||||
sessionAffinity: None
|
||||
loadBalancerIP: "${ip_address}"
|
||||
%{~ endif ~}
|
||||
volumeMounts:
|
||||
- mountPath: "/tmp"
|
||||
name: cache
|
||||
readOnly: false
|
||||
volumes:
|
||||
- emptyDir:
|
||||
sizeLimit: 1024Mi
|
||||
name: cache
|
||||
@@ -0,0 +1,102 @@
|
||||
data "http" "coder_healthy" {
|
||||
url = local.deployments.primary.url
|
||||
// Wait up to 5 minutes for DNS to propagate
|
||||
retry {
|
||||
attempts = 30
|
||||
min_delay_ms = 10000
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
postcondition {
|
||||
condition = self.status_code == 200
|
||||
error_message = "${self.url} returned an unhealthy status code"
|
||||
}
|
||||
}
|
||||
|
||||
depends_on = [helm_release.coder_primary, cloudflare_record.coder["primary"]]
|
||||
}
|
||||
|
||||
resource "null_resource" "api_key" {
|
||||
provisioner "local-exec" {
|
||||
interpreter = ["/bin/bash", "-c"]
|
||||
command = <<EOF
|
||||
set -e
|
||||
|
||||
curl '${local.deployments.primary.url}/api/v2/users/first' \
|
||||
--data-raw $'{"email":"${local.coder_admin_email}","password":"${local.coder_admin_password}","username":"${local.coder_admin_user}","name":"${local.coder_admin_full_name}","trial":false}' \
|
||||
--insecure --silent --output /dev/null
|
||||
|
||||
session_token=$(curl '${local.deployments.primary.url}/api/v2/users/login' \
|
||||
--data-raw $'{"email":"${local.coder_admin_email}","password":"${local.coder_admin_password}"}' \
|
||||
--insecure --silent | jq -r .session_token)
|
||||
|
||||
echo -n $${session_token} > ${path.module}/.coderv2/session_token
|
||||
|
||||
api_key=$(curl '${local.deployments.primary.url}/api/v2/users/me/keys/tokens' \
|
||||
-H "Coder-Session-Token: $${session_token}" \
|
||||
--data-raw '{"token_name":"terraform","scope":"all"}' \
|
||||
--insecure --silent | jq -r .key)
|
||||
|
||||
echo -n $${api_key} > ${path.module}/.coderv2/api_key
|
||||
EOF
|
||||
}
|
||||
|
||||
depends_on = [data.http.coder_healthy]
|
||||
}
|
||||
|
||||
data "local_file" "api_key" {
|
||||
filename = "${path.module}/.coderv2/api_key"
|
||||
depends_on = [null_resource.api_key]
|
||||
}
|
||||
|
||||
resource "null_resource" "license" {
|
||||
provisioner "local-exec" {
|
||||
interpreter = ["/bin/bash", "-c"]
|
||||
command = <<EOF
|
||||
curl '${local.deployments.primary.url}/api/v2/licenses' \
|
||||
-H "Coder-Session-Token: ${trimspace(data.local_file.api_key.content)}" \
|
||||
--data-raw '{"license":"${var.coder_license}"}' \
|
||||
--insecure --silent --output /dev/null
|
||||
EOF
|
||||
}
|
||||
}
|
||||
|
||||
resource "null_resource" "europe_proxy_token" {
|
||||
provisioner "local-exec" {
|
||||
interpreter = ["/bin/bash", "-c"]
|
||||
command = <<EOF
|
||||
curl '${local.deployments.primary.url}/api/v2/workspaceproxies' \
|
||||
-H "Coder-Session-Token: ${trimspace(data.local_file.api_key.content)}" \
|
||||
--data-raw '{"name":"europe","display_name":"Europe","icon":"/emojis/1f950.png"}' \
|
||||
--insecure --silent \
|
||||
| jq -r .proxy_token > ${path.module}/.coderv2/europe_proxy_token
|
||||
EOF
|
||||
}
|
||||
|
||||
depends_on = [null_resource.license]
|
||||
}
|
||||
|
||||
data "local_file" "europe_proxy_token" {
|
||||
filename = "${path.module}/.coderv2/europe_proxy_token"
|
||||
depends_on = [null_resource.europe_proxy_token]
|
||||
}
|
||||
|
||||
resource "null_resource" "asia_proxy_token" {
|
||||
provisioner "local-exec" {
|
||||
interpreter = ["/bin/bash", "-c"]
|
||||
command = <<EOF
|
||||
curl '${local.deployments.primary.url}/api/v2/workspaceproxies' \
|
||||
-H "Coder-Session-Token: ${trimspace(data.local_file.api_key.content)}" \
|
||||
--data-raw '{"name":"asia","display_name":"Asia","icon":"/emojis/1f35b.png"}' \
|
||||
--insecure --silent \
|
||||
| jq -r .proxy_token > ${path.module}/.coderv2/asia_proxy_token
|
||||
EOF
|
||||
}
|
||||
|
||||
depends_on = [null_resource.license]
|
||||
}
|
||||
|
||||
data "local_file" "asia_proxy_token" {
|
||||
filename = "${path.module}/.coderv2/asia_proxy_token"
|
||||
depends_on = [null_resource.asia_proxy_token]
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
resource "local_file" "kubernetes_template" {
|
||||
filename = "${path.module}/.coderv2/templates/kubernetes/main.tf"
|
||||
content = <<EOF
|
||||
terraform {
|
||||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "~> 0.23.0"
|
||||
}
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "~> 2.30"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "coder" {}
|
||||
|
||||
provider "kubernetes" {
|
||||
config_path = null # always use host
|
||||
}
|
||||
|
||||
data "coder_workspace" "me" {}
|
||||
data "coder_workspace_owner" "me" {}
|
||||
|
||||
resource "coder_agent" "main" {
|
||||
os = "linux"
|
||||
arch = "amd64"
|
||||
}
|
||||
|
||||
resource "kubernetes_pod" "main" {
|
||||
count = data.coder_workspace.me.start_count
|
||||
metadata {
|
||||
name = "coder-$${lower(data.coder_workspace_owner.me.name)}-$${lower(data.coder_workspace.me.name)}"
|
||||
namespace = "${local.coder_namespace}"
|
||||
labels = {
|
||||
"app.kubernetes.io/name" = "coder-workspace"
|
||||
"app.kubernetes.io/instance" = "coder-workspace-$${lower(data.coder_workspace_owner.me.name)}-$${lower(data.coder_workspace.me.name)}"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
security_context {
|
||||
run_as_user = "1000"
|
||||
fs_group = "1000"
|
||||
}
|
||||
container {
|
||||
name = "dev"
|
||||
image = "${var.workspace_image}"
|
||||
image_pull_policy = "Always"
|
||||
command = ["sh", "-c", coder_agent.main.init_script]
|
||||
security_context {
|
||||
run_as_user = "1000"
|
||||
}
|
||||
env {
|
||||
name = "CODER_AGENT_TOKEN"
|
||||
value = coder_agent.main.token
|
||||
}
|
||||
resources {
|
||||
requests = {
|
||||
"cpu" = "${local.scenarios[var.scenario].workspaces.cpu_request}"
|
||||
"memory" = "${local.scenarios[var.scenario].workspaces.mem_request}"
|
||||
}
|
||||
limits = {
|
||||
"cpu" = "${local.scenarios[var.scenario].workspaces.cpu_limit}"
|
||||
"memory" = "${local.scenarios[var.scenario].workspaces.mem_limit}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
affinity {
|
||||
node_affinity {
|
||||
required_during_scheduling_ignored_during_execution {
|
||||
node_selector_term {
|
||||
match_expressions {
|
||||
key = "cloud.google.com/gke-nodepool"
|
||||
operator = "In"
|
||||
values = ["${google_container_node_pool.node_pool["primary_workspaces"].name}","${google_container_node_pool.node_pool["europe_workspaces"].name}","${google_container_node_pool.node_pool["asia_workspaces"].name}"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "template" {
|
||||
provider = kubernetes.primary
|
||||
|
||||
metadata {
|
||||
name = "coder-template"
|
||||
namespace = kubernetes_namespace.coder_primary.metadata.0.name
|
||||
}
|
||||
|
||||
data = {
|
||||
"main.tf" = local_file.kubernetes_template.content
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_job" "push_template" {
|
||||
provider = kubernetes.primary
|
||||
|
||||
metadata {
|
||||
name = "${var.name}-push-template"
|
||||
namespace = kubernetes_namespace.coder_primary.metadata.0.name
|
||||
labels = {
|
||||
"app.kubernetes.io/name" = "${var.name}-push-template"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
completions = 1
|
||||
template {
|
||||
metadata {}
|
||||
spec {
|
||||
affinity {
|
||||
node_affinity {
|
||||
required_during_scheduling_ignored_during_execution {
|
||||
node_selector_term {
|
||||
match_expressions {
|
||||
key = "cloud.google.com/gke-nodepool"
|
||||
operator = "In"
|
||||
values = ["${google_container_node_pool.node_pool["primary_misc"].name}"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
container {
|
||||
name = "cli"
|
||||
image = "${var.coder_image_repo}:${var.coder_image_tag}"
|
||||
command = [
|
||||
"/opt/coder",
|
||||
"--verbose",
|
||||
"--url=${local.deployments.primary.url}",
|
||||
"--token=${trimspace(data.local_file.api_key.content)}",
|
||||
"templates",
|
||||
"push",
|
||||
"--directory=/home/coder/template",
|
||||
"--yes",
|
||||
"kubernetes"
|
||||
]
|
||||
volume_mount {
|
||||
name = "coder-template"
|
||||
mount_path = "/home/coder/template/main.tf"
|
||||
sub_path = "main.tf"
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "coder-template"
|
||||
config_map {
|
||||
name = kubernetes_config_map.template.metadata.0.name
|
||||
}
|
||||
}
|
||||
restart_policy = "Never"
|
||||
}
|
||||
}
|
||||
}
|
||||
wait_for_completion = true
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
data "google_compute_default_service_account" "default" {
|
||||
project = var.project_id
|
||||
depends_on = [google_project_service.api["compute.googleapis.com"]]
|
||||
}
|
||||
|
||||
locals {
|
||||
deployments = {
|
||||
primary = {
|
||||
subdomain = "${var.name}-scaletest"
|
||||
url = "http://${var.name}-scaletest.${var.cloudflare_domain}"
|
||||
region = "us-east1"
|
||||
zone = "us-east1-c"
|
||||
cidr = "10.200.0.0/24"
|
||||
}
|
||||
europe = {
|
||||
subdomain = "${var.name}-europe-scaletest"
|
||||
url = "http://${var.name}-europe-scaletest.${var.cloudflare_domain}"
|
||||
region = "europe-west1"
|
||||
zone = "europe-west1-b"
|
||||
cidr = "10.201.0.0/24"
|
||||
}
|
||||
asia = {
|
||||
subdomain = "${var.name}-asia-scaletest"
|
||||
url = "http://${var.name}-asia-scaletest.${var.cloudflare_domain}"
|
||||
region = "asia-southeast1"
|
||||
zone = "asia-southeast1-a"
|
||||
cidr = "10.202.0.0/24"
|
||||
}
|
||||
}
|
||||
node_pools = {
|
||||
primary_coder = {
|
||||
name = "coder"
|
||||
cluster = "primary"
|
||||
}
|
||||
primary_workspaces = {
|
||||
name = "workspaces"
|
||||
cluster = "primary"
|
||||
}
|
||||
primary_misc = {
|
||||
name = "misc"
|
||||
cluster = "primary"
|
||||
}
|
||||
europe_coder = {
|
||||
name = "coder"
|
||||
cluster = "europe"
|
||||
}
|
||||
europe_workspaces = {
|
||||
name = "workspaces"
|
||||
cluster = "europe"
|
||||
}
|
||||
europe_misc = {
|
||||
name = "misc"
|
||||
cluster = "europe"
|
||||
}
|
||||
asia_coder = {
|
||||
name = "coder"
|
||||
cluster = "asia"
|
||||
}
|
||||
asia_workspaces = {
|
||||
name = "workspaces"
|
||||
cluster = "asia"
|
||||
}
|
||||
asia_misc = {
|
||||
name = "misc"
|
||||
cluster = "asia"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_container_cluster" "cluster" {
|
||||
for_each = local.deployments
|
||||
name = "${var.name}-${each.key}"
|
||||
location = each.value.zone
|
||||
project = var.project_id
|
||||
network = google_compute_network.vpc.name
|
||||
subnetwork = google_compute_subnetwork.subnet[each.key].name
|
||||
networking_mode = "VPC_NATIVE"
|
||||
default_max_pods_per_node = 256
|
||||
ip_allocation_policy { # Required with networking_mode=VPC_NATIVE
|
||||
|
||||
}
|
||||
release_channel {
|
||||
# Setting release channel as STABLE can cause unexpected cluster upgrades.
|
||||
channel = "UNSPECIFIED"
|
||||
}
|
||||
initial_node_count = 1
|
||||
remove_default_node_pool = true
|
||||
|
||||
network_policy {
|
||||
enabled = true
|
||||
}
|
||||
depends_on = [
|
||||
google_project_service.api["container.googleapis.com"]
|
||||
]
|
||||
monitoring_config {
|
||||
enable_components = ["SYSTEM_COMPONENTS"]
|
||||
managed_prometheus {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
workload_identity_config {
|
||||
workload_pool = "${data.google_project.project.project_id}.svc.id.goog"
|
||||
}
|
||||
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
maintenance_policy,
|
||||
release_channel,
|
||||
remove_default_node_pool
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_container_node_pool" "node_pool" {
|
||||
for_each = local.node_pools
|
||||
name = each.value.name
|
||||
location = local.deployments[each.value.cluster].zone
|
||||
project = var.project_id
|
||||
cluster = google_container_cluster.cluster[each.value.cluster].name
|
||||
node_count = local.scenarios[var.scenario][each.value.name].nodepool_size
|
||||
node_config {
|
||||
oauth_scopes = [
|
||||
"https://www.googleapis.com/auth/logging.write",
|
||||
"https://www.googleapis.com/auth/monitoring",
|
||||
"https://www.googleapis.com/auth/trace.append",
|
||||
"https://www.googleapis.com/auth/devstorage.read_only",
|
||||
"https://www.googleapis.com/auth/service.management.readonly",
|
||||
"https://www.googleapis.com/auth/servicecontrol",
|
||||
]
|
||||
disk_size_gb = 100
|
||||
machine_type = local.scenarios[var.scenario][each.value.name].machine_type
|
||||
image_type = "cos_containerd"
|
||||
service_account = data.google_compute_default_service_account.default.email
|
||||
tags = ["gke-node", "${var.project_id}-gke"]
|
||||
labels = {
|
||||
env = var.project_id
|
||||
}
|
||||
metadata = {
|
||||
disable-legacy-endpoints = "true"
|
||||
}
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [management[0].auto_repair, management[0].auto_upgrade, timeouts]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
resource "google_sql_database_instance" "db" {
|
||||
name = "${var.name}-coder"
|
||||
project = var.project_id
|
||||
region = local.deployments.primary.region
|
||||
database_version = "POSTGRES_14"
|
||||
deletion_protection = false
|
||||
|
||||
depends_on = [google_service_networking_connection.private_vpc_connection]
|
||||
|
||||
settings {
|
||||
tier = local.scenarios[var.scenario].cloudsql.tier
|
||||
activation_policy = "ALWAYS"
|
||||
availability_type = "ZONAL"
|
||||
|
||||
location_preference {
|
||||
zone = local.deployments.primary.zone
|
||||
}
|
||||
|
||||
database_flags {
|
||||
name = "max_connections"
|
||||
value = local.scenarios[var.scenario].cloudsql.max_connections
|
||||
}
|
||||
|
||||
ip_configuration {
|
||||
ipv4_enabled = false
|
||||
private_network = google_compute_network.vpc.id
|
||||
}
|
||||
|
||||
insights_config {
|
||||
query_insights_enabled = true
|
||||
query_string_length = 1024
|
||||
record_application_tags = false
|
||||
record_client_address = false
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [deletion_protection, timeouts]
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_sql_database" "coder" {
|
||||
project = var.project_id
|
||||
instance = google_sql_database_instance.db.id
|
||||
name = "${var.name}-coder"
|
||||
# required for postgres, otherwise db fails to delete
|
||||
deletion_policy = "ABANDON"
|
||||
lifecycle {
|
||||
ignore_changes = [deletion_policy]
|
||||
}
|
||||
}
|
||||
|
||||
resource "random_password" "coder_postgres_password" {
|
||||
length = 12
|
||||
}
|
||||
|
||||
resource "random_password" "prometheus_postgres_password" {
|
||||
length = 12
|
||||
}
|
||||
|
||||
resource "google_sql_user" "coder" {
|
||||
project = var.project_id
|
||||
instance = google_sql_database_instance.db.id
|
||||
name = "${var.name}-coder"
|
||||
type = "BUILT_IN"
|
||||
password = random_password.coder_postgres_password.result
|
||||
# required for postgres, otherwise user fails to delete
|
||||
deletion_policy = "ABANDON"
|
||||
lifecycle {
|
||||
ignore_changes = [deletion_policy, password]
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_sql_user" "prometheus" {
|
||||
project = var.project_id
|
||||
instance = google_sql_database_instance.db.id
|
||||
name = "${var.name}-prometheus"
|
||||
type = "BUILT_IN"
|
||||
password = random_password.prometheus_postgres_password.result
|
||||
# required for postgres, otherwise user fails to delete
|
||||
deletion_policy = "ABANDON"
|
||||
lifecycle {
|
||||
ignore_changes = [deletion_policy, password]
|
||||
}
|
||||
}
|
||||
|
||||
locals {
|
||||
coder_db_url = "postgres://${google_sql_user.coder.name}:${urlencode(random_password.coder_postgres_password.result)}@${google_sql_database_instance.db.private_ip_address}/${google_sql_database.coder.name}?sslmode=disable"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
locals {
|
||||
project_apis = [
|
||||
"cloudtrace",
|
||||
"compute",
|
||||
"container",
|
||||
"logging",
|
||||
"monitoring",
|
||||
"servicemanagement",
|
||||
"servicenetworking",
|
||||
"sqladmin",
|
||||
"stackdriver",
|
||||
"storage-api",
|
||||
]
|
||||
}
|
||||
|
||||
data "google_project" "project" {
|
||||
project_id = var.project_id
|
||||
}
|
||||
|
||||
resource "google_project_service" "api" {
|
||||
for_each = toset(local.project_apis)
|
||||
project = data.google_project.project.project_id
|
||||
service = "${each.value}.googleapis.com"
|
||||
|
||||
disable_dependent_services = false
|
||||
disable_on_destroy = false
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
resource "google_compute_network" "vpc" {
|
||||
project = var.project_id
|
||||
name = var.name
|
||||
auto_create_subnetworks = "false"
|
||||
depends_on = [
|
||||
google_project_service.api["compute.googleapis.com"]
|
||||
]
|
||||
}
|
||||
|
||||
resource "google_compute_subnetwork" "subnet" {
|
||||
for_each = local.deployments
|
||||
name = "${var.name}-${each.key}"
|
||||
project = var.project_id
|
||||
region = each.value.region
|
||||
network = google_compute_network.vpc.name
|
||||
ip_cidr_range = each.value.cidr
|
||||
}
|
||||
|
||||
resource "google_compute_address" "coder" {
|
||||
for_each = local.deployments
|
||||
project = var.project_id
|
||||
region = each.value.region
|
||||
name = "${var.name}-${each.key}-coder"
|
||||
address_type = "EXTERNAL"
|
||||
network_tier = "PREMIUM"
|
||||
}
|
||||
|
||||
resource "google_compute_global_address" "sql_peering" {
|
||||
project = var.project_id
|
||||
name = "${var.name}-sql-peering"
|
||||
purpose = "VPC_PEERING"
|
||||
address_type = "INTERNAL"
|
||||
prefix_length = 16
|
||||
network = google_compute_network.vpc.id
|
||||
}
|
||||
|
||||
resource "google_service_networking_connection" "private_vpc_connection" {
|
||||
network = google_compute_network.vpc.id
|
||||
service = "servicenetworking.googleapis.com"
|
||||
reserved_peering_ranges = [google_compute_global_address.sql_peering.name]
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
resource "kubernetes_namespace" "coder_asia" {
|
||||
provider = kubernetes.asia
|
||||
|
||||
metadata {
|
||||
name = local.coder_namespace
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [timeouts, wait_for_default_service_account]
|
||||
}
|
||||
|
||||
depends_on = [google_container_node_pool.node_pool["asia_misc"]]
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "provisionerd_psk_asia" {
|
||||
provider = kubernetes.asia
|
||||
|
||||
type = "Opaque"
|
||||
metadata {
|
||||
name = "coder-provisioner-psk"
|
||||
namespace = kubernetes_namespace.coder_asia.metadata.0.name
|
||||
}
|
||||
data = {
|
||||
psk = random_password.provisionerd_psk.result
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [timeouts, wait_for_service_account_token]
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "proxy_token_asia" {
|
||||
provider = kubernetes.asia
|
||||
|
||||
type = "Opaque"
|
||||
metadata {
|
||||
name = "coder-proxy-token"
|
||||
namespace = kubernetes_namespace.coder_asia.metadata.0.name
|
||||
}
|
||||
data = {
|
||||
token = trimspace(data.local_file.asia_proxy_token.content)
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [timeouts, wait_for_service_account_token]
|
||||
}
|
||||
}
|
||||
|
||||
resource "helm_release" "coder_asia" {
|
||||
provider = helm.asia
|
||||
|
||||
repository = local.coder_helm_repo
|
||||
chart = local.coder_helm_chart
|
||||
name = local.coder_release_name
|
||||
version = var.coder_chart_version
|
||||
namespace = kubernetes_namespace.coder_asia.metadata.0.name
|
||||
values = [templatefile("${path.module}/coder_helm_values.tftpl", {
|
||||
workspace_proxy = true,
|
||||
provisionerd = false,
|
||||
primary_url = local.deployments.primary.url,
|
||||
proxy_token = kubernetes_secret.proxy_token_asia.metadata.0.name,
|
||||
db_secret = null,
|
||||
ip_address = google_compute_address.coder["asia"].address,
|
||||
provisionerd_psk = null,
|
||||
access_url = local.deployments.asia.url,
|
||||
node_pool = google_container_node_pool.node_pool["asia_coder"].name,
|
||||
release_name = local.coder_release_name,
|
||||
experiments = var.coder_experiments,
|
||||
image_repo = var.coder_image_repo,
|
||||
image_tag = var.coder_image_tag,
|
||||
replicas = local.scenarios[var.scenario].coder.replicas,
|
||||
cpu_request = local.scenarios[var.scenario].coder.cpu_request,
|
||||
mem_request = local.scenarios[var.scenario].coder.mem_request,
|
||||
cpu_limit = local.scenarios[var.scenario].coder.cpu_limit,
|
||||
mem_limit = local.scenarios[var.scenario].coder.mem_limit,
|
||||
})]
|
||||
}
|
||||
|
||||
resource "helm_release" "provisionerd_asia" {
|
||||
provider = helm.asia
|
||||
|
||||
repository = local.coder_helm_repo
|
||||
chart = local.provisionerd_helm_chart
|
||||
name = local.provisionerd_release_name
|
||||
version = var.provisionerd_chart_version
|
||||
namespace = kubernetes_namespace.coder_asia.metadata.0.name
|
||||
values = [templatefile("${path.module}/coder_helm_values.tftpl", {
|
||||
workspace_proxy = false,
|
||||
provisionerd = true,
|
||||
primary_url = null,
|
||||
proxy_token = null,
|
||||
db_secret = null,
|
||||
ip_address = null,
|
||||
provisionerd_psk = kubernetes_secret.provisionerd_psk_asia.metadata.0.name,
|
||||
access_url = local.deployments.primary.url,
|
||||
node_pool = google_container_node_pool.node_pool["asia_coder"].name,
|
||||
release_name = local.coder_release_name,
|
||||
experiments = var.coder_experiments,
|
||||
image_repo = var.coder_image_repo,
|
||||
image_tag = var.coder_image_tag,
|
||||
replicas = local.scenarios[var.scenario].provisionerd.replicas,
|
||||
cpu_request = local.scenarios[var.scenario].provisionerd.cpu_request,
|
||||
mem_request = local.scenarios[var.scenario].provisionerd.mem_request,
|
||||
cpu_limit = local.scenarios[var.scenario].provisionerd.cpu_limit,
|
||||
mem_limit = local.scenarios[var.scenario].provisionerd.mem_limit,
|
||||
})]
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
resource "kubernetes_namespace" "coder_europe" {
|
||||
provider = kubernetes.europe
|
||||
|
||||
metadata {
|
||||
name = local.coder_namespace
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [timeouts, wait_for_default_service_account]
|
||||
}
|
||||
|
||||
depends_on = [google_container_node_pool.node_pool["europe_misc"]]
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "provisionerd_psk_europe" {
|
||||
provider = kubernetes.europe
|
||||
|
||||
type = "Opaque"
|
||||
metadata {
|
||||
name = "coder-provisioner-psk"
|
||||
namespace = kubernetes_namespace.coder_europe.metadata.0.name
|
||||
}
|
||||
data = {
|
||||
psk = random_password.provisionerd_psk.result
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [timeouts, wait_for_service_account_token]
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "proxy_token_europe" {
|
||||
provider = kubernetes.europe
|
||||
|
||||
type = "Opaque"
|
||||
metadata {
|
||||
name = "coder-proxy-token"
|
||||
namespace = kubernetes_namespace.coder_europe.metadata.0.name
|
||||
}
|
||||
data = {
|
||||
token = trimspace(data.local_file.europe_proxy_token.content)
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [timeouts, wait_for_service_account_token]
|
||||
}
|
||||
}
|
||||
|
||||
resource "helm_release" "coder_europe" {
|
||||
provider = helm.europe
|
||||
|
||||
repository = local.coder_helm_repo
|
||||
chart = local.coder_helm_chart
|
||||
name = local.coder_release_name
|
||||
version = var.coder_chart_version
|
||||
namespace = kubernetes_namespace.coder_europe.metadata.0.name
|
||||
values = [templatefile("${path.module}/coder_helm_values.tftpl", {
|
||||
workspace_proxy = true,
|
||||
provisionerd = false,
|
||||
primary_url = local.deployments.primary.url,
|
||||
proxy_token = kubernetes_secret.proxy_token_europe.metadata.0.name,
|
||||
db_secret = null,
|
||||
ip_address = google_compute_address.coder["europe"].address,
|
||||
provisionerd_psk = null,
|
||||
access_url = local.deployments.europe.url,
|
||||
node_pool = google_container_node_pool.node_pool["europe_coder"].name,
|
||||
release_name = local.coder_release_name,
|
||||
experiments = var.coder_experiments,
|
||||
image_repo = var.coder_image_repo,
|
||||
image_tag = var.coder_image_tag,
|
||||
replicas = local.scenarios[var.scenario].coder.replicas,
|
||||
cpu_request = local.scenarios[var.scenario].coder.cpu_request,
|
||||
mem_request = local.scenarios[var.scenario].coder.mem_request,
|
||||
cpu_limit = local.scenarios[var.scenario].coder.cpu_limit,
|
||||
mem_limit = local.scenarios[var.scenario].coder.mem_limit,
|
||||
})]
|
||||
}
|
||||
|
||||
resource "helm_release" "provisionerd_europe" {
|
||||
provider = helm.europe
|
||||
|
||||
repository = local.coder_helm_repo
|
||||
chart = local.provisionerd_helm_chart
|
||||
name = local.provisionerd_release_name
|
||||
version = var.provisionerd_chart_version
|
||||
namespace = kubernetes_namespace.coder_europe.metadata.0.name
|
||||
values = [templatefile("${path.module}/coder_helm_values.tftpl", {
|
||||
workspace_proxy = false,
|
||||
provisionerd = true,
|
||||
primary_url = null,
|
||||
proxy_token = null,
|
||||
db_secret = null,
|
||||
ip_address = null,
|
||||
provisionerd_psk = kubernetes_secret.provisionerd_psk_europe.metadata.0.name,
|
||||
access_url = local.deployments.primary.url,
|
||||
node_pool = google_container_node_pool.node_pool["europe_coder"].name,
|
||||
release_name = local.coder_release_name,
|
||||
experiments = var.coder_experiments,
|
||||
image_repo = var.coder_image_repo,
|
||||
image_tag = var.coder_image_tag,
|
||||
replicas = local.scenarios[var.scenario].provisionerd.replicas,
|
||||
cpu_request = local.scenarios[var.scenario].provisionerd.cpu_request,
|
||||
mem_request = local.scenarios[var.scenario].provisionerd.mem_request,
|
||||
cpu_limit = local.scenarios[var.scenario].provisionerd.cpu_limit,
|
||||
mem_limit = local.scenarios[var.scenario].provisionerd.mem_limit,
|
||||
})]
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
data "google_client_config" "default" {}
|
||||
|
||||
locals {
|
||||
coder_admin_email = "admin@coder.com"
|
||||
coder_admin_full_name = "Coder Admin"
|
||||
coder_admin_user = "coder"
|
||||
coder_admin_password = "SomeSecurePassword!"
|
||||
coder_helm_repo = "https://helm.coder.com/v2"
|
||||
coder_helm_chart = "coder"
|
||||
coder_namespace = "coder"
|
||||
coder_release_name = "${var.name}-coder"
|
||||
provisionerd_helm_chart = "coder-provisioner"
|
||||
provisionerd_release_name = "${var.name}-provisionerd"
|
||||
|
||||
}
|
||||
|
||||
resource "random_password" "provisionerd_psk" {
|
||||
length = 26
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace" "coder_primary" {
|
||||
provider = kubernetes.primary
|
||||
|
||||
metadata {
|
||||
name = local.coder_namespace
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [timeouts, wait_for_default_service_account]
|
||||
}
|
||||
|
||||
depends_on = [google_container_node_pool.node_pool["primary_misc"]]
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "coder_db" {
|
||||
provider = kubernetes.primary
|
||||
|
||||
type = "Opaque"
|
||||
metadata {
|
||||
name = "coder-db-url"
|
||||
namespace = kubernetes_namespace.coder_primary.metadata.0.name
|
||||
}
|
||||
data = {
|
||||
url = local.coder_db_url
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [timeouts, wait_for_service_account_token]
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "provisionerd_psk_primary" {
|
||||
provider = kubernetes.primary
|
||||
|
||||
type = "Opaque"
|
||||
metadata {
|
||||
name = "coder-provisioner-psk"
|
||||
namespace = kubernetes_namespace.coder_primary.metadata.0.name
|
||||
}
|
||||
data = {
|
||||
psk = random_password.provisionerd_psk.result
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [timeouts, wait_for_service_account_token]
|
||||
}
|
||||
}
|
||||
|
||||
resource "helm_release" "coder_primary" {
|
||||
provider = helm.primary
|
||||
|
||||
repository = local.coder_helm_repo
|
||||
chart = local.coder_helm_chart
|
||||
name = local.coder_release_name
|
||||
version = var.coder_chart_version
|
||||
namespace = kubernetes_namespace.coder_primary.metadata.0.name
|
||||
values = [templatefile("${path.module}/coder_helm_values.tftpl", {
|
||||
workspace_proxy = false,
|
||||
provisionerd = false,
|
||||
primary_url = null,
|
||||
proxy_token = null,
|
||||
db_secret = kubernetes_secret.coder_db.metadata.0.name,
|
||||
ip_address = google_compute_address.coder["primary"].address,
|
||||
provisionerd_psk = kubernetes_secret.provisionerd_psk_primary.metadata.0.name,
|
||||
access_url = local.deployments.primary.url,
|
||||
node_pool = google_container_node_pool.node_pool["primary_coder"].name,
|
||||
release_name = local.coder_release_name,
|
||||
experiments = var.coder_experiments,
|
||||
image_repo = var.coder_image_repo,
|
||||
image_tag = var.coder_image_tag,
|
||||
replicas = local.scenarios[var.scenario].coder.replicas,
|
||||
cpu_request = local.scenarios[var.scenario].coder.cpu_request,
|
||||
mem_request = local.scenarios[var.scenario].coder.mem_request,
|
||||
cpu_limit = local.scenarios[var.scenario].coder.cpu_limit,
|
||||
mem_limit = local.scenarios[var.scenario].coder.mem_limit,
|
||||
})]
|
||||
}
|
||||
|
||||
resource "helm_release" "provisionerd_chart" {
|
||||
provider = helm.primary
|
||||
|
||||
repository = local.coder_helm_repo
|
||||
chart = local.provisionerd_helm_chart
|
||||
name = local.provisionerd_release_name
|
||||
version = var.provisionerd_chart_version
|
||||
namespace = kubernetes_namespace.coder_primary.metadata.0.name
|
||||
values = [templatefile("${path.module}/coder_helm_values.tftpl", {
|
||||
workspace_proxy = false,
|
||||
provisionerd = true,
|
||||
primary_url = null,
|
||||
proxy_token = null,
|
||||
db_secret = null,
|
||||
ip_address = null,
|
||||
provisionerd_psk = kubernetes_secret.provisionerd_psk_primary.metadata.0.name,
|
||||
access_url = local.deployments.primary.url,
|
||||
node_pool = google_container_node_pool.node_pool["primary_coder"].name,
|
||||
release_name = local.coder_release_name,
|
||||
experiments = var.coder_experiments,
|
||||
image_repo = var.coder_image_repo,
|
||||
image_tag = var.coder_image_tag,
|
||||
replicas = local.scenarios[var.scenario].provisionerd.replicas,
|
||||
cpu_request = local.scenarios[var.scenario].provisionerd.cpu_request,
|
||||
mem_request = local.scenarios[var.scenario].provisionerd.mem_request,
|
||||
cpu_limit = local.scenarios[var.scenario].provisionerd.cpu_limit,
|
||||
mem_limit = local.scenarios[var.scenario].provisionerd.mem_limit,
|
||||
})]
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
google = {
|
||||
source = "hashicorp/google"
|
||||
version = "~> 4.36"
|
||||
}
|
||||
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "~> 3.5"
|
||||
}
|
||||
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "~> 2.20"
|
||||
}
|
||||
|
||||
// We use the kubectl provider to apply Custom Resources.
|
||||
// The kubernetes provider requires the CRD is already present
|
||||
// and would require a separate apply step beforehand.
|
||||
// https://github.com/hashicorp/terraform-provider-kubernetes/issues/1367
|
||||
kubectl = {
|
||||
source = "alekc/kubectl"
|
||||
version = ">= 2.0.0"
|
||||
}
|
||||
|
||||
helm = {
|
||||
source = "hashicorp/helm"
|
||||
version = "~> 2.9"
|
||||
}
|
||||
|
||||
tls = {
|
||||
source = "hashicorp/tls"
|
||||
version = "~> 4.0"
|
||||
}
|
||||
|
||||
cloudflare = {
|
||||
source = "cloudflare/cloudflare"
|
||||
version = "~> 4.0"
|
||||
}
|
||||
}
|
||||
|
||||
required_version = "~> 1.9.0"
|
||||
}
|
||||
|
||||
provider "google" {
|
||||
}
|
||||
|
||||
provider "cloudflare" {
|
||||
api_token = var.cloudflare_api_token
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
alias = "primary"
|
||||
host = "https://${google_container_cluster.cluster["primary"].endpoint}"
|
||||
cluster_ca_certificate = base64decode(google_container_cluster.cluster["primary"].master_auth.0.cluster_ca_certificate)
|
||||
token = data.google_client_config.default.access_token
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
alias = "europe"
|
||||
host = "https://${google_container_cluster.cluster["europe"].endpoint}"
|
||||
cluster_ca_certificate = base64decode(google_container_cluster.cluster["europe"].master_auth.0.cluster_ca_certificate)
|
||||
token = data.google_client_config.default.access_token
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
alias = "asia"
|
||||
host = "https://${google_container_cluster.cluster["asia"].endpoint}"
|
||||
cluster_ca_certificate = base64decode(google_container_cluster.cluster["asia"].master_auth.0.cluster_ca_certificate)
|
||||
token = data.google_client_config.default.access_token
|
||||
}
|
||||
|
||||
provider "kubectl" {
|
||||
alias = "primary"
|
||||
host = "https://${google_container_cluster.cluster["primary"].endpoint}"
|
||||
cluster_ca_certificate = base64decode(google_container_cluster.cluster["primary"].master_auth.0.cluster_ca_certificate)
|
||||
token = data.google_client_config.default.access_token
|
||||
load_config_file = false
|
||||
}
|
||||
|
||||
provider "kubectl" {
|
||||
alias = "europe"
|
||||
host = "https://${google_container_cluster.cluster["europe"].endpoint}"
|
||||
cluster_ca_certificate = base64decode(google_container_cluster.cluster["europe"].master_auth.0.cluster_ca_certificate)
|
||||
token = data.google_client_config.default.access_token
|
||||
load_config_file = false
|
||||
}
|
||||
|
||||
provider "kubectl" {
|
||||
alias = "asia"
|
||||
host = "https://${google_container_cluster.cluster["asia"].endpoint}"
|
||||
cluster_ca_certificate = base64decode(google_container_cluster.cluster["asia"].master_auth.0.cluster_ca_certificate)
|
||||
token = data.google_client_config.default.access_token
|
||||
load_config_file = false
|
||||
}
|
||||
|
||||
provider "helm" {
|
||||
alias = "primary"
|
||||
kubernetes {
|
||||
host = "https://${google_container_cluster.cluster["primary"].endpoint}"
|
||||
cluster_ca_certificate = base64decode(google_container_cluster.cluster["primary"].master_auth.0.cluster_ca_certificate)
|
||||
token = data.google_client_config.default.access_token
|
||||
}
|
||||
}
|
||||
|
||||
provider "helm" {
|
||||
alias = "europe"
|
||||
kubernetes {
|
||||
host = "https://${google_container_cluster.cluster["europe"].endpoint}"
|
||||
cluster_ca_certificate = base64decode(google_container_cluster.cluster["europe"].master_auth.0.cluster_ca_certificate)
|
||||
token = data.google_client_config.default.access_token
|
||||
}
|
||||
}
|
||||
|
||||
provider "helm" {
|
||||
alias = "asia"
|
||||
kubernetes {
|
||||
host = "https://${google_container_cluster.cluster["asia"].endpoint}"
|
||||
cluster_ca_certificate = base64decode(google_container_cluster.cluster["asia"].master_auth.0.cluster_ca_certificate)
|
||||
token = data.google_client_config.default.access_token
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
locals {
|
||||
scenarios = {
|
||||
small = {
|
||||
coder = {
|
||||
nodepool_size = 1
|
||||
machine_type = "t2d-standard-4"
|
||||
replicas = 1
|
||||
cpu_request = "1000m"
|
||||
mem_request = "6Gi"
|
||||
cpu_limit = "2000m"
|
||||
mem_limit = "12Gi"
|
||||
}
|
||||
provisionerd = {
|
||||
replicas = 1
|
||||
cpu_request = "100m"
|
||||
mem_request = "1Gi"
|
||||
cpu_limit = "1000m"
|
||||
mem_limit = "1Gi"
|
||||
}
|
||||
workspaces = {
|
||||
nodepool_size = 1
|
||||
machine_type = "t2d-standard-4"
|
||||
cpu_request = "100m"
|
||||
mem_request = "128Mi"
|
||||
cpu_limit = "100m"
|
||||
mem_limit = "128Mi"
|
||||
}
|
||||
misc = {
|
||||
nodepool_size = 1
|
||||
machine_type = "t2d-standard-4"
|
||||
}
|
||||
cloudsql = {
|
||||
tier = "db-f1-micro"
|
||||
max_connections = 500
|
||||
}
|
||||
}
|
||||
medium = {
|
||||
coder = {
|
||||
nodepool_size = 1
|
||||
machine_type = "t2d-standard-8"
|
||||
replicas = 1
|
||||
cpu_request = "3000m"
|
||||
mem_request = "12Gi"
|
||||
cpu_limit = "6000m"
|
||||
mem_limit = "24Gi"
|
||||
}
|
||||
provisionerd = {
|
||||
replicas = 1
|
||||
cpu_request = "100m"
|
||||
mem_request = "1Gi"
|
||||
cpu_limit = "1000m"
|
||||
mem_limit = "1Gi"
|
||||
}
|
||||
workspaces = {
|
||||
nodepool_size = 1
|
||||
machine_type = "t2d-standard-8"
|
||||
cpu_request = "100m"
|
||||
mem_request = "128Mi"
|
||||
cpu_limit = "100m"
|
||||
mem_limit = "128Mi"
|
||||
}
|
||||
misc = {
|
||||
nodepool_size = 1
|
||||
machine_type = "t2d-standard-4"
|
||||
}
|
||||
cloudsql = {
|
||||
tier = "db-custom-1-3840"
|
||||
max_connections = 500
|
||||
}
|
||||
}
|
||||
large = {
|
||||
coder = {
|
||||
nodepool_size = 3
|
||||
machine_type = "t2d-standard-8"
|
||||
replicas = 3
|
||||
cpu_request = "1000m"
|
||||
mem_request = "6Gi"
|
||||
cpu_limit = "2000m"
|
||||
mem_limit = "12Gi"
|
||||
}
|
||||
provisionerd = {
|
||||
replicas = 1
|
||||
cpu_request = "100m"
|
||||
mem_request = "1Gi"
|
||||
cpu_limit = "1000m"
|
||||
mem_limit = "1Gi"
|
||||
}
|
||||
workspaces = {
|
||||
nodepool_size = 1
|
||||
machine_type = "t2d-standard-8"
|
||||
cpu_request = "100m"
|
||||
mem_request = "128Mi"
|
||||
cpu_limit = "100m"
|
||||
mem_limit = "128Mi"
|
||||
}
|
||||
misc = {
|
||||
nodepool_size = 1
|
||||
machine_type = "t2d-standard-4"
|
||||
}
|
||||
cloudsql = {
|
||||
tier = "db-custom-2-7680"
|
||||
max_connections = 500
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
variable "name" {
|
||||
description = "The name all resources will be prefixed with"
|
||||
}
|
||||
|
||||
variable "scenario" {
|
||||
description = "The scenario to deploy"
|
||||
validation {
|
||||
condition = contains(["small", "medium", "large"], var.scenario)
|
||||
error_message = "Scenario must be one of small, medium, or large"
|
||||
}
|
||||
}
|
||||
|
||||
// GCP
|
||||
variable "project_id" {
|
||||
description = "The project in which to provision resources"
|
||||
}
|
||||
|
||||
variable "k8s_version" {
|
||||
description = "Kubernetes version to provision."
|
||||
default = "1.24"
|
||||
}
|
||||
|
||||
// Cloudflare
|
||||
variable "cloudflare_api_token" {
|
||||
description = "Cloudflare API token."
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "cloudflare_email" {
|
||||
description = "Cloudflare email address."
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "cloudflare_domain" {
|
||||
description = "Cloudflare coder domain."
|
||||
}
|
||||
|
||||
variable "cloudflare_zone_id" {
|
||||
description = "Cloudflare zone ID."
|
||||
}
|
||||
|
||||
// Coder
|
||||
variable "coder_license" {
|
||||
description = "Coder license key."
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "coder_chart_version" {
|
||||
description = "Version of the Coder Helm chart to install. Defaults to latest."
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "coder_image_tag" {
|
||||
description = "Tag to use for Coder image."
|
||||
default = "latest"
|
||||
}
|
||||
|
||||
variable "coder_image_repo" {
|
||||
description = "Repository to use for Coder image."
|
||||
default = "ghcr.io/coder/coder"
|
||||
}
|
||||
|
||||
variable "coder_experiments" {
|
||||
description = "Coder Experiments to enable."
|
||||
default = ""
|
||||
}
|
||||
|
||||
// Workspaces
|
||||
variable "workspace_image" {
|
||||
description = "Image and tag to use for workspaces."
|
||||
default = "docker.io/codercom/enterprise-minimal:ubuntu"
|
||||
}
|
||||
|
||||
variable "provisionerd_chart_version" {
|
||||
description = "Version of the Provisionerd Helm chart to install. Defaults to latest."
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "provisionerd_image_repo" {
|
||||
description = "Repository to use for Provisionerd image."
|
||||
default = "ghcr.io/coder/coder"
|
||||
}
|
||||
|
||||
variable "provisionerd_image_tag" {
|
||||
description = "Tag to use for Provisionerd image."
|
||||
default = "latest"
|
||||
}
|
||||
Reference in New Issue
Block a user