From d2bed4ea8da90b60189712c4beede140841a9b81 Mon Sep 17 00:00:00 2001 From: RaviAnand Mohabir Date: Tue, 24 Jan 2023 15:17:53 +0100 Subject: [PATCH] feat: :sparkles: implement Drone runner Terraform module --- .gitignore | 34 +++++++++++++ main.tf | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++ variables.tf | 58 ++++++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 .gitignore create mode 100644 main.tf create mode 100644 variables.tf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b8a46e --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..9a98067 --- /dev/null +++ b/main.tf @@ -0,0 +1,138 @@ +terraform { + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.13.1" + } + } +} + +locals { + match_labels = merge({ + "app.kubernetes.io/instance" = "drone" + "app.kubernetes.io/name" = "drone-runner" + }, var.match_labels) + labels = merge(local.match_labels, { + "app.kubernetes.io/version" = var.image_tag + }, var.labels) +} + +resource "kubernetes_role" "drone" { + metadata { + name = "drone-runner" + namespace = var.namespace + } + rule { + api_groups = [""] + resources = ["secrets"] + verbs = ["create", "delete"] + } + rule { + api_groups = [""] + resources = ["pods", "pods/log"] + verbs = ["get", "create", "delete", "list", "watch", "update"] + } +} + +resource "kubernetes_service_account" "drone_runner" { + metadata { + name = "drone-runner" + namespace = var.namespace + labels = local.labels + } +} + +resource "kubernetes_role_binding" "drone" { + metadata { + name = "drone-runner" + namespace = var.namespace + } + subject { + kind = "ServiceAccount" + name = kubernetes_service_account.drone_runner.metadata.0.name + namespace = var.namespace + } + role_ref { + kind = "Role" + name = kubernetes_role.drone.metadata.0.name + api_group = "rbac.authorization.k8s.io" + } +} + +resource "kubernetes_deployment" "drone_runner" { + metadata { + name = "drone-runner" + namespace = var.namespace + labels = local.labels + } + spec { + replicas = var.drone_runner_replicas + selector { + match_labels = local.match_labels + } + template { + metadata { + labels = local.labels + annotations = { + "ravianand.me/config-hash" = sha1(jsonencode(merge( + kubernetes_secret.drone_runner.data + ))) + } + } + spec { + service_account_name = kubernetes_service_account.drone_runner.metadata.0.name + container { + image = var.image_registry == "" ? "${var.image_repository}:${var.image_tag}" : "${var.image_registry}/${var.image_repository}:${var.image_tag}" + name = "drone-runner" + security_context {} + env { + name = "DRONE_RPC_HOST" + value = var.drone_rpc_host + } + env { + name = "DRONE_RPC_PROTO" + value = var.drone_rpc_proto + } + env { + name = "DRONE_NAMESPACE_DEFAULT" + value = var.namespace + } + env { + name = "DRONE_RPC_SECRET" + value_from { + secret_key_ref { + name = kubernetes_secret.drone_runner.metadata.0.name + key = "drone-runner-secret" + } + } + } + port { + container_port = 3000 + name = "http" + protocol = "TCP" + } + resources { + requests = { + cpu = "250m" + memory = "250Mi" + } + limits = { + cpu = 2 + memory = "2Gi" + } + } + } + } + } + } +} + +resource "kubernetes_secret" "drone_runner" { + metadata { + name = "drone-runner" + namespace = var.namespace + } + data = { + "drone-runner-secret" = var.drone_runner_secret + } +} diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..bd79231 --- /dev/null +++ b/variables.tf @@ -0,0 +1,58 @@ +variable "namespace" { + description = "Namespace to deploy workloads and configuration" + type = string + default = "default" +} + +variable "match_labels" { + description = "Match labels to add to the MariaDB deployment, will be merged with labels" + type = map(any) + default = {} +} + +variable "labels" { + description = "Labels to add to the Drone runner deployment" + type = map(any) + default = {} +} + +variable "image_registry" { + description = "Image registry, e.g. gcr.io, docker.io" + type = string + default = "" +} + +variable "image_repository" { + description = "Image to start for the runner" + type = string + default = "drone/drone-runner-kube" +} + +variable "image_tag" { + description = "Image tag to for the runner" + type = string + default = "latest" +} + +variable "drone_runner_replicas" { + description = "Number of runner replicas to deploy" + type = number + default = 1 +} + +variable "drone_rpc_host" { + description = "Drone hostname" + type = string +} + +variable "drone_rpc_proto" { + description = "Drone protocol" + type = string + default = "https" +} + +variable "drone_runner_secret" { + description = "Drone runner secret" + type = string + sensitive = true +}