- Notifications
You must be signed in to change notification settings - Fork4
External-DNS Webhook Provider to manage STACKIT DNS Records
License
stackitcloud/external-dns-stackit-webhook
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
ExternalDNS serves as an add-on for Kubernetes designed to automate the management of Domain Name System (DNS)records for Kubernetes services by utilizing various DNS providers. While Kubernetes traditionally manages DNSrecords internally, ExternalDNS augments this functionality by transferring the responsibility of DNS recordsmanagement to an external DNS provider such as STACKIT. Consequently, the STACKIT webhook enables the managementof your STACKIT domains within your Kubernetes cluster usingExternalDNS.
For utilizing ExternalDNS with STACKIT, it is mandatory to establish a STACKIT project, a service accountwithin the project, generate an authentication token for the service account, authorize the service accountto create and read dns zones, and finally, establish a STACKIT zone.
The STACKIT webhook is presented as a standard Open Container Initiative (OCI) image released in theGitHub container registry.The deployment is compatible with all Kubernetes-supported methods. The subsequent exampledemonstrates the deployment as asidecar containerwithin the ExternalDNS pod.
# We create a Secret from an auth token. Alternatively, you can also# use keys to authenticate the webhook - see "Authentication" below.kubectl create secret generic external-dns-stackit-webhook --from-literal=auth-token='<Your-Token>'
kubectl apply -f -<<EOFapiVersion: v1kind: ServiceAccountmetadata: name: external-dns namespace: default labels: app.kubernetes.io/name: external-dns app.kubernetes.io/instance: external-dns---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: external-dns labels: app.kubernetes.io/name: external-dns app.kubernetes.io/instance: external-dnsrules: - apiGroups: [""] resources: ["nodes"] verbs: ["list","watch"] - apiGroups: [""] resources: ["pods"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["services","endpoints"] verbs: ["get","watch","list"] - apiGroups: ["extensions","networking.k8s.io"] resources: ["ingresses"] verbs: ["get","watch","list"]---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: external-dns-viewer labels: app.kubernetes.io/name: external-dns app.kubernetes.io/instance: external-dnsroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: external-dnssubjects: - kind: ServiceAccount name: external-dns namespace: default---apiVersion: v1kind: Servicemetadata: name: external-dns namespace: default labels: app.kubernetes.io/name: external-dns app.kubernetes.io/instance: external-dnsspec: type: ClusterIP selector: app.kubernetes.io/name: external-dns app.kubernetes.io/instance: external-dns ports: - name: http port: 7979 targetPort: http protocol: TCP---apiVersion: apps/v1kind: Deploymentmetadata: name: external-dns namespace: default labels: app.kubernetes.io/name: external-dns app.kubernetes.io/instance: external-dnsspec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: external-dns app.kubernetes.io/instance: external-dns strategy: type: Recreate template: metadata: labels: app.kubernetes.io/name: external-dns app.kubernetes.io/instance: external-dns spec: serviceAccountName: external-dns securityContext: fsGroup: 65534 containers: - name: external-dns securityContext: capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 65534 image: registry.k8s.io/external-dns/external-dns:v0.14.0 imagePullPolicy: IfNotPresent args: - --log-level=info - --log-format=text - --interval=1m - --source=service - --source=ingress - --policy=sync # set it upsert-only if you don't want it to delete records - --provider=webhook ports: - name: http protocol: TCP containerPort: 7979 livenessProbe: failureThreshold: 2 httpGet: path: /healthz port: http initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5 readinessProbe: failureThreshold: 6 httpGet: path: /healthz port: http initialDelaySeconds: 5 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5 - name: webhook securityContext: capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 65534 image: ghcr.io/stackitcloud/external-dns-stackit-webhook:v0.2.0 imagePullPolicy: IfNotPresent args: - --project-id=c158c736-0300-4044-95c4-b7d404279b35 # your project id ports: - name: http protocol: TCP containerPort: 8888 livenessProbe: failureThreshold: 2 httpGet: path: /healthz port: http initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5 readinessProbe: failureThreshold: 6 httpGet: path: /healthz port: http initialDelaySeconds: 5 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5 env: - name: AUTH_TOKEN valueFrom: secretKeyRef: name: external-dns-stackit-webhook key: auth-tokenEOF
The configuration of the STACKIT webhook can be accomplished through command line arguments and environment variables.Below are the options that are available.
--project-id/PROJECT_ID(required): Specifies the project id of the STACKIT project.--auth-token/AUTH_TOKEN(required ifauth-key-pathis not set): Defines the authentication token for the STACKIT API. Mutually exclusive with 'auth-key-path'.--auth-key-path/AUTH_KEY_PATH(required ifauth-tokenis not set): Defines the file path of the service account key for the STACKIT API. Mutually exclusive with 'auth-token'.--worker/WORKER(optional): Specifies the number of workers to employ for querying the API. Given that weneed to iterate over all zones and records, it can be parallelized. However, it is important to avoidsetting this number excessively high to prevent receiving 429 rate limiting from the API (default 10).--base-url/BASE_URL(optional): Identifies the Base URL for utilizing the API (default "https://dns.api.stackit.cloud").--api-port/API_PORT(optional): Specifies the port to listen on (default 8888).--domain-filter/DOMAIN_FILER(optional): Establishes a filter for DNS zone names (default []).--dry-run/DRY_RUN(optional): Specifies whether to perform a dry run (default false).--log-level/LOG_LEVEL(optional): Defines the log level (default "info"). Possible values are: debug, info, warn,error.
If your zone isexample.runs.onstackit.cloud and you're trying to create a service with the following external DNSannotation:
```yamlapiVersion: v1kind: Servicemetadata: annotations: external-dns.alpha.kubernetes.io/hostname: example.runs.onstackit.cloud labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/component: controller name: nginx-ingress-controller namespace: nginx-ingress-controllerspec: type: LoadBalancer externalTrafficPolicy: Local ipFamilyPolicy: SingleStack ipFamilies: - IPv4 ports: - name: http port: 80 protocol: TCP targetPort: http - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: nginx app.kubernetes.io/name: ingress-nginx```Why isn't it working?
Answer: The External DNS will try to create a TXT record nameda-example.runs.onstackit.cloud, which will failbecause you can't establish a record outside the zone. The solution is to use a name that's within the zone, such asnginx.example.runs.onstackit.cloud.
For a project containing the zoneexample.runs.onstackit.cloud, suppose you've created these two ingress:
```yamlapiVersion: networking.k8s.io/v1kind: Ingressmetadata: annotations: ingress.kubernetes.io/rewrite-target: / kubernetes.io/ingress.class: nginx name: example-ingress-external-dns namespace: defaultspec: rules: - host: test.example.runs.onstackit.cloud http: paths: - backend: service: name: example port: number: 80 path: / pathType: Prefix - host: test.example.stackit.rocks http: paths: - backend: service: name: example port: number: 80 path: / pathType: Prefix```Why isn't it working?
Answer: External DNS will attempt to establish a record set fortest.example.stackit.rocks. As the zoneexample.stackit.rocks isn't within the project, it'll fail. There are two potential fixes:
- Incorporate the zone
example.stackit.rocksinto the project. - Adjust the domain filter to
example.runs.onstackit.cloudby setting the domain filterflag--domain-filter="example.runs.onstackit.cloud". This will excludetest.example.stackit.rocksand onlygeneratethe record set fortest.example.runs.onstackit.cloud.
Run the app:
export BASE_URL="https://dns.api.stackit.cloud"export PROJECT_ID="c158c736-0300-4044-95c4-b7d404279b35"export AUTH_TOKEN="your-auth-token"make run
Lint the code:
make lint
Test the code:
maketestAbout
External-DNS Webhook Provider to manage STACKIT DNS Records
Topics
Resources
License
Contributing
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Contributors7
Uh oh!
There was an error while loading.Please reload this page.