add pvc-autoresizer for automatic PVC expansion before volumes fill up [ci skip]

Deploy topolvm/pvc-autoresizer controller that monitors kubelet_volume_stats
via Prometheus and auto-expands annotated PVCs. Annotated all 9 block-storage
PVCs (proxmox-lvm) with per-PVC thresholds and max limits. Updated PVFillingUp
alert to critical/10m (means auto-expansion failed) and added PVAutoExpanding
info alert at 80%.
This commit is contained in:
Viktor Barzin 2026-04-03 23:30:00 +03:00
parent b2cac8cc97
commit ce7b8c2b2e
12 changed files with 113 additions and 3 deletions

View file

@ -157,6 +157,13 @@ resource "helm_release" "mysql_cluster" {
datadirVolumeClaimTemplate = {
storageClassName = "proxmox-lvm"
metadata = {
annotations = {
"resize.topolvm.io/threshold" = "80%"
"resize.topolvm.io/increase" = "20%"
"resize.topolvm.io/storage_limit" = "100Gi"
}
}
resources = {
requests = {
storage = "30Gi"
@ -897,6 +904,11 @@ resource "null_resource" "pg_cluster" {
search_path: '"$user", public'
enableAlterSystem: true
enableSuperuserAccess: true
inheritedMetadata:
annotations:
resize.topolvm.io/threshold: "80%"
resize.topolvm.io/increase: "20%"
resize.topolvm.io/storage_limit: "100Gi"
storage:
size: 20Gi
storageClass: proxmox-lvm

View file

@ -145,6 +145,11 @@ resource "kubernetes_persistent_volume_claim" "calibre_config_iscsi" {
metadata {
name = "ebooks-calibre-config-proxmox"
namespace = kubernetes_namespace.ebooks.metadata[0].name
annotations = {
"resize.topolvm.io/threshold" = "80%"
"resize.topolvm.io/increase" = "50%"
"resize.topolvm.io/storage_limit" = "10Gi"
}
}
spec {
access_modes = ["ReadWriteOnce"]

View file

@ -4,6 +4,11 @@ resource "kubernetes_persistent_volume_claim" "prometheus_server_pvc" {
metadata {
name = "prometheus-data-proxmox"
namespace = kubernetes_namespace.monitoring.metadata[0].name
annotations = {
"resize.topolvm.io/threshold" = "90%"
"resize.topolvm.io/increase" = "10%"
"resize.topolvm.io/storage_limit" = "500Gi"
}
}
spec {

View file

@ -801,13 +801,20 @@ serverFiles:
severity: warning
annotations:
summary: "Disk {{ $labels.mountpoint }} on {{ $labels.instance }}: {{ $value | printf \"%.1f\" }}% free (threshold: 10%)"
- alert: PVAutoExpanding
expr: (kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes) * 100 > 80 and kubelet_volume_stats_capacity_bytes < 1099511627776
for: 5m
labels:
severity: info
annotations:
summary: "PV {{ $labels.persistentvolumeclaim }} in {{ $labels.namespace }}: {{ $value | printf \"%.0f\" }}% used — auto-expansion should trigger"
- alert: PVFillingUp
expr: (kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes) * 100 > 95 and kubelet_volume_stats_capacity_bytes < 1099511627776
for: 30m
for: 10m
labels:
severity: warning
severity: critical
annotations:
summary: "PV {{ $labels.persistentvolumeclaim }} in {{ $labels.namespace }}: {{ $value | printf \"%.0f\" }}% used (threshold: 95%)"
summary: "PV {{ $labels.persistentvolumeclaim }} in {{ $labels.namespace }}: {{ $value | printf \"%.0f\" }}% used — auto-expansion may have failed"
- alert: PVPredictedFull
expr: predict_linear(kubelet_volume_stats_used_bytes[6h], 3600*24) > kubelet_volume_stats_capacity_bytes
for: 1h

View file

@ -188,6 +188,11 @@ resource "kubernetes_persistent_volume_claim" "nextcloud_data_iscsi" {
metadata {
name = "nextcloud-data-proxmox"
namespace = kubernetes_namespace.nextcloud.metadata[0].name
annotations = {
"resize.topolvm.io/threshold" = "80%"
"resize.topolvm.io/increase" = "20%"
"resize.topolvm.io/storage_limit" = "100Gi"
}
}
spec {
access_modes = ["ReadWriteOnce"]

View file

@ -50,6 +50,11 @@ resource "kubernetes_persistent_volume_claim" "novelapp-data" {
metadata {
name = "novelapp-data-proxmox"
namespace = kubernetes_namespace.novelapp.metadata[0].name
annotations = {
"resize.topolvm.io/threshold" = "80%"
"resize.topolvm.io/increase" = "100%"
"resize.topolvm.io/storage_limit" = "5Gi"
}
}
spec {
access_modes = ["ReadWriteOnce"]

View file

@ -50,6 +50,11 @@ resource "kubernetes_persistent_volume_claim" "plotting-book-data" {
metadata {
name = "plotting-book-data-proxmox"
namespace = kubernetes_namespace.plotting-book.metadata[0].name
annotations = {
"resize.topolvm.io/threshold" = "80%"
"resize.topolvm.io/increase" = "100%"
"resize.topolvm.io/storage_limit" = "5Gi"
}
}
spec {
access_modes = ["ReadWriteOnce"]

View file

@ -0,0 +1,4 @@
module "pvc_autoresizer" {
source = "./modules/pvc-autoresizer"
tier = local.tiers.cluster
}

View file

@ -0,0 +1,39 @@
variable "tier" { type = string }
resource "kubernetes_namespace" "pvc_autoresizer" {
metadata {
name = "pvc-autoresizer"
labels = {
tier = var.tier
}
}
}
resource "helm_release" "pvc_autoresizer" {
namespace = kubernetes_namespace.pvc_autoresizer.metadata[0].name
create_namespace = false
name = "pvc-autoresizer"
atomic = true
timeout = 300
repository = "https://topolvm.github.io/pvc-autoresizer"
chart = "pvc-autoresizer"
values = [yamlencode({
controller = {
args = {
prometheusURL = "http://prometheus-server.monitoring.svc.cluster.local:80"
interval = "10m"
}
resources = {
requests = {
memory = "64Mi"
cpu = "10m"
}
limits = {
memory = "128Mi"
}
}
}
})]
}

View file

@ -0,0 +1,8 @@
include "root" {
path = find_in_parent_folders()
}
dependency "infra" {
config_path = "../infra"
skip_outputs = true
}

View file

@ -61,6 +61,11 @@ resource "helm_release" "redis" {
enabled = true
storageClass = "proxmox-lvm"
size = "2Gi"
annotations = {
"resize.topolvm.io/threshold" = "80%"
"resize.topolvm.io/increase" = "50%"
"resize.topolvm.io/storage_limit" = "10Gi"
}
}
resources = {
@ -81,6 +86,11 @@ resource "helm_release" "redis" {
enabled = true
storageClass = "proxmox-lvm"
size = "2Gi"
annotations = {
"resize.topolvm.io/threshold" = "80%"
"resize.topolvm.io/increase" = "50%"
"resize.topolvm.io/storage_limit" = "10Gi"
}
}
resources = {

View file

@ -24,6 +24,11 @@ resource "kubernetes_persistent_volume_claim" "vaultwarden_data" {
metadata {
name = "vaultwarden-data-proxmox"
namespace = kubernetes_namespace.vaultwarden.metadata[0].name
annotations = {
"resize.topolvm.io/threshold" = "80%"
"resize.topolvm.io/increase" = "100%"
"resize.topolvm.io/storage_limit" = "5Gi"
}
}
spec {
access_modes = ["ReadWriteOnce"]