Refer to these instructions to install ExternalDNS on TKG cluster provisioned with a TKr for vSphere 7.x.
Prerequisites
See Workflow for Installing Standard Packages on TKr for vSphere 7.x.
Install ExternalDNS
Install ExternalDNS on a TKG cluster provisioned with TKr for vSphere 7.x.
- List the available ExternalDNS versions in the repository.
kubectl get packages -n tkg-system | grep external-dns
- Create the ExternalDNS namespace.
kubectl create namespace tanzu-system-service-discovery --dry-run=client -o yaml | kubectl apply -f -
- Set the security posture on the namespace.
kubectl label namespace tanzu-system-service-discovery pod-security.kubernetes.io/enforce=privileged
- Prepare the Bind deployment YAML.
See bind-deployment.yaml.
- Deploy the Bind DNS server.
kubectl apply -n tanzu-system-service-discovery -f bind-deployment.yaml
- Prepare the ExternalDNS deployment YAML.
- Create a secret using the
external-dns-default-values.yaml
file.svcip=$(kubectl get svc bind -n tanzu-system-service-discovery -o jsonpath='{.spec.clusterIP}')sed -i "s/--rfc2136-host=[0-9.]\+/--rfc2136-host=$svcip/g" external-dns-deploy.yaml
kubectl create secret generic external-dns-default-values --from-file=values.yaml=external-dns-deploy.yaml -n tkg-system
- Verify the secret.
kubectl get secret external-dns-default-values -n tkg-system
kubectl get secret external-dns-default-values -n tkg-system -oyaml
- Prepare the ExternalDNS package install YAML.
- Configure Bind.
sed -i "s/--rfc2136-host=[0-9.]\+/--rfc2136-host=$svcip/g" external-dns-packageinstall.yaml
- Create the External DNS package.
kubectl apply -f external-dns-packageinstall.yaml
- Verify ExternalDNS installation.
kubectl get all -n tanzu-system-service-discovery
bind-deployment.yaml
Example
bind-deployment.yaml
.
--- apiVersion: v1 kind: ConfigMap metadata: name: bind-config data: named.conf: | key "externaldns-key" { algorithm hmac-sha256; secret "O0DhTJzZ0GjfuQmB9TBc1ELchv5oDMTlQs3NNOdMZJU="; }; # bind needs to recurse to coredns in the case of resolving CNAME records # it may know about to A records. E.g This test runs on AWS which uses # CNAMEs for their LoadBalancer Services and bind will want to resolve # those CNAME records to A records using an upstream DNS server. options { recursion yes; forwarders { COREDNS_CLUSTER_IP; }; forward only; dnssec-enable yes; dnssec-validation yes; }; zone "k8s.example.org" { type master; file "/etc/bind/k8s.zone"; allow-transfer { key "externaldns-key"; }; update-policy { grant externaldns-key zonesub ANY; }; }; k8s.zone: | $TTL 60 ; 1 minute @ IN SOA k8s.example.org. root.k8s.example.org. ( 16 ; serial 60 ; refresh (1 minute) 60 ; retry (1 minute) 60 ; expire (1 minute) 60 ; minimum (1 minute) ) NS ns.k8s.example.org. ns A 1.2.3.4 --- apiVersion: apps/v1 kind: Deployment metadata: name: bind spec: selector: matchLabels: app: bind template: metadata: labels: app: bind spec: containers: - name: bind image: docker.io/internetsystemsconsortium/bind9:9.16 imagePullPolicy: IfNotPresent command: - 'sh' - '-c' - | /usr/sbin/named -g -c /etc/bind/named.conf ports: - containerPort: 53 name: dns protocol: UDP - containerPort: 53 name: dns-tcp protocol: TCP volumeMounts: - name: named-conf-volume mountPath: /etc/bind/named.conf subPath: named.conf - name: k8s-zone-volume mountPath: /etc/bind/k8s.zone subPath: k8s.zone volumes: - name: data emptyDir: {} - name: named-conf-volume configMap: name: bind-config items: - key: named.conf path: named.conf - name: k8s-zone-volume configMap: name: bind-config items: - key: k8s.zone path: k8s.zone --- apiVersion: v1 kind: Service metadata: name: bind labels: app: bind spec: selector: app: bind type: ClusterIP ports: - port: 53 targetPort: 53 protocol: TCP name: dns-tcp - port: 53 targetPort: 53 protocol: UDP name: dns
external-dns-deploy.yaml
Example
external-dns-deploy.yaml
.
deployment: args: - --source=service - --source=ingress - --txt-owner-id=k8s - --domain-filter=k8s.example.org - --namespace=default - --provider=rfc2136 - --rfc2136-host=198.201.49.227 - --rfc2136-port=53 - --rfc2136-zone=k8s.example.org - --rfc2136-tsig-secret=O0DhTJzZ0GjfuQmB9TBc1ELchv5oDMTlQs3NNOdMZJU= - --rfc2136-tsig-secret-alg=hmac-sha256 - --rfc2136-tsig-keyname=externaldns-key
external-dns-packageinstall.yaml
The following example can be used for BIND. Update the package version as needed.
apiVersion: v1 kind: ServiceAccount metadata: name: external-dns-default-sa namespace: tkg-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: dns-role-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: external-dns-default-sa namespace: tkg-system --- apiVersion: packaging.carvel.dev/v1alpha1 kind: PackageInstall metadata: name: dns namespace: tkg-system spec: serviceAccountName: external-dns-default-sa packageRef: refName: external-dns.tanzu.vmware.com versionSelection: constraints: 0.13.6+vmware.1-tkg.1 values: - secretRef: name: external-dns-default-values --- apiVersion: v1 kind: Secret metadata: name: external-dns-reg-creds namespace: tanzu-system-service-discovery stringData: values.yml: | --- namespace: tanzu-system-service-discovery dns: deployment: args: - --txt-owner-id=k8s - --provider=rfc2136 - --rfc2136-host=198.201.49.227 #! IP of compatible DNS server - --rfc2136-port=53 - --rfc2136-zone=mk8s.example.org #! zone where services are deployed - --rfc2136-tsig-secret=O0DhTJzZ0GjfuQmB9TBc1ELchv5oDMTlQs3NNOdMZJU= #! TSIG secret authorized to update DNS - --rfc2136-tsig-secret-alg=hmac-sha256 - --rfc2136-tsig-keyname=externaldns-key - --rfc2136-tsig-axfr - --source=service - --source=ingress - --domain-filter=k8s.example.org1 #! zone where services are deployed
The following example can be used for AWS DNS provider (Route 53). Update the package version as needed.
apiVersion: v1 kind: ServiceAccount metadata: name: dns-sa namespace: tkg-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: dns-role-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: dns-sa namespace: tkg-system --- apiVersion: packaging.carvel.dev/v1alpha1 kind: PackageInstall metadata: name: dns namespace: tkg-system spec: serviceAccountName: dns-sa packageRef: refName: dns.tanzu.vmware.com versionSelection: constraints: 0.13.6+vmware.1-tkg.1 values: - secretRef: name: dns-data-values --- apiVersion: v1 kind: Secret metadata: name: dns-data-values namespace: tkg-system stringData: values.yml: | --- namespace: tanzu-system-service-discovery dns: pspNames: "vmware-system-restricted" deployment: args: - --source=service - --source=ingress - --source=contour-httpproxy #! configure external-dns to read Contour HTTPProxy resources - --domain-filter=my-zone.example.org #! zone where services are deployed - --provider=aws - --policy=upsert-only #! prevent deleting any records, omit to enable full sync - --aws-zone-type=public #! only look at public hosted zones (public, private, no value for both) - --aws-prefer-cname - --registry=txt - --txt-owner-id=ROUTE_53_HOSTED_ZONE_ID #! Route53 hosted zone identifier for my-zone.example.org - --txt-prefix=txt #! disambiguates TXT records from CNAME records env: - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: name: route53-credentials #! Kubernetes secret for route53 credentials key: aws_access_key_id - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: route53-credentials #! Kubernetes secret for route53 credentials key: aws_secret_access_key
The following example can be used for an Azure DNS provider. Update the package version as needed.
apiVersion: v1 kind: ServiceAccount metadata: name: dns-sa namespace: tkg-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: dns-role-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: dns-sa namespace: tkg-system --- apiVersion: packaging.carvel.dev/v1alpha1 kind: PackageInstall metadata: name: dns namespace: tkg-system spec: serviceAccountName: dns-sa packageRef: refName: dns.tanzu.vmware.com versionSelection: constraints: 0.13.6+vmware.1-tkg.1 values: - secretRef: name: dns-data-values --- apiVersion: v1 kind: Secret metadata: name: dns-data-values namespace: tkg-system stringData: values.yml: | --- namespace: tanzu-system-service-discovery dns: pspNames: "vmware-system-restricted" deployment: args: - --provider=azure - --source=service - --source=ingress - --source=contour-httpproxy #! read Contour HTTPProxy resources - --domain-filter=my-zone.example.org #! zone where services are deployed - --azure-resource-group=my-resource-group #! Azure resource group volumeMounts: - name: azure-config-file mountPath: /etc/kubernetes readOnly: true #@overlay/replace volumes: - name: azure-config-file secret: secretName: azure-config-file