more code

This commit is contained in:
developer committed 2026-09-27 11:34:26 +00:00
1 parent f24fd63e9a
commit ee72257c64
29 files changed
+5636 -440

No files matched your search

+120
View File
@@ -0,0 +1,120 @@
apiVersion: v1
kind: Namespace
metadata:
name: dns
---
apiVersion: v1
kind: ConfigMap
metadata:
name: fancy-dns-config
namespace: dns
labels:
app.kubernetes.io/name: fancy-dns
data:
config.yaml: |
# Rendered by the deployment below; kept in a ConfigMap so a change is a
# `kubectl apply` rather than a rebuild.
server:
max_concurrent: 2048
timeouts:
upstream: 2s
list_fetch: 60s
dns:
udp: ["0.0.0.0:53", "[::]:53"]
tcp: ["0.0.0.0:53", "[::]:53"]
max_udp_size: 1232
dot:
enabled: true
listen: ["0.0.0.0:853"]
cert_file: /etc/fancy-dns/tls/tls.crt
key_file: /etc/fancy-dns/tls/tls.key
doh:
enabled: true
listen: ["0.0.0.0:443"]
cert_file: /etc/fancy-dns/tls/tls.crt
key_file: /etc/fancy-dns/tls/tls.key
base_path: /dns-query
upstream:
policy: parallel
max_attempts: 3
healthcheck_interval: 30s
servers:
- addr: 9.9.9.9:53
proto: udp
- addr: 1.1.1.1:53
proto: tls
server_name: cloudflare-dns.com
- addr: 9.9.9.9:853
proto: tls
server_name: dns.quad9.net
cache:
enabled: true
size: 500000
max_ttl: 1h
serve_stale: 30m
persist:
enabled: true
path: /var/lib/fancy-dns/cache.db
interval: 30s
blocklist:
enabled: true
default_action: nxdomain
local_zones: [/etc/fancy-dns/zones/*.zone]
lists:
- name: haas
format: plain
url: https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
path: /var/lib/fancy-dns/lists/hosts
enabled: true
refresh: 24h
categories: [ads, tracking]
acl:
default_policy: allow
groups: []
qlog:
enabled: true
path: /var/lib/fancy-dns/queries.db
max_entries: 200000
sample_rate: 1.0
log_blocked: true
log_cached: false
api:
enabled: true
listen: ["0.0.0.0:8080"]
base_path: /api
ui: true
allow_config_write: false
# Read the key from a Secret and mount it; the value here is a placeholder
# that MUST be replaced before this reaches a network.
auth:
mode: apikey
api_keys: ["REPLACE-ME"]
trust_loopback: false
metrics:
enabled: true
path: /metrics
protect: true
log:
level: info
format: json
---
apiVersion: v1
kind: Secret
metadata:
name: fancy-dns-tls
namespace: dns
type: kubernetes.io/tls
# Replace with a real cert-manager managed secret in production:
# cert-manager.io/v1 -> Certificate -> CertificateRequest -> Secret
stringData:
tls.crt: ""
tls.key: ""
+245
View File
@@ -0,0 +1,245 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: fancy-dns
namespace: dns
labels:
app.kubernetes.io/name: fancy-dns
spec:
serviceName: fancy-dns
replicas: 2
podManagementPolicy: Parallel
selector:
matchLabels:
app.kubernetes.io/name: fancy-dns
template:
metadata:
labels:
app.kubernetes.io/name: fancy-dns
annotations:
# A config change is a SIGHUP, not a restart: the server re-reads the
# file and hot-swaps every component.
reloader.stakater.com/auto: "true"
spec:
# DNS on a non-privileged port needs NET_BIND_SERVICE on Linux, or
# hostNetwork. hostNetwork is used here so the node's port 53 is served
# directly and the load balancer does not add a hop.
hostNetwork: true
dnsPolicy: Default
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
seccompProfile:
type: RuntimeDefault
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: fancy-dns
containers:
- name: fancy-dns
image: fancydns/fancy-dns:latest
imagePullPolicy: IfNotPresent
args:
- -config
- /etc/fancy-dns/config.yaml
ports:
- name: dns-udp
containerPort: 53
protocol: UDP
- name: dns-tcp
containerPort: 53
protocol: TCP
- name: dot
containerPort: 853
protocol: TCP
- name: doh
containerPort: 443
protocol: TCP
- name: admin
containerPort: 8080
protocol: TCP
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
# Liveness: the process is up. /api/healthz is unauthenticated on
# purpose, because a probe cannot carry an API key.
livenessProbe:
httpGet:
path: /api/healthz
port: admin
initialDelaySeconds: 5
periodSeconds: 20
# Readiness: the listener is actually bound, so the Service does not
# send traffic to a pod that is still binding.
readinessProbe:
httpGet:
path: /api/healthz
port: admin
initialDelaySeconds: 3
periodSeconds: 5
failureThreshold: 2
# Startup: binding :53 and fetching the first blocklist can take a
# while on a cold node, so give it room before the liveness probe
# starts killing it.
startupProbe:
httpGet:
path: /api/healthz
port: admin
periodSeconds: 3
failureThreshold: 30
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
# No CPU limit on purpose: a DNS server that gets throttled
# turns into dropped queries, which is worse than a noisy
# neighbour. The memory limit is the one that matters, because
# the cache is sized in entries.
memory: 1Gi
volumeMounts:
- name: config
mountPath: /etc/fancy-dns/config.yaml
subPath: config.yaml
readOnly: true
- name: zones
mountPath: /etc/fancy-dns/zones
readOnly: true
- name: tls
mountPath: /etc/fancy-dns/tls
readOnly: true
- name: data
mountPath: /var/lib/fancy-dns
- name: tmp
mountPath: /tmp
volumes:
- name: config
configMap:
name: fancy-dns-config
- name: zones
configMap:
name: fancy-dns-zones
optional: true
- name: tls
secret:
secretName: fancy-dns-tls
- name: data
emptyDir: {}
- name: tmp
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: fancy-dns
namespace: dns
labels:
app.kubernetes.io/name: fancy-dns
spec:
clusterIP: None
selector:
app.kubernetes.io/name: fancy-dns
ports:
- name: dns-udp
port: 53
targetPort: dns-udp
protocol: UDP
- name: dns-tcp
port: 53
targetPort: dns-tcp
protocol: TCP
- name: dot
port: 853
targetPort: dot
- name: doh
port: 443
targetPort: doh
- name: admin
port: 8080
targetPort: admin
---
# The admin console and the DoH endpoint share a port only if the ingress
# terminates TLS; when it does, this routes /api and /dns-query to the same
# backend. Kept separate from the Service above because a headless Service
# cannot front an Ingress.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: fancy-dns
namespace: dns
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/proxy-buffering: "off"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
spec:
rules:
- host: dns.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: fancy-dns
port:
name: admin
- path: /dns-query
pathType: Prefix
backend:
service:
name: fancy-dns
port:
name: doh
- path: /
pathType: Prefix
backend:
service:
name: fancy-dns
port:
name: admin
tls:
- hosts: [dns.example.com]
secretName: fancy-dns-tls
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: fancy-dns
namespace: dns
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: fancy-dns
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: fancy-dns
namespace: dns
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: StatefulSet
name: fancy-dns
minReplicas: 2
maxReplicas: 6
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
# A DNS server that flaps is worse than one that is briefly oversized:
# every scale-down drops the local cache and the blocklist lease.
stabilizationWindowSeconds: 600