CoreDNS is a flexible, extensible DNS server that serves as the DNS service for Kubernetes clusters. It chains plugins to provide DNS resolution, service discovery, and custom DNS entries.
Overview
CoreDNS replaces kube-dns as the default DNS solution in modern Kubernetes clusters. It provides:
- Service Discovery: Automatic DNS resolution for Kubernetes services
- Pod DNS: DNS records for pods based on their IP addresses
- Custom DNS: Support for custom DNS entries and zone files
- Plugin Architecture: Extensible through a plugin system
- High Availability: Supports autoscaling and clustering
Prerequisites
- Kubernetes cluster v1.14+
- Cluster-admin permissions for RBAC resources
- Helm 3.x
CoreDNS is a critical cluster component. Misconfiguration can break DNS resolution for all pods and services. Always test changes in a non-production environment first.
Installation
Basic Installation
Install CoreDNS with default configuration:
helm repo add douban https://douban.github.io/charts/
helm install coredns douban/coredns \
--namespace kube-system
Custom Installation
Install with custom replicas and resources:
helm install coredns douban/coredns \
--namespace kube-system \
--set replicaCount=3 \
--set resources.limits.memory=256Mi \
--set resources.requests.cpu=200m
Configuration
Essential Parameters
| Parameter | Description | Default |
|---|
replicaCount | Number of CoreDNS replicas | 1 |
image.repository | CoreDNS image repository | coredns/coredns |
image.tag | CoreDNS version | "" (uses appVersion) |
isClusterService | Deploy as cluster-service | true |
serviceType | Kubernetes service type | ClusterIP |
DNS Server Configuration
Configure DNS plugins through the servers section:
servers:
- zones:
- zone: .
port: 53
plugins:
- name: errors
- name: health
configBlock: |
lameduck 10s
- name: ready
- name: kubernetes
parameters: cluster.local in-addr.arpa ip6.arpa
configBlock: |
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
- name: prometheus
parameters: 0.0.0.0:9153
- name: forward
parameters: . /etc/resolv.conf
- name: cache
parameters: 30
- name: loop
- name: reload
- name: loadbalance
Resource Management
Set appropriate resource limits:
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
Autoscaling Options
Horizontal Pod Autoscaler
Enable HPA based on metrics:
hpa:
enabled: true
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
Cluster Proportional Autoscaler
Scale based on cluster size:
autoscaler:
enabled: true
coresPerReplica: 256
nodesPerReplica: 16
min: 2
max: 10
preventSinglePointFailure: true
RBAC Configuration
Enable RBAC resources (recommended):
rbac:
create: true
serviceAccount:
create: true
name: coredns
Real-World Examples
Example 1: Production High-Availability Setup
replicaCount: 3
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
autoscaler:
enabled: true
coresPerReplica: 256
nodesPerReplica: 16
min: 3
max: 10
preventSinglePointFailure: true
podDisruptionBudget:
minAvailable: 2
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
k8s-app: kube-dns
prometheus:
service:
enabled: true
monitor:
enabled: true
additionalLabels:
prometheus: kube-prometheus
Example 2: Custom DNS Zones
Add custom DNS entries for internal services:
zoneFiles:
- filename: example.db
domain: example.com
contents: |
example.com. IN SOA sns.dns.icann.com. noc.dns.icann.com. 2015082541 7200 3600 1209600 3600
example.com. IN NS ns1.example.com.
example.com. IN A 192.168.1.100
www.example.com. IN A 192.168.1.100
api.example.com. IN A 192.168.1.101
servers:
- zones:
- zone: example.com
port: 53
plugins:
- name: file
parameters: /etc/coredns/example.db example.com
- zones:
- zone: .
port: 53
plugins:
- name: kubernetes
parameters: cluster.local in-addr.arpa ip6.arpa
- name: forward
parameters: . /etc/resolv.conf
- name: cache
parameters: 30
Example 3: DaemonSet Deployment
Run CoreDNS on every node:
deployment:
enabled: false
daemonset:
enabled: true
tolerations:
- operator: Exists
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 50m
memory: 64Mi
Monitoring and Observability
Prometheus Integration
Enable Prometheus metrics:
prometheus:
service:
enabled: true
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9153"
monitor:
enabled: true
namespace: monitoring
additionalLabels:
release: prometheus
interval: 30s
CoreDNS exposes metrics on port 9153:
coredns_dns_requests_total - Total DNS requests
coredns_dns_responses_total - Total DNS responses
coredns_cache_hits_total - Cache hit count
coredns_cache_misses_total - Cache miss count
Health Checks
Configure liveness and readiness probes:
livenessProbe:
enabled: true
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
readinessProbe:
enabled: true
initialDelaySeconds: 30
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 1
Troubleshooting
DNS Resolution Failures
- Check CoreDNS pod status:
kubectl get pods -n kube-system -l k8s-app=kube-dns
- View CoreDNS logs:
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=100
- Test DNS resolution from a pod:
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup kubernetes.default
High CPU Usage
- Enable query logging temporarily:
servers:
- plugins:
- name: log
servers:
- plugins:
- name: cache
parameters: 60 # Increase cache TTL
configBlock: |
success 9984 30
denial 9984 5
Memory Leaks
- Check for too many cached entries
- Restart CoreDNS pods:
kubectl rollout restart deployment/coredns -n kube-system
- Monitor memory usage:
kubectl top pods -n kube-system -l k8s-app=kube-dns
Configuration Errors
Validate the Corefile:
kubectl get configmap coredns -n kube-system -o yaml
Test configuration changes:
# Edit configmap
kubectl edit configmap coredns -n kube-system
# Force reload
kubectl rollout restart deployment/coredns -n kube-system
Advanced Configuration
External DNS Integration
Forward specific zones to external DNS:
servers:
- zones:
- zone: external.com
plugins:
- name: forward
parameters: . 8.8.8.8 8.8.4.4
- zones:
- zone: .
plugins:
- name: kubernetes
parameters: cluster.local
- name: forward
parameters: . /etc/resolv.conf
Cilium Local Redirect Policy
Optimize DNS with Cilium:
cilium:
localRedirectPolicy:
enabled: true
frontend:
ip: "169.254.169.254"
toPorts:
- port: "53"
protocol: "UDP"
- port: "53"
protocol: "TCP"
This feature requires Cilium CNI with localRedirectPolicy enabled.
Security Considerations
Pod Security Context
securityContext:
allowPrivilegeEscalation: false
capabilities:
add:
- NET_BIND_SERVICE
drop:
- ALL
readOnlyRootFilesystem: true
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
Network Policies
Restrict access to CoreDNS:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: coredns-network-policy
namespace: kube-system
spec:
podSelector:
matchLabels:
k8s-app: kube-dns
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
Uninstallation
Removing CoreDNS will break DNS resolution for all pods. Ensure you have an alternative DNS solution before uninstalling.
helm uninstall coredns --namespace kube-system
Additional Resources