Skip to content

Commit

Permalink
Use kubernetes_job_v1 to create DB in AWS RDS
Browse files Browse the repository at this point in the history
  • Loading branch information
paydaylight committed Nov 27, 2024
1 parent fa72d55 commit a749761
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 171 deletions.
149 changes: 68 additions & 81 deletions aws/mysql/mysql.tf
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
source = "hashicorp/aws"
version = "~> 3.0"
}
random = {
source = "hashicorp/random"
source = "hashicorp/random"
version = "~> 3.1"
}
null = {
source = "hashicorp/null"
source = "hashicorp/null"
version = "~> 3.1"
}
}
Expand Down Expand Up @@ -48,8 +48,8 @@ variable "allow_security_group_ids" {
resource "aws_subnet" "database" {
for_each = var.database_subnets

vpc_id = var.vpc_id
cidr_block = each.key
vpc_id = var.vpc_id
cidr_block = each.key
availability_zone = each.value

tags = {
Expand All @@ -58,9 +58,9 @@ resource "aws_subnet" "database" {
}

resource "aws_security_group" "database" {
name = "${var.app}-${var.environment}-rds-mysql"
name = "${var.app}-${var.environment}-rds-mysql"
description = "MySQL security group"
vpc_id = var.vpc_id
vpc_id = var.vpc_id

lifecycle {
create_before_destroy = true
Expand All @@ -73,23 +73,23 @@ module "rds" {

identifier = "${var.app}-${var.environment}"

engine = "mysql"
family = "mysql8.0"
engine_version = "8.0.23"
engine = "mysql"
family = "mysql8.0"
engine_version = "8.0.23"
major_engine_version = "8.0"
instance_class = "db.t2.micro"
allocated_storage = 10
instance_class = "db.t2.micro"
allocated_storage = 10

backup_window = "03:00-06:00"
backup_window = "03:00-06:00"
backup_retention_period = 15
maintenance_window = "Mon:00:00-Mon:03:00"
maintenance_window = "Mon:00:00-Mon:03:00"

name = "main"
username = "root"
name = "main"
username = "root"
create_random_password = true
port = 3306
port = 3306

subnet_ids = [for subnet in aws_subnet.database: subnet.id]
subnet_ids = [for subnet in aws_subnet.database : subnet.id]

vpc_security_group_ids = [aws_security_group.database.id]

Expand All @@ -108,100 +108,87 @@ module "rds" {
resource "aws_security_group_rule" "db_ingress" {
for_each = toset(var.allow_security_group_ids)

security_group_id = aws_security_group.database.id
description = "Ingress to mysql"
type = "ingress"
protocol = "tcp"
from_port = module.rds.db_instance_port
to_port = module.rds.db_instance_port
security_group_id = aws_security_group.database.id
description = "Ingress to mysql"
type = "ingress"
protocol = "tcp"
from_port = module.rds.db_instance_port
to_port = module.rds.db_instance_port
source_security_group_id = each.value
}

resource "aws_security_group_rule" "egress_to_db" {
for_each = toset(var.allow_security_group_ids)

security_group_id = each.value
description = "Egress to mysql"
type = "egress"
protocol = "tcp"
from_port = module.rds.db_instance_port
to_port = module.rds.db_instance_port
security_group_id = each.value
description = "Egress to mysql"
type = "egress"
protocol = "tcp"
from_port = module.rds.db_instance_port
to_port = module.rds.db_instance_port
source_security_group_id = aws_security_group.database.id
}

resource "random_password" "database" {
length = 20
length = 20
special = true
}

# TODO: use kubernetes_job resource with ttl_seconds_after_finished argument when
# upgraded to Kubernetes 1.21.
# Since 1.21 TTL Controller is enabled by default.
#
# If the job pod fails with error, see logs for failed pod:
# kubectl -n <namespace> get pods
# and destroy the job for proper recreation later:
# kubectl -n <namespace> delete jobs/database-creator
resource "null_resource" "database" {
resource "kubernetes_job_v1" "database_creator" {
depends_on = [
module.rds,
random_password.database
]

triggers = {
rds_instance_id = module.rds.db_instance_resource_id
metadata {
generate_name = "${var.app}-database-creator"
}

provisioner "local-exec" {
command = <<-EOC
set -e
aws eks --region ${var.region} update-kubeconfig --name ${var.eks.cluster_name}
cat << JOB | kubectl -n default apply -f -
apiVersion: batch/v1
kind: Job
metadata:
name: database-creator
spec:
template:
spec:
containers:
- name: database-creator
image: mysql:8.0.23
command:
- "mysql"
- "--user=${module.rds.db_instance_username}"
- "--password=${module.rds.db_master_password}"
- "--host=${module.rds.db_instance_address}"
- "--port=${module.rds.db_instance_port}"
- "--database=${module.rds.db_instance_name}"
- "-e"
- |
CREATE DATABASE ${var.app};
CREATE USER ${var.app} IDENTIFIED BY '${random_password.database.result}';
GRANT ALL PRIVILEGES ON ${var.app}.* TO ${var.app};
restartPolicy: Never
backoffLimit: 0
JOB
kubectl -n default wait --for=condition=complete jobs/database-creator
kubectl -n default delete jobs/database-creator
EOC
spec {
template {
metadata {}
spec {
container {
name = "database-creator"
image = "mysql:8.0.23"
command = [
"mysql",
"--user=${module.rds.db_instance_username}",
"--password=${module.rds.db_master_password}",
"--host=${module.rds.db_instance_address}",
"--port=${module.rds.db_instance_port}",
"--database=${module.rds.db_instance_name}",
"-e",
<<EOC
CREATE DATABASE ${var.app};
CREATE USER ${var.app} IDENTIFIED BY '${sensitive(random_password.database.result)}';
GRANT ALL PRIVILEGES ON ${var.app}.* TO ${var.app};
EOC
]
}
restart_policy = "Never"
}
}
backoff_limit = 0
ttl_seconds_after_finished = 60
}
wait_for_completion = true
timeouts {
create = "5m"
}
}

output "database" {
value = {
host = module.rds.db_instance_address
port = module.rds.db_instance_port
host = module.rds.db_instance_address
port = module.rds.db_instance_port
username = var.app
database = var.app
}
}

output "database_password" {
value = random_password.database.result
value = random_password.database.result
sensitive = true
}

Expand Down
Loading

0 comments on commit a749761

Please sign in to comment.