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}