mirror of
https://github.com/funkypenguin/geek-cookbook/
synced 2025-12-13 17:56:26 +00:00
174 lines
7.0 KiB
Markdown
174 lines
7.0 KiB
Markdown
---
|
|
title: Support CSI VolumeSnapshots with snapshot-controller
|
|
description: Add CSI VolumeSnapshot support with snapshot support
|
|
values_yaml_url: https://github.com/bitnami/charts/blob/master/bitnami/external-dns/values.yaml
|
|
helm_chart_version: 5.1.x
|
|
helm_chart_name: external-dns
|
|
helm_chart_repo_name: bitnami
|
|
helm_chart_repo_url: https://charts.bitnami.com/bitnami
|
|
helmrelease_name: external-dns
|
|
helmrelease_namespace: external-dns
|
|
kustomization_name: external-dns
|
|
slug: External DNS
|
|
---
|
|
|
|
# External DNS
|
|
|
|
Kubernetes' internal DNS / service-discovery means that every service is resolvable within the cluster. You can create a Wordpress pod with a database URL pointing to "mysql", and trust that it'll find the service named "mysql" in the same namespace. (*Or "mysql.weirdothernamespace" if you prefer*)
|
|
|
|
This super-handy DNS magic only works within the cluster though. When you wanted to connect to the hypothetical Wordpress service from **outside** of the cluster, you'd need to manually create a DNS entry pointing to the [LoadBalancer](/kubernetes/loadbalancer/) IP of that service. While using wildcard DNS might make this a **little** easier, it's still too manual and not at all "*gitopsy*" enough!
|
|
|
|
ExternalDNS is a controller for Kubernetes which watches the objects you create (*Services, Ingresses, etc*), and configures External DNS providers (*like CloudFlare, Route53, etc*) accordingly. With External DNS, you **can** just deploy an ingress referencing "*mywordywordpressblog.batman.com*", and have that DNS entry autocreated on your provider within minutes 💪
|
|
|
|
!!! summary "Ingredients"
|
|
|
|
* [x] A [Kubernetes cluster](/kubernetes/cluster/)
|
|
* [x] [Flux deployment process](/kubernetes/deployment/flux/) bootstrapped
|
|
* [x] API credentials for a [supported DNS provider](https://github.com/kubernetes-sigs/external-dns)
|
|
|
|
{% include 'kubernetes-flux-namespace.md' %}
|
|
{% include 'kubernetes-flux-helmrepository.md' %}
|
|
{% include 'kubernetes-flux-kustomization.md' %}
|
|
{% include 'kubernetes-flux-helmrelease.md' %}
|
|
|
|
#### Enable CRDs
|
|
|
|
By default, the helm chart doesn't install the DNSEndpoint CRD.
|
|
|
|
If you intend to use CRDs, enable it in the HelmRelease like the example below:
|
|
|
|
```yaml hl_lines="4" title="Enable CRD creation"
|
|
crd:
|
|
## @param crd.create Install and use the integrated DNSEndpoint CRD
|
|
##
|
|
create: true
|
|
```
|
|
|
|
|
|
#### Configure sources
|
|
|
|
I recommend changing:
|
|
|
|
```yaml
|
|
sources:
|
|
# - crd
|
|
- service
|
|
- ingress
|
|
# - contour-httpproxy
|
|
```
|
|
|
|
To:
|
|
|
|
```yaml
|
|
sources:
|
|
- crd
|
|
# - service
|
|
# - ingress
|
|
# - contour-httpproxy
|
|
```
|
|
|
|
!!! question "Why only use CRDs as a source?"
|
|
> I thought the whole point of this magic was to create DNS entries from services or ingresses!
|
|
|
|
You can do that, yes. However, I prefer to be prescriptive, and explicitly decide when a DNS entry will be created. By [using CRDs](#using-crds) (*External DNS creates a new type of resource called a "DNSEndpoint"*), I add my DNS entries as YAML files into each kustomization, and I can still employ wildcard DNS where appropriate.
|
|
|
|
### Secret
|
|
|
|
As you work your way through `values.yaml`, you'll notice that it contains specific placeholders for credentials for various DNS providers.
|
|
|
|
Take for example, this config for cloudflare:
|
|
|
|
```yaml title="Example snippet of CloudFlare config from upstream values.yaml"
|
|
cloudflare:
|
|
## @param cloudflare.apiToken When using the Cloudflare provider, `CF_API_TOKEN` to set (optional)
|
|
##
|
|
apiToken: ""
|
|
## @param cloudflare.apiKey When using the Cloudflare provider, `CF_API_KEY` to set (optional)
|
|
##
|
|
apiKey: ""
|
|
## @param cloudflare.secretName When using the Cloudflare provider, it's the name of the secret containing cloudflare_api_token or cloudflare_api_key.
|
|
## This ignores cloudflare.apiToken, and cloudflare.apiKey
|
|
##
|
|
secretName: ""
|
|
## @param cloudflare.email When using the Cloudflare provider, `CF_API_EMAIL` to set (optional). Needed when using CF_API_KEY
|
|
##
|
|
email: ""
|
|
## @param cloudflare.proxied When using the Cloudflare provider, enable the proxy feature (DDOS protection, CDN...) (optional)
|
|
##
|
|
proxied: true
|
|
```
|
|
|
|
In the case of CloudFlare (*and this may differ per-provider*), you can either enter your credentials in cleartext (*baaad idea, since we intend to commit these files into a repo*), or you can reference a secret, which External DNS will expect to find in its namespace.
|
|
|
|
Thanks to [Sealed Secrets](/kubernetes/sealed-secrets/), we have a safe way of committing secrets into our repository, so to create this cloudflare secret, you'd run something like this:
|
|
|
|
```bash
|
|
kubectl create secret generic cloudflare-api-token \
|
|
--namespace external-dns \
|
|
--dry-run=client \
|
|
--from-literal=cloudflare_api_token=gobbledegook -o json \
|
|
| kubeseal --cert <path to public cert> \
|
|
> <path to repo>/external-dns/sealedsecret-cloudflare-api-token.yaml
|
|
```
|
|
|
|
And your sealed secret would end up in `external-dns/sealedsecret-cloudflare-api-token.yaml`.
|
|
|
|
{% include 'kubernetes-flux-check.md' %}
|
|
|
|
### Using CRDs
|
|
|
|
If you're the sort of person who doesn't like to just leak[^1] every service/ingress name into public DNS, you may prefer to manage your DNS entries using CRDs.
|
|
|
|
You can instruct ExternalDNS to create any DNS entry you please, using a **DNSEndpoint** resource, and place these in the appropriate folder in your flux repo to be deployed with your HelmRelease:
|
|
|
|
```yaml
|
|
apiVersion: externaldns.k8s.io/v1alpha1
|
|
kind: DNSEndpoint
|
|
metadata:
|
|
name: batcave.example.com
|
|
namespace: batcave
|
|
spec:
|
|
endpoints:
|
|
- dnsName: batcave.example.com
|
|
recordTTL: 180
|
|
recordType: A
|
|
targets:
|
|
- 192.168.99.216
|
|
```
|
|
|
|
You can even create wildcard DNS entries, for example by setting `dnsName: *.batcave.example.com`.
|
|
|
|
Finally, (*and this is how I prefer to manage mine*), you can create a few A records for "permanent" endpoints stuff like Ingresses, and then point arbitrary DNS names to these records, like this:
|
|
|
|
```yaml
|
|
apiVersion: externaldns.k8s.io/v1alpha1
|
|
kind: DNSEndpoint
|
|
metadata:
|
|
name: "robinsroost.example.com"
|
|
namespace: batcave
|
|
spec:
|
|
endpoints:
|
|
- dnsName: "robinsroost.example.com"
|
|
recordTTL: 180
|
|
recordType: CNAME
|
|
targets:
|
|
- "batcave.example.com"
|
|
```
|
|
|
|
### Troubleshooting
|
|
|
|
If DNS entries **aren't** created as you expect, then the best approach is to check the external-dns logs, by running `kubectl logs -n external-dns -l app.kubernetes.io/name=external-dns`.
|
|
|
|
## Summary
|
|
|
|
What have we achieved? By simply creating another YAML in our flux repo alongside our app HelmReleases, we can record and create the necessary DNS entries, without fiddly manual intervetion!
|
|
|
|
!!! summary "Summary"
|
|
Created:
|
|
|
|
* [X] DNS records are created automatically based on YAMLs (*or even just on services and ingresses!*)
|
|
|
|
{% include 'recipe-footer.md' %}
|
|
|
|
[^1]: Why yes, I **have** accidentally caused outages / conflicts by "leaking" DNS entries automatically!
|