Skip to content

Commit

Permalink
Merge pull request #1 from ormequ/main
Browse files Browse the repository at this point in the history
feat(all) Add support of Selectel DNS
  • Loading branch information
TawR1024 authored Apr 8, 2024
2 parents c5a9e2d + c486e99 commit 155ad16
Show file tree
Hide file tree
Showing 49 changed files with 1,427 additions and 1,586 deletions.
10 changes: 5 additions & 5 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
project_name: external-dns-stackit-webhook
project_name: external-dns-selectel-webhook
snapshot:
name_template: '{{ .Tag }}-SNAPSHOT'
builds:
- id: external-dns-stackit-webhook
- id: external-dns-selectel-webhook
goos:
- linux
- windows
Expand All @@ -11,7 +11,7 @@ builds:
- amd64
- arm64
main: ./cmd/webhook
binary: external-dns-stackit-webhook
binary: external-dns-selectel-webhook
env:
- CGO_ENABLED=0
ldflags:
Expand All @@ -36,7 +36,7 @@ archives:
- goos: windows
format: zip
dockers:
- id: external-dns-stackit-webhook
- id: external-dns-selectel-webhook
use: buildx
image_templates:
- "{{ .Env.REGISTRY }}/{{ .Env.IMAGE_NAME }}:{{ .Tag }}"
Expand All @@ -46,7 +46,7 @@ dockers:
goarch: amd64
build_flag_templates:
- --label=org.opencontainers.image.title={{ .ProjectName }}
- --label=org.opencontainers.image.description=stackit DNS webhook for external-dns
- --label=org.opencontainers.image.description=selectel DNS webhook for external-dns
- --label=org.opencontainers.image.url=https://{{ .Env.GITHUB_SERVER_URL }}/{{ .Env.GITHUB_REPOSITORY}}
- --label=org.opencontainers.image.source=https://{{ .Env.GITHUB_SERVER_URL }}/{{ .Env.GITHUB_REPOSITORY}}
- --label=org.opencontainers.image.version={{ .Version }}
Expand Down
37 changes: 0 additions & 37 deletions CONTRIBUTING.md

This file was deleted.

4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FROM gcr.io/distroless/static-debian11:nonroot

COPY external-dns-stackit-webhook /external-dns-stackit-webhook
COPY external-dns-selectel-webhook /external-dns-selectel-webhook

ENTRYPOINT ["/external-dns-stackit-webhook"]
ENTRYPOINT ["/external-dns-selectel-webhook"]
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ GOLANGCI_VERSION = 1.53.3
LICENCES_IGNORE_LIST = $(shell cat licenses/licenses-ignore-list.txt)

VERSION ?= 0.0.1
IMAGE_TAG_BASE ?= stackitcloud/external-dns-stackit-webhook
IMAGE_TAG_BASE ?= selectel/external-dns-selectel-webhook
IMG ?= $(IMAGE_TAG_BASE):$(VERSION)

BUILD_VERSION ?= $(shell git branch --show-current)
Expand All @@ -17,7 +17,7 @@ download:

.PHONY: build
build:
CGO_ENABLED=0 go build -ldflags "-s -w" -o ./bin/external-dns-stackit-webhook -v cmd/webhook/main.go
CGO_ENABLED=0 go build -ldflags "-s -w" -o ./bin/external-dns-selectel-webhook -v cmd/webhook/main.go

.PHONY: docker-build
docker-build:
Expand Down Expand Up @@ -67,7 +67,7 @@ $(GO_RELEASER):

.PHONY: release-check
release-check: $(GO_RELEASER) ## Check if the release will work
GITHUB_SERVER_URL=github.com GITHUB_REPOSITORY=stackitcloud/external-dns-stackit-webhook REGISTRY=$(REGISTRY) IMAGE_NAME=$(IMAGE_NAME) $(GO_RELEASER) release --snapshot --clean --skip-publish
GITHUB_SERVER_URL=github.com GITHUB_REPOSITORY=selectel/external-dns-selectel-webhook REGISTRY=$(REGISTRY) IMAGE_NAME=$(IMAGE_NAME) $(GO_RELEASER) release --snapshot --clean --skip-publish

GO_LICENSES = bin/go-licenses
$(GO_LICENSES):
Expand Down
166 changes: 37 additions & 129 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,36 @@
# STACKIT Webhook - ExternalDNS
# Selectel Webhook - ExternalDNS

[![GoTemplate](https://img.shields.io/badge/go/template-black?logo=go)](https://github.com/golang-standards/project-layout)
[![CI](https://github.com/stackitcloud/external-dns-stackit-webhook/actions/workflows/main.yml/badge.svg)](https://github.com/stackitcloud/external-dns-stackit-webhook/actions/workflows/main.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/stackitcloud/external-dns-stackit-webhook)](https://goreportcard.com/report/github.com/stackitcloud/external-dns-stackit-webhook)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![GitHub release](https://img.shields.io/github/release/stackitcloud/external-dns-stackit-webhook.svg)](https://github.com/stackitcloud/external-dns-stackit-webhook/releases)
[![Last Commit](https://img.shields.io/github/last-commit/stackitcloud/external-dns-stackit-webhook/main.svg)](https://github.com/stackitcloud/external-dns-stackit-webhook/commits/main)
[![GitHub issues](https://img.shields.io/github/issues/stackitcloud/external-dns-stackit-webhook.svg)](https://github.com/stackitcloud/external-dns-stackit-webhook/issues)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/stackitcloud/external-dns-stackit-webhook.svg)](https://github.com/stackitcloud/external-dns-stackit-webhook/pulls)
[![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)
[![CI](https://github.com/selectel/external-dns-selectel-webhook/actions/workflows/main.yml/badge.svg)](https://github.com/selectel/external-dns-selectel-webhook/actions/workflows/main.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/selectel/external-dns-selectel-webhook)](https://goreportcard.com/report/github.com/selectel/external-dns-selectel-webhook)
[![GitHub release](https://img.shields.io/github/release/selectel/external-dns-selectel-webhook.svg)](https://github.com/selectel/external-dns-selectel-webhook/releases)
[![Last Commit](https://img.shields.io/github/last-commit/selectel/external-dns-selectel-webhook/main.svg)](https://github.com/selectel/external-dns-selectel-webhook/commits/main)
[![GitHub issues](https://img.shields.io/github/issues/selectel/external-dns-selectel-webhook.svg)](https://github.com/selectel/external-dns-selectel-webhook/issues)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/selectel/external-dns-selectel-webhook.svg)](https://github.com/selectel/external-dns-selectel-webhook/pulls)
[![GitHub stars](https://img.shields.io/github/stars/selectel/external-dns-selectel-webhook.svg?style=social&label=Star&maxAge=2592000)](https://github.com/selectel/external-dns-selectel-webhook/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/selectel/external-dns-selectel-webhook.svg?style=social&label=Fork&maxAge=2592000)](https://github.com/selectel/external-dns-selectel-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
management to an external DNS provider such as Selectel. Consequently, the Selectel webhook enables the management
of your Selectel 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
to create and read dns zones, and finally, establish a STACKIT zone.
For utilizing ExternalDNS with Selectel, it is mandatory to establish a Selectel project, a service account
within the project, and finally, establish a domain 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 Selectel webhook is presented as a standard Open Container Initiative (OCI) image released in the
[GitHub container registry](https://github.com/selectel/external-dns-selectel-webhook/pkgs/container/external-dns-selectel-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
# 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>'
```shell
kubectl create secret generic external-dns-selectel-webhook --from-literal=password='<Service-User-Password>'
```

```shell
Expand Down Expand Up @@ -178,10 +174,12 @@ spec:
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65534
image: ghcr.io/stackitcloud/external-dns-stackit-webhook:v0.2.0
image: ghcr.io/selectel/external-dns-selectel-webhook:v0.1.0
imagePullPolicy: IfNotPresent
args:
- --project-id=c158c736-0300-4044-95c4-b7d404279b35 # your project id
- --account-id=000000 # your account id
- --username=Username # your service user's name
ports:
- name: http
protocol: TCP
Expand All @@ -205,136 +203,46 @@ spec:
successThreshold: 1
timeoutSeconds: 5
env:
- name: AUTH_TOKEN
- name: PASSWORD
valueFrom:
secretKeyRef:
name: external-dns-stackit-webhook
key: auth-token
name: external-dns-selectel-webhook
key: password
EOF
```

## Configuration

The configuration of the STACKIT webhook can be accomplished through command line arguments and environment variables.
Below are the options that are available.
The configuration of the Selectel webhook can be accomplished through command line arguments and environment variables.
Below are the options that are available in format `--cli-argument`/`ENVIRONMENT_VARIABLE`.

- `--project-id`/`PROJECT_ID` (required): Specifies the project id of the STACKIT project.
- `--auth-token`/`AUTH_TOKEN` (required if `auth-key-path` is not set): Defines the authentication token for the STACKIT API. Mutually exclusive with 'auth-key-path'.
- `--auth-key-path`/`AUTH_KEY_PATH` (required if `auth-token` is not set): Defines the file path of the service account key for the STACKIT API. Mutually exclusive with 'auth-token'.
- `--project-id`/`PROJECT_ID` (required): Specifies the project id to authorize.
- `--account-id`/`ACCOUNT_ID` (required): Specifies the account id to authorize.
- `--username`/`USERNAME` (required): Specifies the username of your service user to authorize.
- `--password`/`PASSWORD` (required): Specifies the password of your service user to authorize.
- `--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").
- `--base-url`/`BASE_URL` (optional): Identifies the Base URL for utilizing the API
(default "https://api.selectel.ru/domains/v2"). The full list of Selectel API URLs you can
see [here](https://developers.selectel.ru/docs/control-panel/urls/).
- `--auth-url`/`AUTH_URL` (optional): Identifies the URL for utilizing the API to receive keystone-token
(default "https://cloud.api.selcloud.ru/identity/v3").
- `--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"
export AUTH_TOKEN="your-auth-token"
export ACCOUNT_ID="123456"
export USERNAME="username"
export PASSWORD ="password"

make run
```
Expand Down
Loading

0 comments on commit 155ad16

Please sign in to comment.