Sign inSign up

bunnyshell/external-dns-custom

By bunnyshell

•Updated over 2 years ago

Image
0

114

bunnyshell/external-dns-custom repository overview

This image is meant to be used as sidecar for external-dns⁠ and implements a custom DNS provider. The custom provider is in fact 2 providers, and AWS one and a Cloudflare one, configured to be used in Cloudflare Zero Trust setup.

It can be installed with bitnami external-dns chart⁠ with a values.yaml like:

provider: webhook
policy: sync
interval: "1m"
sources:
  - ingress
domainFilters:
  - mydomain.com

registry: "txt"
txtPrefix: "reg-"
txtOwnerId: k8s-ext-dns-custom

logLevel: info
logFormat: text

extraArgs:
  webhook-provider-url: http://localhost:8888

aws:
  credentials:
    accessKey: "AKIA123..."
    secretKey: "abc123..."
  region: eu-west-1
  zoneType: public
  apiRetries: 3
  preferCNAME: true


cloudflare:
  apiToken: "abc123..."

custom:
  image: bunnyshell/external-dns-custom:v0.14.1
  secretName: &custom-secret-name external-dns-custom
  awsTargetSuffix: .cdn.cloudflare.net
  cloudflareTargetOverride: abc-123.cfargotunnel.com

sidecars:
  |-
  - name: ext-dns-custom
    image: {{ .Values.custom.image }}
    imagePullPolicy: Always
    args:
      - --metrics-address=:7879   # use another port than the main container
      {{- if .Values.logLevel }}
      - --log-level={{ .Values.logLevel }}
      {{- end }}
      {{- if .Values.logFormat }}
      - --log-format={{ .Values.logFormat }}
      {{- end }}
      {{- range .Values.domainFilters }}
      - --domain-filter={{ . }}
      {{- end }}
      {{- range .Values.excludeDomains }}
      - --exclude-domains={{ . }}
      {{- end }}
      {{- if .Values.regexDomainFilter }}
      - --regex-domain-filter={{ .Values.regexDomainFilter }}
      {{- end }}
      {{- if .Values.regexDomainExclusion }}
      - --regex-domain-exclusion={{ .Values.regexDomainExclusion }}
      {{- end }}
      {{- range .Values.zoneNameFilters }}
      - --zone-name-filter={{ . }}
      {{- end }}
      {{- range .Values.zoneIdFilters }}
      - --zone-id-filter={{ . }}
      {{- end }}
      - --policy={{ .Values.policy }}
      - --registry={{ .Values.registry }}
      - --interval={{ .Values.interval }}
      {{- if or (ne .Values.registry "aws-sd" ) .Values.forceTxtOwnerId }}
      {{- if .Values.txtOwnerId }}
      - --txt-owner-id={{ .Values.txtOwnerId }}
      {{- end }}
      {{- end }}
      {{- if eq .Values.registry "txt" }}
      {{- if .Values.txtPrefix }}
      - --txt-prefix={{ .Values.txtPrefix }}
      {{- end }}
      {{- if .Values.txtSuffix }}
      - --txt-suffix={{ .Values.txtSuffix }}
      {{- end }}
      {{- end }}
      # AWS arguments
      {{- if .Values.aws.apiRetries }}
      - --aws-api-retries={{ .Values.aws.apiRetries }}
      {{- end }}
      - --aws-zone-type={{ .Values.aws.zoneType }}
      {{- if .Values.aws.assumeRoleArn }}
      - --aws-assume-role={{ .Values.aws.assumeRoleArn }}
      {{- end }}
      {{- if .Values.aws.batchChangeSize }}
      - --aws-batch-change-size={{ .Values.aws.batchChangeSize }}
      {{- end }}
      {{- if .Values.aws.zonesCacheDuration }}
      - --aws-zones-cache-duration={{ .Values.aws.zonesCacheDuration }}
      {{- end }}
      {{- range .Values.aws.zoneTags }}
      - --aws-zone-tags={{ . }}
      {{- end }}
      {{- if .Values.aws.preferCNAME }}
      - --aws-prefer-cname
      {{- end }}
      {{- if .Values.aws.dynamodbTable }}
      - --dynamodb-table={{ .Values.aws.dynamodbTable }}
      {{- end }}
      {{- if .Values.aws.dynamodbRegion }}
      - --dynamodb-region={{ .Values.aws.dynamodbRegion }}
      {{- end }}
      {{- if and (kindIs "bool" .Values.aws.evaluateTargetHealth) (not .Values.aws.evaluateTargetHealth) }}
      - --no-aws-evaluate-target-health
      {{- end }}
      # Cloudflare arguments
      {{- if .Values.cloudflare.proxied }}
      - --cloudflare-proxied
      {{- end }}
      # args for custom provider
      - --webhook-server # act like a 3rd party provider (not as controller); main container should be set on provider=webhook
      - --source=fake # ignored in webhook-server setup but required; this one is preferred as it does nothing extra
      - --provider=custom # specially crafted provider with desired logic inside
      - --custom-aws-target-suffix={{ .Values.custom.awsTargetSuffix }} # all AWS R53 DNS records will point to target = hostname + this suffix; should be .cloudflare.net
      - --custom-cf-target-override={{ .Values.custom.cloudflareTargetOverride }} # all CloudFlare DNS records will point to this target; should be the tunnel domain
    env:
      # AWS environment variables
      {{- if .Values.aws.region }}
      - name: AWS_DEFAULT_REGION
        value: {{ .Values.aws.region }}
      {{- end }}
      {{- if .Values.aws.roleArn }}
      - name: AWS_CONFIG_FILE
        value: {{ .Values.aws.credentials.mountPath }}/config
      {{- end }}
      {{- if and .Values.aws.credentials.secretKey .Values.aws.credentials.accessKey (not (include "external-dns.aws-credentials-secret-ref-defined" . )) }}
      - name: AWS_SHARED_CREDENTIALS_FILE
        value: {{ .Values.aws.credentials.mountPath }}/credentials
      {{- end }}
      {{- if (include "external-dns.aws-credentials-secret-ref-defined" . ) }}
      - name: AWS_ACCESS_KEY_ID
        valueFrom:
          secretKeyRef:
            name: {{ .Values.aws.credentials.accessKeyIDSecretRef.name }}
            key: {{ .Values.aws.credentials.accessKeyIDSecretRef.key }}
      - name: AWS_SECRET_KEY
        valueFrom:
          secretKeyRef:
            name: {{ .Values.aws.credentials.secretAccessKeySecretRef.name }}
            key: {{ .Values.aws.credentials.secretAccessKeySecretRef.key }}
      {{- end }}
      # Cloudflare environment variables
      - name: CF_API_TOKEN
        valueFrom:
          secretKeyRef:
            name: {{ .Values.custom.secretName }}
            key: cloudflare_api_token
            optional: true
      - name: CF_API_KEY
        valueFrom:
          secretKeyRef:
            name: {{ .Values.custom.secretName }}
            key: cloudflare_api_key
            optional: true
      - name: CF_API_EMAIL
        value: {{ .Values.cloudflare.email | quote }}

      {{- if and .Values.txtEncrypt.enabled }}
      - name: TXT_AES_ENCRYPTION_KEY
        valueFrom:
          secretKeyRef:
            name: {{ template "external-dns.txtEncryptKeySecretName" . }}
            key: txt_aes_encryption_key
      {{- end }}
    ports:
      - containerPort: 8888 # port on which external-dns acts as a 3rd party provider (hardcoded)
        name: webhook
    {{- if .Values.resources }}
    resources: {{- toYaml .Values.resources | nindent 12 }}
    {{- else if ne .Values.resourcesPreset "none" }}
    resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }}
    {{- end }}
    volumeMounts:
      {{- if and (or (and .Values.aws.credentials.secretKey .Values.aws.credentials.accessKey) .Values.aws.credentials.secretName) (not (include "external-dns.aws-credentials-secret-ref-defined" . )) }}
      # AWS mountPath(s)
      - name: aws-credentials # volume mount just like when provider=aws; add the volume in Helm at extraVolumes
        mountPath: {{ .Values.aws.credentials.mountPath }}
        readOnly: true
      {{- end }}


extraDeploy:
  - |
    {{- if eq .Values.provider "webhook" }}
    apiVersion: v1
    kind: Secret
    metadata:
      name: {{ .Values.custom.secretName }}
      namespace: {{ .Release.Namespace | quote }}
      labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
      {{- if or .Values.secretAnnotations .Values.commonAnnotations }}
      {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.secretAnnotations .Values.commonAnnotations ) "context" . ) }}
      annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
      {{- end }}
    type: Opaque
    data:
      credentials: {{ include "external-dns.aws-credentials" . | b64enc | quote }}
      {{- if .Values.aws.region }}
      config: {{ include "external-dns.aws-config" . | b64enc | quote }}
      {{- end }}
      {{- if .Values.cloudflare.apiToken }}
      cloudflare_api_token: {{ .Values.cloudflare.apiToken | b64enc | quote }}
      {{- else }}
      cloudflare_api_key: {{ required "cloudflare.apiKey is required if cloudflare.apiToken is not provided" .Values.cloudflare.apiKey | b64enc | quote }}
      {{- end }}
    {{- end }}

extraVolumes:
  # AWS volume(s)
  - name: aws-credentials
    secret:
      secretName: *custom-secret-name

Tag summary

Content type

Image

Digest

sha256:c0c8127b2…

Size

52 MB

Last updated

over 2 years ago

docker pull bunnyshell/external-dns-custom:v0.14.1