feat: Implement MariaDB and backup job modules with configuration and secrets management
This commit is contained in:
@@ -78,7 +78,7 @@ resource "kubernetes_secret" "gitea_mail_credentials" {
|
||||
# Setup MariaDB database
|
||||
#
|
||||
module "gitea_database" {
|
||||
source = "./modules/k8s_mariadb"
|
||||
source = "../modules/k8s_mariadb"
|
||||
|
||||
namespace = kubernetes_namespace.gitea.metadata[0].name
|
||||
app_name = "gitea"
|
||||
@@ -97,7 +97,7 @@ module "gitea_database" {
|
||||
# Setup rsync backup job to scaleway bucket
|
||||
#
|
||||
module "gitea_backup" {
|
||||
source = "./modules/scw_backup_job"
|
||||
source = "../modules/scw_backup_job"
|
||||
|
||||
namespace = kubernetes_namespace.gitea.metadata[0].name
|
||||
app_name = "gitea"
|
||||
|
||||
@@ -209,7 +209,7 @@ resource "kubernetes_manifest" "mail_certificate" {
|
||||
|
||||
module "mail_backup" {
|
||||
|
||||
source = "./modules/scw_backup_job"
|
||||
source = "../modules/scw_backup_job"
|
||||
|
||||
namespace = kubernetes_namespace.mail.metadata[0].name
|
||||
app_name = "mail"
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
resource "kubernetes_secret" "root_password" {
|
||||
metadata {
|
||||
name = "${var.app_name}-root-credentials"
|
||||
namespace = var.namespace
|
||||
}
|
||||
data = {
|
||||
username = "root"
|
||||
password = var.root_password
|
||||
}
|
||||
type = "Opaque"
|
||||
}
|
||||
|
||||
resource "kubernetes_service_account" "service_account" {
|
||||
|
||||
metadata {
|
||||
name = "${var.app_name}-mariadb-sa"
|
||||
namespace = var.namespace
|
||||
}
|
||||
|
||||
automount_service_account_token = false
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "app_password" {
|
||||
metadata {
|
||||
name = "${var.app_name}-app-credentials"
|
||||
namespace = var.namespace
|
||||
}
|
||||
data = {
|
||||
username = var.app_name
|
||||
password = var.app_password
|
||||
}
|
||||
type = "Opaque"
|
||||
}
|
||||
|
||||
resource "kubernetes_service" "service" {
|
||||
metadata {
|
||||
name = "mariadb"
|
||||
namespace = var.namespace
|
||||
}
|
||||
spec {
|
||||
port {
|
||||
port = 3306
|
||||
}
|
||||
selector = {
|
||||
app = "mariadb"
|
||||
}
|
||||
cluster_ip = "None"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_deployment" "deployment" {
|
||||
metadata {
|
||||
name = "mariadb"
|
||||
namespace = var.namespace
|
||||
}
|
||||
spec {
|
||||
selector {
|
||||
match_labels = {
|
||||
app = "mariadb"
|
||||
}
|
||||
}
|
||||
strategy {
|
||||
type = "Recreate"
|
||||
}
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "mariadb"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
service_account_name = kubernetes_service_account.service_account.metadata[0].name
|
||||
container {
|
||||
name = "mariadb"
|
||||
image = "mariadb:${var.current_version}"
|
||||
|
||||
resources {
|
||||
requests = {
|
||||
memory = "100Mi"
|
||||
}
|
||||
}
|
||||
|
||||
liveness_probe {
|
||||
exec {
|
||||
command = ["sh", "-c", "mysqladmin status -uroot -p$MARIADB_ROOT_PASSWORD"]
|
||||
}
|
||||
initial_delay_seconds = 30
|
||||
period_seconds = 300
|
||||
timeout_seconds = 1
|
||||
failure_threshold = 15
|
||||
}
|
||||
|
||||
readiness_probe {
|
||||
exec {
|
||||
command = ["sh", "-c", "mysqladmin status -uroot -p$MARIADB_ROOT_PASSWORD"]
|
||||
}
|
||||
initial_delay_seconds = 120
|
||||
period_seconds = 10
|
||||
timeout_seconds = 1
|
||||
failure_threshold = 15
|
||||
}
|
||||
|
||||
env {
|
||||
name = "MARIADB_ROOT_PASSWORD"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
key = "password"
|
||||
name = kubernetes_secret.root_password.metadata[0].name
|
||||
}
|
||||
}
|
||||
}
|
||||
env {
|
||||
name = "MARIADB_ROOT_HOST"
|
||||
value = "10.%"
|
||||
}
|
||||
env {
|
||||
name = "MARIADB_USER"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
key = "username"
|
||||
name = kubernetes_secret.app_password.metadata[0].name
|
||||
}
|
||||
}
|
||||
}
|
||||
env {
|
||||
name = "MARIADB_PASSWORD"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
key = "password"
|
||||
name = kubernetes_secret.app_password.metadata[0].name
|
||||
}
|
||||
}
|
||||
}
|
||||
env {
|
||||
name = "MARIADB_DATABASE"
|
||||
value = var.app_name
|
||||
}
|
||||
port {
|
||||
container_port = 3306
|
||||
name = "mariadb"
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/var/lib/mysql"
|
||||
name = "persistent-storage"
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/docker-entrypoint-initdb.d"
|
||||
name = "initdb-storage"
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "persistent-storage"
|
||||
host_path {
|
||||
path = "${var.database_folder}/${var.app_name}.data"
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "initdb-storage"
|
||||
host_path {
|
||||
path = "${var.database_folder}/${var.app_name}.initdb.d"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# TODO: This should move out of here
|
||||
resource "kubernetes_cron_job_v1" "backup_data_cron" {
|
||||
metadata {
|
||||
name = "mariadb-backup-job"
|
||||
namespace = var.namespace
|
||||
}
|
||||
spec {
|
||||
concurrency_policy = "Forbid"
|
||||
schedule = var.cron_schedule
|
||||
failed_jobs_history_limit = 2
|
||||
successful_jobs_history_limit = 2
|
||||
job_template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "mariadb"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
backoff_limit = 1
|
||||
parallelism = 1
|
||||
completions = 1
|
||||
active_deadline_seconds = 1800
|
||||
template {
|
||||
metadata {}
|
||||
spec {
|
||||
container {
|
||||
name = "sql-cron-job"
|
||||
image = "mariadb:${var.current_version}"
|
||||
env {
|
||||
name = "MARIADB_USER"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
key = "username"
|
||||
name = kubernetes_secret.app_password.metadata[0].name
|
||||
}
|
||||
}
|
||||
}
|
||||
env {
|
||||
name = "MARIADB_PASSWORD"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
key = "password"
|
||||
name = kubernetes_secret.app_password.metadata[0].name
|
||||
}
|
||||
}
|
||||
}
|
||||
env {
|
||||
name = "MARIADB_DATABASE"
|
||||
value = var.app_name
|
||||
}
|
||||
security_context {
|
||||
allow_privilege_escalation = false
|
||||
}
|
||||
command = ["/bin/sh", "-c"]
|
||||
args = [join(";", [
|
||||
"/usr/bin/mariadb-dump --single-transaction -h mariadb -u $MARIADB_USER -p$MARIADB_PASSWORD $MARIADB_DATABASE | gzip > /backups/${var.app_name}-sql-`date +\"%Y%m%d\"`.sql.gz",
|
||||
"find /backups -type f -name '${var.app_name}-sql-*.sql.gz' -mtime +${var.retention_days} | xargs --no-run-if-empty rm"
|
||||
])]
|
||||
volume_mount {
|
||||
mount_path = "/backups"
|
||||
name = "backups-storage"
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "backups-storage"
|
||||
host_path {
|
||||
path = var.backup_folder
|
||||
}
|
||||
}
|
||||
restart_policy = "Never"
|
||||
termination_grace_period_seconds = 30
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
output "host" {
|
||||
value = "mariadb"
|
||||
}
|
||||
|
||||
output "port" {
|
||||
value = 3306
|
||||
}
|
||||
|
||||
output "root_crendentials_name" {
|
||||
value = kubernetes_secret.root_password.metadata[0].name
|
||||
}
|
||||
|
||||
output "app_crendentials_name" {
|
||||
value = kubernetes_secret.app_password.metadata[0].name
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
terraform {
|
||||
required_version = "~>1.8"
|
||||
required_providers {
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "~>2.18"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
variable "namespace" {
|
||||
description = "namespace"
|
||||
sensitive = false
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "app_name" {
|
||||
description = "database name"
|
||||
sensitive = false
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "root_password" {
|
||||
description = "root password"
|
||||
sensitive = true
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "app_password" {
|
||||
description = "user password"
|
||||
sensitive = true
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "database_folder" {
|
||||
description = "host storage path"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cron_schedule" {
|
||||
description = "Cronjob schedule for data backups"
|
||||
default = "* 2 * * *"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "retention_days" {
|
||||
description = "Backup retention days"
|
||||
default = 14
|
||||
type = number
|
||||
}
|
||||
|
||||
variable "current_version" {
|
||||
description = "version"
|
||||
default = "10.7.8"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "backup_folder" {
|
||||
description = "Backup source location"
|
||||
type = string
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
locals {
|
||||
rclone_version = "1.61.1"
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
resource "kubernetes_service_account" "service_account" {
|
||||
metadata {
|
||||
name = "${var.app_name}-backup-sa"
|
||||
namespace = var.namespace
|
||||
}
|
||||
|
||||
automount_service_account_token = false
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "scaleway_api_credentials" {
|
||||
metadata {
|
||||
name = "${var.app_name}-scaleway-api-credentials"
|
||||
namespace = var.namespace
|
||||
}
|
||||
data = {
|
||||
access_key = var.access_key
|
||||
secret_key = var.secret_key
|
||||
}
|
||||
type = "Opaque"
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "rclone_config" {
|
||||
metadata {
|
||||
name = "rclone-config"
|
||||
namespace = var.namespace
|
||||
}
|
||||
data = {
|
||||
"rclone.conf" = file("${path.module}/resources/rclone.conf")
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_cron_job_v1" "backup_job" {
|
||||
metadata {
|
||||
name = "${var.app_name}-backup"
|
||||
namespace = var.namespace
|
||||
}
|
||||
spec {
|
||||
concurrency_policy = "Forbid"
|
||||
schedule = var.cron_schedule
|
||||
failed_jobs_history_limit = 2
|
||||
successful_jobs_history_limit = 2
|
||||
job_template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "${var.app_name}-backup"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
backoff_limit = 1
|
||||
parallelism = 1
|
||||
completions = 1
|
||||
active_deadline_seconds = 1800
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "${var.app_name}-backup"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
service_account_name = kubernetes_service_account.service_account.metadata[0].name
|
||||
security_context {
|
||||
run_as_user = 0
|
||||
}
|
||||
container {
|
||||
|
||||
name = "${var.app_name}-backup"
|
||||
image = "rclone/rclone:${local.rclone_version}"
|
||||
image_pull_policy = "Always"
|
||||
|
||||
resources {
|
||||
requests = {
|
||||
memory = "100Mi"
|
||||
}
|
||||
}
|
||||
|
||||
env {
|
||||
name = "SCW_ACCESS_KEY"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
key = "access_key"
|
||||
name = kubernetes_secret.scaleway_api_credentials.metadata[0].name
|
||||
}
|
||||
}
|
||||
}
|
||||
env {
|
||||
name = "SCW_SECRET_KEY"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
key = "secret_key"
|
||||
name = kubernetes_secret.scaleway_api_credentials.metadata[0].name
|
||||
}
|
||||
}
|
||||
}
|
||||
env {
|
||||
name = "SCW_DEFAULT_PROJECT_ID"
|
||||
value = var.scaleway_project_id
|
||||
}
|
||||
env {
|
||||
name = "SCW_DEFAULT_ORGANIZATION_ID"
|
||||
value = var.scaleway_organization_id
|
||||
}
|
||||
env {
|
||||
name = "SCW_DEFAULT_REGION"
|
||||
value = var.scaleway_region
|
||||
}
|
||||
env {
|
||||
name = "SCW_DEFAULT_ZONE"
|
||||
value = var.scaleway_zone
|
||||
}
|
||||
env {
|
||||
name = "BUCKET_NAME"
|
||||
value = var.bucket_name
|
||||
}
|
||||
command = ["/bin/sh", "-c"]
|
||||
args = [join(";", [
|
||||
"apk update",
|
||||
"apk add gettext",
|
||||
"envsubst</etc/rclone.conf.tmpl>/etc/rclone.conf",
|
||||
"tar -zcvpf /backup/${var.app_name}-files-`date +\"%Y%m%d\"`.tar.gz /files",
|
||||
"find /backup -type f -name '${var.app_name}-files-*.tar.gz' -mtime +${var.retention_days} | xargs --no-run-if-empty rm",
|
||||
"/usr/local/bin/rclone --config=/etc/rclone.conf sync --progress /backup scaleway:$BUCKET_NAME/${var.app_name}-backup"
|
||||
])]
|
||||
security_context {
|
||||
allow_privilege_escalation = false
|
||||
}
|
||||
volume_mount {
|
||||
name = "backup-storage"
|
||||
mount_path = "/backup"
|
||||
}
|
||||
volume_mount {
|
||||
name = "persistent-storage"
|
||||
mount_path = "/files"
|
||||
read_only = true
|
||||
}
|
||||
volume_mount {
|
||||
name = "rclone-conf"
|
||||
mount_path = "/etc/rclone.conf.tmpl"
|
||||
sub_path = "rclone.conf"
|
||||
read_only = true
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "backup-storage"
|
||||
host_path {
|
||||
path = var.target_folder
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "persistent-storage"
|
||||
host_path {
|
||||
path = var.source_folder
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "rclone-conf"
|
||||
config_map {
|
||||
name = kubernetes_config_map.rclone_config.metadata[0].name
|
||||
}
|
||||
}
|
||||
restart_policy = "Never"
|
||||
termination_grace_period_seconds = 30
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
terraform {
|
||||
required_version = "~>1.8"
|
||||
required_providers {
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "~>2.18"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
[scaleway]
|
||||
type = s3
|
||||
provider = Scaleway
|
||||
env_auth = false
|
||||
access_key_id = $SCW_ACCESS_KEY
|
||||
secret_access_key = $SCW_SECRET_KEY
|
||||
region = $SCW_DEFAULT_REGION
|
||||
endpoint = s3.$SCW_DEFAULT_REGION.scw.cloud
|
||||
acl = private
|
||||
storage_class = STANDARD
|
||||
@@ -1,70 +0,0 @@
|
||||
variable "bucket_name" {
|
||||
description = "Backup bucket name"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "namespace" {
|
||||
description = "Namespace"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "scaleway_project_id" {
|
||||
description = "Scaleway project id"
|
||||
sensitive = true
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "scaleway_organization_id" {
|
||||
description = "Scaleway organization id"
|
||||
sensitive = true
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "scaleway_region" {
|
||||
description = "Scaleway region"
|
||||
default = "fr-par"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "scaleway_zone" {
|
||||
default = "fr-par-2"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cron_schedule" {
|
||||
description = "Cronjob schedule for data backups"
|
||||
default = "* 2 * * *"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "access_key" {
|
||||
description = "Access key"
|
||||
sensitive = true
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "secret_key" {
|
||||
description = "Secret key"
|
||||
sensitive = true
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "app_name" {
|
||||
description = "Name of the app to backup"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "source_folder" {
|
||||
description = "Name of host folder"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "target_folder" {
|
||||
description = "Backup source location"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "retention_days" {
|
||||
description = "backup retention days"
|
||||
type = string
|
||||
}
|
||||
@@ -154,7 +154,7 @@ resource "kubernetes_config_map" "nextcloud_apache_config" {
|
||||
# Setup MariaDB database
|
||||
#
|
||||
module "nextcloud_database" {
|
||||
source = "./modules/k8s_mariadb"
|
||||
source = "../modules/k8s_mariadb"
|
||||
|
||||
namespace = kubernetes_namespace.nextcloud.metadata[0].name
|
||||
app_name = "nextcloud"
|
||||
@@ -174,7 +174,7 @@ module "nextcloud_database" {
|
||||
#
|
||||
module "nextcloud_backup" {
|
||||
|
||||
source = "./modules/scw_backup_job"
|
||||
source = "../modules/scw_backup_job"
|
||||
|
||||
namespace = kubernetes_namespace.nextcloud.metadata[0].name
|
||||
app_name = "nextcloud"
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
gzip on;
|
||||
gzip_comp_level 9;
|
||||
gzip_types
|
||||
text/html
|
||||
text/plain
|
||||
text/css
|
||||
text/js
|
||||
text/xml
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/json
|
||||
application/xml
|
||||
application/rss+xml
|
||||
image/svg+xml;
|
||||
|
||||
root /tmp/site;
|
||||
|
||||
location / {
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
location ~* ^/([^/]+) {
|
||||
index index.html index.htm;
|
||||
error_page 404 = @error;
|
||||
}
|
||||
|
||||
error_page 404 /404.html;
|
||||
location @error {
|
||||
try_files /$1/404.html /404.html =404;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /tmp/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
proxy_temp_path /tmp/proxy_temp;
|
||||
client_body_temp_path /tmp/client_temp;
|
||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||
scgi_temp_path /tmp/scgi_temp;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
Reference in New Issue
Block a user