apiVersion: v1 kind: ConfigMap metadata: name: blocky-valkey-init-scripts labels: helm.sh/chart: valkey-0.9.3 app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky app.kubernetes.io/version: "9.0.3" app.kubernetes.io/managed-by: Helm data: init.sh: |- #!/bin/sh set -eu # Default config paths VALKEY_CONFIG=${VALKEY_CONFIG_PATH:-/data/conf/valkey.conf} LOGFILE="/data/init.log" DATA_DIR="/data/conf" # Logging function (outputs to stderr and file) log() { echo "$(date) $1" | tee -a "$LOGFILE" >&2 } # Clean old log if requested if [ "${KEEP_OLD_LOGS:-false}" != "true" ]; then rm -f "$LOGFILE" fi if [ -f "$LOGFILE" ]; then log "Detected restart of this instance ($HOSTNAME)" fi log "Creating configuration in $DATA_DIR..." mkdir -p "$DATA_DIR" rm -f "$VALKEY_CONFIG" # Base valkey.conf log "Generating base valkey.conf" { echo "port 6379" echo "protected-mode no" echo "bind * -::*" echo "dir /data" } >>"$VALKEY_CONFIG" # Replica mode configuration log "Configuring replication mode" # Use POD_INDEX from Kubernetes metadata POD_INDEX=${POD_INDEX:-0} IS_MASTER=false # Check if this is pod-0 (master) if [ "$POD_INDEX" = "0" ]; then IS_MASTER=true log "This pod (index $POD_INDEX) is configured as MASTER" else log "This pod (index $POD_INDEX) is configured as REPLICA" fi # Configure replica settings if [ "$IS_MASTER" = "false" ]; then MASTER_HOST="blocky-valkey-0.blocky-valkey-headless.blocky.svc.cluster.local" MASTER_PORT="6379" log "Configuring replica to follow master at $MASTER_HOST:$MASTER_PORT" { echo "" echo "# Replica Configuration" echo "replicaof $MASTER_HOST $MASTER_PORT" echo "replica-announce-ip blocky-valkey-$POD_INDEX.blocky-valkey-headless.blocky.svc.cluster.local" } >>"$VALKEY_CONFIG" fi # Append extra configs if present if [ -f /usr/local/etc/valkey/valkey.conf ]; then log "Appending /usr/local/etc/valkey/valkey.conf" cat /usr/local/etc/valkey/valkey.conf >>"$VALKEY_CONFIG" fi if [ -d /extravalkeyconfigs ]; then log "Appending files in /extravalkeyconfigs/" cat /extravalkeyconfigs/* >>"$VALKEY_CONFIG" fi --- apiVersion: v1 kind: ConfigMap metadata: name: blocky labels: app.kubernetes.io/instance: blocky app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: blocky helm.sh/chart: blocky-4.6.2 namespace: blocky data: config.yml: | upstreams: init: strategy: fast groups: default: - tcp-tls:1.1.1.1:853 - tcp-tls:1.0.0.1:853 strategy: parallel_best timeout: 2s connectIPVersion: v4 customDNS: filterUnmappedTypes: false zone: | $ORIGIN alexlebens.net. $TTL 86400 ;; Name Server IN NS patryk.ns.cloudflare.com. IN NS veda.ns.cloudflare.com. IN NS dns1. IN NS dns2. IN NS dns3. dns1 IN A 10.232.1.22 dns2 IN A 10.232.1.51 dns3 IN A 10.232.1.52 ;; Computer Names nw01un IN A 192.168.1.1 ; Unifi Gateway ps08rp IN A 10.232.1.51 ; DNS ps09rp IN A 10.232.1.52 ; DNS ps02sn IN A 10.232.1.61 ; Synology Web ps02sn-bond IN A 10.232.1.64 ; Synology Bond for Storage pd05wd IN A 10.230.0.115 ; Desktop pl02mc IN A 10.230.0.105 ; Laptop dv01hr IN A 10.232.1.72 ; HD Homerun dv02kv IN A 10.232.1.71 ; Pi KVM it01ag IN A 10.232.1.83 ; Airgradient it02ph IN A 10.232.1.85 ; Phillips Hue it03tb IN A 10.232.1.81 ; TubesZB ZigBee it04tb IN A 10.232.1.82 ; TubesZB Z-Wave it05sp IN A 10.230.0.100 ; Shelly Plug ;; Common Names synology IN CNAME ps02sn synologybond IN CNAME ps02sn-bond unifi IN CNAME nw01un airgradient IN CNAME it01ag hdhr IN CNAME dv01hr pikvm IN CNAME dv02kv ;; Service Names cl01tl IN A 10.232.1.11 cl01tl IN A 10.232.1.12 cl01tl IN A 10.232.1.13 cl01tl-api IN A 10.232.1.11 cl01tl-api IN A 10.232.1.12 cl01tl-api IN A 10.232.1.13 cl01tl-endpoint IN A 10.232.1.21 cl01tl-endpoint IN A 10.232.1.22 cl01tl-endpoint IN A 10.232.1.23 traefik-cl01tl IN A 10.232.1.21 blocky IN A 10.232.1.22 cilium-cl01tl IN A 10.232.1.23 ;; Application Names actual IN CNAME traefik-cl01tl alertmanager IN CNAME traefik-cl01tl argo-workflows IN CNAME traefik-cl01tl argocd IN CNAME traefik-cl01tl audiobookshelf IN CNAME traefik-cl01tl authentik IN CNAME traefik-cl01tl backrest IN CNAME traefik-cl01tl bazarr IN CNAME traefik-cl01tl booklore IN CNAME traefik-cl01tl ceph IN CNAME traefik-cl01tl code-server IN CNAME traefik-cl01tl dawarich IN CNAME traefik-cl01tl directus IN CNAME traefik-cl01tl excalidraw IN CNAME traefik-cl01tl feishin IN CNAME traefik-cl01tl garage-s3 IN CNAME traefik-cl01tl garage-webui IN CNAME traefik-cl01tl gatus IN CNAME traefik-cl01tl gitea IN CNAME traefik-cl01tl grafana IN CNAME traefik-cl01tl harbor IN CNAME traefik-cl01tl headlamp IN CNAME traefik-cl01tl home IN CNAME traefik-cl01tl home-assistant IN CNAME traefik-cl01tl home-assistant-code-server IN CNAME traefik-cl01tl hubble IN CNAME traefik-cl01tl immich IN CNAME traefik-cl01tl jellyfin IN CNAME traefik-cl01tl jellystat IN CNAME traefik-cl01tl kiwix IN CNAME traefik-cl01tl komodo IN CNAME traefik-cl01tl lidarr IN CNAME traefik-cl01tl mail IN CNAME traefik-cl01tl movie-roulette IN CNAME traefik-cl01tl music-grabber IN CNAME traefik-cl01tl navidrome IN CNAME traefik-cl01tl ntfy IN CNAME traefik-cl01tl objects IN CNAME traefik-cl01tl ollama IN CNAME traefik-cl01tl omni-tools IN CNAME traefik-cl01tl photoview IN CNAME traefik-cl01tl plex IN CNAME traefik-cl01tl postiz IN CNAME traefik-cl01tl prometheus IN CNAME traefik-cl01tl prowlarr IN CNAME traefik-cl01tl qbittorrent IN CNAME traefik-cl01tl qui IN CNAME traefik-cl01tl radarr IN CNAME traefik-cl01tl radarr-4k IN CNAME traefik-cl01tl radarr-anime IN CNAME traefik-cl01tl radarr-standup IN CNAME traefik-cl01tl searxng IN CNAME traefik-cl01tl seerr IN CNAME traefik-cl01tl shelfmark IN CNAME traefik-cl01tl slskd IN CNAME traefik-cl01tl sonarr IN CNAME traefik-cl01tl sonarr-4k IN CNAME traefik-cl01tl sonarr-anime IN CNAME traefik-cl01tl stalwart IN CNAME traefik-cl01tl tdarr IN CNAME traefik-cl01tl tubearchivist IN CNAME traefik-cl01tl vault IN CNAME traefik-cl01tl whodb IN CNAME traefik-cl01tl yamtrack IN CNAME traefik-cl01tl yubal IN CNAME traefik-cl01tl blocking: denylists: sus: - https://v.firebog.net/hosts/static/w3kbl.txt ads: - https://v.firebog.net/hosts/AdguardDNS.txt - https://v.firebog.net/hosts/Admiral.txt - https://v.firebog.net/hosts/Easylist.txt - https://adaway.org/hosts.txt priv: - https://v.firebog.net/hosts/Easyprivacy.txt - https://v.firebog.net/hosts/Prigent-Ads.txt mal: - https://v.firebog.net/hosts/Prigent-Crypto.txt pro: - https://raw.githubusercontent.com/hagezi/dns-blocklists/main/wildcard/pro.plus.txt oisd: - https://big.oisd.nl/domainswild allowlists: sus: - | *.alexlebens.net *.alexlebens.dev *.boreal-beaufort.ts.net *.discord.com cdn.trackjs.com ads: - | *.alexlebens.net *.alexlebens.dev *.boreal-beaufort.ts.net *.discord.com cdn.trackjs.com priv: - | *.alexlebens.net *.alexlebens.dev *.boreal-beaufort.ts.net *.discord.com cdn.trackjs.com mal: - | *.alexlebens.net *.alexlebens.dev *.boreal-beaufort.ts.net *.discord.com cdn.trackjs.com pro: - | *.alexlebens.net *.alexlebens.dev *.boreal-beaufort.ts.net *.discord.com cdn.trackjs.com oisd: - | *.alexlebens.net *.alexlebens.dev *.boreal-beaufort.ts.net *.discord.com cdn.trackjs.com clientGroupsBlock: default: - sus - ads - priv - mal - pro - oisd blockType: zeroIp blockTTL: 1m loading: refreshPeriod: 24h downloads: timeout: 60s attempts: 5 cooldown: 10s concurrency: 16 strategy: fast maxErrorsPerSource: 5 caching: minTime: 5m maxTime: 30m maxItemsCount: 0 prefetching: true prefetchExpires: 2h prefetchThreshold: 5 prefetchMaxItemsCount: 0 cacheTimeNegative: 30m redis: address: blocky-valkey.blocky:6379 required: true prometheus: enable: true path: /metrics queryLog: type: console logRetentionDays: 7 creationAttempts: 1 creationCooldown: 2s flushInterval: 30s minTlsServeVersion: 1.3 ports: dns: 53 http: 4000 log: level: info format: text timestamp: true privacy: false --- apiVersion: apps/v1 kind: Deployment metadata: name: blocky labels: app.kubernetes.io/controller: main app.kubernetes.io/instance: blocky app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: blocky helm.sh/chart: blocky-4.6.2 namespace: blocky spec: revisionHistoryLimit: 3 replicas: 3 strategy: type: RollingUpdate selector: matchLabels: app.kubernetes.io/controller: main app.kubernetes.io/name: blocky app.kubernetes.io/instance: blocky template: metadata: annotations: checksum/configMaps: 0507ebbebae473812f0ac690ba8a1b134615a71597698d395330ce6bfb9f4c21 labels: app.kubernetes.io/controller: main app.kubernetes.io/instance: blocky app.kubernetes.io/name: blocky spec: enableServiceLinks: false serviceAccountName: default automountServiceAccountToken: true hostIPC: false hostNetwork: false hostPID: false dnsPolicy: ClusterFirst containers: - env: - name: TZ value: US/Central image: ghcr.io/0xerr0r/blocky:v0.29.0@sha256:a6d99f323d3036a99a3767a52ad612f4d8f3f31167492bfc14d4ea57b24cdfd0 imagePullPolicy: IfNotPresent name: main resources: requests: cpu: 10m memory: 128Mi volumeMounts: - mountPath: /app/config.yml mountPropagation: None name: config readOnly: true subPath: config.yml volumes: - configMap: name: blocky name: config --- apiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: name: blocky-valkey labels: helm.sh/chart: valkey-0.9.3 app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky app.kubernetes.io/version: "9.0.3" app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: valkey app.kubernetes.io/component: podmonitor spec: podMetricsEndpoints: - port: metrics interval: 30s namespaceSelector: matchNames: - blocky selector: matchLabels: app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky --- apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: blocky-valkey labels: helm.sh/chart: valkey-0.9.3 app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky app.kubernetes.io/version: "9.0.3" app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: valkey spec: groups: - name: blocky-valkey rules: - alert: ValkeyDown annotations: description: Valkey instance {{ $labels.instance }} is down. summary: Valkey instance {{ $labels.instance }} down expr: | redis_up{service="blocky-valkey-metrics"} == 0 for: 2m labels: severity: error - alert: ValkeyMemoryHigh annotations: description: | Valkey instance {{ $labels.instance }} is using {{ $value }}% of its available memory. summary: Valkey instance {{ $labels.instance }} is using too much memory expr: | redis_memory_used_bytes{service="blocky-valkey-metrics"} * 100 / redis_memory_max_bytes{service="blocky-valkey-metrics"} > 90 <= 100 for: 2m labels: severity: error - alert: ValkeyKeyEviction annotations: description: | Valkey instance {{ $labels.instance }} has evicted {{ $value }} keys in the last 5 minutes. summary: Valkey instance {{ $labels.instance }} has evicted keys expr: | increase(redis_evicted_keys_total{service="blocky-valkey-metrics"}[5m]) > 0 for: 1s labels: severity: error --- apiVersion: v1 kind: Service metadata: name: blocky-dns-external labels: app.kubernetes.io/instance: blocky app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: blocky app.kubernetes.io/service: blocky-dns-external helm.sh/chart: blocky-4.6.2 annotations: tailscale.com/expose: "true" namespace: blocky spec: type: LoadBalancer ports: - port: 53 targetPort: 53 protocol: TCP name: tcp - port: 53 targetPort: 53 protocol: UDP name: udp selector: app.kubernetes.io/controller: main app.kubernetes.io/instance: blocky app.kubernetes.io/name: blocky --- apiVersion: v1 kind: Service metadata: name: blocky-metrics labels: app.kubernetes.io/instance: blocky app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: blocky app.kubernetes.io/service: blocky-metrics helm.sh/chart: blocky-4.6.2 namespace: blocky spec: type: ClusterIP ports: - port: 4000 targetPort: 4000 protocol: TCP name: metrics selector: app.kubernetes.io/controller: main app.kubernetes.io/instance: blocky app.kubernetes.io/name: blocky --- apiVersion: v1 kind: Service metadata: name: blocky-valkey-headless labels: helm.sh/chart: valkey-0.9.3 app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky app.kubernetes.io/version: "9.0.3" app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: headless spec: type: ClusterIP clusterIP: None publishNotReadyAddresses: true ports: - name: tcp port: 6379 targetPort: tcp protocol: TCP selector: app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky --- apiVersion: v1 kind: Service metadata: name: blocky-valkey-metrics labels: helm.sh/chart: valkey-0.9.3 app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky app.kubernetes.io/version: "9.0.3" app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: metrics app.kubernetes.io/part-of: valkey annotations: spec: type: ClusterIP ports: - name: metrics port: 9121 protocol: TCP targetPort: metrics selector: app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky --- apiVersion: v1 kind: Service metadata: name: blocky-valkey-read labels: helm.sh/chart: valkey-0.9.3 app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky app.kubernetes.io/version: "9.0.3" app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: read spec: type: ClusterIP ports: - name: tcp port: 6379 targetPort: tcp protocol: TCP selector: app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky --- apiVersion: v1 kind: Service metadata: name: blocky-valkey labels: helm.sh/chart: valkey-0.9.3 app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky app.kubernetes.io/version: "9.0.3" app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: primary spec: type: ClusterIP ports: - port: 6379 targetPort: tcp protocol: TCP name: tcp selector: app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky statefulset.kubernetes.io/pod-name: blocky-valkey-0 --- apiVersion: v1 kind: ServiceAccount metadata: name: blocky-valkey labels: helm.sh/chart: valkey-0.9.3 app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky app.kubernetes.io/version: "9.0.3" app.kubernetes.io/managed-by: Helm automountServiceAccountToken: false --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: blocky-valkey labels: helm.sh/chart: valkey-0.9.3 app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky app.kubernetes.io/version: "9.0.3" app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: valkey app.kubernetes.io/component: service-monitor spec: endpoints: - port: metrics interval: 30s namespaceSelector: matchNames: - blocky selector: matchLabels: app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky app.kubernetes.io/component: metrics --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: blocky labels: app.kubernetes.io/instance: blocky app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: blocky helm.sh/chart: blocky-4.6.2 namespace: blocky spec: jobLabel: blocky namespaceSelector: matchNames: - blocky selector: matchLabels: app.kubernetes.io/instance: blocky app.kubernetes.io/name: blocky endpoints: - interval: 30s path: /metrics port: metrics scheme: http scrapeTimeout: 10s --- apiVersion: apps/v1 kind: StatefulSet metadata: name: blocky-valkey labels: helm.sh/chart: valkey-0.9.3 app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky app.kubernetes.io/version: "9.0.3" app.kubernetes.io/managed-by: Helm spec: serviceName: blocky-valkey-headless replicas: 3 podManagementPolicy: OrderedReady selector: matchLabels: app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky volumeClaimTemplates: - metadata: name: valkey-data spec: accessModes: - ReadWriteOnce storageClassName: "ceph-block" resources: requests: storage: "1Gi" template: metadata: labels: app.kubernetes.io/name: valkey app.kubernetes.io/instance: blocky annotations: checksum/initconfig: "b997c0967aeeee370412add1d41691a1" spec: automountServiceAccountToken: false serviceAccountName: blocky-valkey securityContext: fsGroup: 1000 runAsGroup: 1000 runAsUser: 1000 initContainers: - name: blocky-valkey-init image: docker.io/valkey/valkey:9.0.3 imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1000 command: ["/scripts/init.sh"] env: - name: POD_INDEX valueFrom: fieldRef: fieldPath: metadata.labels['apps.kubernetes.io/pod-index'] volumeMounts: - name: valkey-data mountPath: /data - name: scripts mountPath: /scripts containers: - name: blocky-valkey image: docker.io/valkey/valkey:9.0.3 imagePullPolicy: IfNotPresent command: ["valkey-server"] args: ["/data/conf/valkey.conf"] securityContext: capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1000 env: - name: POD_INDEX valueFrom: fieldRef: fieldPath: metadata.labels['apps.kubernetes.io/pod-index'] - name: VALKEY_LOGLEVEL value: "notice" ports: - name: tcp containerPort: 6379 protocol: TCP startupProbe: exec: command: ["sh", "-c", "valkey-cli ping"] livenessProbe: exec: command: ["sh", "-c", "valkey-cli ping"] resources: requests: cpu: 10m memory: 128Mi volumeMounts: - name: valkey-data mountPath: /data - name: metrics image: ghcr.io/oliver006/redis_exporter:v1.82.0 imagePullPolicy: "IfNotPresent" ports: - name: metrics containerPort: 9121 startupProbe: tcpSocket: port: metrics livenessProbe: tcpSocket: port: metrics readinessProbe: httpGet: path: / port: metrics resources: requests: cpu: 10m memory: 64M env: - name: REDIS_ALIAS value: blocky-valkey volumes: - name: scripts configMap: name: blocky-valkey-init-scripts defaultMode: 0555