Skip to content

Commit 11ea577

Browse files
authored
Merge pull request #106 from klicktipp/powerdns/allow_deploying_as_daemonset
PowerDNS: Add DaemonSet support to Helm chart
2 parents 216455b + 9d88c9d commit 11ea577

9 files changed

Lines changed: 367 additions & 115 deletions

File tree

charts/powerdns-recursor/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apiVersion: v2
22
name: powerdns-recursor
33
description: Helm chart for deploying PowerDNS Recursor on Kubernetes
44
type: application
5-
version: 0.2.4
5+
version: 0.3.0
66
appVersion: 5.4.0
77
keywords:
88
- dns

charts/powerdns-recursor/README.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# powerdns-recursor
22

3-
![Version: 0.2.4](https://img.shields.io/badge/Version-0.2.4-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 5.4.0](https://img.shields.io/badge/AppVersion-5.4.0-informational?style=flat-square)
3+
![Version: 0.3.0](https://img.shields.io/badge/Version-0.3.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 5.4.0](https://img.shields.io/badge/AppVersion-5.4.0-informational?style=flat-square)
44

55
Helm chart for deploying PowerDNS Recursor on Kubernetes
66

@@ -16,8 +16,15 @@ Helm chart for deploying PowerDNS Recursor on Kubernetes
1616

1717
| Key | Type | Default | Description |
1818
|-----|------|---------|-------------|
19-
| replicaCount | int | `1` | Number of pod replicas. |
20-
| revisionHistoryLimit | int | `10` | Number of old ReplicaSets to retain. |
19+
| replicaCount | int | `1` | Number of pod replicas. Ignored in DaemonSet mode. |
20+
| revisionHistoryLimit | int | `10` | Number of old ReplicaSets to retain. Used by both Deployment and DaemonSet histories. |
21+
| workload | object | `{"daemonSet":{"minReadySeconds":5,"updateStrategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0},"type":"RollingUpdate"}},"type":"Deployment"}` | Workload configuration. |
22+
| workload.type | string | `"Deployment"` | Workload kind. Supported values: Deployment, DaemonSet. |
23+
| workload.daemonSet.updateStrategy | object | `{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0},"type":"RollingUpdate"}` | DaemonSet-only settings. Ignored when workload.type=Deployment. |
24+
| workload.daemonSet.updateStrategy.type | string | `"RollingUpdate"` | DaemonSet update strategy type. |
25+
| workload.daemonSet.updateStrategy.rollingUpdate.maxUnavailable | int | `0` | Keep the existing pod on a node until a surged replacement is ready. |
26+
| workload.daemonSet.updateStrategy.rollingUpdate.maxSurge | int | `1` | Allow one extra pod per node during rolling updates to avoid local DNS gaps. |
27+
| workload.daemonSet.minReadySeconds | int | `5` | Time a new DaemonSet pod must stay ready before it is considered available. |
2128
| imagePullSecrets | list | `[]` | Image pull secrets. |
2229
| nameOverride | string | `""` | Partially override generated resource names. |
2330
| fullnameOverride | string | `""` | Fully override generated resource names. |
@@ -36,15 +43,16 @@ Helm chart for deploying PowerDNS Recursor on Kubernetes
3643
| securityContext.runAsGroup | int | `953` | Unix group id. |
3744
| priorityClassName | string | `""` | Optional priority class for pods. |
3845
| podAntiAffinity | object | `{"topologyKey":"kubernetes.io/hostname","type":"soft"}` | Pod anti-affinity shortcut (used when affinity is empty). |
39-
| podAntiAffinity.type | string | `"soft"` | "soft", "hard" or "disabled". |
46+
| podAntiAffinity.type | string | `"soft"` | "soft", "hard" or "disabled". Ignored in DaemonSet mode. |
4047
| podAntiAffinity.topologyKey | string | `"kubernetes.io/hostname"` | Topology key used by anti-affinity. |
4148
| affinity | object | `{}` | Native affinity rules. If set, this overrides podAntiAffinity. |
4249
| nodeSelector | object | `{}` | Node selector for scheduling. |
4350
| tolerations | list | `[]` | Tolerations for scheduling. |
44-
| podDisruptionBudget | object | `{}` | PodDisruptionBudget spec snippet. Example: { maxUnavailable: 1 } |
45-
| service | object | `{"annotations":{},"clusterIP":"","headless":{"annotations":{},"enabled":false,"includeDnsPorts":true,"publishNotReadyAddresses":false},"loadBalancerIP":"","loadBalancerSourceRanges":[],"port":53,"type":"ClusterIP"}` | Service configuration. |
51+
| podDisruptionBudget | object | `{}` | PodDisruptionBudget spec snippet. Example: { maxUnavailable: 1 }. Ignored in DaemonSet mode. |
52+
| service | object | `{"annotations":{},"clusterIP":"","headless":{"annotations":{},"enabled":false,"includeDnsPorts":true,"publishNotReadyAddresses":false},"internalTrafficPolicy":"","loadBalancerIP":"","loadBalancerSourceRanges":[],"port":53,"type":"ClusterIP"}` | Service configuration. |
4653
| service.type | string | `"ClusterIP"` | Service type. |
4754
| service.clusterIP | string | `""` | Optional fixed ClusterIP for the primary Service. |
55+
| service.internalTrafficPolicy | string | `""` | Service internal traffic policy. When empty, DaemonSet mode defaults to "Local". |
4856
| service.port | int | `53` | DNS service port (TCP/UDP). |
4957
| service.annotations | object | `{}` | Service annotations. |
5058
| service.loadBalancerIP | string | `""` | Optional fixed LoadBalancer IP. |
@@ -95,14 +103,14 @@ Helm chart for deploying PowerDNS Recursor on Kubernetes
95103
| probes.readiness.periodSeconds | int | `5` | Probe period. |
96104
| probes.readiness.timeoutSeconds | int | `3` | Probe timeout. |
97105
| probes.readiness.failureThreshold | int | `3` | Failure threshold. |
98-
| pdns | object | `{"api":{"enabled":false,"port":8082},"config":{"dnssec":{"validation":"process"},"incoming":{"listen":["0.0.0.0"],"port":5353},"logging":{"loglevel":6,"quiet":true},"outgoing":{"source_address":["0.0.0.0"]},"recordcache":{"refresh_on_ttl_perc":10},"recursor":{"config_dir":"/etc/powerdns","setgid":"pdns","setuid":"pdns","socket_mode":"660"},"webservice":{"webserver":"false"}},"lua":{"enabled":false,"script":"zoneToCache(\".\", \"url\", \"https://www.internic.net/domain/root.zone\", { refreshPeriod = 86400 })\n"},"metrics":{"enabled":false},"port":5353}` | PowerDNS recursor runtime configuration. |
106+
| pdns | object | `{"api":{"enabled":false,"port":8082},"config":{"dnssec":{"validation":"process"},"incoming":{"listen":["0.0.0.0"],"port":5353},"logging":{"loglevel":6,"quiet":true},"outgoing":{"source_address":["0.0.0.0"]},"recordcache":{"refresh_on_ttl_perc":10},"recursor":{"config_dir":"/etc/powerdns","setgid":"pdns","setuid":"pdns","socket_mode":"660"},"webservice":{"webserver":false}},"lua":{"enabled":false,"script":"zoneToCache(\".\", \"url\", \"https://www.internic.net/domain/root.zone\", { refreshPeriod = 86400 })\n"},"metrics":{"enabled":false},"port":5353}` | PowerDNS recursor runtime configuration. |
99107
| pdns.port | int | `5353` | Container DNS port. |
100108
| pdns.api | object | `{"enabled":false,"port":8082}` | API endpoint settings. |
101109
| pdns.api.enabled | bool | `false` | Expose API port through the Service and container. |
102110
| pdns.api.port | int | `8082` | API TCP port. |
103111
| pdns.lua | object | `{"enabled":false,"script":"zoneToCache(\".\", \"url\", \"https://www.internic.net/domain/root.zone\", { refreshPeriod = 86400 })\n"}` | Optional Lua config file support. |
104112
| pdns.lua.enabled | bool | `false` | Create additional Lua ConfigMap and mount recursor.lua. |
105113
| pdns.lua.script | string | `"zoneToCache(\".\", \"url\", \"https://www.internic.net/domain/root.zone\", { refreshPeriod = 86400 })\n"` | Lua script content written to /etc/powerdns/recursor.lua. |
106-
| pdns.config | object | `{"dnssec":{"validation":"process"},"incoming":{"listen":["0.0.0.0"],"port":5353},"logging":{"loglevel":6,"quiet":true},"outgoing":{"source_address":["0.0.0.0"]},"recordcache":{"refresh_on_ttl_perc":10},"recursor":{"config_dir":"/etc/powerdns","setgid":"pdns","setuid":"pdns","socket_mode":"660"},"webservice":{"webserver":"false"}}` | Rendered directly into recursor.yml. |
114+
| pdns.config | object | `{"dnssec":{"validation":"process"},"incoming":{"listen":["0.0.0.0"],"port":5353},"logging":{"loglevel":6,"quiet":true},"outgoing":{"source_address":["0.0.0.0"]},"recordcache":{"refresh_on_ttl_perc":10},"recursor":{"config_dir":"/etc/powerdns","setgid":"pdns","setuid":"pdns","socket_mode":"660"},"webservice":{"webserver":false}}` | Rendered directly into recursor.yml. |
107115
| pdns.config.recordcache.refresh_on_ttl_perc | int | `10` | Refresh cache entries shortly before TTL expiry to reduce miss spikes. |
108116
| pdns.metrics | object | `{"enabled":false}` | Legacy compatibility block. |

charts/powerdns-recursor/templates/_helpers.tpl

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,138 @@ Backwards compatible podMonitor enabled flag.
8080
{{- default false .Values.podMonitor.enabled -}}
8181
{{- end -}}
8282
{{- end }}
83+
84+
{{/*
85+
Selected workload type.
86+
*/}}
87+
{{- define "pdns.workloadType" -}}
88+
{{- $workloadType := default "Deployment" .Values.workload.type -}}
89+
{{- if not (has $workloadType (list "Deployment" "DaemonSet")) -}}
90+
{{- fail (printf "workload.type must be either Deployment or DaemonSet, got %q" $workloadType) -}}
91+
{{- end -}}
92+
{{- $workloadType -}}
93+
{{- end }}
94+
95+
{{/*
96+
Internal traffic policy with DaemonSet-aware default.
97+
*/}}
98+
{{- define "pdns.internalTrafficPolicy" -}}
99+
{{- if .Values.service.internalTrafficPolicy -}}
100+
{{- .Values.service.internalTrafficPolicy -}}
101+
{{- else if eq (include "pdns.workloadType" .) "DaemonSet" -}}
102+
{{- "Local" -}}
103+
{{- end -}}
104+
{{- end }}
105+
106+
{{/*
107+
Shared affinity configuration.
108+
*/}}
109+
{{- define "pdns.affinity" -}}
110+
{{- if .Values.affinity }}
111+
affinity:
112+
{{- toYaml .Values.affinity | nindent 2 }}
113+
{{- else if and (eq (include "pdns.workloadType" .) "Deployment") (ne (default "soft" .Values.podAntiAffinity.type) "disabled") }}
114+
affinity:
115+
podAntiAffinity:
116+
{{- $instanceLabel := .Release.Name }}
117+
{{- $topologyKey := default "kubernetes.io/hostname" .Values.podAntiAffinity.topologyKey }}
118+
{{- if eq (default "soft" .Values.podAntiAffinity.type) "hard" }}
119+
requiredDuringSchedulingIgnoredDuringExecution:
120+
- labelSelector:
121+
matchExpressions:
122+
- key: app.kubernetes.io/instance
123+
operator: In
124+
values:
125+
- {{ $instanceLabel }}
126+
topologyKey: {{ $topologyKey | quote }}
127+
{{- else }}
128+
preferredDuringSchedulingIgnoredDuringExecution:
129+
- weight: 100
130+
podAffinityTerm:
131+
labelSelector:
132+
matchExpressions:
133+
- key: app.kubernetes.io/instance
134+
operator: In
135+
values:
136+
- {{ $instanceLabel }}
137+
topologyKey: {{ $topologyKey | quote }}
138+
{{- end }}
139+
{{- end }}
140+
{{- end }}
141+
142+
{{/*
143+
Shared pod spec for Deployment and DaemonSet.
144+
*/}}
145+
{{- define "pdns.podSpec" -}}
146+
serviceAccountName: {{ include "pdns.serviceAccountName" . }}
147+
{{- with .Values.imagePullSecrets }}
148+
imagePullSecrets:
149+
{{- toYaml . | nindent 2 }}
150+
{{- end }}
151+
securityContext:
152+
{{- toYaml .Values.podSecurityContext | nindent 2 }}
153+
{{- with .Values.priorityClassName }}
154+
priorityClassName: {{ . | quote }}
155+
{{- end }}
156+
{{- with .Values.nodeSelector }}
157+
nodeSelector:
158+
{{- toYaml . | nindent 2 }}
159+
{{- end }}
160+
{{- include "pdns.affinity" . }}
161+
{{- with .Values.tolerations }}
162+
tolerations:
163+
{{- toYaml . | nindent 2 }}
164+
{{- end }}
165+
containers:
166+
- name: {{ .Chart.Name }}
167+
image: {{ include "pdns.image" . | quote }}
168+
imagePullPolicy: {{ default .Values.image.imagePullPolicy .Values.image.pullPolicy }}
169+
securityContext:
170+
{{- toYaml .Values.securityContext | nindent 6 }}
171+
ports:
172+
- name: dns-udp
173+
containerPort: {{ .Values.pdns.port }}
174+
protocol: UDP
175+
- name: dns-tcp
176+
containerPort: {{ .Values.pdns.port }}
177+
protocol: TCP
178+
{{- if or .Values.pdns.api.enabled (include "pdns.podMonitorEnabled" . | trim | eq "true") }}
179+
- name: api
180+
containerPort: {{ .Values.pdns.api.port }}
181+
protocol: TCP
182+
{{- end }}
183+
livenessProbe:
184+
tcpSocket:
185+
port: dns-tcp
186+
initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}
187+
periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
188+
timeoutSeconds: {{ .Values.probes.liveness.timeoutSeconds }}
189+
failureThreshold: {{ .Values.probes.liveness.failureThreshold }}
190+
readinessProbe:
191+
tcpSocket:
192+
port: dns-tcp
193+
initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
194+
periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
195+
timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }}
196+
failureThreshold: {{ .Values.probes.readiness.failureThreshold }}
197+
resources:
198+
{{- toYaml .Values.resources | nindent 6 }}
199+
volumeMounts:
200+
- name: pdns-config
201+
mountPath: /etc/powerdns/recursor.yml
202+
subPath: recursor.yml
203+
{{- if or .Values.pdns.lua.enabled .Values.pdns.config.recursor.lua_config_file }}
204+
- name: pdns-lua
205+
mountPath: /etc/powerdns/recursor.lua
206+
subPath: recursor.lua
207+
{{- end }}
208+
volumes:
209+
- name: pdns-config
210+
configMap:
211+
name: {{ include "pdns.fullname" . }}-config
212+
{{- if or .Values.pdns.lua.enabled .Values.pdns.config.recursor.lua_config_file }}
213+
- name: pdns-lua
214+
configMap:
215+
name: {{ include "pdns.fullname" . }}-lua
216+
{{- end }}
217+
{{- end }}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{{- if eq (include "pdns.workloadType" .) "DaemonSet" }}
2+
---
3+
apiVersion: apps/v1
4+
kind: DaemonSet
5+
metadata:
6+
name: {{ include "pdns.fullname" . }}
7+
labels:
8+
{{- include "pdns.labels" . | nindent 4 }}
9+
spec:
10+
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
11+
minReadySeconds: {{ default 0 .Values.workload.daemonSet.minReadySeconds }}
12+
updateStrategy:
13+
{{- toYaml .Values.workload.daemonSet.updateStrategy | nindent 4 }}
14+
selector:
15+
matchLabels:
16+
{{- include "pdns.selectorLabels" . | nindent 6 }}
17+
template:
18+
metadata:
19+
labels:
20+
{{- include "pdns.selectorLabels" . | nindent 8 }}
21+
{{- with .Values.podLabels }}
22+
{{- toYaml . | nindent 8 }}
23+
{{- end }}
24+
annotations:
25+
checksum/config: {{ include (print $.Template.BasePath "/configmaps.yaml") . | sha256sum }}
26+
{{- with .Values.podAnnotations }}
27+
{{- toYaml . | nindent 8 }}
28+
{{- end }}
29+
spec:
30+
{{- include "pdns.podSpec" . | nindent 6 }}
31+
{{- end }}
Lines changed: 3 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{{- if eq (include "pdns.workloadType" .) "Deployment" }}
12
---
23
apiVersion: apps/v1
34
kind: Deployment
@@ -24,103 +25,5 @@ spec:
2425
{{- toYaml . | nindent 8 }}
2526
{{- end }}
2627
spec:
27-
serviceAccountName: {{ include "pdns.serviceAccountName" . }}
28-
{{- with .Values.imagePullSecrets }}
29-
imagePullSecrets:
30-
{{- toYaml . | nindent 8 }}
31-
{{- end }}
32-
securityContext:
33-
{{- toYaml .Values.podSecurityContext | nindent 8 }}
34-
{{- with .Values.priorityClassName }}
35-
priorityClassName: {{ . | quote }}
36-
{{- end }}
37-
{{- with .Values.nodeSelector }}
38-
nodeSelector:
39-
{{- toYaml . | nindent 8 }}
40-
{{- end }}
41-
{{- if .Values.affinity }}
42-
affinity:
43-
{{- toYaml .Values.affinity | nindent 8 }}
44-
{{- else if ne (default "soft" .Values.podAntiAffinity.type) "disabled" }}
45-
affinity:
46-
podAntiAffinity:
47-
{{- $instanceLabel := .Release.Name }}
48-
{{- $topologyKey := default "kubernetes.io/hostname" .Values.podAntiAffinity.topologyKey }}
49-
{{- if eq (default "soft" .Values.podAntiAffinity.type) "hard" }}
50-
requiredDuringSchedulingIgnoredDuringExecution:
51-
- labelSelector:
52-
matchExpressions:
53-
- key: app.kubernetes.io/instance
54-
operator: In
55-
values:
56-
- {{ $instanceLabel }}
57-
topologyKey: {{ $topologyKey | quote }}
58-
{{- else }}
59-
preferredDuringSchedulingIgnoredDuringExecution:
60-
- weight: 100
61-
podAffinityTerm:
62-
labelSelector:
63-
matchExpressions:
64-
- key: app.kubernetes.io/instance
65-
operator: In
66-
values:
67-
- {{ $instanceLabel }}
68-
topologyKey: {{ $topologyKey | quote }}
69-
{{- end }}
70-
{{- end }}
71-
{{- with .Values.tolerations }}
72-
tolerations:
73-
{{- toYaml . | nindent 8 }}
74-
{{- end }}
75-
containers:
76-
- name: {{ .Chart.Name }}
77-
image: {{ include "pdns.image" . | quote }}
78-
imagePullPolicy: {{ default .Values.image.imagePullPolicy .Values.image.pullPolicy }}
79-
securityContext:
80-
{{- toYaml .Values.securityContext | nindent 12 }}
81-
ports:
82-
- name: dns-udp
83-
containerPort: {{ .Values.pdns.port }}
84-
protocol: UDP
85-
- name: dns-tcp
86-
containerPort: {{ .Values.pdns.port }}
87-
protocol: TCP
88-
{{- if or .Values.pdns.api.enabled (include "pdns.podMonitorEnabled" . | trim | eq "true") }}
89-
- name: api
90-
containerPort: {{ .Values.pdns.api.port }}
91-
protocol: TCP
92-
{{- end }}
93-
livenessProbe:
94-
tcpSocket:
95-
port: dns-tcp
96-
initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}
97-
periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
98-
timeoutSeconds: {{ .Values.probes.liveness.timeoutSeconds }}
99-
failureThreshold: {{ .Values.probes.liveness.failureThreshold }}
100-
readinessProbe:
101-
tcpSocket:
102-
port: dns-tcp
103-
initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
104-
periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
105-
timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }}
106-
failureThreshold: {{ .Values.probes.readiness.failureThreshold }}
107-
resources:
108-
{{- toYaml .Values.resources | nindent 12 }}
109-
volumeMounts:
110-
- name: pdns-config
111-
mountPath: /etc/powerdns/recursor.yml
112-
subPath: recursor.yml
113-
{{- if or .Values.pdns.lua.enabled .Values.pdns.config.recursor.lua_config_file }}
114-
- name: pdns-lua
115-
mountPath: /etc/powerdns/recursor.lua
116-
subPath: recursor.lua
117-
{{- end }}
118-
volumes:
119-
- name: pdns-config
120-
configMap:
121-
name: {{ include "pdns.fullname" . }}-config
122-
{{- if or .Values.pdns.lua.enabled .Values.pdns.config.recursor.lua_config_file }}
123-
- name: pdns-lua
124-
configMap:
125-
name: {{ include "pdns.fullname" . }}-lua
126-
{{- end }}
28+
{{- include "pdns.podSpec" . | nindent 6 }}
29+
{{- end }}

charts/powerdns-recursor/templates/poddisruptionbudget.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{{- $pdb := .Values.podDisruptionBudget -}}
2-
{{- if and (kindIs "map" $pdb) (or (hasKey $pdb "maxUnavailable") (hasKey $pdb "minAvailable")) }}
2+
{{- if and (eq (include "pdns.workloadType" .) "Deployment") (kindIs "map" $pdb) (or (hasKey $pdb "maxUnavailable") (hasKey $pdb "minAvailable")) }}
33
---
44
apiVersion: policy/v1
55
kind: PodDisruptionBudget

charts/powerdns-recursor/templates/service.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ spec:
1414
{{- with .Values.service.clusterIP }}
1515
clusterIP: {{ . | quote }}
1616
{{- end }}
17+
{{- with (include "pdns.internalTrafficPolicy" .) }}
18+
internalTrafficPolicy: {{ . | quote }}
19+
{{- end }}
1720
{{- with .Values.service.loadBalancerIP }}
1821
loadBalancerIP: {{ . | quote }}
1922
{{- end }}

0 commit comments

Comments
 (0)