From 79142570238e4161b9d2538c627e39681df3e093 Mon Sep 17 00:00:00 2001 From: Troy Benson Date: Tue, 2 May 2023 15:19:27 +0000 Subject: [PATCH] feat: add terraform --- k8s/production.template.yaml | 117 -------------------------- k8s/staging.template.yaml | 115 ------------------------- terraform/.gitignore | 2 + terraform/discord/.gitignore | 1 + terraform/discord/config.yaml | 33 ++++++++ terraform/discord/main.tf | 148 +++++++++++++++++++++++++++++++++ terraform/discord/outputs.tf | 3 + terraform/discord/providers.tf | 12 +++ terraform/discord/variables.tf | 30 +++++++ terraform/main.tf | 20 +++++ terraform/outputs.tf | 4 + terraform/providers.tf | 30 +++++++ terraform/variables.tf | 32 +++++++ 13 files changed, 315 insertions(+), 232 deletions(-) delete mode 100644 k8s/production.template.yaml delete mode 100644 k8s/staging.template.yaml create mode 100644 terraform/.gitignore create mode 100644 terraform/discord/.gitignore create mode 100644 terraform/discord/config.yaml create mode 100644 terraform/discord/main.tf create mode 100644 terraform/discord/outputs.tf create mode 100644 terraform/discord/providers.tf create mode 100644 terraform/discord/variables.tf create mode 100644 terraform/main.tf create mode 100644 terraform/outputs.tf create mode 100644 terraform/providers.tf create mode 100644 terraform/variables.tf diff --git a/k8s/production.template.yaml b/k8s/production.template.yaml deleted file mode 100644 index 56a01d0..0000000 --- a/k8s/production.template.yaml +++ /dev/null @@ -1,117 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: compactdisc - namespace: app -spec: - selector: - matchLabels: - app: compactdisc - template: - metadata: - labels: - app: compactdisc - spec: - volumes: - - name: config - configMap: - name: compactdisc-config - defaultMode: 420 - containers: - - name: compactdisc - image: ${IMAGE} - ports: - - name: api - containerPort: 3000 - protocol: TCP - - name: health - containerPort: 9200 - protocol: TCP - envFrom: - - secretRef: - name: compactdisc-secret - env: - - name: API_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: API_K8S_NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - resources: - limits: - cpu: 200m - memory: 384Mi - requests: - cpu: 150m - memory: 384Mi - volumeMounts: - - name: config - mountPath: /app/config.yaml - subPath: config.yaml - livenessProbe: - tcpSocket: - port: health - initialDelaySeconds: 30 - timeoutSeconds: 5 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 6 - readinessProbe: - tcpSocket: - port: health - initialDelaySeconds: 5 - timeoutSeconds: 5 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 6 - imagePullPolicy: Always ---- -apiVersion: v1 -kind: Service -metadata: - name: compactdisc - namespace: app - labels: - app: compactdisc -spec: - ports: - - name: api - protocol: TCP - port: 3000 - targetPort: api - - name: health - protocol: TCP - port: 9200 - targetPort: health - selector: - app: compactdisc ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: compactdisc-config - namespace: app -data: - config.yaml: | - # Log level - level: info - - cdn_url: cdn.7tv.app - website_url: https://7tv.app - - http: - addr: "0.0.0.0" - port: 3000 - - discord: - channels: - activity_feed: "817375925271527449" - mod_logs: "989251544165777450" - mod_actor_tracker: "1080982942156869743" - events: "1015281319758004335" - - health: - enabled: true - bind: 0.0.0.0:9200 diff --git a/k8s/staging.template.yaml b/k8s/staging.template.yaml deleted file mode 100644 index 5219705..0000000 --- a/k8s/staging.template.yaml +++ /dev/null @@ -1,115 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: compactdisc - namespace: app -spec: - selector: - matchLabels: - app: compactdisc - template: - metadata: - labels: - app: compactdisc - spec: - volumes: - - name: config - configMap: - name: compactdisc-config - defaultMode: 420 - containers: - - name: compactdisc - image: ${IMAGE} - ports: - - name: api - containerPort: 3000 - protocol: TCP - - name: health - containerPort: 9200 - protocol: TCP - envFrom: - - secretRef: - name: compactdisc-secret - env: - - name: API_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: API_K8S_NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - resources: - limits: - cpu: 200m - memory: 384Mi - requests: - cpu: 150m - memory: 384Mi - volumeMounts: - - name: config - mountPath: /app/config.yaml - subPath: config.yaml - livenessProbe: - tcpSocket: - port: health - initialDelaySeconds: 30 - timeoutSeconds: 5 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 6 - readinessProbe: - tcpSocket: - port: health - initialDelaySeconds: 5 - timeoutSeconds: 5 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 6 - imagePullPolicy: Always ---- -apiVersion: v1 -kind: Service -metadata: - name: compactdisc - namespace: app - labels: - app: compactdisc -spec: - ports: - - name: api - protocol: TCP - port: 3000 - targetPort: api - - name: health - protocol: TCP - port: 9200 - targetPort: health - selector: - app: compactdisc ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: compactdisc-config - namespace: app -data: - config.yaml: | - # Log level - level: info - - cdn_url: cdn.7tv.dev - website_url: https://7tv.dev - - http: - addr: "0.0.0.0" - port: 3000 - - discord: - channels: - activity_feed: "817375925271527449" - mod_logs: "989251544165777450" - - health: - enabled: true - bind: 0.0.0.0:9200 diff --git a/terraform/.gitignore b/terraform/.gitignore new file mode 100644 index 0000000..8bdfa91 --- /dev/null +++ b/terraform/.gitignore @@ -0,0 +1,2 @@ +.terraform.lock.hcl +.terraform diff --git a/terraform/discord/.gitignore b/terraform/discord/.gitignore new file mode 100644 index 0000000..9dac6e5 --- /dev/null +++ b/terraform/discord/.gitignore @@ -0,0 +1 @@ +!config.yaml diff --git a/terraform/discord/config.yaml b/terraform/discord/config.yaml new file mode 100644 index 0000000..8798d43 --- /dev/null +++ b/terraform/discord/config.yaml @@ -0,0 +1,33 @@ +level: info + +cdn_url: ${cdn_url} +website_url: ${website_url} + +http: + addr: "0.0.0.0" + port: 3000 + +discord: + guild_id: ${discord_guild_id} + token: ${discord_token} + channels: + activity_feed: "817375925271527449" + mod_logs: "989251544165777450" + mod_actor_tracker: "1080982942156869743" + events: "1015281319758004335" + +mongo: + db: ${mongo_db} + mongo_uri: ${mongo_uri} + +redis: + addresses: + - ${redis_address} + database: 1 + master_name: mymaster + password: ${redis_password} + sentinel: true + +health: + enabled: true + bind: 0.0.0.0:9200 diff --git a/terraform/discord/main.tf b/terraform/discord/main.tf new file mode 100644 index 0000000..9a4e7b4 --- /dev/null +++ b/terraform/discord/main.tf @@ -0,0 +1,148 @@ +resource "kubernetes_namespace" "discord" { + metadata { + name = var.namespace + } +} + +resource "kubernetes_secret" "discord" { + metadata { + name = "discord" + namespace = kubernetes_namespace.discord.metadata[0].name + } + data = { + "config.yaml" = templatefile("${path.module}/config.yaml", { + website_url = var.website_url + cdn_url = var.cdn_url + discord_guild_id = var.discord_guild_id + discord_token = var.discord_token + mongo_db = "seventv" + mongo_uri = "mongodb://root:${var.infra.mongo_password}@${var.infra.mongo_host}/?authSource=admin&readPreference=secondaryPreferred" + redis_address = var.infra.redis_host + redis_password = var.infra.redis_password + }) + } +} + +resource "kubernetes_deployment" "discord" { + metadata { + name = "discord" + labels = { + app = "discord" + } + namespace = kubernetes_namespace.discord.metadata[0].name + } + + timeouts { + create = "2m" + update = "2m" + delete = "2m" + } + + spec { + selector { + match_labels = { + app = "discord" + } + } + template { + metadata { + labels = { + app = "discord" + } + } + spec { + container { + name = "discord" + image = var.docker_image + image_pull_policy = "Always" + port { + container_port = 3000 + name = "api" + } + port { + container_port = 9200 + name = "health" + } + readiness_probe { + initial_delay_seconds = 5 + period_seconds = 5 + tcp_socket { + port = "health" + } + } + liveness_probe { + initial_delay_seconds = 5 + period_seconds = 5 + tcp_socket { + port = "health" + } + } + startup_probe { + initial_delay_seconds = 5 + period_seconds = 5 + tcp_socket { + port = "health" + } + } + security_context { + allow_privilege_escalation = false + privileged = false + read_only_root_filesystem = true + run_as_non_root = true + run_as_user = 1000 + run_as_group = 1000 + capabilities { + drop = ["ALL"] + } + } + resources { + limits = { + "cpu" = "250m" + "memory" = "250Mi" + } + requests = { + "cpu" = "250m" + "memory" = "250Mi" + } + } + volume_mount { + name = "config" + mount_path = "/app/config.yaml" + sub_path = "config.yaml" + read_only = true + } + } + volume { + name = "config" + secret { + secret_name = kubernetes_secret.discord.metadata[0].name + default_mode = "0644" + } + } + } + } + } +} + +resource "kubernetes_service" "discord" { + metadata { + name = "discord" + namespace = kubernetes_namespace.discord.metadata[0].name + } + + spec { + selector = { + app = "discord" + } + port { + name = "api" + port = 3000 + target_port = "api" + } + port { + name = "health" + port = 9200 + target_port = "health" + } + } +} diff --git a/terraform/discord/outputs.tf b/terraform/discord/outputs.tf new file mode 100644 index 0000000..e49b0ab --- /dev/null +++ b/terraform/discord/outputs.tf @@ -0,0 +1,3 @@ +output "hostname" { + value = "${kubernetes_service.discord.metadata[0].name}.${var.namespace}.svc.cluster.local" +} diff --git a/terraform/discord/providers.tf b/terraform/discord/providers.tf new file mode 100644 index 0000000..c3d7f1c --- /dev/null +++ b/terraform/discord/providers.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.18.1" + } + random = { + source = "hashicorp/random" + version = "3.4.3" + } + } +} diff --git a/terraform/discord/variables.tf b/terraform/discord/variables.tf new file mode 100644 index 0000000..eba8478 --- /dev/null +++ b/terraform/discord/variables.tf @@ -0,0 +1,30 @@ +variable "docker_image" { + type = string +} + +variable "namespace" { + type = string + default = "compactdisc" +} + +variable "infra" { + type = any + sensitive = true +} + +variable "website_url" { + type = string +} + +variable "cdn_url" { + type = string +} + +variable "discord_guild_id" { + type = string +} + +variable "discord_token" { + type = string + sensitive = true +} diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..8fd5463 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,20 @@ +terraform { + backend "remote" { + hostname = "app.terraform.io" + organization = "7tv" + + workspaces { + prefix = "7tv-discord-" + } + } +} + +module "discord" { + source = "./discord" + cdn_url = var.cdn_url + docker_image = var.discord_docker_image + discord_guild_id = var.discord_guild_id + discord_token = var.discord_token + website_url = var.website_url + infra = data.terraform_remote_state.infra.outputs +} diff --git a/terraform/outputs.tf b/terraform/outputs.tf new file mode 100644 index 0000000..d2c01b7 --- /dev/null +++ b/terraform/outputs.tf @@ -0,0 +1,4 @@ +output "hostname" { + value = module.discord.hostname + description = "The hostname of the discord service" +} diff --git a/terraform/providers.tf b/terraform/providers.tf new file mode 100644 index 0000000..4120886 --- /dev/null +++ b/terraform/providers.tf @@ -0,0 +1,30 @@ +terraform { + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.18.1" + } + helm = { + source = "hashicorp/helm" + version = "2.9.0" + } + } +} + +locals { + kubeconfig = yamldecode(base64decode(data.terraform_remote_state.infra.outputs.kubeconfig)) +} + +provider "kubernetes" { + host = local.kubeconfig.clusters[0].cluster.server + cluster_ca_certificate = base64decode(local.kubeconfig.clusters[0].cluster.certificate-authority-data) + token = local.kubeconfig.users[0].user.token +} + +provider "helm" { + kubernetes { + host = local.kubeconfig.clusters[0].cluster.server + cluster_ca_certificate = base64decode(local.kubeconfig.clusters[0].cluster.certificate-authority-data) + token = local.kubeconfig.users[0].user.token + } +} diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..e9d4141 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,32 @@ +variable "discord_docker_image" { + type = string + default = "ghcr.io/seventv/compactdisc:latest" +} + +data "terraform_remote_state" "infra" { + backend = "remote" + + config = { + organization = "7tv" + workspaces = { + name = "7tv-infra-${trimprefix(terraform.workspace, "7tv-discord-")}" + } + } +} + +variable "website_url" { + type = string +} + +variable "cdn_url" { + type = string +} + +variable "discord_guild_id" { + type = string +} + +variable "discord_token" { + type = string + sensitive = true +}