From fe68c686334753d6e8cb1534557e994e53a5c76f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Huss?= Date: Thu, 16 May 2024 18:39:05 +0200 Subject: [PATCH] fix --- apps/dolibarr/postgresql.tf | 8 +- apps/gitea/postgresql.tf | 8 +- apps/wordpress/check.rhai | 13 + apps/wordpress/common.tf | 29 ++ apps/wordpress/database.tf | 104 ++++++ apps/wordpress/index.yaml | 495 ++++++++++++++++++++++++++ apps/wordpress/presentation.tf | 67 ++++ apps/wordpress/pvc.tf | 28 ++ apps/wordpress/redis.tf | 32 ++ apps/wordpress/template.rhai | 6 + apps/wordpress/wordpress_ConfigMap.tf | 236 ++++++++++++ apps/wordpress/wordpress_Secret.tf | 147 ++++++++ apps/wordpress/wordpress_workload.tf | 165 +++++++++ 13 files changed, 1332 insertions(+), 6 deletions(-) create mode 100644 apps/wordpress/check.rhai create mode 100644 apps/wordpress/common.tf create mode 100644 apps/wordpress/database.tf create mode 100644 apps/wordpress/index.yaml create mode 100644 apps/wordpress/presentation.tf create mode 100644 apps/wordpress/pvc.tf create mode 100644 apps/wordpress/redis.tf create mode 100644 apps/wordpress/template.rhai create mode 100644 apps/wordpress/wordpress_ConfigMap.tf create mode 100644 apps/wordpress/wordpress_Secret.tf create mode 100644 apps/wordpress/wordpress_workload.tf diff --git a/apps/dolibarr/postgresql.tf b/apps/dolibarr/postgresql.tf index d7aa1bc..93d74bf 100644 --- a/apps/dolibarr/postgresql.tf +++ b/apps/dolibarr/postgresql.tf @@ -12,9 +12,6 @@ resource "kubectl_manifest" "prj_pg" { name: "${var.instance}-${var.component}-pg" namespace: "${var.namespace}" labels: ${jsonencode(local.pg-labels)} - annotations: - "k8up.io/backupcommand": "pg_dump -U postgres -d ${var.component} --clean" - "k8up.io/file-extension": ".sql" spec: instances: ${var.postgres.replicas} imageName: "${var.images.postgresql.registry}/${var.images.postgresql.repository}:${var.images.postgresql.tag}" @@ -26,6 +23,11 @@ resource "kubectl_manifest" "prj_pg" { owner: "${var.component}" monitoring: enablePodMonitor: true + inheritedMetadata: + annotations: + "k8up.io/backupcommand": "pg_dump -U postgres -d ${var.component} --clean" + "k8up.io/file-extension": ".sql" + "k8up.io/backup": "true" EOF ], var.backups.enable&&var.backups.use_barman?[<<-EOF backup: diff --git a/apps/gitea/postgresql.tf b/apps/gitea/postgresql.tf index d7aa1bc..93d74bf 100644 --- a/apps/gitea/postgresql.tf +++ b/apps/gitea/postgresql.tf @@ -12,9 +12,6 @@ resource "kubectl_manifest" "prj_pg" { name: "${var.instance}-${var.component}-pg" namespace: "${var.namespace}" labels: ${jsonencode(local.pg-labels)} - annotations: - "k8up.io/backupcommand": "pg_dump -U postgres -d ${var.component} --clean" - "k8up.io/file-extension": ".sql" spec: instances: ${var.postgres.replicas} imageName: "${var.images.postgresql.registry}/${var.images.postgresql.repository}:${var.images.postgresql.tag}" @@ -26,6 +23,11 @@ resource "kubectl_manifest" "prj_pg" { owner: "${var.component}" monitoring: enablePodMonitor: true + inheritedMetadata: + annotations: + "k8up.io/backupcommand": "pg_dump -U postgres -d ${var.component} --clean" + "k8up.io/file-extension": ".sql" + "k8up.io/backup": "true" EOF ], var.backups.enable&&var.backups.use_barman?[<<-EOF backup: diff --git a/apps/wordpress/check.rhai b/apps/wordpress/check.rhai new file mode 100644 index 0000000..1d67ecd --- /dev/null +++ b/apps/wordpress/check.rhai @@ -0,0 +1,13 @@ +const DOMAIN = config.domain; +fn check_domain() { + assert(have_namespace(`${global::DOMAIN}`), `There is no ${global::DOMAIN} namespace`); +} +fn check_authentik() { + assert(have_namespace(`${global::DOMAIN}-auth`), `There is no ${global::DOMAIN}-auth namespace`); + assert(have_install(`${global::DOMAIN}-auth`, "authentik"), `No authentik installation in ${global::DOMAIN}-auth`); + assert(have_secret(`${global::DOMAIN}-auth`, "authentik"), `No authentik secret in ${global::DOMAIN}-auth`); +} +fn pre_check() { + check_domain(); + check_authentik(); +} diff --git a/apps/wordpress/common.tf b/apps/wordpress/common.tf new file mode 100644 index 0000000..aea80ff --- /dev/null +++ b/apps/wordpress/common.tf @@ -0,0 +1,29 @@ + +locals { + core_labels = { + "app.kubernetes.io/name" = var.component + "app.kubernetes.io/instance" = var.instance + } + common_labels = merge({ + "vynil.solidite.fr/owner-name" = var.instance + "vynil.solidite.fr/owner-namespace" = var.namespace + "vynil.solidite.fr/owner-category" = var.category + "vynil.solidite.fr/owner-component" = var.component + "app.kubernetes.io/managed-by" = "vynil" + },local.core_labels) + wp_labels = merge({ + "app.kubernetes.io/componant" = var.component + },local.core_labels) + wp_all_labels = merge({ + "app.kubernetes.io/componant" = var.component + },local.common_labels) + db_labels = merge({ + "app.kubernetes.io/componant" = "database" + },local.common_labels) + secrets_labels = merge(local.common_labels, { + "app.kubernetes.io/component" = "backup-secret" + }) + secret_labels = merge(local.secrets_labels, { + "k8up.io/backup" = "true" + }) +} diff --git a/apps/wordpress/database.tf b/apps/wordpress/database.tf new file mode 100644 index 0000000..520ed3c --- /dev/null +++ b/apps/wordpress/database.tf @@ -0,0 +1,104 @@ +resource "random_password" "mysql_root_pass" { + length = 32 + special = false +} +resource "random_password" "mysql_comp_pass" { + length = 32 + special = false +} +locals { + mysql_host = "${var.instance}-${var.component}-rw.${var.namespace}.svc" + mysql_username = "root" + mysql_password = random_password.mysql_root_pass.result +} +resource "kubectl_manifest" "mysql_root_pass" { + yaml_body = <<-EOF + apiVersion: v1 + kind: Secret + metadata: + name: "${var.instance}-${var.component}-mysql-root" + labels: ${jsonencode(local.common_labels)} + namespace: ${var.namespace} + stringData: + password: "${random_password.mysql_root_pass.result}" +EOF +} + +resource "kubectl_manifest" "ndb" { + yaml_body = <<-EOF + apiVersion: mysql.oracle.com/v1 + kind: NdbCluster + metadata: + name: "${var.instance}-${var.component}" + labels: ${jsonencode(local.db_labels)} + namespace: ${var.namespace} + spec: + redundancyLevel: 1 + dataNode: + nodeCount: 1 + pvcSpec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + mysqlNode: + nodeCount: 1 + rootPasswordSecretName: ${kubectl_manifest.mysql_root_pass.name} + myCnf: | + [mysqld] + default_storage_engine=NDBCLUSTER +EOF +} +resource "time_sleep" "wait_ndb_ready" { + depends_on = [kubectl_manifest.ndb] + create_duration = "180s" +} +resource "mysql_database" "component" { + depends_on = [ time_sleep.wait_ndb_ready, kubectl_manifest.ndb ] + name = var.component +} +resource "mysql_user" "component" { + depends_on = [ time_sleep.wait_ndb_ready, kubectl_manifest.ndb ] + user = var.component + host = "%.${module.service.default_definition.name}.${var.namespace}.%" + plaintext_password = random_password.mysql_comp_pass.result +} +resource "mysql_grant" "component" { + user = mysql_user.component.user + host = mysql_user.component.host + database = mysql_database.component.name + privileges = ["ALL"] +} + +resource "kubectl_manifest" "pre_backup_pod_db" { + count = var.backups.enable?1:0 + ignore_fields = ["metadata.annotations"] + yaml_body = <<-EOF + apiVersion: k8up.io/v1 + kind: PreBackupPod + metadata: + name: "${var.instance}-${var.component}-db" + namespace: "${var.namespace}" + labels: ${jsonencode(local.secrets_labels)} + spec: + backupCommand: mysqldump --all-databases --password=$$MYSQL_PWD --host=${var.instance}-${var.component}-mysqld.${var.namespace}.svc --no-create-db --add-drop-table + pod: + spec: + containers: + - command: + - cat + env: + - name: MYSQL_PWD + valueFrom: + secretKeyRef: + key: password + name: "${kubectl_manifest.mysql_root_pass.name}" + image: "${var.images.mysql.registry}/${var.images.mysql.repository}:${var.images.mysql.tag}" + imagePullPolicy: "${var.images.mysql.pull_policy}" + name: secret + tty: true + serviceAccount: backup-secret + serviceAccountName: backup-secret + EOF +} diff --git a/apps/wordpress/index.yaml b/apps/wordpress/index.yaml new file mode 100644 index 0000000..e54ff54 --- /dev/null +++ b/apps/wordpress/index.yaml @@ -0,0 +1,495 @@ +--- +apiVersion: vinyl.solidite.fr/v1beta1 +kind: Component +category: apps +metadata: + name: wordpress + description: null +options: + app_group: + default: apps + examples: + - apps + type: string + backups: + default: + enable: false + endpoint: '' + key_id_key: s3-id + restic_key: bck-password + retention: + db: 30d + keepDaily: 14 + keepMonthly: 12 + keepWeekly: 6 + keepYearly: 12 + schedule: + backup: 10 3 * * * + check: 10 5 * * 1 + db: 10 3 * * * + prune: 10 1 * * 0 + secret_key: s3-secret + secret_name: backup-settings + use_barman: false + examples: + - enable: false + endpoint: '' + key_id_key: s3-id + restic_key: bck-password + retention: + db: 30d + keepDaily: 14 + keepMonthly: 12 + keepWeekly: 6 + keepYearly: 12 + schedule: + backup: 10 3 * * * + check: 10 5 * * 1 + db: 10 3 * * * + prune: 10 1 * * 0 + secret_key: s3-secret + secret_name: backup-settings + use_barman: false + properties: + enable: + default: false + type: boolean + endpoint: + default: '' + type: string + key_id_key: + default: s3-id + type: string + restic_key: + default: bck-password + type: string + retention: + default: + db: 30d + keepDaily: 14 + keepMonthly: 12 + keepWeekly: 6 + keepYearly: 12 + properties: + db: + default: 30d + type: string + keepDaily: + default: 14 + type: integer + keepMonthly: + default: 12 + type: integer + keepWeekly: + default: 6 + type: integer + keepYearly: + default: 12 + type: integer + type: object + schedule: + default: + backup: 10 3 * * * + check: 10 5 * * 1 + db: 10 3 * * * + prune: 10 1 * * 0 + properties: + backup: + default: 10 3 * * * + type: string + check: + default: 10 5 * * 1 + type: string + db: + default: 10 3 * * * + type: string + prune: + default: 10 1 * * 0 + type: string + type: object + secret_key: + default: s3-secret + type: string + secret_name: + default: backup-settings + type: string + use_barman: + default: false + type: boolean + type: object + domain: + default: your-company + examples: + - your-company + type: string + domain_name: + default: your-company.com + examples: + - your-company.com + type: string + hpa: + default: + avg-cpu: 50 + max-replicas: 5 + min-replicas: 1 + examples: + - avg-cpu: 50 + max-replicas: 5 + min-replicas: 1 + properties: + avg-cpu: + default: 50 + type: integer + max-replicas: + default: 5 + type: integer + min-replicas: + default: 1 + type: integer + type: object + images: + default: + kubectl: + pull_policy: IfNotPresent + registry: docker.io + repository: sebt3/basic-toolbox-image + tag: 1.29.3 + mysql: + pull_policy: IfNotPresent + registry: docker.io + repository: mysql + tag: 8.4.0-oraclelinux9 + nginx: + pull_policy: IfNotPresent + registry: docker.io + repository: nginx + tag: alpine + redis: + pull_policy: IfNotPresent + registry: quay.io + repository: opstree/redis + tag: v7.0.12 + redis_exporter: + pull_policy: IfNotPresent + registry: quay.io + repository: opstree/redis-exporter + tag: v1.44.0 + wordpress: + pull_policy: IfNotPresent + registry: docker.io + repository: wordpress + tag: 6.5.3-php8.3-fpm + examples: + - kubectl: + pull_policy: IfNotPresent + registry: docker.io + repository: sebt3/basic-toolbox-image + tag: 1.29.3 + mysql: + pull_policy: IfNotPresent + registry: docker.io + repository: mysql + tag: 8.4.0-oraclelinux9 + nginx: + pull_policy: IfNotPresent + registry: docker.io + repository: nginx + tag: alpine + redis: + pull_policy: IfNotPresent + registry: quay.io + repository: opstree/redis + tag: v7.0.12 + redis_exporter: + pull_policy: IfNotPresent + registry: quay.io + repository: opstree/redis-exporter + tag: v1.44.0 + wordpress: + pull_policy: IfNotPresent + registry: docker.io + repository: wordpress + tag: 6.5.3-php8.3-fpm + properties: + kubectl: + default: + pull_policy: IfNotPresent + registry: docker.io + repository: sebt3/basic-toolbox-image + tag: 1.29.3 + properties: + pull_policy: + default: IfNotPresent + enum: + - Always + - Never + - IfNotPresent + type: string + registry: + default: docker.io + type: string + repository: + default: sebt3/basic-toolbox-image + type: string + tag: + default: 1.29.3 + type: string + type: object + mysql: + default: + pull_policy: IfNotPresent + registry: docker.io + repository: mysql + tag: 8.4.0-oraclelinux9 + properties: + pull_policy: + default: IfNotPresent + enum: + - Always + - Never + - IfNotPresent + type: string + registry: + default: docker.io + type: string + repository: + default: mysql + type: string + tag: + default: 8.4.0-oraclelinux9 + type: string + type: object + nginx: + default: + pull_policy: IfNotPresent + registry: docker.io + repository: nginx + tag: alpine + properties: + pull_policy: + default: IfNotPresent + enum: + - Always + - Never + - IfNotPresent + type: string + registry: + default: docker.io + type: string + repository: + default: nginx + type: string + tag: + default: alpine + type: string + type: object + redis: + default: + pull_policy: IfNotPresent + registry: quay.io + repository: opstree/redis + tag: v7.0.12 + properties: + pull_policy: + default: IfNotPresent + enum: + - Always + - Never + - IfNotPresent + type: string + registry: + default: quay.io + type: string + repository: + default: opstree/redis + type: string + tag: + default: v7.0.12 + type: string + type: object + redis_exporter: + default: + pull_policy: IfNotPresent + registry: quay.io + repository: opstree/redis-exporter + tag: v1.44.0 + properties: + pull_policy: + default: IfNotPresent + enum: + - Always + - Never + - IfNotPresent + type: string + registry: + default: quay.io + type: string + repository: + default: opstree/redis-exporter + type: string + tag: + default: v1.44.0 + type: string + type: object + wordpress: + default: + pull_policy: IfNotPresent + registry: docker.io + repository: wordpress + tag: 6.5.3-php8.3-fpm + properties: + pull_policy: + default: IfNotPresent + enum: + - Always + - Never + - IfNotPresent + type: string + registry: + default: docker.io + type: string + repository: + default: wordpress + type: string + tag: + default: 6.5.3-php8.3-fpm + type: string + type: object + type: object + ingress_class: + default: traefik + examples: + - traefik + type: string + issuer: + default: letsencrypt-prod + examples: + - letsencrypt-prod + type: string + ndb: + default: + replicas: 1 + examples: + - replicas: 1 + properties: + replicas: + default: 1 + type: integer + type: object + redis: + default: + exporter: + enabled: true + examples: + - exporter: + enabled: true + properties: + exporter: + default: + enabled: true + properties: + enabled: + default: true + type: boolean + type: object + type: object + replicas: + default: 1 + examples: + - 1 + type: integer + storage: + default: + ndb: + size: 10Gi + redis: + size: 2Gi + volume: + accessMode: ReadWriteOnce + class: '' + maxSize: 100Gi + size: 10Gi + type: Filesystem + description: Configure this app storage + examples: + - ndb: + size: 10Gi + redis: + size: 2Gi + volume: + accessMode: ReadWriteOnce + class: '' + maxSize: 100Gi + size: 10Gi + type: Filesystem + properties: + ndb: + default: + size: 10Gi + properties: + size: + default: 10Gi + type: string + type: object + redis: + default: + size: 2Gi + properties: + size: + default: 2Gi + type: string + type: object + volume: + default: + accessMode: ReadWriteOnce + class: '' + maxSize: 100Gi + size: 10Gi + type: Filesystem + properties: + accessMode: + default: ReadWriteOnce + enum: + - ReadWriteOnce + - ReadOnlyMany + - ReadWriteMany + type: string + class: + default: '' + type: string + maxSize: + default: 100Gi + type: string + size: + default: 10Gi + type: string + type: + default: Filesystem + enum: + - Filesystem + - Block + type: string + type: object + type: object + sub_domain: + default: www + examples: + - www + type: string +dependencies: +- dist: null + category: dbo + component: ndb +- dist: null + category: dbo + component: redis +providers: + kubernetes: true + authentik: true + kubectl: true + postgresql: null + mysql: true + restapi: true + http: true + gitea: null +tfaddtype: null diff --git a/apps/wordpress/presentation.tf b/apps/wordpress/presentation.tf new file mode 100644 index 0000000..fac0270 --- /dev/null +++ b/apps/wordpress/presentation.tf @@ -0,0 +1,67 @@ +locals { + dns_name = "${var.sub_domain}.${var.domain_name}" + dns_names = [local.dns_name] + app_name = var.component == var.instance ? var.instance : format("%s-%s", var.component, var.instance) + icon = "logo192.png" + request_headers = { + "Content-Type" = "application/json" + Authorization = "Bearer ${data.kubernetes_secret_v1.authentik.data["AUTHENTIK_BOOTSTRAP_TOKEN"]}" + } +} + +module "service" { + source = "git::https://git.solidite.fr/vynil/kydah-modules.git//service" + component = var.component + instance = var.instance + namespace = var.namespace + labels = local.common_labels + targets = ["http"] + providers = { + kubectl = kubectl + } +} + +module "ingress" { + source = "git::https://git.solidite.fr/vynil/kydah-modules.git//ingress" + component = "" + instance = var.instance + namespace = var.namespace + issuer = var.issuer + ingress_class = var.ingress_class + labels = local.common_labels + dns_names = local.dns_names + middlewares = [] + services = [module.service.default_definition] + providers = { + kubectl = kubectl + } +} + +module "application" { + source = "git::https://git.solidite.fr/vynil/kydah-modules.git//application" + component = var.component + instance = var.instance + app_group = var.app_group + dns_name = local.dns_name + icon = local.icon + protocol_provider = module.oauth2.provider-id + providers = { + authentik = authentik + } +} + +module "oauth2" { + source = "git::https://git.solidite.fr/vynil/kydah-modules.git//oauth2" + component = var.component + instance = var.instance + namespace = var.namespace + domain = var.domain + labels = local.common_labels + dns_name = local.dns_name + redirect_path = "" + providers = { + kubernetes = kubernetes + kubectl = kubectl + authentik = authentik + } +} diff --git a/apps/wordpress/pvc.tf b/apps/wordpress/pvc.tf new file mode 100644 index 0000000..2cabafb --- /dev/null +++ b/apps/wordpress/pvc.tf @@ -0,0 +1,28 @@ +locals { + pvc_spec = merge({ + "accessModes" = [var.storage.volume.accessMode] + "volumeMode" = var.storage.volume.type + "resources" = { + "requests" = { + "storage" = "${var.storage.volume.size}" + } + } + }, var.storage.volume.class != "" ?{ + "storageClassName" = var.storage.volume.class + }:{}) +} +resource "kubectl_manifest" "pvc" { + ignore_fields = ["spec.resources.requests.storage"] + yaml_body = <<-EOF + apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: ${var.instance} + namespace: "${var.namespace}" + annotations: + k8up.io/backup: "true" + resize.kubesphere.io/storage_limit: "${var.storage.volume.maxSize}" + labels: ${jsonencode(local.common_labels)} + spec: ${jsonencode(local.pvc_spec)} + EOF +} diff --git a/apps/wordpress/redis.tf b/apps/wordpress/redis.tf new file mode 100644 index 0000000..791a3ca --- /dev/null +++ b/apps/wordpress/redis.tf @@ -0,0 +1,32 @@ +locals { + redis-labels = merge(local.common_labels, { + "app.kubernetes.io/component" = "redis" + }) +} +resource "kubectl_manifest" "dolibarr_redis" { + yaml_body = <<-EOF + apiVersion: "redis.redis.opstreelabs.in/v1beta1" + kind: "Redis" + metadata: + name: "${var.instance}-${var.component}-redis" + namespace: "${var.namespace}" + labels: ${jsonencode(local.redis-labels)} + spec: + kubernetesConfig: + image: "${var.images.redis.registry}/${var.images.redis.repository}:${var.images.redis.tag}" + imagePullPolicy: "${var.images.redis.pull_policy}" + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: "${var.storage.redis.size}" + redisExporter: + enabled: ${var.redis.exporter.enabled} + image: "${var.images.redis_exporter.registry}/${var.images.redis_exporter.repository}:${var.images.redis_exporter.tag}" + securityContext: + runAsUser: 1000 + fsGroup: 1000 + EOF +} diff --git a/apps/wordpress/template.rhai b/apps/wordpress/template.rhai new file mode 100644 index 0000000..627f037 --- /dev/null +++ b/apps/wordpress/template.rhai @@ -0,0 +1,6 @@ +const DEST=dest; +fn post_template() { + save_to_tf(`${global::DEST}/conditions.tf`, "conditions", #{ + have_servicemonitors: have_crd("servicemonitors.monitoring.coreos.com") + }); +} diff --git a/apps/wordpress/wordpress_ConfigMap.tf b/apps/wordpress/wordpress_ConfigMap.tf new file mode 100644 index 0000000..a3bddb1 --- /dev/null +++ b/apps/wordpress/wordpress_ConfigMap.tf @@ -0,0 +1,236 @@ +resource "kubectl_manifest" "wordpress_cfg" { + yaml_body = <<-EOF + apiVersion: v1 + kind: ConfigMap + metadata: + name: "${var.instance}-${var.component}-envs" + labels: ${jsonencode(local.common_labels)} + namespace: ${var.namespace} + data: + WORDPRESS_DB_HOST: ${var.instance}-${var.component}-mysqld.${var.namespace}.svc:3306 + WORDPRESS_DB_NAME: ${mysql_database.component.name} + WORDPRESS_DB_USER: ${mysql_user.component.user} + WORDPRESS_HOST: ${local.dns_name} + WORDPRESS_TABLE_PREFIX: wp_ + WORDPRESS_DEBUG: "" + WORDPRESS_CONFIG_EXTRA: | + #### general settings + define('WP_HOME', 'https://$${WORDPRESS_HOST}'); + define('WP_SITEURL', 'https://$${WORDPRESS_HOST}'); + define('WP_CACHE', true ); + #### memory limits + # define('WP_MEMORY_LIMIT', '40' ); # default + # define('WP_MAX_MEMORY_LIMIT', '256' ); # default +EOF +} + +resource "kubectl_manifest" "wordpress_files" { + yaml_body = <<-EOF + apiVersion: v1 + kind: ConfigMap + metadata: + name: "${var.instance}-${var.component}-files" + labels: ${jsonencode(local.common_labels)} + namespace: ${var.namespace} + data: + wp-cli: |- + #!/bin/sh + WP_PATH=/var/www/html/ + CLI=/tmp/wp-cli.phar + if ! [ -f "$CLI" ]; then + curl https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar -o $CLI + fi + export PAGER="more" + php $CLI --path=$WP_PATH "$@" + docker-php-ext-redis.ini: |- + extension = redis.so + session.save_handler = redis + session.save_path = "tcp://${var.instance}-${var.component}-redis.${var.namespace}.svc:6379/?prefix=SESSION_${var.component}_${var.instance}:" + php-fpm-zz-docker.conf: |- + [global] + daemonize = no + [www] + listen = 8080 + php-opcache-recommended.ini: |- + opcache.enable=1 + opcache.memory_consumption=128 + opcache.interned_strings_buffer=8 + opcache.max_accelerated_files=10000 + opcache.validate_timestamps=1 + opcache.revalidate_freq=60 + php-uploads.ini: |- + memory_limit = 256M + max_file_uploads = 50 + upload_max_filesize = 96M + post_max_size = 96M + max_execution_time = 300 + max_input_time = 600 + nginx.conf: |- + worker_processes auto; + error_log /dev/stderr; + pid /tmp/nginx.pid; + worker_rlimit_nofile 8192; + events { + worker_connections 1024; + multi_accept on; + } + http { + # cache informations about FDs, frequently accessed files + # can boost performance, but you need to test those values + open_file_cache max=40000 inactive=20s; + open_file_cache_valid 60s; + open_file_cache_min_uses 2; + open_file_cache_errors on; + # copies data between one FD and other from within the kernel + # faster than read() + write() + sendfile on; + # send headers in one piece, it is better than sending them one by one + tcp_nopush on; + # don't buffer data sent, good for small data bursts in real time + tcp_nodelay on; + # gzip settings + gzip on; + gzip_buffers 16 8k; + gzip_min_length 10k; + gzip_proxied any; + gzip_types + text/css + text/javascript + text/xml + text/plain + text/x-component + application/javascript + application/x-javascript + application/json + application/xml + application/rss+xml + application/atom+xml + font/truetype + font/opentype + application/vnd.ms-fontobject + image/svg+xml; + # allow the server to close connection on non responding client, this will free up memory + reset_timedout_connection on; + # request timed out -- default 60 + client_body_timeout 20; + # if client stop responding, free up memory -- default 60 + send_timeout 10; + # server will close connection after this time -- default 75 + keepalive_timeout 30; + # number of requests client can make over keep-alive -- for testing environment + keepalive_requests 10000; + # other settings + client_max_body_size 96M; + server_tokens off; + include mime.types; + default_type application/octet-stream; + add_header X-Frame-Options SAMEORIGIN; + # trust these ips to set the correct http_x_forwarded_for header + set_real_ip_from 10.0.0.0/8; + set_real_ip_from 127.0.0.1; + real_ip_header X-Forwarded-For; + # to boost I/O on HDD we can disable access logs + # access_log off; + log_format main '$remote_addr - $status [$request] $body_bytes_sent ' + '"$http_referer" "$http_user_agent" via $realip_remote_addr'; + access_log "/dev/stdout" main buffer=2048 flush=5s; + client_body_temp_path /tmp/client_temp 1 2; + proxy_temp_path /tmp/proxy_temp_path 1 2; + fastcgi_temp_path /tmp/fastcgi_temp 1 2; + uwsgi_temp_path /tmp/uwsgi_temp 1 2; + scgi_temp_path /tmp/scgi_temp 1 2; + #################################### + ### fastcgi cache start + #fastcgi_cache_path /tmp/fastcgi-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=10m; + #fastcgi_cache_key "$scheme$request_method$host$request_uri"; + #fastcgi_cache_use_stale error timeout invalid_header http_500; + #fastcgi_ignore_headers Cache-Control Expires Set-Cookie; + ### fastcgi cache end + #################################### + server { + listen 8080 default_server; + server_name _; + root /var/www/html; + index index.php; + location / { + # deliver files directly or from php + # $uri - for regular files (html, css, js, jpg, ...) + # $uri/ - needed for indexes like /wp-config/ or /tag/nice/ + # /index.php?$args - sends the request to wordpress using fastcgi / php + try_files $uri $uri/ /index.php?$args; + } + # DISABLE_DIRECT_CONTENT_PHP_EXECUTION + location ~ /(?:wp-content|wp-includes|uploads)/.*\.php$ { + deny all; + #access_log off; + #log_not_found off; + } + # Deny access to load load-scripts.php, load-styles.php; can be used for DOS attacks; + location ~ \/wp-admin\/load\-(scripts|styles)\.php { + deny all; + } + # START Nginx Rewrites for Rank Math Sitemaps + rewrite ^/sitemap_index.xml$ /index.php?sitemap=1 last; + rewrite ^/([^/]+?)-sitemap([0-9]+)?.xml$ /index.php?sitemap=$1&sitemap_n=$2 last; + # END Nginx Rewrites for Rank Math Sitemaps + #################################### + ### fastcgi cache start + # define when to skip the cache + #set $skip_cache 0; + # Requests with a query string should not be cached + #if ($query_string != "") { + # set $skip_cache 1; + #} + # Don't cache uris containing the following segments + #if ($request_uri ~ "/wp-admin/|/xmlrpc.php|wp-.*.php|index.php") { + # set $skip_cache 1; + #} + # Don't use the cache for logged in users or recent commenters + #if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") { + # set $skip_cache 1; + #} + ### fastcgi cache end + #################################### + # send .php requests to wordpress using (fastcgi) + location ~ [^/]\.php(/|$) { + # split the request path into its components + fastcgi_split_path_info ^(.+?\.php)(/.*)$; + # check if the requested php file exits; + # don't send the request to fastcgi if no such file exits (saves some resources) + if (!-f $document_root$fastcgi_script_name) { + return 404; + } + # include fastcgi_params from nginx directory (/etc/nginx/fastcgi_params) + include fastcgi_params; + # set the script filename (eg. /var/www/html/index.php) + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; + fastcgi_index index.php; + # tell wordpress that the request came over https to avoid redirect-loops + fastcgi_param REQUEST_SCHEME 'https'; + fastcgi_param HTTPS 'on'; + # hide PHP header + fastcgi_hide_header X-Powered-By; + # send the request to php + fastcgi_pass localhost:9000; + #fastcgi_pass unix:/run/php/fpm.sock; + #################################### + ### fastcgi cache start + #fastcgi_cache_methods GET HEAD; + #fastcgi_cache_bypass $skip_cache; + #fastcgi_no_cache $skip_cache; + #fastcgi_cache WORDPRESS; + #fastcgi_cache_valid 10m; + #add_header X-FastCGI-Cache $upstream_cache_status; + ### fastcgi cache end + #################################### + } + # enable client cache for media files and fonts + location ~* \.(css|js|ico|gif|jpeg|jpg|webp|png|svg|eot|otf|woff|woff2|ttf|ogg|pdf)$ { + expires 120d; + } + } + } +EOF +} diff --git a/apps/wordpress/wordpress_Secret.tf b/apps/wordpress/wordpress_Secret.tf new file mode 100644 index 0000000..aa35270 --- /dev/null +++ b/apps/wordpress/wordpress_Secret.tf @@ -0,0 +1,147 @@ +resource "random_password" "AUTH_KEY" { + length = 32 + special = false +} + +resource "random_password" "SECURE_AUTH_KEY" { + length = 32 + special = false +} + +resource "random_password" "LOGGED_IN_KEY" { + length = 32 + special = false +} + +resource "random_password" "NONCE_KEY" { + length = 32 + special = false +} + +resource "random_password" "AUTH_SALT" { + length = 32 + special = false +} + +resource "random_password" "SECURE_AUTH_SALT" { + length = 32 + special = false +} + +resource "random_password" "LOGGED_IN_SALT" { + length = 32 + special = false +} + +resource "random_password" "NONCE_SALT" { + length = 32 + special = false +} + +resource "kubectl_manifest" "secret" { + yaml_body = <<-EOF + apiVersion: v1 + kind: Secret + metadata: + name: "${var.instance}-${var.component}" + labels: ${jsonencode(local.secret_labels)} + namespace: ${var.namespace} + stringData: + WORDPRESS_AUTH_KEY: "${random_password.AUTH_KEY.result}" + WORDPRESS_SECURE_AUTH_KEY: "${random_password.SECURE_AUTH_KEY.result}" + WORDPRESS_LOGGED_IN_KEY: "${random_password.LOGGED_IN_KEY.result}" + WORDPRESS_NONCE_KEY: "${random_password.NONCE_KEY.result}" + WORDPRESS_AUTH_SALT: "${random_password.AUTH_SALT.result}" + WORDPRESS_SECURE_AUTH_SALT: "${random_password.SECURE_AUTH_SALT.result}" + WORDPRESS_LOGGED_IN_SALT: "${random_password.LOGGED_IN_SALT.result}" + WORDPRESS_NONCE_SALT: "${random_password.NONCE_SALT.result}" + WORDPRESS_DB_PASSWORD: "${random_password.mysql_comp_pass.result}" +EOF +} + +resource "kubectl_manifest" "pre_backup_sa" { + count = var.backups.enable?1:0 + ignore_fields = ["metadata.annotations"] + yaml_body = <<-EOF + apiVersion: v1 + kind: ServiceAccount + metadata: + name: "${var.instance}-${var.component}-backup-secret" + namespace: "${var.namespace}" + labels: ${jsonencode(local.secrets_labels)} + EOF +} + +resource "kubectl_manifest" "pre_backup_role" { + count = var.backups.enable?1:0 + ignore_fields = ["metadata.annotations"] + yaml_body = <<-EOF + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: "${var.instance}-${var.component}-backup-secret" + namespace: "${var.namespace}" + labels: ${jsonencode(local.secrets_labels)} + rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + EOF +} + +resource "kubectl_manifest" "pre_backup_rb" { + count = var.backups.enable?1:0 + ignore_fields = ["metadata.annotations"] + yaml_body = <<-EOF + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: "${var.instance}-${var.component}-backup-secret" + namespace: "${var.namespace}" + labels: ${jsonencode(local.secrets_labels)} + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ${kubectl_manifest.pre_backup_role.name} + subjects: + - kind: ServiceAccount + name: ${kubectl_manifest.pre_backup_sa.name} + namespace: "${var.namespace}" + EOF +} + +resource "kubectl_manifest" "pre_backup_pod_secret" { + count = var.backups.enable?1:0 + ignore_fields = ["metadata.annotations"] + yaml_body = <<-EOF + apiVersion: k8up.io/v1 + kind: PreBackupPod + metadata: + name: "${var.instance}-${var.component}-secret" + namespace: "${var.namespace}" + labels: ${jsonencode(local.secrets_labels)} + spec: + backupCommand: kubectl get secrets -o yaml -l k8up.io/backup=true + pod: + spec: + containers: + - command: + - cat + env: + - name: MYSQL_PWD + valueFrom: + secretKeyRef: + key: password + name: "${var.component}-${var.instance}" + image: "${var.images.kubectl.registry}/${var.images.kubectl.repository}:${var.images.kubectl.tag}" + imagePullPolicy: "${var.images.kubectl.pull_policy}" + name: secret + tty: true + serviceAccount: backup-secret + serviceAccountName: backup-secret + EOF +} diff --git a/apps/wordpress/wordpress_workload.tf b/apps/wordpress/wordpress_workload.tf new file mode 100644 index 0000000..a65cc09 --- /dev/null +++ b/apps/wordpress/wordpress_workload.tf @@ -0,0 +1,165 @@ +resource "kubectl_manifest" "Deployment_wordpress" { + yaml_body = <<-EOF + apiVersion: apps/v1 + kind: Deployment + metadata: + name: "${var.instance}-${var.component}" + labels: ${jsonencode(local.wp_all_labels)} + namespace: ${var.namespace} + spec: + replicas: 1 + selector: + matchLabels: ${jsonencode(local.wp_labels)} + template: + metadata: + labels: ${jsonencode(local.wp_labels)} + spec: + serviceAccountName: default + securityContext: + fsGroup: 12000 + runAsGroup: 12000 + runAsNonRoot: true + runAsUser: 12000 + initContainers: + - name: copy-wordpress-app + image: ${var.images.wordpress.registry}/${var.images.wordpress.repository}:${var.images.wordpress.tag} + imagePullPolicy: ${var.images.wordpress.pull_policy} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + command: [sh, -cx] + args: + - >- + echo Copying Wordpress source ...; + ls -l /usr/src/wordpress/; + cp -r /usr/src/wordpress/. /wordpress-app/; + if [ -z "$(ls -A /wordpress-data/wp-content/)" ]; then echo "Copying initial files to wp-content ..."; cp -r /usr/src/wordpress/wp-content/* /wordpress-data/wp-content/; fi; + volumeMounts: + - mountPath: /wordpress-app/ + name: wordpress-app + - mountPath: /wordpress-data/wp-content/ + name: wordpress-data + subPath: wp-content + containers: + - name: wordpress + image: ${var.images.wordpress.registry}/${var.images.wordpress.repository}:${var.images.wordpress.tag} + imagePullPolicy: ${var.images.wordpress.pull_policy} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + envFrom: + - configMapRef: + name: "${kubectl_manifest.wordpress_cfg.name}" + - secretRef: + name: "${kubectl_manifest.secret.name}" + resources: {} + ports: + - name: php-fpm + containerPort: 9000 + protocol: TCP + livenessProbe: + initialDelaySeconds: 10 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + tcpSocket: + port: php-fpm + readinessProbe: + initialDelaySeconds: 10 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + tcpSocket: + port: php-fpm + lifecycle: + postStart: + exec: + command: ["/bin/sh", "-c", "test -f /var/www/html/wp-config.php && chmod 444 /var/www/html/wp-config.php"] + volumeMounts: + - mountPath: /var/www/html/ + name: wordpress-app + - name: wordpress-data + mountPath: /var/www/html/wp-content/ + subPath: wp-content + - name: wordpress-config + mountPath: /usr/local/etc/php-fpm.d/zz-docker.conf + subPath: php-fpm-zz-docker.conf + - name: wordpress-config + mountPath: /usr/local/etc/php/conf.d/uploads.ini + subPath: php-uploads.ini + - name: wordpress-config + mountPath: /usr/local/etc/php/conf.d/opcache-recommended.ini + subPath: php-opcache-recommended.ini + - name: wordpress-config + mountPath: /usr/local/etc/php/conf.d/docker-php-ext-redis.ini + subPath: docker-php-ext-redis.ini + - name: wordpress-config + mountPath: /usr/local/bin/wp + subPath: wp-cli + - name: nginx + image: ${var.images.nginx.registry}/${var.images.nginx.repository}:${var.images.nginx.tag} + imagePullPolicy: ${var.images.nginx.pull_policy} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + ports: + - name: http + containerPort: 8080 + livenessProbe: + initialDelaySeconds: 10 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + httpGet: + path: /wp-admin/install.php + port: http + scheme: HTTP + httpHeaders: + - name: X-Forwarded-Proto + value: https + readinessProbe: + initialDelaySeconds: 10 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + tcpSocket: + port: http + volumeMounts: + - mountPath: /var/www/html/ + name: wordpress-app + - mountPath: /var/www/html/wp-content/ + name: wordpress-data + subPath: wp-content + - mountPath: /etc/nginx/nginx.conf + name: wordpress-config + subPath: nginx.conf + - mountPath: /tmp/ + name: nginx-tmp + volumes: + - name: wordpress-app + emptyDir: {} + - name: wordpress-config + configMap: + name: ${kubectl_manifest.wordpress_files.name} + - name: wordpress-data + persistentVolumeClaim: + claimName: ${kubectl_manifest.pvc.name} + - name: nginx-tmp + emptyDir: + medium: Memory +EOF +} +