Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use kubernetes_job_v1 to create DB in AWS RDS #20

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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