sigs.k8s.io/external-dns@v0.14.1/docs/tutorials/public-private-route53.md (about) 1 # Setting up ExternalDNS using the same domain for public and private Route53 zones 2 3 This tutorial describes how to setup ExternalDNS using the same domain for public and private Route53 zones and [nginx-ingress-controller](https://github.com/kubernetes/ingress-nginx). It also outlines how to use [cert-manager](https://github.com/jetstack/cert-manager) to automatically issue SSL certificates from [Let's Encrypt](https://letsencrypt.org/) for both public and private records. 4 5 ## Deploy public nginx-ingress-controller 6 7 Consult [External DNS nginx ingress docs](nginx-ingress.md) for installation guidelines. 8 9 Specify `ingress-class` in nginx-ingress-controller container args: 10 11 ```yaml 12 apiVersion: apps/v1 13 kind: Deployment 14 metadata: 15 labels: 16 app: external-ingress 17 name: external-ingress-controller 18 spec: 19 replicas: 1 20 selector: 21 matchLabels: 22 app: external-ingress 23 template: 24 metadata: 25 labels: 26 app: external-ingress 27 spec: 28 containers: 29 - args: 30 - /nginx-ingress-controller 31 - --default-backend-service=$(POD_NAMESPACE)/default-http-backend 32 - --configmap=$(POD_NAMESPACE)/external-ingress-configuration 33 - --tcp-services-configmap=$(POD_NAMESPACE)/external-tcp-services 34 - --udp-services-configmap=$(POD_NAMESPACE)/external-udp-services 35 - --annotations-prefix=nginx.ingress.kubernetes.io 36 - --ingress-class=external-ingress 37 - --publish-service=$(POD_NAMESPACE)/external-ingress 38 env: 39 - name: POD_NAME 40 valueFrom: 41 fieldRef: 42 apiVersion: v1 43 fieldPath: metadata.name 44 - name: POD_NAMESPACE 45 valueFrom: 46 fieldRef: 47 apiVersion: v1 48 fieldPath: metadata.namespace 49 image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.11.0 50 livenessProbe: 51 failureThreshold: 3 52 httpGet: 53 path: /healthz 54 port: 10254 55 scheme: HTTP 56 initialDelaySeconds: 10 57 periodSeconds: 10 58 successThreshold: 1 59 timeoutSeconds: 1 60 name: external-ingress-controller 61 ports: 62 - containerPort: 80 63 name: http 64 protocol: TCP 65 - containerPort: 443 66 name: https 67 protocol: TCP 68 readinessProbe: 69 failureThreshold: 3 70 httpGet: 71 path: /healthz 72 port: 10254 73 scheme: HTTP 74 periodSeconds: 10 75 successThreshold: 1 76 timeoutSeconds: 1 77 ``` 78 79 Set `type: LoadBalancer` in your public nginx-ingress-controller Service definition. 80 81 ```yaml 82 apiVersion: v1 83 kind: Service 84 metadata: 85 annotations: 86 service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "3600" 87 service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: '*' 88 labels: 89 app: external-ingress 90 name: external-ingress 91 spec: 92 externalTrafficPolicy: Cluster 93 ports: 94 - name: http 95 port: 80 96 protocol: TCP 97 targetPort: http 98 - name: https 99 port: 443 100 protocol: TCP 101 targetPort: https 102 selector: 103 app: external-ingress 104 sessionAffinity: None 105 type: LoadBalancer 106 ``` 107 108 ## Deploy private nginx-ingress-controller 109 110 Consult [External DNS nginx ingress docs](nginx-ingress.md) for installation guidelines. 111 112 Make sure to specify `ingress-class` in nginx-ingress-controller container args: 113 114 ```yaml 115 apiVersion: apps/v1 116 kind: Deployment 117 metadata: 118 labels: 119 app: internal-ingress 120 name: internal-ingress-controller 121 spec: 122 replicas: 1 123 selector: 124 matchLabels: 125 app: internal-ingress 126 template: 127 metadata: 128 labels: 129 app: internal-ingress 130 spec: 131 containers: 132 - args: 133 - /nginx-ingress-controller 134 - --default-backend-service=$(POD_NAMESPACE)/default-http-backend 135 - --configmap=$(POD_NAMESPACE)/internal-ingress-configuration 136 - --tcp-services-configmap=$(POD_NAMESPACE)/internal-tcp-services 137 - --udp-services-configmap=$(POD_NAMESPACE)/internal-udp-services 138 - --annotations-prefix=nginx.ingress.kubernetes.io 139 - --ingress-class=internal-ingress 140 - --publish-service=$(POD_NAMESPACE)/internal-ingress 141 env: 142 - name: POD_NAME 143 valueFrom: 144 fieldRef: 145 apiVersion: v1 146 fieldPath: metadata.name 147 - name: POD_NAMESPACE 148 valueFrom: 149 fieldRef: 150 apiVersion: v1 151 fieldPath: metadata.namespace 152 image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.11.0 153 livenessProbe: 154 failureThreshold: 3 155 httpGet: 156 path: /healthz 157 port: 10254 158 scheme: HTTP 159 initialDelaySeconds: 10 160 periodSeconds: 10 161 successThreshold: 1 162 timeoutSeconds: 1 163 name: internal-ingress-controller 164 ports: 165 - containerPort: 80 166 name: http 167 protocol: TCP 168 - containerPort: 443 169 name: https 170 protocol: TCP 171 readinessProbe: 172 failureThreshold: 3 173 httpGet: 174 path: /healthz 175 port: 10254 176 scheme: HTTP 177 periodSeconds: 10 178 successThreshold: 1 179 timeoutSeconds: 1 180 ``` 181 182 Set additional annotations in your private nginx-ingress-controller Service definition to create an internal load balancer. 183 184 ```yaml 185 apiVersion: v1 186 kind: Service 187 metadata: 188 annotations: 189 service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "3600" 190 service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0 191 service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: '*' 192 labels: 193 app: internal-ingress 194 name: internal-ingress 195 spec: 196 externalTrafficPolicy: Cluster 197 ports: 198 - name: http 199 port: 80 200 protocol: TCP 201 targetPort: http 202 - name: https 203 port: 443 204 protocol: TCP 205 targetPort: https 206 selector: 207 app: internal-ingress 208 sessionAffinity: None 209 type: LoadBalancer 210 ``` 211 212 ## Deploy the public zone ExternalDNS 213 214 Consult [AWS ExternalDNS setup docs](aws.md) for installation guidelines. 215 216 In ExternalDNS containers args, make sure to specify `aws-zone-type` and `ingress-class`: 217 218 ```yaml 219 apiVersion: apps/v1 220 kind: Deployment 221 metadata: 222 labels: 223 app: external-dns-public 224 name: external-dns-public 225 namespace: kube-system 226 spec: 227 replicas: 1 228 selector: 229 matchLabels: 230 app: external-dns-public 231 strategy: 232 type: Recreate 233 template: 234 metadata: 235 labels: 236 app: external-dns-public 237 spec: 238 containers: 239 - args: 240 - --source=ingress 241 - --provider=aws 242 - --registry=txt 243 - --txt-owner-id=external-dns 244 - --ingress-class=external-ingress 245 - --aws-zone-type=public 246 image: registry.k8s.io/external-dns/external-dns:v0.14.0 247 name: external-dns-public 248 ``` 249 250 ## Deploy the private zone ExternalDNS 251 252 Consult [AWS ExternalDNS setup docs](aws.md) for installation guidelines. 253 254 In ExternalDNS containers args, make sure to specify `aws-zone-type` and `ingress-class`: 255 256 ```yaml 257 apiVersion: apps/v1 258 kind: Deployment 259 metadata: 260 labels: 261 app: external-dns-private 262 name: external-dns-private 263 namespace: kube-system 264 spec: 265 replicas: 1 266 selector: 267 matchLabels: 268 app: external-dns-private 269 strategy: 270 type: Recreate 271 template: 272 metadata: 273 labels: 274 app: external-dns-private 275 spec: 276 containers: 277 - args: 278 - --source=ingress 279 - --provider=aws 280 - --registry=txt 281 - --txt-owner-id=dev.k8s.nexus 282 - --ingress-class=internal-ingress 283 - --aws-zone-type=private 284 image: registry.k8s.io/external-dns/external-dns:v0.14.0 285 name: external-dns-private 286 ``` 287 288 ## Create application Service definitions 289 290 For this setup to work, you need to create two Ingress definitions for your application. 291 292 At first, create a public Ingress definition: 293 294 ```yaml 295 apiVersion: networking.k8s.io/v1 296 kind: Ingress 297 metadata: 298 labels: 299 app: app 300 name: app-public 301 spec: 302 ingressClassName: external-ingress 303 rules: 304 - host: app.domain.com 305 http: 306 paths: 307 - backend: 308 service: 309 name: app 310 port: 311 number: 80 312 pathType: Prefix 313 ``` 314 315 Then create a private Ingress definition: 316 317 ```yaml 318 apiVersion: networking.k8s.io/v1 319 kind: Ingress 320 metadata: 321 labels: 322 app: app 323 name: app-private 324 spec: 325 ingressClassName: internal-ingress 326 rules: 327 - host: app.domain.com 328 http: 329 paths: 330 - backend: 331 service: 332 name: app 333 port: 334 number: 80 335 pathType: Prefix 336 ``` 337 338 Additionally, you may leverage [cert-manager](https://github.com/jetstack/cert-manager) to automatically issue SSL certificates from [Let's Encrypt](https://letsencrypt.org/). To do that, request a certificate in public service definition: 339 340 ```yaml 341 apiVersion: networking.k8s.io/v1 342 kind: Ingress 343 metadata: 344 annotations: 345 certmanager.k8s.io/acme-challenge-type: "dns01" 346 certmanager.k8s.io/acme-dns01-provider: "route53" 347 certmanager.k8s.io/cluster-issuer: "letsencrypt-production" 348 kubernetes.io/tls-acme: "true" 349 labels: 350 app: app 351 name: app-public 352 spec: 353 ingressClassName: "external-ingress" 354 rules: 355 - host: app.domain.com 356 http: 357 paths: 358 - backend: 359 service: 360 name: app 361 port: 362 number: 80 363 pathType: Prefix 364 tls: 365 - hosts: 366 - app.domain.com 367 secretName: app-tls 368 ``` 369 370 And reuse the requested certificate in private Service definition: 371 372 ```yaml 373 apiVersion: networking.k8s.io/v1 374 kind: Ingress 375 metadata: 376 labels: 377 app: app 378 name: app-private 379 spec: 380 ingressClassName: "internal-ingress" 381 rules: 382 - host: app.domain.com 383 http: 384 paths: 385 - backend: 386 service: 387 name: app 388 port: 389 number: 80 390 pathType: Prefix 391 tls: 392 - hosts: 393 - app.domain.com 394 secretName: app-tls 395 ```