migrate iSCSI block volumes from democratic-csi to Proxmox CSI [ci skip]
Replace TrueNAS iSCSI (democratic-csi) with Proxmox CSI plugin for all block storage PVCs. Eliminates double-CoW (ZFS + LVM-thin) and removes the iSCSI network hop for database I/O. New stack: stacks/proxmox-csi/ — deploys proxmox-csi-plugin Helm chart with StorageClass "proxmox-lvm" using existing local-lvm thin pool. Migrated PVCs (12 total): - Phase 1 standalone: plotting-book, novelapp, vaultwarden, nextcloud, prometheus - Phase 2 StatefulSets: CNPG PostgreSQL (2), MySQL InnoDB (3), Redis (2) All services verified healthy post-migration.
This commit is contained in:
parent
337da2184d
commit
dd59512153
14 changed files with 154 additions and 21 deletions
|
|
@ -156,7 +156,7 @@ resource "helm_release" "mysql_cluster" {
|
||||||
}
|
}
|
||||||
|
|
||||||
datadirVolumeClaimTemplate = {
|
datadirVolumeClaimTemplate = {
|
||||||
storageClassName = "iscsi-truenas"
|
storageClassName = "proxmox-lvm"
|
||||||
resources = {
|
resources = {
|
||||||
requests = {
|
requests = {
|
||||||
storage = "30Gi"
|
storage = "30Gi"
|
||||||
|
|
@ -189,7 +189,7 @@ resource "helm_release" "mysql_cluster" {
|
||||||
memory = "2Gi"
|
memory = "2Gi"
|
||||||
}
|
}
|
||||||
limits = {
|
limits = {
|
||||||
memory = "5Gi"
|
memory = "4Gi"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,7 +225,7 @@ resource "helm_release" "mysql_cluster" {
|
||||||
cpu = "250m"
|
cpu = "250m"
|
||||||
}
|
}
|
||||||
limits = {
|
limits = {
|
||||||
memory = "5Gi"
|
memory = "4Gi"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
|
|
@ -876,7 +876,7 @@ resource "null_resource" "pg_cluster" {
|
||||||
instances = "2"
|
instances = "2"
|
||||||
image = "ghcr.io/cloudnative-pg/postgis:16"
|
image = "ghcr.io/cloudnative-pg/postgis:16"
|
||||||
storage_size = "20Gi"
|
storage_size = "20Gi"
|
||||||
storage_class = "iscsi-truenas"
|
storage_class = "proxmox-lvm"
|
||||||
memory_limit = "512Mi"
|
memory_limit = "512Mi"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -899,7 +899,7 @@ resource "null_resource" "pg_cluster" {
|
||||||
enableSuperuserAccess: true
|
enableSuperuserAccess: true
|
||||||
storage:
|
storage:
|
||||||
size: 20Gi
|
size: 20Gi
|
||||||
storageClass: iscsi-truenas
|
storageClass: proxmox-lvm
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: "50m"
|
cpu: "50m"
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
resource "kubernetes_persistent_volume_claim" "prometheus_server_pvc" {
|
resource "kubernetes_persistent_volume_claim" "prometheus_server_pvc" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "prometheus-data"
|
name = "prometheus-data-proxmox"
|
||||||
namespace = kubernetes_namespace.monitoring.metadata[0].name
|
namespace = kubernetes_namespace.monitoring.metadata[0].name
|
||||||
}
|
}
|
||||||
|
|
||||||
spec {
|
spec {
|
||||||
access_modes = ["ReadWriteOnce"]
|
access_modes = ["ReadWriteOnce"]
|
||||||
storage_class_name = "iscsi-truenas"
|
storage_class_name = "proxmox-lvm"
|
||||||
resources {
|
resources {
|
||||||
requests = {
|
requests = {
|
||||||
storage = "200Gi"
|
storage = "200Gi"
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ server:
|
||||||
- "storage.tsdb.wal-compression"
|
- "storage.tsdb.wal-compression"
|
||||||
persistentVolume:
|
persistentVolume:
|
||||||
# enabled: false
|
# enabled: false
|
||||||
existingClaim: prometheus-data
|
existingClaim: prometheus-data-proxmox
|
||||||
# storageClass: rook-cephfs
|
# storageClass: rook-cephfs
|
||||||
retention: "52w"
|
retention: "52w"
|
||||||
# NOTE: Memory must be >= 4Gi. The WAL tmpfs (2Gi, medium: Memory) shares
|
# NOTE: Memory must be >= 4Gi. The WAL tmpfs (2Gi, medium: Memory) shares
|
||||||
|
|
|
||||||
|
|
@ -186,12 +186,12 @@ resource "kubernetes_config_map" "apache_tuning" {
|
||||||
|
|
||||||
resource "kubernetes_persistent_volume_claim" "nextcloud_data_iscsi" {
|
resource "kubernetes_persistent_volume_claim" "nextcloud_data_iscsi" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "nextcloud-data-iscsi"
|
name = "nextcloud-data-proxmox"
|
||||||
namespace = kubernetes_namespace.nextcloud.metadata[0].name
|
namespace = kubernetes_namespace.nextcloud.metadata[0].name
|
||||||
}
|
}
|
||||||
spec {
|
spec {
|
||||||
access_modes = ["ReadWriteOnce"]
|
access_modes = ["ReadWriteOnce"]
|
||||||
storage_class_name = "iscsi-truenas"
|
storage_class_name = "proxmox-lvm"
|
||||||
resources {
|
resources {
|
||||||
requests = {
|
requests = {
|
||||||
storage = "20Gi"
|
storage = "20Gi"
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,12 @@ module "tls_secret" {
|
||||||
|
|
||||||
resource "kubernetes_persistent_volume_claim" "novelapp-data" {
|
resource "kubernetes_persistent_volume_claim" "novelapp-data" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "novelapp-data"
|
name = "novelapp-data-proxmox"
|
||||||
namespace = kubernetes_namespace.novelapp.metadata[0].name
|
namespace = kubernetes_namespace.novelapp.metadata[0].name
|
||||||
}
|
}
|
||||||
spec {
|
spec {
|
||||||
access_modes = ["ReadWriteOnce"]
|
access_modes = ["ReadWriteOnce"]
|
||||||
storage_class_name = "iscsi-truenas"
|
storage_class_name = "proxmox-lvm"
|
||||||
resources {
|
resources {
|
||||||
requests = {
|
requests = {
|
||||||
storage = "1Gi"
|
storage = "1Gi"
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
resource "kubernetes_persistent_volume_claim" "prometheus_server_pvc" {
|
resource "kubernetes_persistent_volume_claim" "prometheus_server_pvc" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "prometheus-data"
|
name = "prometheus-data-proxmox"
|
||||||
namespace = kubernetes_namespace.monitoring.metadata[0].name
|
namespace = kubernetes_namespace.monitoring.metadata[0].name
|
||||||
}
|
}
|
||||||
|
|
||||||
spec {
|
spec {
|
||||||
access_modes = ["ReadWriteOnce"]
|
access_modes = ["ReadWriteOnce"]
|
||||||
storage_class_name = "iscsi-truenas"
|
storage_class_name = "proxmox-lvm"
|
||||||
resources {
|
resources {
|
||||||
requests = {
|
requests = {
|
||||||
storage = "200Gi"
|
storage = "200Gi"
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ server:
|
||||||
- "storage.tsdb.wal-compression"
|
- "storage.tsdb.wal-compression"
|
||||||
persistentVolume:
|
persistentVolume:
|
||||||
# enabled: false
|
# enabled: false
|
||||||
existingClaim: prometheus-data
|
existingClaim: prometheus-data-proxmox
|
||||||
# storageClass: rook-cephfs
|
# storageClass: rook-cephfs
|
||||||
retention: "52w"
|
retention: "52w"
|
||||||
resources:
|
resources:
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,12 @@ module "tls_secret" {
|
||||||
|
|
||||||
resource "kubernetes_persistent_volume_claim" "plotting-book-data" {
|
resource "kubernetes_persistent_volume_claim" "plotting-book-data" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "plotting-book-data"
|
name = "plotting-book-data-proxmox"
|
||||||
namespace = kubernetes_namespace.plotting-book.metadata[0].name
|
namespace = kubernetes_namespace.plotting-book.metadata[0].name
|
||||||
}
|
}
|
||||||
spec {
|
spec {
|
||||||
access_modes = ["ReadWriteOnce"]
|
access_modes = ["ReadWriteOnce"]
|
||||||
storage_class_name = "iscsi-truenas"
|
storage_class_name = "proxmox-lvm"
|
||||||
resources {
|
resources {
|
||||||
requests = {
|
requests = {
|
||||||
storage = "1Gi"
|
storage = "1Gi"
|
||||||
|
|
|
||||||
16
stacks/proxmox-csi/main.tf
Normal file
16
stacks/proxmox-csi/main.tf
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
variable "nfs_server" { type = string }
|
||||||
|
|
||||||
|
data "vault_kv_secret_v2" "secrets" {
|
||||||
|
mount = "secret"
|
||||||
|
name = "viktor"
|
||||||
|
}
|
||||||
|
|
||||||
|
module "proxmox-csi" {
|
||||||
|
source = "./modules/proxmox-csi"
|
||||||
|
tier = local.tiers.cluster
|
||||||
|
proxmox_url = "https://192.168.1.127:8006/api2/json"
|
||||||
|
proxmox_token_id = data.vault_kv_secret_v2.secrets.data["proxmox_csi_token_id"]
|
||||||
|
proxmox_token_secret = data.vault_kv_secret_v2.secrets.data["proxmox_csi_token_secret"]
|
||||||
|
proxmox_cluster_name = "pve"
|
||||||
|
kube_config_path = var.kube_config_path
|
||||||
|
}
|
||||||
91
stacks/proxmox-csi/modules/proxmox-csi/main.tf
Normal file
91
stacks/proxmox-csi/modules/proxmox-csi/main.tf
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
resource "kubernetes_namespace" "proxmox_csi" {
|
||||||
|
metadata {
|
||||||
|
name = "proxmox-csi"
|
||||||
|
labels = {
|
||||||
|
tier = var.tier
|
||||||
|
"resource-governance/custom-quota" = "true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "helm_release" "proxmox_csi" {
|
||||||
|
namespace = kubernetes_namespace.proxmox_csi.metadata[0].name
|
||||||
|
create_namespace = false
|
||||||
|
name = "proxmox-csi-plugin"
|
||||||
|
atomic = true
|
||||||
|
timeout = 300
|
||||||
|
|
||||||
|
repository = "oci://ghcr.io/sergelogvinov/charts"
|
||||||
|
chart = "proxmox-csi-plugin"
|
||||||
|
|
||||||
|
values = [yamlencode({
|
||||||
|
config = {
|
||||||
|
clusters = [{
|
||||||
|
url = var.proxmox_url
|
||||||
|
insecure = true
|
||||||
|
token_id = var.proxmox_token_id
|
||||||
|
token_secret = var.proxmox_token_secret
|
||||||
|
region = var.proxmox_cluster_name
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
# StorageClass for block volumes on existing HDD thin pool
|
||||||
|
storageClass = [{
|
||||||
|
name = "proxmox-lvm"
|
||||||
|
storage = "local-lvm"
|
||||||
|
reclaimPolicy = "Retain"
|
||||||
|
fstype = "ext4"
|
||||||
|
ssd = false
|
||||||
|
cache = "none"
|
||||||
|
volumeBindingMode = "WaitForFirstConsumer"
|
||||||
|
allowVolumeExpansion = true
|
||||||
|
}]
|
||||||
|
|
||||||
|
controller = {
|
||||||
|
replicas = 2
|
||||||
|
resources = {
|
||||||
|
requests = { cpu = "10m", memory = "32Mi" }
|
||||||
|
limits = { memory = "64Mi" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node = {
|
||||||
|
resources = {
|
||||||
|
requests = { cpu = "10m", memory = "32Mi" }
|
||||||
|
limits = { memory = "64Mi" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Topology labels on K8s nodes — required for Proxmox CSI to map nodes to Proxmox VMs.
|
||||||
|
# region = Proxmox cluster name, zone = Proxmox node name (where the VM runs).
|
||||||
|
# All our VMs run on the single Proxmox node "pve".
|
||||||
|
locals {
|
||||||
|
k8s_nodes = {
|
||||||
|
"k8s-master" = { vmid = 200, proxmox_node = "pve" }
|
||||||
|
"k8s-node1" = { vmid = 201, proxmox_node = "pve" }
|
||||||
|
"k8s-node2" = { vmid = 202, proxmox_node = "pve" }
|
||||||
|
"k8s-node3" = { vmid = 203, proxmox_node = "pve" }
|
||||||
|
"k8s-node4" = { vmid = 204, proxmox_node = "pve" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "null_resource" "node_labels" {
|
||||||
|
for_each = local.k8s_nodes
|
||||||
|
|
||||||
|
provisioner "local-exec" {
|
||||||
|
command = <<-EOT
|
||||||
|
kubectl --kubeconfig=${var.kube_config_path} label node ${each.key} \
|
||||||
|
topology.kubernetes.io/region=${var.proxmox_cluster_name} \
|
||||||
|
topology.kubernetes.io/zone=${each.value.proxmox_node} \
|
||||||
|
node.csi.proxmox.sinextra.dev/name=${each.key} \
|
||||||
|
--overwrite
|
||||||
|
EOT
|
||||||
|
}
|
||||||
|
|
||||||
|
triggers = {
|
||||||
|
region = var.proxmox_cluster_name
|
||||||
|
zone = each.value.proxmox_node
|
||||||
|
}
|
||||||
|
}
|
||||||
18
stacks/proxmox-csi/modules/proxmox-csi/variables.tf
Normal file
18
stacks/proxmox-csi/modules/proxmox-csi/variables.tf
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
variable "tier" { type = string }
|
||||||
|
variable "proxmox_url" { type = string }
|
||||||
|
variable "proxmox_token_id" {
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
variable "proxmox_token_secret" {
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
variable "proxmox_cluster_name" {
|
||||||
|
type = string
|
||||||
|
default = "pve"
|
||||||
|
}
|
||||||
|
variable "kube_config_path" {
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
8
stacks/proxmox-csi/terragrunt.hcl
Normal file
8
stacks/proxmox-csi/terragrunt.hcl
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
include "root" {
|
||||||
|
path = find_in_parent_folders()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependency "infra" {
|
||||||
|
config_path = "../infra"
|
||||||
|
skip_outputs = true
|
||||||
|
}
|
||||||
|
|
@ -59,7 +59,7 @@ resource "helm_release" "redis" {
|
||||||
master = {
|
master = {
|
||||||
persistence = {
|
persistence = {
|
||||||
enabled = true
|
enabled = true
|
||||||
storageClass = "iscsi-truenas"
|
storageClass = "proxmox-lvm"
|
||||||
size = "2Gi"
|
size = "2Gi"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,7 +79,7 @@ resource "helm_release" "redis" {
|
||||||
|
|
||||||
persistence = {
|
persistence = {
|
||||||
enabled = true
|
enabled = true
|
||||||
storageClass = "iscsi-truenas"
|
storageClass = "proxmox-lvm"
|
||||||
size = "2Gi"
|
size = "2Gi"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,12 @@ module "tls_secret" {
|
||||||
|
|
||||||
resource "kubernetes_persistent_volume_claim" "vaultwarden_data" {
|
resource "kubernetes_persistent_volume_claim" "vaultwarden_data" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "vaultwarden-data-iscsi"
|
name = "vaultwarden-data-proxmox"
|
||||||
namespace = kubernetes_namespace.vaultwarden.metadata[0].name
|
namespace = kubernetes_namespace.vaultwarden.metadata[0].name
|
||||||
}
|
}
|
||||||
spec {
|
spec {
|
||||||
access_modes = ["ReadWriteOnce"]
|
access_modes = ["ReadWriteOnce"]
|
||||||
storage_class_name = "iscsi-truenas"
|
storage_class_name = "proxmox-lvm"
|
||||||
resources {
|
resources {
|
||||||
requests = {
|
requests = {
|
||||||
storage = "1Gi"
|
storage = "1Gi"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue