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 8bb8568
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 137 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
108 changes: 52 additions & 56 deletions aws/postgresql/postgresql.tf
Original file line number Diff line number Diff line change
Expand Up @@ -134,68 +134,64 @@ resource "random_password" "database" {
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: postgres:latest
command:
- psql
- "--echo-errors"
- "-c"
- "CREATE DATABASE ${var.app};"
- "-c"
- |
CREATE USER ${var.app} WITH PASSWORD '${random_password.database.result}';
GRANT ALL PRIVILEGES ON DATABASE ${var.app} TO ${var.app};
env:
- name: PGHOST
value: "${module.rds.db_instance_address}"
- name: PGPORT
value: "${module.rds.db_instance_port}"
- name: PGUSER
value: "${module.rds.db_instance_username}"
- name: PGPASSWORD
value: "${module.rds.db_master_password}"
- name: PGDATABASE
value: "${module.rds.db_instance_name}"
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 = "postgres:latest"
command = [
"psql",
"--echo-errors",
"-c",
"CREATE DATABASE ${var.app};",
"-c",
<<EOC
CREATE USER ${var.app} WITH PASSWORD '${sensitive(random_password.database.result)}';
GRANT ALL PRIVILEGES ON DATABASE ${var.app} TO ${var.app};
EOC
]
env {
name = "PGHOST"
value = module.rds.db_instance_address
}
env {
name = "PGPORT"
value = module.rds.db_instance_port
}
env {
name = "PGUSER"
value = module.rds.db_instance_username
}
env {
name = "PGPASSWORD"
value = module.rds.db_master_password
}
env {
name = "PGDATABASE"
value = module.rds.db_instance_name
}
}
restart_policy = "Never"
}
}
backoff_limit = 0
ttl_seconds_after_finished = 60
}
wait_for_completion = true
timeouts {
create = "5m"
}
}

Expand Down

0 comments on commit 8bb8568

Please sign in to comment.