Files
k3s-cluster/pihole/pihole.yaml
2026-06-28 09:34:43 +02:00

266 lines
6.2 KiB
YAML

---
apiVersion: v1
kind: Namespace
metadata:
name: pihole
---
apiVersion: v1
kind: ConfigMap
metadata:
name: unbound-config
namespace: pihole
data:
unbound.conf: |
server:
# Listen only on loopback so only the co-located pihole can query it
interface: 127.0.0.1
port: 5335
# IPv4 only for simplicity
do-ip4: yes
do-udp: yes
do-tcp: yes
do-ip6: no
prefer-ip6: no
# Recursive resolver: do not use any forwarders, start from the root servers
root-hints: "/opt/unbound/etc/unbound/root.hints"
# DNSSEC / hardening
harden-glue: yes
harden-dnssec-stripped: yes
harden-referral-path: yes
# Performance / privacy
prefetch: yes
prefetch-key: yes
qname-minimisation: yes
aggressive-nsec: yes
edns-buffer-size: 1232
num-threads: 1
so-rcvbuf: 1m
# RFC1918 / link-local addresses should never come back from the internet
private-address: 10.0.0.0/8
private-address: 172.16.0.0/12
private-address: 192.168.0.0/16
private-address: 169.254.0.0/16
private-address: fd00::/8
private-address: fe80::/10
# Hide identity / version
hide-identity: yes
hide-version: yes
---
# Pi-hole config that points dnsmasq at the local unbound sidecar.
# Mounted into /etc/dnsmasq.d so it is read on (re)start.
apiVersion: v1
kind: ConfigMap
metadata:
name: pihole-dnsmasq-config
namespace: pihole
data:
99-unbound.conf: |
# Use the recursive unbound sidecar as the only upstream DNS
server=127.0.0.1#5335
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pihole-pvc
namespace: pihole
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: unbound-pvc
namespace: pihole
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: pihole
namespace: pihole
labels:
app: pihole
spec:
replicas: 1
selector:
matchLabels:
app: pihole
template:
metadata:
labels:
app: pihole
spec:
# The pod itself still needs DNS to (e.g.) download blocklists on gravity
# updates. Use the cluster DNS / a public resolver for that - it is NOT
# used to answer client queries, which go through the unbound sidecar.
dnsPolicy: "None"
dnsConfig:
nameservers:
- 8.8.8.8
- 8.8.4.4
initContainers:
- name: unbound-root-hints
image: curlimages/curl:8.12.1
command:
- /bin/sh
- -c
- |
set -e
if [ ! -s /opt/unbound/etc/unbound/root.hints ]; then
echo "Downloading root hints..."
curl -fsSL https://www.internic.net/domain/named.root -o /opt/unbound/etc/unbound/root.hints
else
echo "Root hints already present, skipping download."
fi
volumeMounts:
- name: unbound-data
mountPath: /opt/unbound/etc/unbound
containers:
- name: pihole
image: pihole/pihole:latest
ports:
- containerPort: 80
name: http
- containerPort: 53
name: dns-tcp
protocol: TCP
- containerPort: 53
name: dns-udp
protocol: UDP
env:
- name: TZ
value: "Europe/Madrid"
#- name: WEBPASSWORD
#value: ""
#- name: FTLCONF_webserver_api_password
#value: ''
#- name: DNSMASQ_LISTENING
#value: "all"
- name: FTLCONF_dns_listeningMode
value: "all"
- name: WEB_PORT
value: "80"
#- name: VIRTUAL_HOST
#value: "pihole"
#- name: FTLCONF_LOCAL_IPV4
#value: "0.0.0.0"
- name: SKIPGRAVITYONBOOT
value: "1"
volumeMounts:
- name: pihole-data
mountPath: /etc/pihole
- name: pihole-dnsmasq-config
mountPath: /etc/dnsmasq.d/99-unbound.conf
subPath: 99-unbound.conf
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
securityContext:
capabilities:
add:
- NET_ADMIN
- SYS_TIME
- SYS_NICE
- name: unbound
image: mvance/unbound:latest
ports:
- containerPort: 5335
name: unbound-dns-tcp
protocol: TCP
- containerPort: 5335
name: unbound-dns-udp
protocol: UDP
volumeMounts:
- name: unbound-config
mountPath: /opt/unbound/etc/unbound/unbound.conf
subPath: unbound.conf
- name: unbound-data
mountPath: /opt/unbound/etc/unbound
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "500m"
livenessProbe:
tcpSocket:
port: 5335
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
tcpSocket:
port: 5335
initialDelaySeconds: 5
periodSeconds: 10
volumes:
- name: pihole-data
persistentVolumeClaim:
claimName: pihole-pvc
- name: unbound-data
persistentVolumeClaim:
claimName: unbound-pvc
- name: unbound-config
configMap:
name: unbound-config
- name: pihole-dnsmasq-config
configMap:
name: pihole-dnsmasq-config
---
apiVersion: v1
kind: Service
metadata:
name: pihole-web
namespace: pihole
labels:
app: pihole
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: pihole
---
apiVersion: v1
kind: Service
metadata:
name: pihole-dns
namespace: pihole
labels:
app: pihole
spec:
type: LoadBalancer
ports:
- port: 53
targetPort: 53
protocol: TCP
name: dns-tcp
- port: 53
targetPort: 53
protocol: UDP
name: dns-udp
selector:
app: pihole