Skip to content

Commit

Permalink
Added init work to support RFC2136 multiple hosts.
Browse files Browse the repository at this point in the history
Signed-off-by: Jeremy-Boyle <[email protected]>

Fixed go tests, added checks to ensure multiple hosts, and RFC2136LoadBalancingStrategy is set and can be overritten

Signed-off-by: Jeremy-Boyle <[email protected]>

Documentation to support Multiple Hosts and Load Balancing features

Signed-off-by: Jeremy-Boyle <[email protected]>

WIP, counter not working correctly

Signed-off-by: Jeremy-Boyle <[email protected]>

Make pointers to the rfc2136 provider, fixed counter issue, log out last error.

Signed-off-by: Jeremy-Boyle <[email protected]>

Fix error with failover not working correctly

Signed-off-by: Jeremy-Boyle <[email protected]>

Repoint makefile us.gcr.io/k8s-artifacts-prod/external-dns

Signed-off-by: Jeremy-Boyle <[email protected]>

Repoint makefile us.gcr.io/k8s-artifacts-prod/external-dns

Signed-off-by: Jeremy-Boyle <[email protected]>

Fix changes that arent related directly to this PR

Signed-off-by: Jeremy-Boyle <[email protected]>

Changed comment message details for counter

Signed-off-by: Jeremy-Boyle <[email protected]>
  • Loading branch information
Jeremy-Boyle committed Nov 14, 2024
1 parent 7343cb9 commit 16dd5b6
Show file tree
Hide file tree
Showing 6 changed files with 431 additions and 106 deletions.
46 changes: 45 additions & 1 deletion docs/tutorials/rfc2136.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ You'll want to configure `external-dns` similarly to the following:
```text
...
- --provider=rfc2136
- --rfc2136-gss-tsig
- --rfc2136-gss-tsig
- --rfc2136-host=dns-host.yourdomain.com
- --rfc2136-port=53
- --rfc2136-zone=your-zone.com
Expand Down Expand Up @@ -434,3 +434,47 @@ If your DNS server does zone transfers over TLS, you can instruct `external-dns`
* `--rfc2136-skip-tls-verify` Disables verification of the certificate supplied by the DNS server.

It is currently not supported to do only zone transfers over TLS, but not the updates. They are enabled and disabled together.

## Configuring RFC2136 Provider with Multiple Hosts and Load Balancing

This section describes how to configure the RFC2136 provider in ExternalDNS to support multiple DNS servers and load balancing options.

### Enhancements Overview

The RFC2136 provider now supports multiple DNS hosts and introduces load balancing options to distribute DNS update requests evenly across available DNS servers. This helps prevent a single server from becoming a bottleneck in environments with multiple DNS servers.

### Configuration Steps

1. **Allow Multiple Hosts for `--rfc2136-host`**
- Modify the `--rfc2136-host` command-line option to accept multiple hosts.
- Example: `--rfc2136-host="dns-host-1.yourdomain.com" --rfc2136-host="dns-host-2.yourdomain.com"`

2. **Introduce Load Balancing Options**
- Add a new command-line option `--rfc2136-load-balancing-strategy` to specify the load balancing strategy.
- Supported options:
- `round-robin`: Distributes DNS updates evenly across all specified hosts in a round-robin manner.
- `random`: Randomly selects a host for each DNS update.
- `disabled` (default): Uses the first host in the list as the primary, only moving to the next host if a failure occurs.

### Example Configuration

```shell
external-dns \
--provider=rfc2136 \
--rfc2136-host="dns-host-1.yourdomain.com" \
--rfc2136-host="dns-host-2.yourdomain.com" \
--rfc2136-host="dns-host-3.yourdomain.com" \
--rfc2136-load-balancing-strategy="round-robin" \
--rfc2136-port=53 \
--rfc2136-zone=example.com \
--rfc2136-tsig-secret-alg=hmac-sha256 \
--rfc2136-tsig-keyname=example-key \
--rfc2136-tsig-secret=example-secret \
--rfc2136-insecure
```

### Benefits

- Distributes the load of DNS updates across multiple data centers, preventing any single DC from becoming a bottleneck.
- Provides flexibility to choose different load balancing strategies based on the environment and requirements.
- Improves the resilience and reliability of DNS updates by introducing a retry mechanism with a list of hosts.
3 changes: 1 addition & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,8 @@ func main() {
CAFilePath: cfg.TLSCA,
ClientCertFilePath: cfg.TLSClientCert,
ClientCertKeyFilePath: cfg.TLSClientCertKey,
ServerName: "",
}
p, err = rfc2136.NewRfc2136Provider(cfg.RFC2136Host, cfg.RFC2136Port, cfg.RFC2136Zone, cfg.RFC2136Insecure, cfg.RFC2136TSIGKeyName, cfg.RFC2136TSIGSecret, cfg.RFC2136TSIGSecretAlg, cfg.RFC2136TAXFR, domainFilter, cfg.DryRun, cfg.RFC2136MinTTL, cfg.RFC2136CreatePTR, cfg.RFC2136GSSTSIG, cfg.RFC2136KerberosUsername, cfg.RFC2136KerberosPassword, cfg.RFC2136KerberosRealm, cfg.RFC2136BatchChangeSize, tlsConfig, nil)
p, err = rfc2136.NewRfc2136Provider(cfg.RFC2136Host, cfg.RFC2136Port, cfg.RFC2136Zone, cfg.RFC2136Insecure, cfg.RFC2136TSIGKeyName, cfg.RFC2136TSIGSecret, cfg.RFC2136TSIGSecretAlg, cfg.RFC2136TAXFR, domainFilter, cfg.DryRun, cfg.RFC2136MinTTL, cfg.RFC2136CreatePTR, cfg.RFC2136GSSTSIG, cfg.RFC2136KerberosUsername, cfg.RFC2136KerberosPassword, cfg.RFC2136KerberosRealm, cfg.RFC2136BatchChangeSize, tlsConfig, cfg.RFC2136LoadBalancingStrategy, nil)
case "ns1":
p, err = ns1.NewNS1Provider(
ns1.NS1Config{
Expand Down
6 changes: 4 additions & 2 deletions pkg/apis/externaldns/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ type Config struct {
CFUsername string
CFPassword string
ResolveServiceLoadBalancerHostname bool
RFC2136Host string
RFC2136Host []string
RFC2136Port int
RFC2136Zone []string
RFC2136Insecure bool
Expand All @@ -174,6 +174,7 @@ type Config struct {
RFC2136TSIGSecretAlg string
RFC2136TAXFR bool
RFC2136MinTTL time.Duration
RFC2136LoadBalancingStrategy string
RFC2136BatchChangeSize int
RFC2136UseTLS bool
RFC2136SkipTLSVerify bool
Expand Down Expand Up @@ -538,7 +539,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("exoscale-apisecret", "Provide your API Secret for the Exoscale provider").Default(defaultConfig.ExoscaleAPISecret).StringVar(&cfg.ExoscaleAPISecret)

// Flags related to RFC2136 provider
app.Flag("rfc2136-host", "When using the RFC2136 provider, specify the host of the DNS server").Default(defaultConfig.RFC2136Host).StringVar(&cfg.RFC2136Host)
app.Flag("rfc2136-host", "When using the RFC2136 provider, specify the host of the DNS server").Default(defaultConfig.RFC2136Host[0]).StringsVar(&cfg.RFC2136Host)
app.Flag("rfc2136-port", "When using the RFC2136 provider, specify the port of the DNS server").Default(strconv.Itoa(defaultConfig.RFC2136Port)).IntVar(&cfg.RFC2136Port)
app.Flag("rfc2136-zone", "When using the RFC2136 provider, specify zone entries of the DNS server to use").StringsVar(&cfg.RFC2136Zone)
app.Flag("rfc2136-create-ptr", "When using the RFC2136 provider, enable PTR management").Default(strconv.FormatBool(defaultConfig.RFC2136CreatePTR)).BoolVar(&cfg.RFC2136CreatePTR)
Expand All @@ -555,6 +556,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("rfc2136-batch-change-size", "When using the RFC2136 provider, set the maximum number of changes that will be applied in each batch.").Default(strconv.Itoa(defaultConfig.RFC2136BatchChangeSize)).IntVar(&cfg.RFC2136BatchChangeSize)
app.Flag("rfc2136-use-tls", "When using the RFC2136 provider, communicate with name server over tls").BoolVar(&cfg.RFC2136UseTLS)
app.Flag("rfc2136-skip-tls-verify", "When using TLS with the RFC2136 provider, disable verification of any TLS certificates").BoolVar(&cfg.RFC2136SkipTLSVerify)
app.Flag("rfc2136-load-balancing-strategy", "When using the RFC2136 provider, specify the load balancing strategy (default: disabled, options: random, round-robin, disabled)").Default(defaultConfig.RFC2136LoadBalancingStrategy).EnumVar(&cfg.RFC2136LoadBalancingStrategy, "random", "round-robin", "disabled")

// Flags related to TransIP provider
app.Flag("transip-account", "When using the TransIP provider, specify the account name (required when --provider=transip)").Default(defaultConfig.TransIPAccountName).StringVar(&cfg.TransIPAccountName)
Expand Down
22 changes: 17 additions & 5 deletions pkg/apis/externaldns/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ var (
AzureSubscriptionID: "",
CloudflareProxied: false,
CloudflareDNSRecordsPerPage: 100,
CloudflareRegionKey: "",
CloudflareRegionKey: "",
CoreDNSPrefix: "/skydns/",
AkamaiServiceConsumerDomain: "",
AkamaiClientToken: "",
Expand Down Expand Up @@ -169,14 +169,20 @@ var (
AWSProfiles: []string{"profile1", "profile2"},
AWSZoneCacheDuration: 10 * time.Second,
AWSSDServiceCleanup: true,
AWSSDCreateTag: map[string]string{"key1": "value1", "key2": "value2"},
AWSDynamoDBTable: "custom-table",
AzureConfigFile: "azure.json",
AzureResourceGroup: "arg",
AzureSubscriptionID: "arg",
BluecatDNSConfiguration: "arg",
BluecatDNSServerName: "arg",
BluecatConfigFile: "bluecat.json",
BluecatDNSView: "arg",
BluecatGatewayHost: "arg",
BluecatRootZone: "arg",
BluecatDNSDeployType: "full-deploy",
BluecatSkipTLSVerify: true,
CloudflareProxied: true,
CloudflareDNSRecordsPerPage: 5000,
CloudflareRegionKey: "us",
CoreDNSPrefix: "/coredns/",
AkamaiServiceConsumerDomain: "oooo-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net",
AkamaiClientToken: "o184671d5307a388180fbf7f11dbdf46",
Expand All @@ -191,7 +197,6 @@ var (
OVHEndpoint: "ovh-ca",
OVHApiRateLimit: 42,
PDNSServer: "http://ns.example.com:8081",
PDNSServerID: "localhost",
PDNSAPIKey: "some-secret-key",
PDNSSkipTLSVerify: true,
TLSCA: "/path/to/ca.crt",
Expand All @@ -217,6 +222,7 @@ var (
ExoscaleAPISecret: "2",
CRDSourceAPIVersion: "test.k8s.io/v1alpha1",
CRDSourceKind: "Endpoint",
RcodezeroTXTEncrypt: true,
NS1Endpoint: "https://api.example.com/v1",
NS1IgnoreSSL: true,
TransIPAccountName: "transip",
Expand Down Expand Up @@ -364,6 +370,9 @@ func TestParseFlags(t *testing.T) {
"--managed-record-types=CNAME",
"--managed-record-types=NS",
"--rfc2136-batch-change-size=100",
"--rfc2136-load-balancing-strategy=round-robin",
"--rfc2136-host=rfc2136-host1",
"--rfc2136-host=rfc2136-host2",
"--ibmcloud-proxied",
"--ibmcloud-config-file=ibmcloud.json",
"--tencent-cloud-config-file=tencent-cloud.json",
Expand Down Expand Up @@ -399,7 +408,7 @@ func TestParseFlags(t *testing.T) {
"EXTERNAL_DNS_AZURE_SUBSCRIPTION_ID": "arg",
"EXTERNAL_DNS_CLOUDFLARE_PROXIED": "1",
"EXTERNAL_DNS_CLOUDFLARE_DNS_RECORDS_PER_PAGE": "5000",
"EXTERNAL_DNS_CLOUDFLARE_REGION_KEY": "us",
"EXTERNAL_DNS_CLOUDFLARE_REGION_KEY": "us",
"EXTERNAL_DNS_COREDNS_PREFIX": "/coredns/",
"EXTERNAL_DNS_AKAMAI_SERVICECONSUMERDOMAIN": "oooo-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net",
"EXTERNAL_DNS_AKAMAI_CLIENT_TOKEN": "o184671d5307a388180fbf7f11dbdf46",
Expand Down Expand Up @@ -473,6 +482,8 @@ func TestParseFlags(t *testing.T) {
"EXTERNAL_DNS_DIGITALOCEAN_API_PAGE_SIZE": "100",
"EXTERNAL_DNS_MANAGED_RECORD_TYPES": "A\nAAAA\nCNAME\nNS",
"EXTERNAL_DNS_RFC2136_BATCH_CHANGE_SIZE": "100",
"EXTERNAL_DNS_RFC2136_LOAD_BALANCING_STRATEGY": "round-robin",
"EXTERNAL_DNS_RFC2136_HOST": "rfc2136-host1\nrfc2136-host2",
"EXTERNAL_DNS_IBMCLOUD_PROXIED": "1",
"EXTERNAL_DNS_IBMCLOUD_CONFIG_FILE": "ibmcloud.json",
"EXTERNAL_DNS_TENCENT_CLOUD_CONFIG_FILE": "tencent-cloud.json",
Expand Down Expand Up @@ -513,6 +524,7 @@ func restoreEnv(t *testing.T, originalEnv map[string]string) {

func TestPasswordsNotLogged(t *testing.T) {
cfg := Config{
DynPassword: "dyn-pass",
PDNSAPIKey: "pdns-api-key",
RFC2136TSIGSecret: "tsig-secret",
}
Expand Down
Loading

0 comments on commit 16dd5b6

Please sign in to comment.