sigs.k8s.io/external-dns@v0.14.1/docs/tutorials/aws-sd.md (about) 1 # Setting up ExternalDNS using AWS Cloud Map API 2 3 This tutorial describes how to set up ExternalDNS for usage within a Kubernetes cluster with [AWS Cloud Map API](https://docs.aws.amazon.com/cloud-map/). 4 5 **AWS Cloud Map** API is an alternative approach to managing DNS records directly using the Route53 API. It is more suitable for a dynamic environment where service endpoints change frequently. It abstracts away technical details of the DNS protocol and offers a simplified model. AWS Cloud Map consists of three main API calls: 6 7 * CreatePublicDnsNamespace – automatically creates a DNS hosted zone 8 * CreateService – creates a new named service inside the specified namespace 9 * RegisterInstance/DeregisterInstance – can be called multiple times to create a DNS record for the specified *Service* 10 11 Learn more about the API in the [AWS Cloud Map API Reference](https://docs.aws.amazon.com/cloud-map/latest/api/API_Operations.html). 12 13 ## IAM Permissions 14 15 To use the AWS Cloud Map API, a user must have permissions to create the DNS namespace. Additionally you need to make sure that your nodes (on which External DNS runs) have an IAM instance profile with the `AWSCloudMapFullAccess` managed policy attached, that provides following permissions: 16 17 ``` 18 { 19 "Version": "2012-10-17", 20 "Statement": [ 21 { 22 "Effect": "Allow", 23 "Action": [ 24 "route53:GetHostedZone", 25 "route53:ListHostedZonesByName", 26 "route53:CreateHostedZone", 27 "route53:DeleteHostedZone", 28 "route53:ChangeResourceRecordSets", 29 "route53:CreateHealthCheck", 30 "route53:GetHealthCheck", 31 "route53:DeleteHealthCheck", 32 "route53:UpdateHealthCheck", 33 "ec2:DescribeVpcs", 34 "ec2:DescribeRegions", 35 "servicediscovery:*" 36 ], 37 "Resource": [ 38 "*" 39 ] 40 } 41 ] 42 } 43 ``` 44 45 ## Set up a namespace 46 47 Create a DNS namespace using the AWS Cloud Map API: 48 49 ```console 50 $ aws servicediscovery create-public-dns-namespace --name "external-dns-test.my-org.com" 51 ``` 52 53 Verify that the namespace was truly created 54 55 ```console 56 $ aws servicediscovery list-namespaces 57 ``` 58 59 ## Deploy ExternalDNS 60 61 Connect your `kubectl` client to the cluster that you want to test ExternalDNS with. 62 Then apply the following manifest file to deploy ExternalDNS. 63 64 ### Manifest (for clusters without RBAC enabled) 65 66 ```yaml 67 apiVersion: apps/v1 68 kind: Deployment 69 metadata: 70 name: external-dns 71 spec: 72 strategy: 73 type: Recreate 74 selector: 75 matchLabels: 76 app: external-dns 77 template: 78 metadata: 79 labels: 80 app: external-dns 81 spec: 82 containers: 83 - name: external-dns 84 image: registry.k8s.io/external-dns/external-dns:v0.14.0 85 env: 86 - name: AWS_REGION 87 value: us-east-1 # put your CloudMap NameSpace region 88 args: 89 - --source=service 90 - --source=ingress 91 - --domain-filter=external-dns-test.my-org.com # Makes ExternalDNS see only the namespaces that match the specified domain. Omit the filter if you want to process all available namespaces. 92 - --provider=aws-sd 93 - --aws-zone-type=public # Only look at public namespaces. Valid values are public, private, or no value for both) 94 - --txt-owner-id=my-identifier 95 ``` 96 97 ### Manifest (for clusters with RBAC enabled) 98 99 ```yaml 100 apiVersion: v1 101 kind: ServiceAccount 102 metadata: 103 name: external-dns 104 --- 105 apiVersion: rbac.authorization.k8s.io/v1 106 kind: ClusterRole 107 metadata: 108 name: external-dns 109 rules: 110 - apiGroups: [""] 111 resources: ["services","endpoints","pods"] 112 verbs: ["get","watch","list"] 113 - apiGroups: ["extensions","networking.k8s.io"] 114 resources: ["ingresses"] 115 verbs: ["get","watch","list"] 116 - apiGroups: [""] 117 resources: ["nodes"] 118 verbs: ["list","watch"] 119 --- 120 apiVersion: rbac.authorization.k8s.io/v1 121 kind: ClusterRoleBinding 122 metadata: 123 name: external-dns-viewer 124 roleRef: 125 apiGroup: rbac.authorization.k8s.io 126 kind: ClusterRole 127 name: external-dns 128 subjects: 129 - kind: ServiceAccount 130 name: external-dns 131 namespace: default 132 --- 133 apiVersion: apps/v1 134 kind: Deployment 135 metadata: 136 name: external-dns 137 spec: 138 strategy: 139 type: Recreate 140 selector: 141 matchLabels: 142 app: external-dns 143 template: 144 metadata: 145 labels: 146 app: external-dns 147 spec: 148 serviceAccountName: external-dns 149 containers: 150 - name: external-dns 151 image: registry.k8s.io/external-dns/external-dns:v0.14.0 152 env: 153 - name: AWS_REGION 154 value: us-east-1 # put your CloudMap NameSpace region 155 args: 156 - --source=service 157 - --source=ingress 158 - --domain-filter=external-dns-test.my-org.com # Makes ExternalDNS see only the namespaces that match the specified domain. Omit the filter if you want to process all available namespaces. 159 - --provider=aws-sd 160 - --aws-zone-type=public # Only look at public namespaces. Valid values are public, private, or no value for both) 161 - --txt-owner-id=my-identifier 162 ``` 163 164 ## Verify that ExternalDNS works (Service example) 165 166 Create the following sample application to test that ExternalDNS works. 167 168 > For services ExternalDNS will look for the annotation `external-dns.alpha.kubernetes.io/hostname` on the service and use the corresponding value. 169 170 ```yaml 171 apiVersion: v1 172 kind: Service 173 metadata: 174 name: nginx 175 annotations: 176 external-dns.alpha.kubernetes.io/hostname: nginx.external-dns-test.my-org.com 177 spec: 178 type: LoadBalancer 179 ports: 180 - port: 80 181 name: http 182 targetPort: 80 183 selector: 184 app: nginx 185 186 --- 187 188 apiVersion: apps/v1 189 kind: Deployment 190 metadata: 191 name: nginx 192 spec: 193 selector: 194 matchLabels: 195 app: nginx 196 template: 197 metadata: 198 labels: 199 app: nginx 200 spec: 201 containers: 202 - image: nginx 203 name: nginx 204 ports: 205 - containerPort: 80 206 name: http 207 ``` 208 209 After one minute check that a corresponding DNS record for your service was created in your hosted zone. We recommended that you use the [Amazon Route53 console](https://console.aws.amazon.com/route53) for that purpose. 210 211 212 ## Custom TTL 213 214 The default DNS record TTL (time to live) is 300 seconds. You can customize this value by setting the annotation `external-dns.alpha.kubernetes.io/ttl`. 215 For example, modify the service manifest YAML file above: 216 217 ```yaml 218 apiVersion: v1 219 kind: Service 220 metadata: 221 name: nginx 222 annotations: 223 external-dns.alpha.kubernetes.io/hostname: nginx.external-dns-test.my-org.com 224 external-dns.alpha.kubernetes.io/ttl: 60 225 spec: 226 ... 227 ``` 228 229 This will set the TTL for the DNS record to 60 seconds. 230 231 232 ## Clean up 233 234 Delete all service objects before terminating the cluster so all load balancers get cleaned up correctly. 235 236 ```console 237 $ kubectl delete service nginx 238 ``` 239 240 Give ExternalDNS some time to clean up the DNS records for you. Then delete the remaining service and namespace. 241 242 ```console 243 $ aws servicediscovery list-services 244 245 { 246 "Services": [ 247 { 248 "Id": "srv-6dygt5ywvyzvi3an", 249 "Arn": "arn:aws:servicediscovery:us-west-2:861574988794:service/srv-6dygt5ywvyzvi3an", 250 "Name": "nginx" 251 } 252 ] 253 } 254 ``` 255 256 ```console 257 $ aws servicediscovery delete-service --id srv-6dygt5ywvyzvi3an 258 ``` 259 260 ```console 261 $ aws servicediscovery list-namespaces 262 { 263 "Namespaces": [ 264 { 265 "Type": "DNS_PUBLIC", 266 "Id": "ns-durf2oxu4gxcgo6z", 267 "Arn": "arn:aws:servicediscovery:us-west-2:861574988794:namespace/ns-durf2oxu4gxcgo6z", 268 "Name": "external-dns-test.my-org.com" 269 } 270 ] 271 } 272 ``` 273 274 ```console 275 $ aws servicediscovery delete-namespace --id ns-durf2oxu4gxcgo6z 276 ```