Files
AFC-Demo/terraform/kubernetes.tf
T
cbazzaandClaude Opus 4.5 fddc78618e
Build and Deploy to Synology NAS / test (push) Failing after 15m0s
Build and Deploy to Synology NAS / build (push) Has been cancelled
Build and Deploy to Synology NAS / deploy (push) Has been cancelled
Build and Deploy to Synology NAS / notify (push) Has been cancelled
feat: add Azure AKS deployment infrastructure with Terraform
- Add Terraform configuration for AKS cluster deployment
- Add Kubernetes manifests for Laravel app (deployment, services, secrets)
- Add PostgreSQL on Kubernetes with multi-schema support
- Add Nginx Ingress Controller configuration
- Add GitHub Actions workflow for Azure deployment
- Add HTTP Basic Authentication for production
- Add database restore functionality via Kubernetes jobs
- Update Dockerfile and nginx config for production
- Update database.php for multi-schema connections
- Add deployment documentation and quickstart guides

Deployed version: 1.0.7 at http://72.144.113.194/

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 09:43:08 +01:00

275 lines
6.5 KiB
Terraform

# Kubernetes Namespace
resource "kubernetes_namespace" "app" {
metadata {
name = var.app_namespace
labels = merge(
local.common_labels,
{
name = var.app_namespace
}
)
}
}
# Kubernetes Secret for Database Connection
resource "kubernetes_secret" "db_credentials" {
metadata {
name = "${var.app_name}-db-credentials"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
data = {
# Primary connection uses DB_HOST2 variables (for pgsql_second connection)
DB_CONNECTION2 = "pgsql"
DB_HOST2 = "postgresql.${kubernetes_namespace.app.metadata[0].name}.svc.cluster.local"
DB_PORT2 = "5432"
DB_DATABASE2 = local.postgresql_db_name
DB_USERNAME2 = var.postgresql_admin_username
DB_PASSWORD2 = local.postgresql_admin_pass
# Also set standard DB_ variables for pgsql connection (used by sessions)
DB_CONNECTION = "pgsql"
DB_HOST = "postgresql.${kubernetes_namespace.app.metadata[0].name}.svc.cluster.local"
DB_PORT = "5432"
DB_DATABASE = local.postgresql_db_name
DB_USERNAME = var.postgresql_admin_username
DB_PASSWORD = local.postgresql_admin_pass
}
type = "Opaque"
depends_on = [
kubernetes_service.postgresql
]
}
# Kubernetes Secret for Laravel Application
resource "kubernetes_secret" "app_secrets" {
metadata {
name = "${var.app_name}-secrets"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
data = {
APP_KEY = var.app_key
}
type = "Opaque"
}
# Kubernetes ConfigMap for Laravel Application
resource "kubernetes_config_map" "app_config" {
metadata {
name = "${var.app_name}-config"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
data = {
APP_NAME = var.app_name
APP_ENV = var.app_env
APP_DEBUG = tostring(var.app_debug)
APP_URL = local.app_url
APP_LOCALE = "en"
APP_FALLBACK_LOCALE = "en"
APP_FAKER_LOCALE = "en_US"
LOG_CHANNEL = "stack"
LOG_STACK = "single"
LOG_LEVEL = "info"
SESSION_DRIVER = "database"
SESSION_CONNECTION = "pgsql"
SESSION_LIFETIME = "120"
SESSION_ENCRYPT = "false"
CACHE_STORE = "database"
QUEUE_CONNECTION = "database"
BROADCAST_CONNECTION = "log"
FILESYSTEM_DISK = "local"
MAIL_MAILER = "log"
VITE_APP_NAME = var.app_name
}
}
# Kubernetes Deployment for Laravel Application
resource "kubernetes_deployment" "app" {
metadata {
name = var.app_name
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
spec {
replicas = var.app_replicas
selector {
match_labels = {
app = var.app_name
}
}
template {
metadata {
labels = merge(
local.common_labels,
{
version = "latest"
}
)
}
spec {
image_pull_secrets {
name = "acr-secret"
}
container {
name = var.app_name
image = var.docker_image
port {
name = "http"
container_port = 80
protocol = "TCP"
}
env_from {
config_map_ref {
name = kubernetes_config_map.app_config.metadata[0].name
}
}
env_from {
secret_ref {
name = kubernetes_secret.app_secrets.metadata[0].name
}
}
env_from {
secret_ref {
name = kubernetes_secret.db_credentials.metadata[0].name
}
}
resources {
requests = {
cpu = var.app_resources_requests_cpu
memory = var.app_resources_requests_memory
}
limits = {
cpu = var.app_resources_limits_cpu
memory = var.app_resources_limits_memory
}
}
liveness_probe {
exec {
command = ["sh", "-c", "ps aux | grep -v grep | grep -q nginx && ps aux | grep -v grep | grep -q php-fpm"]
}
initial_delay_seconds = 30
period_seconds = 10
timeout_seconds = 5
failure_threshold = 3
}
readiness_probe {
exec {
command = ["sh", "-c", "ps aux | grep -v grep | grep -q nginx && ps aux | grep -v grep | grep -q php-fpm"]
}
initial_delay_seconds = 10
period_seconds = 5
timeout_seconds = 3
failure_threshold = 3
}
}
restart_policy = "Always"
}
}
strategy {
type = "RollingUpdate"
rolling_update {
max_surge = "1"
max_unavailable = "0"
}
}
}
depends_on = [
kubernetes_secret.db_credentials,
kubernetes_secret.app_secrets,
kubernetes_config_map.app_config
]
}
# Kubernetes Service for Laravel Application
resource "kubernetes_service" "app" {
metadata {
name = var.app_name
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
spec {
selector = {
app = var.app_name
}
port {
name = "http"
port = 80
target_port = 80
protocol = "TCP"
}
type = "ClusterIP"
}
depends_on = [
kubernetes_deployment.app
]
}
# Horizontal Pod Autoscaler
resource "kubernetes_horizontal_pod_autoscaler_v2" "app" {
metadata {
name = "${var.app_name}-hpa"
namespace = kubernetes_namespace.app.metadata[0].name
labels = local.common_labels
}
spec {
scale_target_ref {
api_version = "apps/v1"
kind = "Deployment"
name = kubernetes_deployment.app.metadata[0].name
}
min_replicas = var.app_replicas
max_replicas = var.app_replicas * 3
metric {
type = "Resource"
resource {
name = "cpu"
target {
type = "Utilization"
average_utilization = 80
}
}
}
metric {
type = "Resource"
resource {
name = "memory"
target {
type = "Utilization"
average_utilization = 80
}
}
}
}
}