Skip to content

Commit

Permalink
CO-61-update-docs-for-co-58 (#68)
Browse files Browse the repository at this point in the history
Update docs to match updated IP object
  • Loading branch information
gi8lino authored Mar 15, 2022
1 parent 49324a6 commit d0adc4d
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 80 deletions.
191 changes: 117 additions & 74 deletions docs/content/core_concept.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ The `Account` object contains your Cloudflare credentials (email & global API ke
Example:

```yaml
---
apiVersion: cf.containeroo.ch/v1beta1
kind: Account
metadata:
Expand All @@ -90,9 +91,9 @@ If cloudflare-operator should only manage some zones, you can specify them in th

### Self-Healing

The `Account` controller reconciles itself in the given interval, if an error occurs. See the following table:
The `Account` controller reconciles itself at the given interval if an error occurs. See the following table:

| error | interval |
| Error | Interval |
| :---------------------------------------------------- | :------- |
| referenced secret (`secretRef`) not found | 30s |
| `apiKey` in referenced secret (`secretRef`) not found | 30s |
Expand All @@ -112,6 +113,7 @@ cloudflare-operator will fetch in the given interval (`spec.interval`) all Cloud
Example:

```yaml
---
apiVersion: cf.containeroo.ch/v1beta1
kind: Zone
metadata:
Expand All @@ -123,9 +125,9 @@ spec:
### Self-Healing
The `Zone` controller reconcile itself in the given interval, if an error occurs. See following table:
The `Zone` controller reconcile itself at the given interval if an error occurs. See following table:

| error | interval |
| Error | Interval |
| :--------------------------------------------------- | :------- |
| `apiKey` in secret from `Account.secretRef` is empty | 5s |
| fetching zones from Cloudflare | 30s |
Expand All @@ -141,80 +143,118 @@ The `IP` object has two purposes:
Let's say you have multiple `DNSRecords` pointing to the same IP. You can use the `IP` object to avoid repeating the IP address in the `DNSRecord.spec.content` field.
If you change the `IP` object, cloudflare-operator will automatically update the `DNSRecord.spec.content` fields.

Example:
2. **Dynamic DNS**

```yaml
apiVersion: cf.containeroo.ch/v1beta1
kind: IP
metadata:
name: static-address
spec:
type: static
address: 142.251.36.35
```
If `type` is set to `dynamic`, cloudflare-operator will fetch your IPv4 address at the specified interval (`spec.interval`).

2. **Dynamic DNS**
### Type Static

If the `type` is set to `dynamic`, cloudflare-operator will fetch your external IPv4 address in a specified interval (`spec.interval`).
An `IP` object with type `static` will update Cloudflare DNS records at the given interval (`DNSRecord.spec.interval`) with its `address`.

Example:
Example:

```yaml
apiVersion: cf.containeroo.ch/v1beta1
kind: IP
metadata:
name: external-ipv4
spec:
type: dynamic
interval: 5m
```
```yaml
---
apiVersion: cf.containeroo.ch/v1beta1
kind: IP
metadata:
name: static-address
spec:
type: static
address: 142.251.36.35
```

If no `dynamicIPSources` are specified, cloudflare-operator will use a hardcoded set of sources.
If you prefer other sources, you can add them as a list in `dynamicIPSources`.
### Type Dynamic

Example:
An `IP` object with type `dynamic` will fetch an IPv4 address from the defined `.spec.ipSources[*].url` at the given interval (`.spec.interval`).
If more than one `ipSources` are configured, cloudflare-operator shuffles the list with `ipSources` and tries to fetch a valid IPv4 address, until the response is valid. If none of the `ipSources` returns a valid IPv4 address, cloudflare-operator will set the status of the `IP` object to `failed`.
Default `interval` is set to 5 minutes.

```yaml
apiVersion: cf.containeroo.ch/v1beta1
kind: IP
metadata:
name: external-ipv4
spec:
type: dynamic
dynamicIPSources:
- https://api.ipify.org
interval: 5m
```
An `ipSource` can have the following keys:

!!! warning
The source must return only the external IPv4 address.
| Key | Description | Example |
| :---------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------ |
| url | URL to fetch IPv4 address | `https://ipecho.net` |
| requestBody | Additional request body to send to the `url` | |
| requestHeaders | Additional request headers to send to the `url`. The key will be passed as http header and the value will be passed as headers value | `Accept: application/json` |
| requestHeadersSecretRef | Link to a `secret` with additional http headers. All secret keys will be passed as http header and the corresponding secret values will be passed as headers value | See example below |
| requestMethod | HTTP request method. Possible values are `GET`, `POST`, `PUT` or `DELETE` | `GET` |
| responseTextRegex | If the IPv4 address must be extracted from the http response. Uses the default golang regex engine. | `\d{1,3}\.\d{1,3}.\.\d{1,3}\.\d{1,3}` |
| responseJSONPath | JSONPath to extract IPv4 address. Uses the kubectl jsonpath library. | `'{.ip}'` |

Good example:
!!! warning "responseTextRegex"
Be aware that the http request will fetch the **complete html document** and not what you see in your browser!

```bash
curl https://api.ipify.org
```
!!! note
If neither `responseJSONPath` nor `responseTextRegex` is set, cloudflare-operator will try to parse the **complete html document** as an IPv4 address.

Output:
Examples:

```console
142.251.36.35
```
**Fetch your external IPv4 address from three "IP" providers**

Bad example:
```yaml
---
apiVersion: cf.containeroo.ch/v1beta1
kind: IP
metadata:
name: external-ipv4
spec:
type: dynamic
IpSources:
- url: https://ipecho.net
responseTextRegex: \d{1,3}\.\d{1,3}.\.\d{1,3}\.\d{1,3}
- url: https://api.ipify.org?format=json
responseJSONPath: '{.ip}'
- url: https://checkip.amazonaws.com
interval: 5m
```

```bash
curl "https://api.ipify.org?format=json"
```
!!! info
Because more than one `source` is set, cloudflare-operator shuffles the list with `ipSources` and tries to fetch a valid IPv4 address, until the response is valid. If none of the `ipSources` returns a valid IPv4 address, cloudflare-operator will set the status of the `IP` object to `failed`.

Output:
**Fetch your external IPv4 from a cloud provider**

```console
{"ip":"142.251.36.35"}
```
Create a secret with your provider API credentials:

!!! tip
To minimize the amount of traffic to each IP source, make sure to add more than one `dynamicIPSources`. cloudflare-operator will randomly choose a source on every `interval`.
```yaml hl_lines="9"
---
apiVersion: v1
kind: Secret
metadata:
  name: hetzner-bearer-token
  namespace: default
type: Opaque
stringData:
  Authorization: Bearer TOKEN123
```

Create an `IP` object which references the secret created above.

```yaml hl_lines="12"
---
apiVersion: cf.containeroo.ch/v1beta1
kind: IP
metadata:
name: hetzner-ipv4
spec:
type: dynamic
IpSources:
- url: https://api.hetzner.cloud/v1/servers
responseJSONPath: '{.servers[0].public_net.ipv4.ip}'
requestHeadersSecretRef:
name: hetzner-bearer-token
namespace: default
interval: 5m
```

### Self-Healing

The `IP` controller reconciles itself at the given interval if an error occurs. See the following table:

| Error | Interval |
| :------------------------------------------------------------------------- | :------- |
| None of the provided `.spec.IpSources[*].urls` return a valid IPv4 address | 60s |
| Fetching `DNSRecord` objects | 30s |

## Ingress

Expand Down Expand Up @@ -244,6 +284,7 @@ The following annotations are supported:
Example:

```yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
Expand Down Expand Up @@ -271,9 +312,9 @@ spec:

### self-healing

The `Ingress` controller reconcile itself in the given interval, if an error occurs. See following table:
The `Ingress` controller reconciles itself at the given interval if an error occurs. See the following table:

| error | interval |
| Error | Interval |
| :--------------------------- | :------- |
| fetching `DNSRecord` objects | 30s |

Expand All @@ -290,6 +331,7 @@ If a `DNSRecord` is deleted, cloudflare-operator will also delete the correspond
Example:

```yaml
---
apiVersion: cf.containeroo.ch/v1beta1
kind: DNSRecord
metadata:
Expand All @@ -308,7 +350,8 @@ Set `spec.ipRef` to the name of an `IP` object to automatically update the `cont

Example:

```yaml
```yaml hl_lines="11"
---
apiVersion: cf.containeroo.ch/v1beta1
kind: DNSRecord
metadata:
Expand All @@ -326,14 +369,14 @@ spec:

### self-healing

The `DNSRecord` controller reconciles itself in the given interval, if an error occurs. See the following table:

| error | interval |
| :------------------------------------------------------------- | :------- |
| `apiKey` in secret from `Account.secretRef` is empty | 5s |
| fetching zones from Cloudflare | 30s |
| `Zone.name` in Cloudflare not found | 30s |
| `Zone` object not ready | 5s |
| fetching zones from Cloudflare | 30s |
| fetching DNS records from Cloudflare | 30s |
| referenced `IP` object (`spec.ipRef.name`) not found | 30s |
The `DNSRecord` controller reconciles itself at the given interval if an error occurs. See the following table:

| Error | Interval |
| :-------------------------------------------------------- | :------- |
| `apiKey` in secret from `Account.spec.secretRef` is empty | 5s |
| Fetching zones from Cloudflare | 30s |
| `Zone.name` in Cloudflare not found | 30s |
| `Zone` object not ready | 5s |
| Fetching zones from Cloudflare | 30s |
| Fetching DNS records from Cloudflare | 30s |
| Referenced `IP` object (`spec.ipRef.name`) not found | 30s |
72 changes: 70 additions & 2 deletions docs/content/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ metadata:
spec:
type: dynamic
interval: 5m
sources:
- url: https://ifconfig.me/ip
- url: https://ipecho.net/plain
- url: https://myip.is/ip/
- url: https://checkip.amazonaws.com
- url: https://api.ipify.org
EOF
```

Expand All @@ -72,8 +78,11 @@ EOF

Annotate all ingresses with your root domain, so cloudflare-operator can create `DNSRecords` for all hosts specified in all ingresses:

```bash
kubectl annotate ingress --all-namespaces --all "cf.containeroo.ch/content=example.com"
```bash hl_lines="4"
kubectl annotate ingress \
--all-namespaces \
--all \
"cf.containeroo.ch/content=example.com"
```

!!! info
Expand All @@ -86,6 +95,7 @@ kubectl annotate ingress --all-namespaces --all "cf.containeroo.ch/content=examp
Let's say you have a vpn-server on a Raspberry Pi. In order to manage the Cloudflare DNS record for you, create a `DNSRecord` object:

```bash
kubectl apply -f - << EOF
apiVersion: cf.containeroo.ch/v1beta1
kind: DNSRecord
metadata:
Expand All @@ -112,6 +122,7 @@ Set `proxied` to `false` because Cloudflare cannot proxy vpn traffic.
Let's say you have an external website `blog.example.com` hosted on a cloud VPC and your external cloud instance IP address is `178.4.20.69`.

```bash
kubectl apply -f - << EOF
apiVersion: cf.containeroo.ch/v1beta1
kind: DNSRecord
metadata:
Expand All @@ -134,3 +145,60 @@ Now your blog will be routed through Cloudflare.

!!! tip "Bonus tip"
If you have multiple cloud services accessible with the same IP, you can also create an `IP` object and link this with `ipRef.name`, so you only have to change the IP address of your cloud instance once in the `IP` object.

If your cloud provider has an API returning the public IPv4 address of your instance, you can also create an `IP` object with type `dynamic` and reference it in the `DNSRecord`.

Create a `secret` with your provider API credentials:

```bash
kubectl apply -f - << EOF
apiVersion: v1
kind: Secret
metadata:
name: hetzner-bearer-token
namespace: default
type: Opaque
stringData:
Authorization: Bearer TOKEN123
EOF
```

Create an `IP` object with a reference to the `secret` created above:

```bash hl_lines="12"
kubectl apply -f - << EOF
apiVersion: cf.containeroo.ch/v1beta1
kind: IP
metadata:
name: hetzner-ipv4
spec:
type: dynamic
sources:
- url: https://api.hetzner.cloud/v1/servers
responseJSONPath: '{.servers[0].public_net.ipv4.ip}'
requestHeadersSecretRef:
name: hetzner-bearer-token
namespace: default
interval: 5m
EOF
```

Create a `DNSRecord` with a reference to the `IP` object created above:

```bash
kubectl apply -f - << EOF
apiVersion: cf.containeroo.ch/v1beta1
kind: DNSRecord
metadata:
name: blog
namespace: cloudflare-operator
spec:
name: blob.example.com
ipRef:
name: hetzner-ipv4
type: A
proxied: true
ttl: 1
interval: 5m
EOF
```
Loading

0 comments on commit d0adc4d

Please sign in to comment.