AWS Open Source Blog

Unified Service Discovery with Amazon ECS and Kubernetes

Service Discovery with ECS and Route 53

中文版

Starting today, you can leverage unified service discovery for services managed by Amazon Elastic Container Service (Amazon ECS) and Kubernetes. We recently introduced ECS Service Discovery, which makes it easy for containerized services to discover and connect with each other by creating and managing a registry of service names using the Amazon Route 53 Auto Naming (Auto Naming) API. Service names are automatically mapped to a set of DNS records. This lets you refer to a service by name (such as backend.example.com) in your code and write DNS queries that resolve to the name to the service’s endpoint at runtime.

We wanted to let Kubernetes users take advantage of the Auto Naming API, too, so we extended support for the Auto Naming API to Kubernetes. This integration makes it easy to automatically replicate Kubernetes services and ingresses to the service registry that is managed by the Auto Naming API. Clients outside of the Kubernetes cluster now can easily resolve these service endpoints using a friendly service name. To enable this integration, we made a contribution to the External DNS, a Kubernetes incubator project.

Now, services that run in Amazon ECS can discovery and connect with services running in Kubernetes by making simple DNS queries to Route 53.

What is Auto Naming?

The Auto Naming API is an alternative approach to managing DNS records and both Route 53 and third-party health checks. Auto Naming abstracts away technical details of the DNS protocol and provides a service registry that makes it easy to manage all of your service endpoints. You can discover your services by making simple DNS calls, and Auto Naming returns the locations of healthy endpoints.

The main APIs in Auto Naming are:

  • CreatePublicDNSNamespace – creates a public Route 53 hosted zone that can be managed only programmatically, for example, using an AWS SDK or the Auto Naming APIs (The Route 53 console currently supports Auto Naming only for viewing hosted zones and records.)
  • CreatePrivateDNSNamespace – creates a private Route 53 hosted zone, available within a VPC that you specify; the hosted zone can be managed only programmatically
  • CreateService – creates a new service in the namespace; the service defines DNS and health checking settings
  • RegisterInstance – registers a particular instance with the service, and creates corresponding DNS records and an optional health check
  • DeregisterInstace – removes the instance registration, and deletes relevant DNS records and an optional health check

Learn more about the Auto Naming API in the Amazon Route 53 API Reference.

Let’s see how to start using Auto Naming with an application running in a Kubernetes cluster.

Step 1: Set IAM Permissions

To start using Kubernetes with Auto Naming, a user must have the permissions that are summarized in the ‘AmazonRoute53AutoNamingFullAccess’ managed IAM policy. In the following AWS CLI example, we create a new user named external-dns and grant the required permissions:

$ aws iam create-group --group-name external-dns

$ aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonRoute53AutoNamingFullAccess --group-name external-dns

$ aws iam create-user --user-name external-dns

$ aws iam add-user-to-group --user-name external-dns --group-name external-dns

When deploying the External DNS connector on Amazon EKS, make sure to add the AmazonRoute53AutoNamingFullAccess managed policy to the worker node group IAM instance role.

For more information about the AWS CLI, see the AWS Command Line Interface User Guide.

Step 2: Set Up a Namespace

To start using service discovery, create a DNS namespace using the AWS CLI. A namespace is a logical group of services discoverable either publicly or from within a Virtual Private Cloud (VPC) of your choice. Alternatively, you can use an existing DNS namespace that you created using ECS Service Discovery.

Create a namespace:

$ aws servicediscovery create-private-dns-namespace --name "external-dns-test.internal" –vpc “your-vpc-id”

Verify that the namespace is created or find an existing namespace:

$ aws servicediscovery list-namespaces

Step 3: Deploy ExternalDNS

ExternalDNS synchronizes exposed Kubernetes Services and Ingresses with DNS providers, such as Route 53 . It allows you to control DNS records dynamically via Kubernetes resources.

Connect your kubectl client to the cluster that you want to test ExternalDNS with and set up the Service Account for ExternalDNS with the following YAML manifest ‘external-dns-serviceaccount.yaml’:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-dns
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: external-dns
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get","watch","list"]
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","watch","list"]
- apiGroups: ["extensions"]
  resources: ["ingresses"]
  verbs: ["get","watch","list"]
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["list"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: external-dns-viewer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: external-dns
subjects:
- kind: ServiceAccount
  name: external-dns
  namespace: default

Apply it to your Kubernetes cluster by running:

$ kubectl apply -f external-dns-serviceaccount.yaml

Then apply the following YAML manifest file “external-dns-deployment.yaml” to deploy ExternalDNS.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: external-dns
spec:
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: external-dns
    spec:
      serviceAccountName: external-dns
      containers:
      - name: external-dns
        image: registry.opensource.zalan.do/teapot/external-dns:latest
        args:
        - --source=service
        - --source=ingress
        - --domain-filter=external-dns-test.internal #search for a specific domain name
        - --provider=aws-sd #use AWS-SD provider
        - --aws-zone-type=private #search for private namespaces only
        - --txt-owner-id=%AWS_Account_ID% #add your AWS account ID as the owner
        env:
          - name: AWS_REGION
            value: us-east-1 #specify the AWS region

Apply the following manifest to deploy ExternalDNS:

$ kubectl apply -f external-dns-deployment.yaml

Now, check how ExternalDNS works by deploying a sample service:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  annotations:
    external-dns.alpha.kubernetes.io/hostname: nginx.external-dns-test.internal
spec:
  type: LoadBalancer
  ports:
  - port: 80
    name: http
    targetPort: 80
  selector:
    app: nginx
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
          name: http

Apply the following manifest to deploy the sample Nginx service:

$ kubectl apply -f nginx-deployment.yaml

After one minute, confirm that a corresponding DNS record for your service was created in your hosted zone. You can use the Amazon Route53 console for that purpose. You can also connect directly to the nginx service by calling from your VPC:

nginx.external-dns-test.internal

Start Using Kubernetes and Amazon ECS Together

Now, applications running in an Amazon ECS cluster and in a Kubernetes cluster can share the same namespace, such as example.com, and discover each other via DNS queries. All the new services created in either of the clusters will become available in the same namespace automatically so that you can seamlessly extend your application running in Amazon ECS by adding components, running in Kubernetes.

To get started, deploy the latest version of the ExternalDNS connector for your services running in Kubernetes along with ECS Service Discovery for your services running in Amazon ECS. For more information check out the documentation.

Alexandr Moroz

Alexandr Moroz

Alex Moroz is a product manager at Amazon Route 53, a highly available and scalable cloud DNS web service. He focuses on topics related to service discovery and microservice-based architectures. In his prior role with CA, Alex led the product side of Mobile API Gateway and pioneered open sourcing of the SDKs that helped developers build secure mobile and IoT apps faster.