add pod dependency management via Kyverno init container injection

Kyverno ClusterPolicy reads dependency.kyverno.io/wait-for annotation
and injects busybox init containers that block until each dependency
is reachable (nc -z). Annotations added to 18 stacks (24 deployments).

Includes graceful-db-maintenance.sh script for planned DB maintenance
(scales dependents to 0, saves replica counts, restores on startup).
This commit is contained in:
Viktor Barzin 2026-03-15 19:17:44 +00:00
parent dc274ab413
commit 0f262ceda3
22 changed files with 282 additions and 4 deletions

View file

@ -112,6 +112,9 @@ resource "kubernetes_deployment" "affine" {
labels = {
app = "affine"
}
annotations = {
"dependency.kyverno.io/wait-for" = "postgresql.dbaas:5432,redis.redis:6379"
}
}
spec {
# Init container to run database migrations

View file

@ -117,6 +117,9 @@ resource "kubernetes_deployment" "claude-memory" {
labels = {
app = "claude-memory"
}
annotations = {
"dependency.kyverno.io/wait-for" = "postgresql.dbaas:5432"
}
}
spec {
affinity {

View file

@ -84,6 +84,7 @@ resource "kubernetes_deployment" "dawarich" {
annotations = {
# "diun.enable" = "true"
# "diun.include_tags" = "latest"
"dependency.kyverno.io/wait-for" = "postgresql.dbaas:5432,redis.redis:6379"
}
}
spec {

View file

@ -137,6 +137,9 @@ resource "kubernetes_deployment" "grampsweb" {
labels = {
app = "grampsweb"
}
annotations = {
"dependency.kyverno.io/wait-for" = "redis.redis:6379"
}
}
spec {
container {

View file

@ -57,6 +57,9 @@ resource "kubernetes_deployment" "hackmd" {
app = "hackmd"
"kubernetes.io/cluster-service" = "true"
}
annotations = {
"dependency.kyverno.io/wait-for" = "mysql.dbaas:3306"
}
}
spec {
# container {

View file

@ -52,6 +52,9 @@ resource "kubernetes_deployment" "health" {
labels = {
app = "health"
}
annotations = {
"dependency.kyverno.io/wait-for" = "postgresql.dbaas:5432"
}
}
spec {
container {

View file

@ -58,6 +58,9 @@ resource "kubernetes_deployment" "immich-frame" {
labels = {
app = "immich-frame"
}
annotations = {
"dependency.kyverno.io/wait-for" = "immich-server.immich:2283"
}
}
spec {
container {

View file

@ -87,8 +87,9 @@ resource "kubernetes_deployment" "linkwarden" {
app = "linkwarden"
}
annotations = {
"diun.enable" = "false"
"diun.include_tags" = "latest"
"diun.enable" = "false"
"diun.include_tags" = "latest"
"dependency.kyverno.io/wait-for" = "postgresql.dbaas:5432"
}
}
spec {

View file

@ -50,6 +50,9 @@ resource "kubernetes_deployment" "matrix" {
labels = {
app = "matrix"
}
annotations = {
"dependency.kyverno.io/wait-for" = "postgresql.dbaas:5432"
}
}
spec {
init_container {

View file

@ -122,6 +122,9 @@ resource "kubernetes_deployment" "n8n" {
labels = {
app = "n8n"
}
annotations = {
"dependency.kyverno.io/wait-for" = "postgresql.dbaas:5432"
}
}
spec {
service_account_name = kubernetes_service_account.n8n.metadata[0].name

View file

@ -98,6 +98,7 @@ readinessProbe:
podAnnotations:
diun.enable: "true"
diun.include_tags: "^[0-9]+(?:.[0-9]+)?(?:.[0-9]+)?.*"
dependency.kyverno.io/wait-for: "mysql.dbaas:3306,redis.redis:6379"
collabora:
enabled: false # Using onlyoffice instead

View file

@ -248,6 +248,9 @@ resource "kubernetes_deployment" "ollama-ui" {
labels = {
app = "ollama-ui"
}
annotations = {
"dependency.kyverno.io/wait-for" = "ollama.ollama:11434"
}
}
spec {
container {

View file

@ -123,6 +123,9 @@ resource "kubernetes_deployment" "onlyoffice-document-server" {
labels = {
app = "onlyoffice-document-server"
}
annotations = {
"dependency.kyverno.io/wait-for" = "mysql.dbaas:3306,redis.redis:6379"
}
}
spec {
container {

View file

@ -97,8 +97,9 @@ resource "kubernetes_deployment" "paperless-ngx" {
app = "paperless-ngx"
}
annotations = {
"diun.enable" = "false"
"diun.include_tags" = "^\\d+(?:\\.\\d+)?(?:\\.\\d+)?$"
"diun.enable" = "false"
"diun.include_tags" = "^\\d+(?:\\.\\d+)?(?:\\.\\d+)?$"
"dependency.kyverno.io/wait-for" = "mysql.dbaas:3306,redis.redis:6379"
}
}
spec {

View file

@ -0,0 +1,72 @@
# =============================================================================
# Pod Dependency Init Container Injection
# =============================================================================
# Reads the annotation dependency.kyverno.io/wait-for from pods and injects
# init containers that wait for each listed dependency to be reachable.
#
# Usage:
# annotations:
# dependency.kyverno.io/wait-for: "postgresql.dbaas:5432,redis.redis:6379"
#
# Each comma-separated entry becomes a busybox init container that runs
# `nc -z <host> <port>` in a loop until the dependency is reachable.
# Existing init containers are preserved Kyverno appends to the array.
resource "kubernetes_manifest" "inject_dependency_init_containers" {
manifest = {
apiVersion = "kyverno.io/v1"
kind = "ClusterPolicy"
metadata = {
name = "inject-dependency-init-containers"
annotations = {
"policies.kyverno.io/title" = "Inject Dependency Init Containers"
"policies.kyverno.io/description" = "Injects wait-for init containers based on dependency.kyverno.io/wait-for pod annotation. Each comma-separated host:port entry becomes a busybox init container that blocks until the dependency is reachable via nc -z."
}
}
spec = {
rules = [
{
name = "wait-for-dependencies"
match = {
any = [
{
resources = {
kinds = ["Pod"]
operations = ["CREATE"]
}
}
]
}
preconditions = {
all = [
{
key = "{{ request.object.metadata.annotations.\"dependency.kyverno.io/wait-for\" || '' }}"
operator = "NotEquals"
value = ""
}
]
}
mutate = {
foreach = [
{
list = "request.object.metadata.annotations.\"dependency.kyverno.io/wait-for\" | split(@, ',')"
patchStrategicMerge = {
spec = {
initContainers = [
{
name = "wait-for-{{ element | split(@, ':') | [0] | replace_all(@, '.', '-') }}"
image = "busybox:1.37"
command = ["sh", "-c", "until nc -z {{ element | split(@, ':') | [0] }} {{ element | split(@, ':') | [1] }}; do echo waiting for {{ element }}; sleep 2; done"]
}
]
}
}
}
]
}
}
]
}
}
}

View file

@ -18,6 +18,8 @@ topologySpreadConstraints:
labelSelector:
matchLabels:
app.kubernetes.io/name: grafana
podAnnotations:
dependency.kyverno.io/wait-for: "mysql.dbaas:3306"
podDisruptionBudget:
maxUnavailable: 1
persistence:

View file

@ -142,6 +142,9 @@ resource "kubernetes_deployment" "realestate-crawler-api" {
app = "realestate-crawler-api"
"kubernetes.io/cluster-service" = "true"
}
annotations = {
"dependency.kyverno.io/wait-for" = "mysql.dbaas:3306,redis.redis:6379"
}
}
spec {
container {
@ -316,6 +319,9 @@ resource "kubernetes_deployment" "realestate-crawler-celery" {
labels = {
app = "realestate-crawler-celery"
}
annotations = {
"dependency.kyverno.io/wait-for" = "mysql.dbaas:3306,redis.redis:6379"
}
}
spec {
container {
@ -430,6 +436,9 @@ resource "kubernetes_deployment" "realestate-crawler-celery-beat" {
labels = {
app = "realestate-crawler-celery-beat"
}
annotations = {
"dependency.kyverno.io/wait-for" = "mysql.dbaas:3306,redis.redis:6379"
}
}
spec {
container {

View file

@ -252,6 +252,9 @@ resource "kubernetes_deployment" "rybbit" {
labels = {
app = "rybbit"
}
annotations = {
"dependency.kyverno.io/wait-for" = "postgresql.dbaas:5432,clickhouse.rybbit:8123"
}
}
spec {
container {
@ -404,6 +407,9 @@ resource "kubernetes_deployment" "rybbit-client" {
labels = {
app = "rybbit-client"
}
annotations = {
"dependency.kyverno.io/wait-for" = "rybbit.rybbit:3001"
}
}
spec {
container {

View file

@ -83,6 +83,9 @@ resource "kubernetes_deployment" "speedtest" {
labels = {
app = "speedtest"
}
annotations = {
"dependency.kyverno.io/wait-for" = "mysql.dbaas:3306"
}
}
spec {
container {

View file

@ -95,6 +95,9 @@ resource "kubernetes_deployment" "tandoor" {
labels = {
app = "tandoor"
}
annotations = {
"dependency.kyverno.io/wait-for" = "postgresql.dbaas:5432"
}
}
spec {
container {

View file

@ -207,6 +207,9 @@ resource "kubernetes_deployment" "trading-bot-frontend" {
labels = {
app = "trading-bot-frontend"
}
annotations = {
"dependency.kyverno.io/wait-for" = "postgresql.dbaas:5432,redis.redis:6379"
}
}
spec {
container {
@ -299,6 +302,9 @@ resource "kubernetes_deployment" "trading-bot-workers" {
labels = {
app = "trading-bot-workers"
}
annotations = {
"dependency.kyverno.io/wait-for" = "postgresql.dbaas:5432,redis.redis:6379"
}
}
spec {
container {