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  ```