Skip to content
Merged
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
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ No modules.
| Name | Type |
|------|------|
| [helm_release.postgres_exporter](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
| [helm_release.postgresql_backup](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
| [helm_release.postgresql_ha](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
| [helm_release.postgresql_restore](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
| [kubernetes_namespace.postgresql](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |

## Inputs
Expand All @@ -109,13 +111,20 @@ No modules.
|------|-------------|------|---------|:--------:|
| <a name="input_chart_version"></a> [chart\_version](#input\_chart\_version) | Version of the Postgresql helm chart that will be deployed. | `string` | `"11.7.9"` | no |
| <a name="input_cluster_name"></a> [cluster\_name](#input\_cluster\_name) | Name of eks cluster | `string` | `""` | no |
| <a name="input_create_namespace"></a> [create\_namespace](#input\_create\_namespace) | Whether or not to deploy postgresql | `bool` | `true` | no |
| <a name="input_custom_credentials_config"></a> [custom\_credentials\_config](#input\_custom\_credentials\_config) | Specify the configuration settings for Postgresql to pass custom credentials during creation. | `any` | <pre>{<br> "postgres_password": "",<br> "repmgr_password": ""<br>}</pre> | no |
| <a name="input_custom_credentials_enabled"></a> [custom\_credentials\_enabled](#input\_custom\_credentials\_enabled) | Specifies whether to enable custom credentials for PostgreSQL database. | `bool` | `false` | no |
| <a name="input_iam_role_arn_backup"></a> [iam\_role\_arn\_backup](#input\_iam\_role\_arn\_backup) | IAM role ARN for backup (AWS) | `string` | `""` | no |
| <a name="input_iam_role_arn_restore"></a> [iam\_role\_arn\_restore](#input\_iam\_role\_arn\_restore) | IAM role ARN for restore (AWS) | `string` | `""` | no |
| <a name="input_postgres_password"></a> [postgres\_password](#input\_postgres\_password) | PostgresQL password | `any` | `""` | no |
| <a name="input_postgresql_backup_config"></a> [postgresql\_backup\_config](#input\_postgresql\_backup\_config) | configuration options for Pgsql database backups. It includes properties such as the S3 bucket Name, the S3 bucket region, and the cron expression for full backups. | `any` | <pre>{<br> "bucket_name": "",<br> "cron_for_full_backup": "",<br> "s3_bucket_region": ""<br>}</pre> | no |
| <a name="input_postgresql_backup_enabled"></a> [postgresql\_backup\_enabled](#input\_postgresql\_backup\_enabled) | Specifies whether to enable backups for Pgsql database. | `bool` | `false` | no |
| <a name="input_postgresql_config"></a> [postgresql\_config](#input\_postgresql\_config) | Configuration options for the postgresql such as number of replica,chart version, storage class and store password at secret manager. | `map(string)` | <pre>{<br> "environment": "",<br> "name": "",<br> "postgresql_values": "",<br> "replicaCount": 3,<br> "storage_class": "gp2",<br> "store_password_to_secret_manager": true<br>}</pre> | no |
| <a name="input_postgresql_enabled"></a> [postgresql\_enabled](#input\_postgresql\_enabled) | Whether or not to deploy postgresql | `bool` | `true` | no |
| <a name="input_postgresql_exporter_enabled"></a> [postgresql\_exporter\_enabled](#input\_postgresql\_exporter\_enabled) | Whether or not to deploy postgresql exporter | `bool` | `false` | no |
| <a name="input_postgresql_namespace"></a> [postgresql\_namespace](#input\_postgresql\_namespace) | Name of the Kubernetes namespace where the postgresql will be deployed. | `string` | `"postgresql"` | no |
| <a name="input_postgresql_restore_config"></a> [postgresql\_restore\_config](#input\_postgresql\_restore\_config) | Configuration options for restoring dump to the Postgresql database. | `any` | <pre>{<br> "bucket_uri": "",<br> "file_name": "",<br> "s3_bucket_region": ""<br>}</pre> | no |
| <a name="input_postgresql_restore_enabled"></a> [postgresql\_restore\_enabled](#input\_postgresql\_restore\_enabled) | Specifies whether to enable restoring dump to the Postgresql database. | `bool` | `false` | no |
| <a name="input_recovery_window_aws_secret"></a> [recovery\_window\_aws\_secret](#input\_recovery\_window\_aws\_secret) | Number of days that AWS Secrets Manager will wait before deleting a secret. This value can be set to 0 to force immediate deletion, or to a value between 7 and 30 days to allow for recovery. | `number` | `0` | no |
| <a name="input_repmgr_password"></a> [repmgr\_password](#input\_repmgr\_password) | Replication manager password | `any` | `""` | no |

Expand Down
4 changes: 2 additions & 2 deletions examples/complete/aws/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ No requirements.

| Name | Source | Version |
|------|--------|---------|
| <a name="module_aws"></a> [aws](#module\_aws) | ../../../modules/resources/aws | n/a |
| <a name="module_postgresql"></a> [postgresql](#module\_postgresql) | ../../../ | n/a |
| <a name="module_aws"></a> [aws](#module\_aws) | git@github.com:sq-ia/terraform-kubernetes-postgresql.git//modules/resources/aws | n/a |
| <a name="module_postgresql"></a> [postgresql](#module\_postgresql) | git@github.com:sq-ia/terraform-kubernetes-postgresql.git | n/a |

## Resources

Expand Down
14 changes: 14 additions & 0 deletions examples/complete/aws/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,18 @@ module "postgresql" {
postgresql_values = file("./helm/postgresql.yaml")
store_password_to_secret_manager = local.store_password_to_secret_manager
}
iam_role_arn_backup = module.aws.iam_role_arn_backup
postgresql_backup_enabled = true
postgresql_backup_config = {
bucket_name = "backup-309017165673"
s3_bucket_region = "us-east-2"
cron_for_full_backup = "*/5 * * * *"
}
postgresql_restore_enabled = true
iam_role_arn_restore = module.aws.iam_role_arn_restore
postgresql_restore_config = {
bucket_uri = "s3://backup-309017165673/pgdump__20231208095502.zip"
file_name = "pgdump__20231208095502.zip"
s3_bucket_region = "us-east-2"
}
}
11 changes: 11 additions & 0 deletions helm/backup/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## Enable Full backup
backup:
bucket_name: ${bucket_name}
aws_default_region: ${s3_bucket_region}
cron_for_full_backup: "${cron_for_full_backup}"

annotations:
${annotations}

auth:
username: ${custom_user_username}
10 changes: 10 additions & 0 deletions helm/restore/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
restore:
bucket_uri: ${bucket_uri}
file_name: ${file_name}
aws_default_region: ${s3_bucket_region}

auth:
username: "${custom_user_username}"

annotations:
${annotations}
43 changes: 40 additions & 3 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
resource "kubernetes_namespace" "postgresql" {
count = var.postgresql_enabled ? 1 : 0
count = var.create_namespace ? 1 : 0
metadata {
name = var.postgresql_namespace
}
}

resource "helm_release" "postgresql_ha" {
count = var.postgresql_enabled ? 1 : 0
depends_on = [kubernetes_namespace.postgresql]
name = "postgresql-ha"
chart = "postgresql-ha"
Expand All @@ -27,7 +26,7 @@ resource "helm_release" "postgresql_ha" {
}

resource "helm_release" "postgres_exporter" {
count = var.postgresql_enabled && var.postgresql_exporter_enabled ? 1 : 0
count = var.postgresql_exporter_enabled ? 1 : 0
depends_on = [helm_release.postgresql_ha]
name = "postgres-exporter"
chart = "prometheus-postgres-exporter"
Expand All @@ -42,3 +41,41 @@ resource "helm_release" "postgres_exporter" {
})
]
}


resource "helm_release" "postgresql_backup" {
depends_on = [helm_release.postgresql_ha]
count = var.postgresql_backup_enabled ? 1 : 0
name = "postgresql-backup"
chart = "${path.module}/modules/backup"
timeout = 600
namespace = var.postgresql_namespace
values = [
templatefile("${path.module}/helm/backup/values.yaml", {
bucket_name = var.postgresql_backup_config.bucket_name,
s3_bucket_region = var.postgresql_backup_config.s3_bucket_region,
cron_for_full_backup = var.postgresql_backup_config.cron_for_full_backup,
custom_user_username = "postgres",
annotations = "eks.amazonaws.com/role-arn: ${var.iam_role_arn_backup}"
})
]
}

## DB dump restore
resource "helm_release" "postgresql_restore" {
depends_on = [helm_release.postgresql_ha]
count = var.postgresql_restore_enabled ? 1 : 0
name = "postgresql-restore"
chart = "${path.module}/modules/restore"
timeout = 600
namespace = var.postgresql_namespace
values = [
templatefile("${path.module}/helm/restore/values.yaml", {
bucket_uri = var.postgresql_restore_config.bucket_uri,
file_name = var.postgresql_restore_config.file_name,
s3_bucket_region = var.postgresql_restore_config.s3_bucket_region,
custom_user_username = "postgres",
annotations = "eks.amazonaws.com/role-arn: ${var.iam_role_arn_restore}"
})
]
}
21 changes: 21 additions & 0 deletions modules/backup/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
4 changes: 4 additions & 0 deletions modules/backup/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
description: A helm chart for Backup of pgsql and stored in S3
name: pgsql-backup
version: 1.0.0
8 changes: 8 additions & 0 deletions modules/backup/templates/backup-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: pgsql-bucket-name
namespace: {{ .Release.Namespace }}
labels:
data:
S3_BUCKET: {{ .Values.backup.bucket_name | b64enc | quote }}
40 changes: 40 additions & 0 deletions modules/backup/templates/cronjob.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup-pgsqldb
spec:
schedule: {{ .Values.backup.cron_for_full_backup | quote }}
concurrencyPolicy: Forbid
suspend: false
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1

jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
imagePullSecrets:
- name: regcred
serviceAccountName: sa-pgsql-backup
containers:
- name: backup-pgsqldb
image: squareops01/pgsqldb-backup:v4
imagePullPolicy: Always
env:
- name: DB_HOST
value: postgresql-ha-postgresql-headless.{{ .Release.Namespace }}.svc.cluster.local
- name: DB_USER
value: {{ .Values.auth.username }}
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: postgresql-ha-postgresql
key: password
- name: S3_BUCKET
valueFrom:
secretKeyRef:
name: pgsql-bucket-name
key: S3_BUCKET
- name: AWS_DEFAULT_REGION
value: {{ .Values.backup.aws_default_region }}
7 changes: 7 additions & 0 deletions modules/backup/templates/service_account.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-pgsql-backup
namespace: {{ .Release.Namespace }}
annotations:
{{ toYaml .Values.annotations | indent 4 }}
5 changes: 5 additions & 0 deletions modules/resources/aws/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ No modules.

| Name | Type |
|------|------|
| [aws_iam_role.pgsql_backup_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.pgsql_restore_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_secretsmanager_secret.postgresql_user_password](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource |
| [aws_secretsmanager_secret_version.postgresql_password](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource |
| [random_password.postgresql_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
Expand All @@ -90,12 +92,15 @@ No modules.
| <a name="input_custom_credentials_enabled"></a> [custom\_credentials\_enabled](#input\_custom\_credentials\_enabled) | Set to true if you want to use custom credentials, false to generate random passwords. | `string` | `false` | no |
| <a name="input_environment"></a> [environment](#input\_environment) | The name of the environment for resource naming. | `string` | `"dev"` | no |
| <a name="input_name"></a> [name](#input\_name) | A name or identifier for resources. | `string` | `""` | no |
| <a name="input_namespace"></a> [namespace](#input\_namespace) | Name of the Kubernetes namespace where the MYSQL deployment will be deployed. | `string` | `"postgresql"` | no |
| <a name="input_recovery_window_aws_secret"></a> [recovery\_window\_aws\_secret](#input\_recovery\_window\_aws\_secret) | The recovery window (in days) for an AWS Secrets Manager secret. | `number` | `0` | no |
| <a name="input_store_password_to_secret_manager"></a> [store\_password\_to\_secret\_manager](#input\_store\_password\_to\_secret\_manager) | Store the password to sceret manager | `bool` | `false` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_iam_role_arn_backup"></a> [iam\_role\_arn\_backup](#output\_iam\_role\_arn\_backup) | IAM role arn for pgsql backup |
| <a name="output_iam_role_arn_restore"></a> [iam\_role\_arn\_restore](#output\_iam\_role\_arn\_restore) | IAM role arn for pgsql restore |
| <a name="output_postgresql_credential"></a> [postgresql\_credential](#output\_postgresql\_credential) | PostgreSQL credentials used for accessing the database. |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
93 changes: 93 additions & 0 deletions modules/resources/aws/main.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
locals {
oidc_provider = replace(
data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer,
"/^https:///",
""
)
}

data "aws_caller_identity" "current" {}

data "aws_eks_cluster" "cluster" {
Expand Down Expand Up @@ -42,4 +50,89 @@ resource "aws_secretsmanager_secret_version" "postgresql_password" {
"repmgr_username" : "repmgr",
"repmgr_password" : "${random_password.repmgrPassword[0].result}"
})
}

resource "aws_iam_role" "pgsql_backup_role" {
name = format("%s-%s-%s", var.cluster_name, var.name, "pgsql-backup")
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Principal = {
Federated = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${local.oidc_provider}"
},
Action = "sts:AssumeRoleWithWebIdentity",
Condition = {
StringEquals = {
"${local.oidc_provider}:aud" = "sts.amazonaws.com",
"${local.oidc_provider}:sub" = "system:serviceaccount:${var.namespace}:sa-pgsql-backup"
}
}
}
]
})
inline_policy {
name = "AllowS3PutObject"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:AbortMultipartUpload",
"s3:ListMultipartUploadParts"
]
Effect = "Allow"
Resource = "*"
}
]
})
}
}


resource "aws_iam_role" "pgsql_restore_role" {
name = format("%s-%s-%s", var.cluster_name, var.name, "pgsql-restore")
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Principal = {
Federated = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${local.oidc_provider}"
},
Action = "sts:AssumeRoleWithWebIdentity",
Condition = {
StringEquals = {
"${local.oidc_provider}:aud" = "sts.amazonaws.com",
"${local.oidc_provider}:sub" = "system:serviceaccount:${var.namespace}:sa-postgresql-restore"
}
}
}
]
})
inline_policy {
name = "AllowS3PutObject"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:AbortMultipartUpload",
"s3:ListMultipartUploadParts"
]
Effect = "Allow"
Resource = "*"
}
]
})
}
}
10 changes: 10 additions & 0 deletions modules/resources/aws/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,13 @@ output "postgresql_credential" {
repmgr_password = var.custom_credentials_enabled ? var.custom_credentials_config.repmgr_password : nonsensitive(random_password.repmgrPassword[0].result),
}
}

output "iam_role_arn_backup" {
value = aws_iam_role.pgsql_backup_role.arn
description = "IAM role arn for pgsql backup"
}

output "iam_role_arn_restore" {
value = aws_iam_role.pgsql_restore_role.arn
description = "IAM role arn for pgsql restore"
}
5 changes: 5 additions & 0 deletions modules/resources/aws/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ variable "name" {
default = ""
description = "A name or identifier for resources."
}
variable "namespace" {
type = string
default = "postgresql"
description = "Name of the Kubernetes namespace where the MYSQL deployment will be deployed."
}

variable "recovery_window_aws_secret" {
type = number
Expand Down
Loading