1{ config, pkgs, lib, ... }:
2
3with lib;
4
5let
6 version = "1.14.4";
7
8 k8s-dns-kube-dns = pkgs.dockerTools.pullImage {
9 imageName = "gcr.io/google_containers/k8s-dns-kube-dns-amd64";
10 imageTag = version;
11 sha256 = "0q97xfqrigrfjl2a9cxl5in619py0zv44gch09jm8gqjkxl80imp";
12 };
13
14 k8s-dns-dnsmasq-nanny = pkgs.dockerTools.pullImage {
15 imageName = "gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64";
16 imageTag = version;
17 sha256 = "051w5ca4qb88mwva4hbnh9xzlsvv7k1mbk3wz50lmig2mqrqqx6c";
18 };
19
20 k8s-dns-sidecar = pkgs.dockerTools.pullImage {
21 imageName = "gcr.io/google_containers/k8s-dns-sidecar-amd64";
22 imageTag = version;
23 sha256 = "1z0d129bcm8i2cqq36x5jhnrv9hirj8c6kjrmdav8vgf7py78vsm";
24 };
25
26 cfg = config.services.kubernetes.addons.dns;
27in {
28 options.services.kubernetes.addons.dns = {
29 enable = mkEnableOption "kubernetes dns addon";
30
31 clusterIp = mkOption {
32 description = "Dns addon clusterIP";
33
34 # this default is also what kubernetes users
35 default = (
36 concatStringsSep "." (
37 take 3 (splitString "." config.services.kubernetes.apiserver.serviceClusterIpRange
38 ))
39 ) + ".254";
40 type = types.str;
41 };
42
43 clusterDomain = mkOption {
44 description = "Dns cluster domain";
45 default = "cluster.local";
46 type = types.str;
47 };
48 };
49
50 config = mkIf cfg.enable {
51 services.kubernetes.kubelet.seedDockerImages = [
52 k8s-dns-kube-dns
53 k8s-dns-dnsmasq-nanny
54 k8s-dns-sidecar
55 ];
56
57 services.kubernetes.addonManager.addons = {
58 kubedns-deployment = {
59 apiVersion = "apps/v1beta1";
60 kind = "Deployment";
61 metadata = {
62 labels = {
63 "addonmanager.kubernetes.io/mode" = "Reconcile";
64 "k8s-app" = "kube-dns";
65 "kubernetes.io/cluster-service" = "true";
66 };
67 name = "kube-dns";
68 namespace = "kube-system";
69 };
70 spec = {
71 selector.matchLabels."k8s-app" = "kube-dns";
72 strategy = {
73 rollingUpdate = {
74 maxSurge = "10%";
75 maxUnavailable = 0;
76 };
77 };
78 template = {
79 metadata = {
80 annotations."scheduler.alpha.kubernetes.io/critical-pod" = "";
81 labels.k8s-app = "kube-dns";
82 };
83 spec = {
84 containers = [
85 {
86 name = "kubedns";
87 args = [
88 "--domain=${cfg.clusterDomain}"
89 "--dns-port=10053"
90 "--config-dir=/kube-dns-config"
91 "--v=2"
92 ];
93 env = [
94 {
95 name = "PROMETHEUS_PORT";
96 value = "10055";
97 }
98 ];
99 image = "gcr.io/google_containers/k8s-dns-kube-dns-amd64:${version}";
100 livenessProbe = {
101 failureThreshold = 5;
102 httpGet = {
103 path = "/healthcheck/kubedns";
104 port = 10054;
105 scheme = "HTTP";
106 };
107 initialDelaySeconds = 60;
108 successThreshold = 1;
109 timeoutSeconds = 5;
110 };
111 ports = [
112 {
113 containerPort = 10053;
114 name = "dns-local";
115 protocol = "UDP";
116 }
117 {
118 containerPort = 10053;
119 name = "dns-tcp-local";
120 protocol = "TCP";
121 }
122 {
123 containerPort = 10055;
124 name = "metrics";
125 protocol = "TCP";
126 }
127 ];
128 readinessProbe = {
129 httpGet = {
130 path = "/readiness";
131 port = 8081;
132 scheme = "HTTP";
133 };
134 initialDelaySeconds = 3;
135 timeoutSeconds = 5;
136 };
137 resources = {
138 limits.memory = "170Mi";
139 requests = {
140 cpu = "100m";
141 memory = "70Mi";
142 };
143 };
144 volumeMounts = [
145 {
146 mountPath = "/kube-dns-config";
147 name = "kube-dns-config";
148 }
149 ];
150 }
151 {
152 args = [
153 "-v=2"
154 "-logtostderr"
155 "-configDir=/etc/k8s/dns/dnsmasq-nanny"
156 "-restartDnsmasq=true"
157 "--"
158 "-k"
159 "--cache-size=1000"
160 "--log-facility=-"
161 "--server=/${cfg.clusterDomain}/127.0.0.1#10053"
162 "--server=/in-addr.arpa/127.0.0.1#10053"
163 "--server=/ip6.arpa/127.0.0.1#10053"
164 ];
165 image = "gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:${version}";
166 livenessProbe = {
167 failureThreshold = 5;
168 httpGet = {
169 path = "/healthcheck/dnsmasq";
170 port = 10054;
171 scheme = "HTTP";
172 };
173 initialDelaySeconds = 60;
174 successThreshold = 1;
175 timeoutSeconds = 5;
176 };
177 name = "dnsmasq";
178 ports = [
179 {
180 containerPort = 53;
181 name = "dns";
182 protocol = "UDP";
183 }
184 {
185 containerPort = 53;
186 name = "dns-tcp";
187 protocol = "TCP";
188 }
189 ];
190 resources = {
191 requests = {
192 cpu = "150m";
193 memory = "20Mi";
194 };
195 };
196 volumeMounts = [
197 {
198 mountPath = "/etc/k8s/dns/dnsmasq-nanny";
199 name = "kube-dns-config";
200 }
201 ];
202 }
203 {
204 name = "sidecar";
205 image = "gcr.io/google_containers/k8s-dns-sidecar-amd64:${version}";
206 args = [
207 "--v=2"
208 "--logtostderr"
209 "--probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.${cfg.clusterDomain},5,A"
210 "--probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.${cfg.clusterDomain},5,A"
211 ];
212 livenessProbe = {
213 failureThreshold = 5;
214 httpGet = {
215 path = "/metrics";
216 port = 10054;
217 scheme = "HTTP";
218 };
219 initialDelaySeconds = 60;
220 successThreshold = 1;
221 timeoutSeconds = 5;
222 };
223 ports = [
224 {
225 containerPort = 10054;
226 name = "metrics";
227 protocol = "TCP";
228 }
229 ];
230 resources = {
231 requests = {
232 cpu = "10m";
233 memory = "20Mi";
234 };
235 };
236 }
237 ];
238 dnsPolicy = "Default";
239 serviceAccountName = "kube-dns";
240 tolerations = [
241 {
242 key = "CriticalAddonsOnly";
243 operator = "Exists";
244 }
245 ];
246 volumes = [
247 {
248 configMap = {
249 name = "kube-dns";
250 optional = true;
251 };
252 name = "kube-dns-config";
253 }
254 ];
255 };
256 };
257 };
258 };
259
260 kubedns-svc = {
261 apiVersion = "v1";
262 kind = "Service";
263 metadata = {
264 labels = {
265 "addonmanager.kubernetes.io/mode" = "Reconcile";
266 "k8s-app" = "kube-dns";
267 "kubernetes.io/cluster-service" = "true";
268 "kubernetes.io/name" = "KubeDNS";
269 };
270 name = "kube-dns";
271 namespace = "kube-system";
272 };
273 spec = {
274 clusterIP = cfg.clusterIp;
275 ports = [
276 {name = "dns"; port = 53; protocol = "UDP";}
277 {name = "dns-tcp"; port = 53; protocol = "TCP";}
278 ];
279 selector.k8s-app = "kube-dns";
280 };
281 };
282
283 kubedns-sa = {
284 apiVersion = "v1";
285 kind = "ServiceAccount";
286 metadata = {
287 name = "kube-dns";
288 namespace = "kube-system";
289 labels = {
290 "kubernetes.io/cluster-service" = "true";
291 "addonmanager.kubernetes.io/mode" = "Reconcile";
292 };
293 };
294 };
295
296 kubedns-cm = {
297 apiVersion = "v1";
298 kind = "ConfigMap";
299 metadata = {
300 name = "kube-dns";
301 namespace = "kube-system";
302 labels = {
303 "addonmanager.kubernetes.io/mode" = "EnsureExists";
304 };
305 };
306 };
307 };
308
309 services.kubernetes.kubelet.clusterDns = mkDefault cfg.clusterIp;
310 };
311}