Add Kubernetes/K3s deployment manifests and documentation

- Complete k8s manifests with Kustomize support
- Production and staging overlays
- ConfigMap/Secret management
- Ingress with TLS (Traefik/NGINX)
- Persistent storage for SQLite
- Comprehensive k8s README with operations guide
- Updated main README with k8s deployment instructions
- Gitignore for k8s secrets

Usage:
  kubectl apply -k k8s/overlays/production
This commit is contained in:
2026-02-01 16:40:16 -05:00
parent 2470f121e2
commit f3f1c0a0c8
16 changed files with 692 additions and 1 deletions

13
k8s/base/configmap.yaml Normal file
View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: dyn-ddns-config
data:
SERVER_PORT: "8080"
DATABASE_PATH: "/data/dyn.db"
BASE_DOMAIN: "dws.rip"
SPACE_SUBDOMAIN: "space"
RATE_LIMIT_PER_IP: "10"
RATE_LIMIT_PER_TOKEN: "1"
# TECHNITIUM_URL: "https://dns.dws.rip"
# Add your Technitium URL above or in overlays

86
k8s/base/deployment.yaml Normal file
View File

@@ -0,0 +1,86 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: dyn-ddns
labels:
app: dyn-ddns
spec:
replicas: 1
selector:
matchLabels:
app: dyn-ddns
template:
metadata:
labels:
app: dyn-ddns
spec:
containers:
- name: dyn-ddns
image: git.dws.rip/DWS/dyn:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
name: http
envFrom:
- configMapRef:
name: dyn-ddns-config
- secretRef:
name: dyn-ddns-secrets
volumeMounts:
- name: data
mountPath: /data
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
volumes:
- name: data
persistentVolumeClaim:
claimName: dyn-ddns-data
---
apiVersion: v1
kind: Service
metadata:
name: dyn-ddns
labels:
app: dyn-ddns
spec:
selector:
app: dyn-ddns
ports:
- port: 80
targetPort: 8080
name: http
type: ClusterIP
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dyn-ddns-data
labels:
app: dyn-ddns
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

30
k8s/base/ingress.yaml Normal file
View File

@@ -0,0 +1,30 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dyn-ddns
annotations:
# Traefik
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
# NGINX (uncomment if using NGINX ingress)
# kubernetes.io/ingress.class: nginx
# cert-manager.io/cluster-issuer: "letsencrypt-prod"
# nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- dyn.dws.rip
secretName: dyn-ddns-tls
rules:
- host: dyn.dws.rip
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: dyn-ddns
port:
number: 80

View File

@@ -0,0 +1,17 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- configmap.yaml
- ingress.yaml
commonLabels:
app.kubernetes.io/name: dyn-ddns
app.kubernetes.io/part-of: dws-dns
namespace: default
images:
- name: git.dws.rip/DWS/dyn
newTag: latest

17
k8s/base/secrets.yaml Normal file
View File

@@ -0,0 +1,17 @@
apiVersion: v1
kind: Secret
metadata:
name: dyn-ddns-secrets
type: Opaque
stringData:
# Choose ONE authentication method:
# Method 1: API Token (recommended)
# TECHNITIUM_TOKEN: "your-api-token-here"
# Method 2: Username/Password
# TECHNITIUM_USERNAME: "admin"
# TECHNITIUM_PASSWORD: "your-password"
# Optional: Trusted proxies (comma-separated)
# TRUSTED_PROXIES: "10.0.0.0/8,172.16.0.0/12"