Chapter 14. External DNS Operator

14.1. External DNS Operator in OpenShift Container Platform

The External DNS Operator deploys and manages ExternalDNS to provide the name resolution for services and routes from the external DNS provider to OpenShift Container Platform.

14.1.1. External DNS Operator

The External DNS Operator implements the External DNS API from the olm.openshift.io API group. The External DNS Operator deploys the ExternalDNS using a deployment resource. The ExternalDNS deployment watches the resources such as services and routes in the cluster and updates the external DNS providers.

Procedure

You can deploy the ExternalDNS Operator on demand from the OperatorHub, this creates a Subscription object.

  1. Check the name of an install plan:

    $ oc -n external-dns-operator get sub external-dns-operator -o yaml | yq '.status.installplan.name'

    Example output

    install-zcvlr

  2. Check the status of an install plan, the status of an install plan must be Complete:

    $ oc -n external-dns-operator get ip <install_plan_name> -o yaml | yq .status.phase'

    Example output

    Complete

  3. Use the oc get command to view the Deployment status:

    $ oc get -n external-dns-operator deployment/external-dns-operator

    Example output

    NAME                    READY     UP-TO-DATE   AVAILABLE   AGE
    external-dns-operator   1/1       1            1           23h

14.1.2. External DNS Operator logs

You can view External DNS Operator logs by using the oc logs command.

Procedure

  1. View the logs of the External DNS Operator:

    $ oc logs -n external-dns-operator deployment/external-dns-operator -c external-dns-operator

14.2. Installing External DNS Operator on cloud providers

You can install External DNS Operator on cloud providers such as AWS, Azure and GCP.

14.2.1. Installing the External DNS Operator

You can install the External DNS Operator using the OpenShift Container Platform OperatorHub.

Procedure

  1. Click OperatorsOperatorHub in the OpenShift Container Platform Web Console.
  2. Click External DNS Operator. You can use the Filter by keyword text box or the filter list to search for External DNS Operator from the list of Operators.
  3. Select the external-dns-operator namespace.
  4. On the External DNS Operator page, click Install.
  5. On the Install Operator page, ensure that you selected the following options:

    1. Update the channel as stable-v1.0.
    2. Installation mode as A specific name on the cluster.
    3. Installed namespace as external-dns-operator. If namespace external-dns-operator does not exist, it gets created during the Operator installation.
    4. Select Approval Strategy as Automatic or Manual. Approval Strategy is set to Automatic by default.
    5. Click Install.

If you select Automatic updates, the Operator Lifecycle Manager (OLM) automatically upgrades the running instance of your Operator without any intervention.

If you select Manual updates, the OLM creates an update request. As a cluster administrator, you must then manually approve that update request to have the Operator updated to the new version.

Verification

Verify that External DNS Operator shows the Status as Succeeded on the Installed Operators dashboard.

14.3. External DNS Operator configuration parameters

The External DNS Operators includes the following configuration parameters:

14.3.1. External DNS Operator configuration parameters

The External DNS Operator includes the following configuration parameters:

ParameterDescription

spec

Enables the type of a cloud provider.

spec:
  provider:
    type: AWS 1
    aws:
      credentials:
        name: aws-access-key 2
1
Defines available options such as AWS, GCP and Azure.
2
Defines a name of the secret which contains credentials for your cloud provider.

zones

Enables you to specify DNS zones by their domains. If you do not specify zones, ExternalDNS discovers all the zones present in your cloud provider account.

zones:
- "myzoneid" 1
1
Specifies the IDs of DNS zones.

domains

Enables you to specify AWS zones by their domains. If you do not specify domains, ExternalDNS discovers all the zones present in your cloud provider account.

domains:
- filterType: Include 1
  matchType: Exact 2
  name: "myzonedomain1.com" 3
- filterType: Include
  matchType: Pattern 4
  pattern: ".*\\.otherzonedomain\\.com" 5
1
Instructs ExternalDNS to include the domain specified.
2
Instructs ExtrnalDNS that the domain matching has to be exact as opposed to regular expression match.
3
Defines the exact domain name by which ExternalDNS filters.
4
Sets regex-domain-filter flag in ExternalDNS. You can limit possible domains by using a Regex filter.
5
Defines the regex pattern to be used by ExternalDNS to filter the domains of the target zones.

source

Enables you to specify the source for the DNS records, Service or Route.

source: 1
  type: Service 2
  service:
    serviceType:3
      - LoadBalancer
      - ClusterIP
  labelFilter: 4
    matchLabels:
      external-dns.mydomain.org/publish: "yes"
  hostnameAnnotation: "Allow" 5
  fqdnTemplate:
  - "{{.Name}}.myzonedomain.com" 6
1
Defines the settings for the source of DNS records.
2
The ExternalDNS uses Service type as source for creating dns records.
3
Sets service-type-filter flag in ExternalDNS. The serviceType contains the following fields:
  • default: LoadBalancer
  • expected: ClusterIP
  • NodePort
  • LoadBalancer
  • ExternalName
4
Ensures that the controller considers only those resources which matches with label filter.
5
The default value for hostnameAnnotation is Ignore which instructs ExternalDNS to generate DNS records using the templates specified in the field fqdnTemplates. When the value is Allow the DNS records get generated based on the value specified in the external-dns.alpha.kubernetes.io/hostname annotation.
6
External DNS Operator uses a string to generate DNS names from sources that don’t define a hostname, or to add a hostname suffix when paired with the fake source.
source:
  type: OpenShiftRoute 1
  openshiftRouteOptions:
    routerName: default 2
    labelFilter:
      matchLabels:
        external-dns.mydomain.org/publish: "yes"
1
ExternalDNS` uses type route as source for creating dns records.
2
If the source is OpenShiftRoute, then you can pass the Ingress Controller name. The ExternalDNS uses canonical name of Ingress Controller as the target for CNAME record.

14.4. Creating DNS records on AWS

You can create DNS records on AWS and AWS GovCloud by using External DNS Operator.

14.4.1. Creating DNS records on an public hosted zone for AWS by using Red Hat External DNS Operator

You can create DNS records on a public hosted zone for AWS by using the Red Hat External DNS Operator. You can use the same instructions to create DNS records on a hosted zone for AWS GovCloud.

Procedure

  1. Check the user. The user must have access to the kube-system namespace. If you don’t have the credentials, as you can fetch the credentials from the kube-system namespace to use the cloud provider client:

    $ oc whoami

    Example output

    system:admin

  2. Fetch the values from aws-creds secret present in kube-system namespace.

    $ export AWS_ACCESS_KEY_ID=$(oc get secrets aws-creds -n kube-system  --template={{.data.aws_access_key_id}} | base64 -d)
    $ export AWS_SECRET_ACCESS_KEY=$(oc get secrets aws-creds -n kube-system  --template={{.data.aws_secret_access_key}} | base64 -d)
  3. Get the routes to check the domain:

    $ oc get routes --all-namespaces | grep console

    Example output

    openshift-console          console             console-openshift-console.apps.testextdnsoperator.apacshift.support                       console             https   reencrypt/Redirect     None
    openshift-console          downloads           downloads-openshift-console.apps.testextdnsoperator.apacshift.support                     downloads           http    edge/Redirect          None

  4. Get the list of dns zones to find the one which corresponds to the previously found route’s domain:

    $ aws route53 list-hosted-zones | grep testextdnsoperator.apacshift.support

    Example output

    HOSTEDZONES	terraform	/hostedzone/Z02355203TNN1XXXX1J6O	testextdnsoperator.apacshift.support.	5

  5. Create ExternalDNS resource for route source:

    $ cat <<EOF | oc create -f -
    apiVersion: externaldns.olm.openshift.io/v1alpha1
    kind: ExternalDNS
    metadata:
      name: sample-aws 1
    spec:
      domains:
      - filterType: Include   2
        matchType: Exact   3
        name: testextdnsoperator.apacshift.support 4
      provider:
        type: AWS 5
      source:  6
        type: OpenShiftRoute 7
        openshiftRouteOptions:
          routerName: default 8
    EOF
    1
    Defines the name of external DNS resource.
    2
    By default all hosted zones are selected as potential targets. You can include a hosted zone that you need.
    3
    The matching of the target zone’s domain has to be exact (as opposed to regular expression match).
    4
    Specify the exact domain of the zone you want to update. The hostname of the routes must be subdomains of the specified domain.
    5
    Defines the AWS Route53 DNS provider.
    6
    Defines options for the source of DNS records.
    7
    Defines OpenShift route resource as the source for the DNS records which gets created in the previously specified DNS provider.
    8
    If the source is OpenShiftRoute, then you can pass the OpenShift Ingress Controller name. External DNS Operator selects the canonical hostname of that router as the target while creating CNAME record.
  6. Check the records created for OCP routes using the following command:

    $ aws route53 list-resource-record-sets --hosted-zone-id Z02355203TNN1XXXX1J6O --query "ResourceRecordSets[?Type == 'CNAME']" | grep console

14.5. Creating DNS records on Azure

You can create DNS records on Azure using External DNS Operator.

14.5.1. Creating DNS records on an public DNS zone for Azure by using Red Hat External DNS Operator

You can create DNS records on a public DNS zone for Azure by using Red Hat External DNS Operator.

Procedure

  1. Check the user. The user must have access to the kube-system namespace. If you don’t have the credentials, as you can fetch the credentials from the kube-system namespace to use the cloud provider client:

    $ oc whoami

    Example output

    system:admin

  2. Fetch the values from azure-credentials secret present in kube-system namespace.

    $ CLIENT_ID=$(oc get secrets azure-credentials  -n kube-system  --template={{.data.azure_client_id}} | base64 -d)
    $ CLIENT_SECRET=$(oc get secrets azure-credentials  -n kube-system  --template={{.data.azure_client_secret}} | base64 -d)
    $ RESOURCE_GROUP=$(oc get secrets azure-credentials  -n kube-system  --template={{.data.azure_resourcegroup}} | base64 -d)
    $ SUBSCRIPTION_ID=$(oc get secrets azure-credentials  -n kube-system  --template={{.data.azure_subscription_id}} | base64 -d)
    $ TENANT_ID=$(oc get secrets azure-credentials  -n kube-system  --template={{.data.azure_tenant_id}} | base64 -d)
  3. Login to azure with base64 decoded values:

    $ az login --service-principal -u "${CLIENT_ID}" -p "${CLIENT_SECRET}" --tenant "${TENANT_ID}"
  4. Get the routes to check the domain:

    $ oc get routes --all-namespaces | grep console

    Example output

    openshift-console          console             console-openshift-console.apps.test.azure.example.com                       console             https   reencrypt/Redirect     None
    openshift-console          downloads           downloads-openshift-console.apps.test.azure.example.com                     downloads           http    edge/Redirect          None

  5. Get the list of dns zones to find the one which corresponds to the previously found route’s domain:

    $ az network dns zone list --resource-group "${RESOURCE_GROUP}"
  6. Create ExternalDNS resource for route source:

    apiVersion: externaldns.olm.openshift.io/v1alpha1
    kind: ExternalDNS
    metadata:
      name: sample-azure 1
    spec:
      zones:
      - "/subscriptions/1234567890/resourceGroups/test-azure-xxxxx-rg/providers/Microsoft.Network/dnszones/test.azure.example.com" 2
      provider:
        type: Azure 3
      source:
        openshiftRouteOptions: 4
          routerName: default 5
        type: OpenShiftRoute 6
    EOF
    1
    Specifies the name of External DNS CR.
    2
    Define the zone ID.
    3
    Defines the Azure DNS provider.
    4
    You can define options for the source of DNS records.
    5
    If the source is OpenShiftRoute then you can pass the OpenShift Ingress Controller name. External DNS selects the canonical hostname of that router as the target while creating CNAME record.
    6
    Defines OpenShift route resource as the source for the DNS records which gets created in the previously specified DNS provider.
  7. Check the records created for OCP routes using the following command:

    $ az network dns record-set list -g "${RESOURCE_GROUP}"  -z test.azure.example.com | grep console
    Note

    To create records on private hosted zones on private Azure dns, you need to specify the private zone under zones which populates the provider type to azure-private-dns in the ExternalDNS container args.

14.6. Creating DNS records on GCP

You can create DNS records on GCP using External DNS Operator.

14.6.1. Creating DNS records on an public managed zone for GCP by using Red Hat External DNS Operator

You can create DNS records on a public managed zone for GCP by using Red Hat External DNS Operator.

Procedure

  1. Check the user. The user must have access to the kube-system namespace. If you don’t have the credentials, as you can fetch the credentials from the kube-system namespace to use the cloud provider client:

    $ oc whoami

    Example output

    system:admin

  2. Copy the value of service_account.json in gcp-credentials secret in a file encoded-gcloud.json by running the following command:

    $ oc get secret gcp-credentials -n kube-system --template='{{$v := index .data "service_account.json"}}{{$v}}' | base64 -d - > decoded-gcloud.json
  3. Export Google credentials:

    $ export GOOGLE_CREDENTIALS=decoded-gcloud.json
  4. Activate your account by using the following command:

    $ gcloud auth activate-service-account  <client_email as per decoded-gcloud.json> --key-file=decoded-gcloud.json
  5. Set your project:

    $ gcloud config set project <project_id as per decoded-gcloud.json>
  6. Get the routes to check the domain:

    $ oc get routes --all-namespaces | grep console

    Example output

    openshift-console          console             console-openshift-console.apps.test.gcp.example.com                       console             https   reencrypt/Redirect     None
    openshift-console          downloads           downloads-openshift-console.apps.test.gcp.example.com                     downloads           http    edge/Redirect          None

  7. Get the list of managed zones to find the zone which corresponds to the previously found route’s domain:

    $ gcloud dns managed-zones list | grep test.gcp.example.com
    qe-cvs4g-private-zone test.gcp.example.com
  8. Create ExternalDNS resource for route source:

    apiVersion: externaldns.olm.openshift.io/v1alpha1
    kind: ExternalDNS
    metadata:
      name: sample-gcp 1
    spec:
      domains:
        - filterType: Include 2
          matchType: Exact 3
          name: test.gcp.example.com 4
      provider:
        type: GCP 5
      source:
        openshiftRouteOptions: 6
          routerName: default 7
        type: OpenShiftRoute 8
    EOF
    1
    Specifies the name of External DNS CR.
    2
    By default all hosted zones are selected as potential targets. You can include a hosted zone that you need.
    3
    The matching of the target zone’s domain has to be exact (as opposed to regular expression match).
    4
    Specify the exact domain of the zone you want to update. The hostname of the routes must be subdomains of the specified domain.
    5
    Defines Google Cloud DNS provider.
    6
    You can define options for the source of DNS records.
    7
    If the source is OpenShiftRoute then you can pass the OpenShift Ingress Controller name. External DNS selects the canonical hostname of that router as the target while creating CNAME record.
    8
    Defines OpenShift route resource as the source for the DNS records which gets created in the previously specified DNS provider.
  9. Check the records created for OCP routes using the following command:

    $ gcloud dns record-sets list --zone=qe-cvs4g-private-zone | grep console

14.7. Configuring the cluster-wide proxy on the External DNS Operator

You can configure the cluster-wide proxy in the External DNS Operator. After configuring the cluster-wide proxy in the External DNS Operator, Operator Lifecycle Manager (OLM) automatically updates all the deployments of the Operators with the environment variables such as HTTP_PROXY, HTTPS_PROXY, and NO_PROXY.

14.7.1. Configuring the External DNS Operator to trust the certificate authority of the cluster-wide proxy

You can configure the External DNS Operator to trust the certificate authority of the cluster-wide proxy.

Procedure

  1. Create the config map to contain the CA bundle in the external-dns-operator namespace by running the following command:

    $ oc -n external-dns-operator create configmap trusted-ca
  2. To inject the trusted CA bundle into the config map, add the config.openshift.io/inject-trusted-cabundle=true label to the config map by running the following command:

    $ oc -n external-dns-operator label cm trusted-ca config.openshift.io/inject-trusted-cabundle=true
  3. Update the subscription of the External DNS Operator by running the following command:

    $ oc -n external-dns-operator patch subscription external-dns-operator --type='json' -p='[{"op": "add", "path": "/spec/config", "value":{"env":[{"name":"TRUSTED_CA_CONFIGMAP_NAME","value":"trusted-ca"}]}}]'

Verification

  • After the deployment of the External DNS Operator is completed, verify that the trusted CA environment variable is added to the external-dns-operator deployment by running the following command:

    $ oc -n external-dns-operator exec deploy/external-dns-operator -c external-dns-operator -- printenv TRUSTED_CA_CONFIGMAP_NAME

    Example output

    trusted-ca