Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cloudflare support #1278

Merged
merged 4 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ Internal k8gb architecture and its components are described [here](/docs/compone
* [General deployment with Infoblox integration](/docs/deploy_infoblox.md)
* [AWS based deployment with Route53 integration](/docs/deploy_route53.md)
* [AWS based deployment with NS1 integration](/docs/deploy_ns1.md)
* [General deployment with Cloudflare integration](/docs/deploy_cloudflare.md)
* [Local playground for testing and development](/docs/local.md)
* [Local playground with Kuar web app](/docs/local-kuar.md)
* [Metrics](/docs/metrics.md)
Expand Down
14 changes: 14 additions & 0 deletions chart/k8gb/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ Create the name of the service account to use
{{- if .Values.rfc2136.enabled }}
{{- print "rfc2136" -}}
{{- end -}}
{{- if .Values.cloudflare.enabled }}
{{- print "cloudflare" -}}
{{- end -}}
{{- end -}}

{{- define "k8gb.extdnsOwnerID" -}}
Expand Down Expand Up @@ -120,6 +123,17 @@ k8gb-{{ .Values.k8gb.dnsZone }}-{{ .Values.k8gb.clusterGeoTag }}
name: rfc2136
key: secret
{{- end -}}
{{- if .Values.cloudflare.enabled -}}
- --zone-id-filter={{ .Values.cloudflare.zoneID }}
- --cloudflare-dns-records-per-page={{
.Values.cloudflare.dnsRecordsPerPage | default 5000 }}
env:
- name: CF_API_TOKEN
valueFrom:
secretKeyRef:
name: cloudflare
key: token
{{- end -}}
{{- end -}}
{{- define "k8gb.metrics_port" -}}
{{ print (split ":" .Values.k8gb.metricsAddress)._1 }}
Expand Down
2 changes: 1 addition & 1 deletion chart/k8gb/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ spec:
name: infoblox
key: INFOBLOX_WAPI_PASSWORD
{{- end }}
{{- if or .Values.route53.enabled .Values.ns1.enabled .Values.rfc2136.enabled }}
{{- if or .Values.route53.enabled .Values.ns1.enabled .Values.rfc2136.enabled .Values.cloudflare.enabled }}
- name: EXTDNS_ENABLED
value: "true"
{{- end }}
Expand Down
3 changes: 2 additions & 1 deletion chart/k8gb/templates/external-dns/external-dns.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{- if or .Values.ns1.enabled .Values.route53.enabled .Values.rfc2136.enabled }}
{{- if or .Values.ns1.enabled .Values.route53.enabled .Values.rfc2136.enabled .Values.cloudflare.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down Expand Up @@ -30,6 +30,7 @@ spec:
- --managed-record-types=NS
- --annotation-filter=k8gb.absa.oss/dnstype=extdns # filter out only relevant DNSEntrypoints
- --txt-owner-id={{ include "k8gb.extdnsOwnerID" . }}
- --txt-prefix=k8gb-{{ .Values.k8gb.clusterGeoTag }}- # add custom prefix to TXT records, critical for Cloudflare NS record creation
- --provider={{ include "k8gb.extdnsProvider" . }}
{{- if .Values.route53.assumeRoleArn }}
- --aws-assume-role={{ .Values.route53.assumeRoleArn }}
Expand Down
2 changes: 1 addition & 1 deletion chart/k8gb/templates/external-dns/rbac.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{- if or .Values.ns1.enabled .Values.route53.enabled .Values.rfc2136.enabled }}
{{- if or .Values.ns1.enabled .Values.route53.enabled .Values.rfc2136.enabled .Values.cloudflare.enabled }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
Expand Down
29 changes: 26 additions & 3 deletions chart/k8gb/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@
"ns1": {
"$ref": "#/definitions/Ns1"
},
"openshift": {
"$ref": "#/definitions/Openshift"
},
"rfc2136": {
"$ref": "#/definitions/Rfc2136"
},
"cloudflare": {
"$ref": "#/definitions/Cloudflare"
},
"openshift": {
"$ref": "#/definitions/Openshift"
},
"tracing": {
"$ref": "#/definitions/Tracing"
}
Expand Down Expand Up @@ -478,6 +481,26 @@
],
"title": "Route53"
},
"Cloudflare": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean"
},
"dnsRecordsPerPage": {
"type": "integer"
},
"zoneID": {
"type": "string"
}
},
"required": [
"enabled",
"zoneID"
],
"title": "Cloudflare"
},
"Tracing": {
"type": "object",
"additionalProperties": false,
Expand Down
19 changes: 15 additions & 4 deletions chart/k8gb/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,6 @@ ns1:
# endpoint: https://api.nsone.net/v1/
ignoreSSL: false

openshift:
# -- Install OpenShift specific RBAC
enabled: false

rfc2136:
enabled: false
rfc2136Opts:
Expand All @@ -130,6 +126,21 @@ rfc2136:
- tsig-secret-alg: hmac-sha256
- tsig-keyname: externaldns-key

cloudflare:
# -- Enable Cloudflare provider
enabled: false
# -- Cloudflare Zone ID
# follow https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/
# to find your zoneID value
zoneID: replaceme
# -- Configure how many DNS records to fetch per request
# see https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/cloudflare.md#throttling
dnsRecordsPerPage: 5000

openshift:
# -- Install OpenShift specific RBAC
enabled: false

tracing:
# -- if the application should be sending the traces to OTLP collector (env var `TRACING_ENABLED`)
enabled: false
Expand Down
165 changes: 165 additions & 0 deletions docs/deploy_cloudflare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# General deployment with Cloudflare integration

In this guide, we will demonstrate how to configure k8gb to integrate with
Cloudflare for automated zone delegation configuration.

## Initial setup

As a prerequisite, we will need two Kubernetes clusters where you want to deploy
k8gb and enable global load balancing between them.

You can reuse local clusters from the [Infoblox tutorial](../docs/deploy_infoblox.html),
the EKS-based setup from [Route53 tutorial](../docs/deploy_route53.md)
or any Kubernetes deployment method that is convenient to you.

The specific Kubernetes deployment method is not essential for the focus of this documentation guide.

For simplicity, we will assume that clusters have simple 'eu' and 'us' geotags.

## Deploy k8gb with Cloudflare integration enabled

Use `helm` to deploy a stable release from the Helm repo.

```sh
helm repo add k8gb https://www.k8gb.io
```

Example `values.yaml` configuration files can be found [here](https://github.com/k8gb-io/k8gb/tree/master/docs/examples/cloudflare)

Remember to change the zone-related values to point configuration to your own DNS zone.

```yaml
k8gb:
dnsZone: "cloudflare-test.k8gb.io"
# -- main zone which would contain gslb zone to delegate
edgeDNSZone: "k8gb.io" # main zone which would contain gslb zone to delegate
```

### Cloudflare-specific configuration

Let's look closer at the Cloudflare section of the configuration examples.

```yaml
cloudflare:
# -- Enable Cloudflare provider
enabled: true
# -- Cloudflare Zone ID
zoneID: cdebf92e613133e4bb176a14a9c5b730
# -- Configure how many DNS records to fetch per request
# see https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/cloudflare.md#throttling
dnsRecordsPerPage: 5000
```

Follow
https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/
to find your `zoneID`

### Install the k8gb helm chart in each cluster

In `eu` cluster, execute
```sh
helm -n k8gb upgrade -i k8gb k8gb/k8gb --create-namespace -f ./docs/examples/cloudflare/k8gb-cluster-cloudflare-eu.yaml
```

In `us` cluster, execute
```sh
helm -n k8gb upgrade -i k8gb k8gb/k8gb --create-namespace -f ./docs/examples/cloudflare/k8gb-cluster-cloudflare-us.yaml
```

### Create a Cloudflare secret in each cluster

```sh
kubectl -n k8gb create secret generic cloudflare --from-literal=token=<api-secret>
```

Note: you can create Cloudflare API tokens at https://dash.cloudflare.com/profile/api-tokens

### Create test Gslb resource

Now we can test the setup with a pretty standard Gslb resource configuration.

```yaml
apiVersion: k8gb.absa.oss/v1beta1
kind: Gslb
metadata:
name: test-gslb-failover
namespace: test-gslb
spec:
ingress:
ingressClassName: nginx
rules:
- host: failover.cloudflare-test.k8gb.io
http:
paths:
- backend:
service:
name: frontend-podinfo
port:
name: http
path: /
pathType: Prefix
strategy:
dnsTtlSeconds: 60 # Minimum for non-Enterprise Cloudflare https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/
primaryGeoTag: eu
splitBrainThresholdSeconds: 300
type: failover
```

The only unusual thing here is `spec.strategy.dnsTtlSeconds` that should be of a
minimum 60-second value in case you are operating a non-Enterprise Cloudflare
subscription. The lower values will be rejected by Cloudflare API.

Apply Gslb resource to each cluster.

```sh
kubectl apply -f ./docs/examples/cloudflare/test-gslb-failover.yaml
```

## Check Zone Delegation configuration

As a result of the setup, you should observe DNSEndpoint automatically created,
similar to the one below:

```yaml
$ kubectl -n k8gb get dnsendpoints.externaldns.k8s.io k8gb-ns-extdns -o yaml
apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
annotations:
k8gb.absa.oss/dnstype: extdns
creationTimestamp: "2023-11-12T19:55:20Z"
generation: 3
name: k8gb-ns-extdns
namespace: k8gb
resourceVersion: "5851"
uid: 5d240eb8-1c19-48c3-bf69-508545f52ea4
spec:
endpoints:
- dnsName: cloudflare-test.k8gb.io
recordTTL: 60
recordType: NS
targets:
- gslb-ns-eu-cloudflare-test.k8gb.io
- gslb-ns-us-cloudflare-test.k8gb.io
- dnsName: gslb-ns-us-cloudflare-test.k8gb.io
recordTTL: 60
recordType: A
targets:
- 172.26.0.8
- 172.26.0.9
```

On the Cloudflare dashboard side, you should observe that NS and glue A records are
automatically created:

![Cloudflare dashboard with Zone Delegation records](/docs/images/k8gb-cloudflare.png)

## Troubleshooting

If something is not working as expected with the integration, check the logs of
the externalDNS pod that is responsible for the creation of the DNS records
with Cloudflare API.

```sh
kubectl -n k8gb logs -f deploy/external-dns
```
17 changes: 17 additions & 0 deletions docs/examples/cloudflare/k8gb-cluster-cloudflare-eu.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
k8gb:
dnsZone: "cloudflare-test.k8gb.io"
# -- main zone which would contain gslb zone to delegate
edgeDNSZone: "k8gb.io" # main zone which would contain gslb zone to delegate
# -- used for places where we need to distinguish between different Gslb instances
clusterGeoTag: "eu"
# -- comma-separated list of external gslb geo tags to pair with
extGslbClustersGeoTags: "us"

cloudflare:
# -- Enable Cloudflare provider
enabled: true
# -- Cloudflare Zone ID
zoneID: cdebf92e613133e4bb176a14a9c5b730
# -- Configure how many DNS records to fetch per request
# see https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/cloudflare.md#throttling
dnsRecordsPerPage: 5000
17 changes: 17 additions & 0 deletions docs/examples/cloudflare/k8gb-cluster-cloudflare-us.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
k8gb:
dnsZone: "cloudflare-test.k8gb.io"
# -- main zone which would contain gslb zone to delegate
edgeDNSZone: "k8gb.io" # main zone which would contain gslb zone to delegate
# -- used for places where we need to distinguish between different Gslb instances
clusterGeoTag: "us"
# -- comma-separated list of external gslb geo tags to pair with
extGslbClustersGeoTags: "eu"

cloudflare:
# -- Enable Cloudflare provider
enabled: true
# -- Cloudflare Zone ID
zoneID: cdebf92e613133e4bb176a14a9c5b730
# -- Configure how many DNS records to fetch per request
# see https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/cloudflare.md#throttling
dnsRecordsPerPage: 5000
24 changes: 24 additions & 0 deletions docs/examples/cloudflare/test-gslb-failover.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: k8gb.absa.oss/v1beta1
kind: Gslb
metadata:
name: test-gslb-failover
namespace: test-gslb
spec:
ingress:
ingressClassName: nginx
rules:
- host: failover.cloudflare-test.k8gb.io
http:
paths:
- backend:
service:
name: frontend-podinfo
port:
name: http
path: /
pathType: Prefix
strategy:
dnsTtlSeconds: 60 # Minimum for non-Enterprise Cloudflare https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/
primaryGeoTag: eu
splitBrainThresholdSeconds: 300
type: failover
Binary file added docs/images/k8gb-cloudflare.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.