Skip to content

Commit

Permalink
adjust readme
Browse files Browse the repository at this point in the history
  • Loading branch information
PatrickKoss committed Oct 18, 2023
1 parent 9c23f99 commit 09ef566
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 26 deletions.
146 changes: 126 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,31 @@
[![GitHub stars](https://img.shields.io/github/stars/stackitcloud/external-dns-stackit-webhook.svg?style=social&label=Star&maxAge=2592000)](https://github.com/stackitcloud/external-dns-stackit-webhook/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/stackitcloud/external-dns-stackit-webhook.svg?style=social&label=Fork&maxAge=2592000)](https://github.com/stackitcloud/external-dns-stackit-webhook/network)

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 DNS
records internally, ExternalDNS augments this functionality by transferring the responsibility of DNS records
management to an external DNS provider such as STACKIT. Consequently, the STACKIT webhook enables the management
of your STACKIT domains within your Kubernetes cluster using
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 DNS
records internally, ExternalDNS augments this functionality by transferring the responsibility of DNS records
management to an external DNS provider such as STACKIT. Consequently, the STACKIT webhook enables the management
of your STACKIT domains within your Kubernetes cluster using
[ExternalDNS](https://github.com/kubernetes-sigs/external-dns).

For utilizing ExternalDNS with STACKIT, it is mandatory to establish a STACKIT project, a service account
within the project, generate an authentication token for the service account, authorize the service account
For utilizing ExternalDNS with STACKIT, it is mandatory to establish a STACKIT project, a service account
within the project, generate an authentication token for the service account, authorize the service account
to create and read dns zones, and finally, establish a STACKIT zone.

## Kubernetes Deployment
The STACKIT webhook is presented as a standard Open Container Initiative (OCI) image released in the
[GitHub container registry](https://github.com/stackitcloud/external-dns-stackit-webhook/pkgs/container/external-dns-stackit-webhook).
The deployment is compatible with all Kubernetes-supported methods. The subsequent example
demonstrates the deployment as a
[sidecar container](https://kubernetes.io/docs/concepts/workloads/pods/#workload-resources-for-managing-pods)

The STACKIT webhook is presented as a standard Open Container Initiative (OCI) image released in the
[GitHub container registry](https://github.com/stackitcloud/external-dns-stackit-webhook/pkgs/container/external-dns-stackit-webhook).
The deployment is compatible with all Kubernetes-supported methods. The subsequent example
demonstrates the deployment as a
[sidecar container](https://kubernetes.io/docs/concepts/workloads/pods/#workload-resources-for-managing-pods)
within the ExternalDNS pod.

```shell
kubectl create secret generic external-dns-stackit-webhook --from-literal=auth-token='<Your-Token>'
```

```shell
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
Expand Down Expand Up @@ -141,9 +144,8 @@ spec:
- --interval=1m
- --source=service
- --source=ingress
- --policy=sync
- --policy=sync # set it upsert-only if you don't want it to delete records
- --provider=webhook
- --webhook-provider-url=http://localhost:8888
ports:
- name: http
protocol: TCP
Expand Down Expand Up @@ -174,7 +176,7 @@ spec:
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65534
image: ghcr.io/stackitcloud/external-dns-stackit-webhook:v0.1.0
image: ghcr.io/stackitcloud/external-dns-stackit-webhook:v0.2.0
imagePullPolicy: IfNotPresent
args:
- --project-id=c158c736-0300-4044-95c4-b7d404279b35 # your project id
Expand Down Expand Up @@ -210,20 +212,122 @@ EOF
```

## Configuration
The configuration of the STACKIT webhook can be accomplished through command line arguments and environment variables.

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): Defines the authentication token for the STACKIT API.
- `--worker`/`WORKER` (optional): Specifies the number of workers to employ for querying the API. Given that we
need to iterate over all zones and records, it can be parallelized. However, it is important to avoid
setting 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").
- `--worker`/`WORKER` (optional): Specifies the number of workers to employ for querying the API. Given that we
need to iterate over all zones and records, it can be parallelized. However, it is important to avoid
setting 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".

## FAQ

### 1. Issue with Creating Service using External DNS Annotation

If your zone is `example.runs.onstackit.cloud` and you're trying to create a service with the following external DNS
annotation:

```yaml
apiVersion: v1
kind: Service
metadata:
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-controller
spec:
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
```

<b>Why isn't it working?</b>

<b>Answer</b>: The External DNS will try to create a TXT record named `a-example.runs.onstackit.cloud`, which will fail
because you can't establish a record outside the zone. The solution is to use a name that's within the zone, such as
`nginx.example.runs.onstackit.cloud`.

### 2. Issues with Creating Ingresses not in the Zone

For a project containing the zone `example.runs.onstackit.cloud`, suppose you've created these two ingress:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: nginx
name: example-ingress-external-dns
namespace: default
spec:
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
```

<b>Why isn't it working?</b>

<b>Answer</b>: External DNS will attempt to establish a record set for `test.example.stackit.rocks`. As the zone
`example.stackit.rocks` isn't within the project, it'll fail. There are two potential fixes:

- Incorporate the zone `example.stackit.rocks` into the project.
- Adjust the domain filter to `example.runs.onstackit.cloud` by setting the domain filter
flag `--domain-filter="example.runs.onstackit.cloud"`. This will exclude `test.example.stackit.rocks` and only
generate
the record set for `test.example.runs.onstackit.cloud`.

## Development

Run the app:

```bash
export BASE_URL="https://dns.api.stackit.cloud"
export PROJECT_ID="c158c736-0300-4044-95c4-b7d404279b35"
Expand All @@ -233,11 +337,13 @@ make run
```

Lint the code:

```bash
make lint
```

Test the code:

```bash
make test
```
12 changes: 6 additions & 6 deletions cmd/webhook/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package cmd

import (
"fmt"
"go.uber.org/zap/zapcore"
"log"
"net/http"
"strings"
Expand All @@ -15,6 +14,7 @@ import (
"github.com/stackitcloud/external-dns-stackit-webhook/pkg/api"
"github.com/stackitcloud/external-dns-stackit-webhook/pkg/metrics"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"sigs.k8s.io/external-dns/endpoint"
)

Expand Down Expand Up @@ -89,13 +89,13 @@ func getLogger() *zap.Logger {

func getZapLogLevel() zapcore.Level {
switch logLevel {
case "DEBUG":
case "debug":
return zapcore.DebugLevel
case "INFO":
case "info":
return zapcore.InfoLevel
case "WARN":
case "warn":
return zapcore.WarnLevel
case "ERROR":
case "error":
return zapcore.ErrorLevel
default:
return zapcore.InfoLevel
Expand All @@ -119,7 +119,7 @@ func init() {
"excessively high to prevent receiving 429 rate limiting from the API.")
rootCmd.PersistentFlags().StringArrayVar(&domainFilter, "domain-filter", []string{}, "Establishes a filter for DNS zone names")
rootCmd.PersistentFlags().BoolVar(&dryRun, "dry-run", false, "Specifies whether to perform a dry run.")
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "INFO", "Specifies the log level. Possible values are: DEBUG, INFO, WARN, ERROR")
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "Specifies the log level. Possible values are: debug, info, warn, error")
}

func initConfig() {
Expand Down

0 comments on commit 09ef566

Please sign in to comment.