Skip to main content

Pi-hole

Purpose: DNS ad-blocker and network-wide ad blocking

Version: Latest (pihole/pihole:latest)

Namespace: pihole

Description

Pi-hole is a DNS sinkhole that blocks ads and trackers at the network level. It acts as a DNS server for your network, blocking requests to known ad-serving domains before they reach your devices.

Key features:

  • Network-wide ad blocking
  • DNS query logging and analytics
  • Custom blocklists and allowlists
  • Web-based admin dashboard
  • Supports multiple devices simultaneously

Installation

Installed via internal Helm chart from charts/pi-hole/

Configuration

Configuration file: config/dev/applications/pi-hole-values.yaml

Key settings:

  • LoadBalancer service for direct DNS and web access
  • Persistent storage for configuration (1Gi)
  • Resource limits: 200m CPU, 256Mi memory
  • External traffic policy: Local (preserves client IPs)

Access

Web Admin Dashboard

ServiceURLPort
Admin Panelhttp://<LoadBalancer-IP>/admin80

DNS Service

ServicePortProtocol
DNS53TCP/UDP

Configure your devices to use the LoadBalancer IP as their DNS server.

Credentials

Admin Password: Set in config/dev/applications/pi-hole-values.yaml

env:
FTLCONF_webserver_api_password: "your-password-here"

Architecture

Service Configuration

Pi-hole uses a LoadBalancer service (via MetalLB) to expose both DNS and web interface:

service:
type: LoadBalancer
externalTrafficPolicy: Local # Preserves client IPs for stats

The externalTrafficPolicy: Local setting ensures that client IP addresses are preserved in DNS query logs, providing accurate statistics about which devices are making queries.

Storage

  • Storage Class: local-path
  • Size: 1Gi
  • Mount Path: /etc/pihole

Ports

PortProtocolPurpose
53TCP/UDPDNS queries
80TCPWeb admin interface
443TCPHTTPS (self-signed)

Environment Variables

VariableDescriptionDefault
TZTimezone for logs and statsUTC
FTLCONF_webserver_api_passwordAdmin dashboard password(required)
FTLCONF_dns_listeningModeDNS listening modeALL

Adding Custom Blocklists

  1. Access the admin dashboard at http://<LoadBalancer-IP>/admin
  2. Navigate to Group ManagementAdlists
  3. Add new blocklist URLs
  4. Run Gravity Update to apply changes

Example Blocklists

https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
https://raw.githubusercontent.com/AdguardTeam/AdguardFilters/master/SpywareFilter/sections/servers.txt

Configuring Clients

Option 1: Manual DNS Configuration

Set DNS server on each device to the Pi-hole LoadBalancer IP:

DNS Server: <LoadBalancer-IP>

Option 2: DHCP Configuration

Configure your router's DHCP settings to distribute Pi-hole as the DNS server.

Option 3: Kubernetes Network

For pods within the cluster, create a ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
name: coredns-custom
namespace: kube-system
data:
pihole.server: |
pihole.ssdk8s.xyz {
forward . <LoadBalancer-IP>
}

Monitoring

Key Metrics

  • Total DNS queries
  • Queries blocked (percentage)
  • Top blocked domains
  • Top clients by query count
  • DNS cache utilization

Logs

# View pod logs
kubectl logs -n pihole -l app.kubernetes.io/name=pi-hole

# View FTL logs
kubectl exec -n pihole deployment/pi-hole -- tail -f /var/log/pihole/FTL.log

Troubleshooting

Pod Failing Liveness Probes

Issue: Pod restarts due to failed HTTP probes

Solution: Ensure probes are configured to check /admin path, not /

livenessProbe:
httpGet:
path: /admin
port: http

DNS Not Resolving

Check service status:

kubectl get svc -n pihole
kubectl get endpoints -n pihole

Test DNS resolution:

nslookup google.com <LoadBalancer-IP>
dig @<LoadBalancer-IP> google.com

High Memory Usage

Solution: Adjust resource limits in values file:

resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi

Client IPs Not Showing in Logs

Issue: All queries show same source IP

Solution: Ensure externalTrafficPolicy: Local is set:

kubectl get svc -n pihole -o yaml | grep externalTrafficPolicy

Should return: externalTrafficPolicy: Local

Reset Admin Password

kubectl exec -n pihole deployment/pi-hole -- pihole -a -p

Then set new password via the web interface.

Backup and Restore

Backup Configuration

# Backup PVC contents
kubectl run backup --rm -it --image=alpine --restart=Never -- \
tar czf - -C /mnt pihole > pihole-backup.tar.gz

Restore Configuration

  1. Stop the deployment: kubectl scale deployment -n pihole pi-hole --replicas=0
  2. Restore PVC contents from backup
  3. Restart deployment: kubectl scale deployment -n pihole pi-hole --replicas=1

Upgrading

Pi-hole auto-updates its components. To force an update:

  1. Access admin dashboard
  2. Go to SettingsGravity
  3. Click Update Gravity

For chart upgrades:

helm upgrade pi-hole ./charts/pi-hole -f config/dev/applications/pi-hole-values.yaml -n pihole