feat!: add mandatory cloudflare tunnel support (#716)
Co-authored-by: Devin Buhl <onedr0p@users.noreply.github.com>
This commit is contained in:
1 parent
b917eccb76
commit
145f575fbb
34 files changed
+352
-395
No files matched your search
+8
-1
@@ -21,9 +21,16 @@ export BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD="generated" # NOTE: Must only conta
|
||||
export BOOTSTRAP_CLOUDFLARE_DOMAIN=""
|
||||
# The email you use to sign into Cloudflare with
|
||||
export BOOTSTRAP_CLOUDFLARE_EMAIL=""
|
||||
# Your global Cloudflare API Key
|
||||
# Your global Cloudflare API Key (not API token)
|
||||
export BOOTSTRAP_CLOUDFLARE_APIKEY=""
|
||||
|
||||
# Create a cloudflare tunnel to automatically ingress into your cluster
|
||||
# https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-guide/local/
|
||||
# cloudflared tunnel create <NAME or UUID>
|
||||
export BOOTSTRAP_CLOUDFLARE_ACCOUNT_TAG=""
|
||||
export BOOTSTRAP_CLOUDFLARE_TUNNEL_SECRET=""
|
||||
export BOOTSTRAP_CLOUDFLARE_TUNNEL_ID=""
|
||||
|
||||
# Pick a range of unused IPs that are on the same network as your nodes
|
||||
# You don't need many IPs, just choose 10 IPs to start with
|
||||
# e.g. 192.168.1.220-192.168.1.230
|
||||
|
||||
@@ -5,7 +5,5 @@ area/github:
|
||||
- ".github/**/*"
|
||||
area/kubernetes:
|
||||
- "kubernetes/**/*"
|
||||
area/terraform:
|
||||
- "terraform/**/*"
|
||||
area/templates:
|
||||
- "tmpl/**/*"
|
||||
@@ -16,10 +16,6 @@
|
||||
color: "72ccf3"
|
||||
description: >-
|
||||
Changes made in the tmpl directory
|
||||
- name: area/terraform
|
||||
color: "72ccf3"
|
||||
description: >-
|
||||
Changes made in the terraform directory
|
||||
# Renovate
|
||||
- name: renovate/ansible
|
||||
color: "ffc300"
|
||||
@@ -31,8 +27,6 @@
|
||||
color: "ffc300"
|
||||
- name: renovate/helm
|
||||
color: "ffc300"
|
||||
- name: renovate/terraform
|
||||
color: "ffc300"
|
||||
# Semantic Type
|
||||
- name: type/patch
|
||||
color: "FFEC19"
|
||||
|
||||
@@ -12,8 +12,6 @@ categories:
|
||||
labels: ["area/github"]
|
||||
- title: "Ansible"
|
||||
labels: ["area/ansible"]
|
||||
- title: "Terraform"
|
||||
labels: ["area/terraform"]
|
||||
- title: "Maintenance"
|
||||
labels: ["docs"]
|
||||
version-resolver:
|
||||
|
||||
@@ -25,10 +25,6 @@
|
||||
"matchDatasources": ["galaxy", "galaxy-collection"],
|
||||
"addLabels": ["renovate/ansible"]
|
||||
},
|
||||
{
|
||||
"matchDatasources": ["terraform-provider"],
|
||||
"addLabels": ["renovate/terraform"]
|
||||
},
|
||||
{
|
||||
"matchDatasources": ["github-releases", "github-tags"],
|
||||
"addLabels": ["renovate/github-release"]
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
"semanticCommitType": "feat",
|
||||
"semanticCommitScope": "helm"
|
||||
},
|
||||
|
||||
{
|
||||
"matchDatasources": ["helm"],
|
||||
"matchUpdateTypes": ["patch"],
|
||||
@@ -53,30 +52,12 @@
|
||||
"semanticCommitType": "feat",
|
||||
"semanticCommitScope": "ansible"
|
||||
},
|
||||
|
||||
{
|
||||
"matchDatasources": ["galaxy", "galaxy-collection"],
|
||||
"matchUpdateTypes": ["patch"],
|
||||
"semanticCommitType": "fix",
|
||||
"semanticCommitScope": "ansible"
|
||||
},
|
||||
{
|
||||
"matchDatasources": ["terraform-provider"],
|
||||
"matchUpdateTypes": ["major"],
|
||||
"commitMessagePrefix": "feat(terraform)!: "
|
||||
},
|
||||
{
|
||||
"matchDatasources": ["terraform-provider"],
|
||||
"matchUpdateTypes": ["minor"],
|
||||
"semanticCommitType": "feat",
|
||||
"semanticCommitScope": "terraform"
|
||||
},
|
||||
{
|
||||
"matchDatasources": ["terraform-provider"],
|
||||
"matchUpdateTypes": ["patch"],
|
||||
"semanticCommitType": "fix",
|
||||
"semanticCommitScope": "terraform"
|
||||
},
|
||||
{
|
||||
"matchDatasources": ["github-releases", "github-tags"],
|
||||
"matchUpdateTypes": ["major"],
|
||||
|
||||
@@ -11,7 +11,3 @@ kubeconfig
|
||||
*.key
|
||||
# Ansible
|
||||
xanmanning.k3s*
|
||||
# Terraform
|
||||
.terraform
|
||||
.terraform.tfstate*
|
||||
terraform.tfstate*
|
||||
@@ -8,7 +8,3 @@ repos:
|
||||
- --config-file
|
||||
- .yamllint.yaml
|
||||
id: yamllint
|
||||
- repo: https://github.com/gruntwork-io/pre-commit
|
||||
rev: v0.1.21
|
||||
hooks:
|
||||
- id: terraform-fmt
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
version: "3"
|
||||
|
||||
tasks:
|
||||
|
||||
init:
|
||||
desc: Initialize terraform dependencies
|
||||
dir: "{{.TERRAFORM_DIR}}/cloudflare"
|
||||
cmds:
|
||||
- terraform init {{.CLI_ARGS}}
|
||||
|
||||
plan:
|
||||
desc: Show the changes terraform will make
|
||||
dir: "{{.TERRAFORM_DIR}}/cloudflare"
|
||||
cmds:
|
||||
- terraform plan {{.CLI_ARGS}}
|
||||
|
||||
apply:
|
||||
desc: Apply the changes to Cloudflare
|
||||
dir: "{{.TERRAFORM_DIR}}/cloudflare"
|
||||
cmds:
|
||||
- terraform apply {{.CLI_ARGS}}
|
||||
Vendored
-1
@@ -8,7 +8,6 @@
|
||||
"signageos.signageos-vscode-sops",
|
||||
"will-stone.in-any-case",
|
||||
"EditorConfig.editorconfig",
|
||||
"HashiCorp.terraform",
|
||||
"PKief.material-icon-theme",
|
||||
]
|
||||
}
|
||||
Vendored
-1
@@ -4,7 +4,6 @@
|
||||
"**/ansible/**/*.yml": "ansible",
|
||||
"**/ansible/**/*.sops.yml": "yaml",
|
||||
"**/ansible/**/inventory/**/*.yml": "yaml",
|
||||
"**/terraform/**/*.tf": "terraform",
|
||||
"**/kubernetes/**/*.sops.toml": "plaintext"
|
||||
},
|
||||
"yaml.schemas": {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Template for deploying k3s backed by Flux
|
||||
|
||||
Highly opinionated template for deploying a single [k3s](https://k3s.io) cluster with [Ansible](https://www.ansible.com) and [Terraform](https://www.terraform.io) backed by [Flux](https://toolkit.fluxcd.io/) and [SOPS](https://toolkit.fluxcd.io/guides/mozilla-sops/).
|
||||
This is a sighly opinionated template for deploying a single [k3s](https://k3s.io) cluster with [Ansible](https://www.ansible.com) and [SOPS](https://toolkit.fluxcd.io/guides/mozilla-sops/). Upon completion you will be able to expose web applications you choose to the internet with [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/)
|
||||
|
||||
The purpose here is to showcase how you can deploy an entire Kubernetes cluster and show it off to the world using the [GitOps](https://www.weave.works/blog/what-is-gitops-really) tool [Flux](https://toolkit.fluxcd.io/). When completed, your Git repository will be driving the state of your Kubernetes cluster. In addition with the help of the [Ansible](https://github.com/ansible-collections/community.sops), [Terraform](https://github.com/carlpett/terraform-provider-sops) and [Flux](https://toolkit.fluxcd.io/guides/mozilla-sops/) SOPS integrations you'll be able to commit [Age](https://github.com/FiloSottile/age) encrypted secrets to your public repo.
|
||||
The purpose here is to showcase how you can deploy an entire Kubernetes cluster and show it off to the world using the [GitOps](https://www.weave.works/blog/what-is-gitops-really) tool [Flux](https://toolkit.fluxcd.io/). When completed, your Git repository will be driving the state of your Kubernetes cluster. In addition with the help of the [Ansible](https://github.com/ansible-collections/community.sops), and [Flux](https://toolkit.fluxcd.io/guides/mozilla-sops/) SOPS integrations you'll be able to commit [Age](https://github.com/FiloSottile/age) encrypted secrets to your public repo.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -31,16 +31,11 @@ The following components will be installed in your [k3s](https://k3s.io/) cluste
|
||||
|
||||
_Additional applications include [hajimari](https://github.com/toboshii/hajimari), [error-pages](https://github.com/tarampampam/error-pages), [echo-server](https://github.com/Ealenn/Echo-Server), [system-upgrade-controller](https://github.com/rancher/system-upgrade-controller), [reloader](https://github.com/stakater/Reloader), and [kured](https://github.com/weaveworks/kured)_
|
||||
|
||||
For provisioning the following tools will be used:
|
||||
|
||||
- [Ansible](https://www.ansible.com) - Sets up the operating system and installs k3s
|
||||
- [Terraform](https://www.terraform.io) - Provisions an existing Cloudflare domain and certain DNS records to be used with your Kubernetes cluster
|
||||
|
||||
## 📝 Prerequisites
|
||||
|
||||
**Note:** _This template has not been tested on cloud providers like AWS EC2, Hetzner, Scaleway etc... Those cloud offerings probably have a better way of provsioning a Kubernetes cluster and it's advisable to use those instead of the Ansible playbooks included here. This repository can still be tweaked for the GitOps/Flux portion if there's a cluster working in one those environments._
|
||||
|
||||
First and foremost some experience in debugging/troubleshooting problems **and a positive attitude is required** ;)
|
||||
First and foremost some experience in debugging/troubleshooting problems **and a positive attitude is required** :)
|
||||
|
||||
### 📚 Reading material
|
||||
|
||||
@@ -48,10 +43,10 @@ First and foremost some experience in debugging/troubleshooting problems **and a
|
||||
|
||||
### 💻 Systems
|
||||
|
||||
- One or more nodes with a fresh install of [Fedora Server 37](https://getfedora.org/en/server/download/) or [Ubuntu 22.04 Server](https://ubuntu.com/download/server) (not minimal).
|
||||
- One or more nodes with a fresh install of [Fedora Server 37+](https://getfedora.org/en/server/download/) or [Ubuntu 22.04 Server](https://ubuntu.com/download/server) (not minimal).
|
||||
- These nodes can be ARM64/AMD64 bare metal or VMs.
|
||||
- An odd number of control plane nodes, greater than or equal to 3 is required if deploying more than one control plane node.
|
||||
- A [Cloudflare](https://www.cloudflare.com/) account with a domain, this will be managed by Terraform and external-dns. You can [register new domains](https://www.cloudflare.com/products/registrar/) directly thru Cloudflare.
|
||||
- A [Cloudflare](https://www.cloudflare.com/) account with a domain, this will be managed by external-dns. You can [register new domains](https://www.cloudflare.com/products/registrar/) directly thru Cloudflare.
|
||||
|
||||
📍 It is recommended to have 3 master nodes for a highly available control plane.
|
||||
|
||||
@@ -80,13 +75,14 @@ Clone **your new repo** to you local workstation and `cd` into it.
|
||||
|
||||
1. Install the following CLI tools on your workstation, if you are **NOT** using [Homebrew](https://brew.sh/) on MacOS or Linux **ignore** steps 4 and 5.
|
||||
|
||||
* Required: [age](https://github.com/FiloSottile/age), [ansible](https://www.ansible.com), [flux](https://toolkit.fluxcd.io/), [weave-gitops](https://docs.gitops.weave.works/docs/installation/weave-gitops/), [go-task](https://github.com/go-task/task), [direnv](https://github.com/direnv/direnv), [ipcalc](http://jodies.de/ipcalc), [jq](https://stedolan.github.io/jq/), [kubectl](https://kubernetes.io/docs/tasks/tools/), [python-pip3](https://pypi.org/project/pip/), [pre-commit](https://github.com/pre-commit/pre-commit), [sops v3](https://github.com/mozilla/sops), [terraform](https://www.terraform.io), [yq v4](https://github.com/mikefarah/yq)
|
||||
- Required: [age](https://github.com/FiloSottile/age), [ansible](https://www.ansible.com), [flux](https://toolkit.fluxcd.io/), [weave-gitops](https://docs.gitops.weave.works/docs/installation/weave-gitops/), [go-task](https://github.com/go-task/task), [direnv](https://github.com/direnv/direnv), [ipcalc](http://jodies.de/ipcalc), [jq](https://stedolan.github.io/jq/), [kubectl](https://kubernetes.io/docs/tasks/tools/), [python-pip3](https://pypi.org/project/pip/), [pre-commit](https://github.com/pre-commit/pre-commit), [sops v3](https://github.com/mozilla/sops), [terraform](https://www.terraform.io), [yq v4](https://github.com/mikefarah/yq)
|
||||
|
||||
* Recommended: [helm](https://helm.sh/), [kustomize](https://github.com/kubernetes-sigs/kustomize), [stern](https://github.com/stern/stern), [yamllint](https://github.com/adrienverge/yamllint)
|
||||
- Recommended: [helm](https://helm.sh/), [kustomize](https://github.com/kubernetes-sigs/kustomize), [stern](https://github.com/stern/stern), [yamllint](https://github.com/adrienverge/yamllint)
|
||||
|
||||
2. This guide heavily relies on [go-task](https://github.com/go-task/task) as a framework for setting things up. It is advised to learn and understand the commands it is running under the hood.
|
||||
|
||||
3. Install Python 3 and pip3 using your Linux OS package manager, or Homebrew if using MacOS.
|
||||
|
||||
- Ensure `pip3` is working on your command line by running `pip3 --version`
|
||||
|
||||
4. [Homebrew] Install [go-task](https://github.com/go-task/task)
|
||||
@@ -119,7 +115,7 @@ It is advisable to install [pre-commit](https://pre-commit.com/) and the pre-com
|
||||
|
||||
### 🔐 Setting up Age
|
||||
|
||||
📍 Here we will create a Age Private and Public key. Using [SOPS](https://github.com/mozilla/sops) with [Age](https://github.com/FiloSottile/age) allows us to encrypt secrets and use them in Ansible, Terraform and Flux.
|
||||
📍 Here we will create a Age Private and Public key. Using [SOPS](https://github.com/mozilla/sops) with [Age](https://github.com/FiloSottile/age) allows us to encrypt secrets and use them in Ansible and Flux.
|
||||
|
||||
1. Create a Age Private / Public Key
|
||||
|
||||
@@ -143,9 +139,9 @@ It is advisable to install [pre-commit](https://pre-commit.com/) and the pre-com
|
||||
|
||||
4. Fill out the Age public key in the appropriate variable in configuration section below, **note** the public key should start with `age`...
|
||||
|
||||
### ☁️ Global Cloudflare API Key
|
||||
### ☁️ Cloudflare API Key
|
||||
|
||||
In order to use Terraform and `cert-manager` with the Cloudflare DNS challenge you will need to create a API key.
|
||||
In order to use `cert-manager` with the Cloudflare DNS challenge you will need to create a API key.
|
||||
|
||||
1. Head over to Cloudflare and create a API key by going [here](https://dash.cloudflare.com/profile/api-tokens).
|
||||
|
||||
@@ -155,9 +151,27 @@ In order to use Terraform and `cert-manager` with the Cloudflare DNS challenge y
|
||||
|
||||
📍 You may wish to update this later on to a Cloudflare **API Token** which can be scoped to certain resources. I do not recommend using a Cloudflare **API Key**, however for the purposes of this template it is easier getting started without having to define which scopes and resources are needed. For more information see the [Cloudflare docs on API Keys and Tokens](https://developers.cloudflare.com/api/).
|
||||
|
||||
### ☁️ Cloudflare Tunnel
|
||||
|
||||
In order to expose services to the internet you will need to create a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/).
|
||||
|
||||
1. Authenticate cloudflared to your domain
|
||||
|
||||
```sh
|
||||
cloudflared tunnel login
|
||||
```
|
||||
|
||||
2. Create the tunnel
|
||||
|
||||
```sh
|
||||
cloudflared tunnel create k8s
|
||||
```
|
||||
|
||||
3. In the `~/.cloudflared` directory there will be a json file with details you need to populate in configuration section below. You can ignore the `cert.pem` file.
|
||||
|
||||
### 📄 Configuration
|
||||
|
||||
📍 The `.config.env` file contains necessary configuration that is needed by Ansible, Terraform and Flux.
|
||||
📍 The `.config.env` file contains necessary configuration that is needed by Ansible and Flux.
|
||||
|
||||
1. Copy the `.config.sample.env` to `.config.env` and start filling out all the environment variables.
|
||||
|
||||
@@ -252,34 +266,6 @@ In order to use Terraform and `cert-manager` with the Cloudflare DNS challenge y
|
||||
# k8s-1 Ready worker 4d20h v1.21.5+k3s1
|
||||
```
|
||||
|
||||
### ☁️ Configuring Cloudflare DNS with Terraform
|
||||
|
||||
📍 Review the Terraform scripts under `./terraform/cloudflare/` and make sure you understand what it's doing (no really review it).
|
||||
|
||||
If your domain already has existing DNS records **be sure to export those DNS settings before you continue**.
|
||||
|
||||
1. Pull in the Terraform deps
|
||||
|
||||
```sh
|
||||
task terraform:init
|
||||
```
|
||||
|
||||
2. Review the changes Terraform will make to your Cloudflare domain
|
||||
|
||||
```sh
|
||||
task terraform:plan
|
||||
```
|
||||
|
||||
3. Have Terraform apply your Cloudflare settings
|
||||
|
||||
```sh
|
||||
task terraform:apply
|
||||
```
|
||||
|
||||
If Terraform was ran successfully you can log into Cloudflare and validate the DNS records are present.
|
||||
|
||||
The cluster application [external-dns](https://github.com/kubernetes-sigs/external-dns) will be managing the rest of the DNS records you will need.
|
||||
|
||||
### 🔹 GitOps with Flux
|
||||
|
||||
📍 Here we will be installing [flux](https://toolkit.fluxcd.io/) after some quick bootstrap steps.
|
||||
@@ -389,7 +375,7 @@ task cluster:resources
|
||||
|
||||
### 🌐 DNS
|
||||
|
||||
📍 The [external-dns](https://github.com/kubernetes-sigs/external-dns) application created in the `networking` namespace will handle creating public DNS records. By default, `echo-server` and the `flux-webhook` are the only public domain exposed on your Cloudflare domain. In order to make additional applications public you must set an ingress annotation (`external-dns.alpha.kubernetes.io/target`) like done in the `HelmRelease` for `echo-server`. You do not need to use Terraform to create additional DNS records unless you need a record outside the purposes of your Kubernetes cluster (e.g. setting up MX records).
|
||||
📍 The [external-dns](https://github.com/kubernetes-sigs/external-dns) application created in the `networking` namespace will handle creating public DNS records. By default, `echo-server` and the `flux-webhook` are the only public domain exposed on your Cloudflare domain. In order to make additional applications public you must set an ingress annotation (`external-dns.alpha.kubernetes.io/target`) like done in the `HelmRelease` for `echo-server`.
|
||||
|
||||
[k8s_gateway](https://github.com/ori-edge/k8s_gateway) is deployed on the IP choosen for `${BOOTSTRAP_METALLB_K8S_GATEWAY_ADDR}`. Inorder to test DNS you can point your clients DNS to the `${BOOTSTRAP_METALLB_K8S_GATEWAY_ADDR}` IP address and load `https://hajimari.${BOOTSTRAP_CLOUDFLARE_DOMAIN}` in your browser.
|
||||
|
||||
@@ -397,8 +383,6 @@ You can also try debugging with the command `dig`, e.g. `dig @${BOOTSTRAP_METALL
|
||||
|
||||
If your router (or Pi-Hole, Adguard Home or whatever) supports conditional DNS forwarding (also know as split-horizon DNS) you may have DNS requests for `${SECRET_DOMAIN}` only point to the `${BOOTSTRAP_METALLB_K8S_GATEWAY_ADDR}` IP address. This will ensure only DNS requests for `${SECRET_DOMAIN}` will only get routed to your [k8s_gateway](https://github.com/ori-edge/k8s_gateway) service thus providing DNS resolution to your cluster applications/ingresses.
|
||||
|
||||
To access services from the outside world port forwarded `80` and `443` in your router to the `${BOOTSTRAP_METALLB_INGRESS_ADDR}` IP, in a few moments head over to your browser and you _should_ be able to access `https://echo-server.${BOOTSTRAP_CLOUDFLARE_DOMAIN}` from a device outside your LAN.
|
||||
|
||||
Now if nothing is working, that is expected. This is DNS after all!
|
||||
|
||||
### 🤖 Renovatebot
|
||||
@@ -457,18 +441,18 @@ By default this template only works on a public GitHub repository, it is advised
|
||||
|
||||
The benefits of a public repository include:
|
||||
|
||||
* Debugging or asking for help, you can provide a link to a resource you are having issues with.
|
||||
* Adding a topic to your repository of `k8s-at-home` to be included in the [k8s-at-home-search](https://whazor.github.io/k8s-at-home-search/). This search helps people discover different configurations of Helm charts across others Flux based repositories.
|
||||
- Debugging or asking for help, you can provide a link to a resource you are having issues with.
|
||||
- Adding a topic to your repository of `k8s-at-home` to be included in the [k8s-at-home-search](https://whazor.github.io/k8s-at-home-search/). This search helps people discover different configurations of Helm charts across others Flux based repositories.
|
||||
|
||||
<details>
|
||||
<summary>Expand to read guide on adding Flux SSH authentication</summary>
|
||||
|
||||
1. Generate new SSH key:
|
||||
1. Generate new SSH key:
|
||||
```sh
|
||||
ssh-keygen -t ecdsa -b 521 -C "github-deploy-key" -f ./kubernetes/bootstrap/github-deploy.key -q -P ""
|
||||
```
|
||||
2. Paste public key in the deploy keys section of your repository settings
|
||||
3. Create sops secret in `./kubernetes/bootstrap/github-deploy-key.sops.yaml` with the contents of:
|
||||
2. Paste public key in the deploy keys section of your repository settings
|
||||
3. Create sops secret in `./kubernetes/bootstrap/github-deploy-key.sops.yaml` with the contents of:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
@@ -487,15 +471,15 @@ The benefits of a public repository include:
|
||||
github.com ecdsa-sha2-nistp256 ...
|
||||
github.com ssh-rsa ...
|
||||
```
|
||||
4. Encrypt secret:
|
||||
4. Encrypt secret:
|
||||
```sh
|
||||
sops --encrypt --in-place ./kubernetes/bootstrap/github-deploy-key.sops.yaml
|
||||
```
|
||||
5. Apply secret to cluster:
|
||||
5. Apply secret to cluster:
|
||||
```sh
|
||||
sops --decrypt ./kubernetes/bootstrap/github-deploy-key.sops.yaml | kubectl apply -f -
|
||||
```
|
||||
6. Update `./kubernetes/flux/config/cluster.yaml`:
|
||||
6. Update `./kubernetes/flux/config/cluster.yaml`:
|
||||
```yaml
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
kind: GitRepository
|
||||
@@ -511,16 +495,16 @@ The benefits of a public repository include:
|
||||
secretRef:
|
||||
name: github-deploy-key
|
||||
```
|
||||
7. Commit and push changes
|
||||
8. Force flux to reconcile your changes
|
||||
7. Commit and push changes
|
||||
8. Force flux to reconcile your changes
|
||||
```sh
|
||||
task cluster:reconcile
|
||||
```
|
||||
9. Verify git repository is now using SSH:
|
||||
9. Verify git repository is now using SSH:
|
||||
```sh
|
||||
task cluster:gitrepositories
|
||||
```
|
||||
10. Optionally set your repository to Private in your repository settings.
|
||||
10. Optionally set your repository to Private in your repository settings.
|
||||
</details>
|
||||
|
||||
### 💨 Kubernetes Dashboard
|
||||
@@ -538,13 +522,20 @@ You should be able to access the dashboard at `https://kubernetes.${SECRET_DOMAI
|
||||
Below is a general guide on trying to debug an issue with an resource or application. For example, if a workload/resource is not showing up or a pod has started but in a `CrashLoopBackOff` or `Pending` state.
|
||||
|
||||
1. Start by checking all Flux Kustomizations and verify they are healthy.
|
||||
- `flux get ks -A`
|
||||
|
||||
- `flux get ks -A`
|
||||
|
||||
2. Then check all the Flux Helm Releases and verify they are healthy.
|
||||
- `flux get hr -A`
|
||||
|
||||
- `flux get hr -A`
|
||||
|
||||
3. Then check the if the pod is present.
|
||||
- `kubectl -n <namespace> get pods`
|
||||
|
||||
- `kubectl -n <namespace> get pods`
|
||||
|
||||
4. Then check the logs of the pod if its there.
|
||||
- `kubectl -n <namespace> logs <pod-name> -f`
|
||||
|
||||
- `kubectl -n <namespace> logs <pod-name> -f`
|
||||
|
||||
Note: If a resource exists, running `kubectl -n <namespace> describe <resource> <name>` might give you insight into what the problem(s) could be.
|
||||
|
||||
|
||||
+1
-5
@@ -4,7 +4,6 @@ version: "3"
|
||||
vars:
|
||||
KUBERNETES_DIR: "{{.ROOT_DIR}}/kubernetes"
|
||||
ANSIBLE_DIR: "{{.ROOT_DIR}}/ansible"
|
||||
TERRAFORM_DIR: "{{.ROOT_DIR}}/terraform"
|
||||
|
||||
dotenv: [".config.env"]
|
||||
|
||||
@@ -16,10 +15,8 @@ includes:
|
||||
ansible: .taskfiles/AnsibleTasks.yml
|
||||
cluster: .taskfiles/ClusterTasks.yml
|
||||
precommit: .taskfiles/PrecommitTasks.yml
|
||||
terraform: .taskfiles/TerraformTasks.yml
|
||||
|
||||
tasks:
|
||||
|
||||
init:
|
||||
desc: Initialize workstation dependencies with Brew
|
||||
cmds:
|
||||
@@ -33,6 +30,7 @@ tasks:
|
||||
DEPS: >-
|
||||
age
|
||||
ansible
|
||||
cloudflare/cloudflare/cloudflared
|
||||
direnv
|
||||
fluxcd/tap/flux
|
||||
go-task/tap/go-task
|
||||
@@ -45,8 +43,6 @@ tasks:
|
||||
prettier
|
||||
sops
|
||||
stern
|
||||
terraform
|
||||
tflint
|
||||
weaveworks/tap/gitops
|
||||
yamllint
|
||||
yq
|
||||
|
||||
@@ -51,15 +51,9 @@ main() {
|
||||
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/cert-manager-secret.sops.yaml" \
|
||||
> "${PROJECT_DIR}/kubernetes/apps/cert-manager/cert-manager/issuers/secret.sops.yaml"
|
||||
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/cert-manager/cert-manager/issuers/secret.sops.yaml"
|
||||
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/cloudflare-ddns-secret.sops.yaml" \
|
||||
> "${PROJECT_DIR}/kubernetes/apps/networking/cloudflare-ddns/app/secret.sops.yaml"
|
||||
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/networking/cloudflare-ddns/app/secret.sops.yaml"
|
||||
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/external-dns-secret.sops.yaml" \
|
||||
> "${PROJECT_DIR}/kubernetes/apps/networking/external-dns/app/secret.sops.yaml"
|
||||
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/networking/external-dns/app/secret.sops.yaml"
|
||||
envsubst < "${PROJECT_DIR}/tmpl/terraform/secret.sops.yaml" \
|
||||
> "${PROJECT_DIR}/terraform/cloudflare/secret.sops.yaml"
|
||||
sops --encrypt --in-place "${PROJECT_DIR}/terraform/cloudflare/secret.sops.yaml"
|
||||
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/cloudflared-secret.sops.yaml" \
|
||||
> "${PROJECT_DIR}/kubernetes/apps/networking/cloudflared/app/secret.sops.yaml"
|
||||
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/networking/cloudflared/app/secret.sops.yaml"
|
||||
# generate ansible settings
|
||||
envsubst < "${PROJECT_DIR}/tmpl/ansible/kube-vip.yml" \
|
||||
> "${PROJECT_DIR}/ansible/inventory/group_vars/kubernetes/kube-vip.yml"
|
||||
@@ -229,7 +223,6 @@ verify_binaries() {
|
||||
_has_binary "sops"
|
||||
_has_binary "ssh"
|
||||
_has_binary "task"
|
||||
_has_binary "terraform"
|
||||
_has_binary "yq"
|
||||
if ! [[ "$(sops --version)" =~ 3\.[0-9]+\.[0-9]+ ]]; then
|
||||
_log "ERROR(${FUNCNAME[0]})" "Incompatible sops version, make sure you are using the latest release of github.com/mozilla/sops"
|
||||
@@ -287,8 +280,8 @@ verify_master_count() {
|
||||
}
|
||||
|
||||
verify_cloudflare() {
|
||||
local account_zone=
|
||||
local errors=
|
||||
local account_zone=
|
||||
_has_envar "BOOTSTRAP_CLOUDFLARE_APIKEY" "true"
|
||||
_has_envar "BOOTSTRAP_CLOUDFLARE_DOMAIN" "true"
|
||||
_has_envar "BOOTSTRAP_CLOUDFLARE_EMAIL" "true"
|
||||
@@ -305,6 +298,23 @@ verify_cloudflare() {
|
||||
_log "ERROR(${FUNCNAME[0]})" "Unable to get Cloudflare Account and Zone information ${errors}"
|
||||
exit 1
|
||||
fi
|
||||
local cloudflare_tunnel=
|
||||
_has_envar "BOOTSTRAP_CLOUDFLARE_ACCOUNT_TAG" "true"
|
||||
_has_envar "BOOTSTRAP_CLOUDFLARE_TUNNEL_SECRET" "true"
|
||||
_has_envar "BOOTSTRAP_CLOUDFLARE_TUNNEL_ID" "true"
|
||||
# Try to retrieve the Cloudflare Tunnel information from Cloudflare's API
|
||||
cloudflare_tunnel=$(curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/${BOOTSTRAP_CLOUDFLARE_ACCOUNT_TAG}/cfd_tunnel/${BOOTSTRAP_CLOUDFLARE_TUNNEL_ID}" \
|
||||
-H "X-Auth-Email: ${BOOTSTRAP_CLOUDFLARE_EMAIL}" \
|
||||
-H "X-Auth-Key: ${BOOTSTRAP_CLOUDFLARE_APIKEY}" \
|
||||
-H "Content-Type: application/json"
|
||||
)
|
||||
if [[ "$(echo "${cloudflare_tunnel}" | jq ".success")" == "true" ]]; then
|
||||
_log "INFO(${FUNCNAME[0]})" "Verified Cloudflare Tunnel information"
|
||||
else
|
||||
errors=$(echo "${cloudflare_tunnel}" | jq -c ".errors")
|
||||
_log "ERROR(${FUNCNAME[0]})" "Unable to get Cloudflare Tunnel information ${errors}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
verify_ansible_hosts() {
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -o nounset
|
||||
set -o errexit
|
||||
|
||||
current_ipv4="$(curl -s https://ipv4.icanhazip.com/)"
|
||||
zone_id=$(curl -s -X GET \
|
||||
"https://api.cloudflare.com/client/v4/zones?name=${CLOUDFLARE_RECORD_NAME#*.}&status=active" \
|
||||
-H "X-Auth-Email: ${CLOUDFLARE_EMAIL}" \
|
||||
-H "X-Auth-Key: ${CLOUDFLARE_APIKEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
| jq --raw-output ".result[0] | .id"
|
||||
)
|
||||
record_ipv4=$(curl -s -X GET \
|
||||
"https://api.cloudflare.com/client/v4/zones/${zone_id}/dns_records?name=${CLOUDFLARE_RECORD_NAME}&type=A" \
|
||||
-H "X-Auth-Email: ${CLOUDFLARE_EMAIL}" \
|
||||
-H "X-Auth-Key: ${CLOUDFLARE_APIKEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
)
|
||||
old_ip4=$(echo "$record_ipv4" | jq --raw-output '.result[0] | .content')
|
||||
if [[ "${current_ipv4}" == "${old_ip4}" ]]; then
|
||||
printf "%s - IP Address '%s' has not changed" "$(date -u)" "${current_ipv4}"
|
||||
exit 0
|
||||
fi
|
||||
record_ipv4_identifier="$(echo "$record_ipv4" | jq --raw-output '.result[0] | .id')"
|
||||
update_ipv4=$(curl -s -X PUT \
|
||||
"https://api.cloudflare.com/client/v4/zones/${zone_id}/dns_records/${record_ipv4_identifier}" \
|
||||
-H "X-Auth-Email: ${CLOUDFLARE_EMAIL}" \
|
||||
-H "X-Auth-Key: ${CLOUDFLARE_APIKEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{\"id\":\"${zone_id}\",\"type\":\"A\",\"proxied\":true,\"name\":\"${CLOUDFLARE_RECORD_NAME}\",\"content\":\"${current_ipv4}\"}" \
|
||||
)
|
||||
if [[ "$(echo "$update_ipv4" | jq --raw-output '.success')" == "true" ]]; then
|
||||
printf "%s - Success - IP Address '%s' has been updated" "$(date -u)" "${current_ipv4}"
|
||||
exit 0
|
||||
else
|
||||
printf "%s - Yikes - Updating IP Address '%s' has failed" "$(date -u)" "${current_ipv4}"
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2beta1
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: cloudflare-ddns
|
||||
namespace: networking
|
||||
spec:
|
||||
interval: 15m
|
||||
chart:
|
||||
spec:
|
||||
chart: app-template
|
||||
version: 1.4.0
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bjw-s
|
||||
namespace: flux-system
|
||||
maxHistory: 3
|
||||
install:
|
||||
createNamespace: true
|
||||
remediation:
|
||||
retries: 3
|
||||
upgrade:
|
||||
cleanupOnFail: true
|
||||
remediation:
|
||||
retries: 3
|
||||
uninstall:
|
||||
keepHistory: false
|
||||
values:
|
||||
controller:
|
||||
type: cronjob
|
||||
cronjob:
|
||||
concurrencyPolicy: Forbid
|
||||
schedule: "@hourly"
|
||||
restartPolicy: OnFailure
|
||||
image:
|
||||
repository: ghcr.io/onedr0p/kubernetes-kubectl
|
||||
tag: 1.27.1@sha256:2067b52145cdcb99b1db4e92fa114babc0a8a91e08711cbe1aae05ba5a277dd9
|
||||
command: ["/bin/bash", "/app/cloudflare-ddns.sh"]
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: cloudflare-ddns-secret
|
||||
service:
|
||||
main:
|
||||
enabled: false
|
||||
persistence:
|
||||
config:
|
||||
enabled: true
|
||||
type: configMap
|
||||
name: cloudflare-ddns-configmap
|
||||
subPath: cloudflare-ddns.sh
|
||||
mountPath: /app/cloudflare-ddns.sh
|
||||
defaultMode: 0775
|
||||
readOnly: true
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
# The `ingress` block tells cloudflared which local service to route incoming
|
||||
# requests to. For more about ingress rules, see
|
||||
# https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/configuration/ingress
|
||||
#
|
||||
# Remember, these rules route traffic from cloudflared to a local service. To route traffic
|
||||
# from the internet to cloudflared, run `cloudflared tunnel route dns <tunnel> <hostname>`.
|
||||
# E.g. `cloudflared tunnel route dns example-tunnel tunnel.example.com`.
|
||||
ingress:
|
||||
- hostname: "${SECRET_DOMAIN}"
|
||||
service: https://ingress-nginx-controller.networking.svc.cluster.local:443
|
||||
originRequest:
|
||||
originServerName: "ipv4.${SECRET_DOMAIN}"
|
||||
- hostname: "*.${SECRET_DOMAIN}"
|
||||
service: https://ingress-nginx-controller.networking.svc.cluster.local:443
|
||||
originRequest:
|
||||
originServerName: "ipv4.${SECRET_DOMAIN}"
|
||||
- service: http_status:404
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
apiVersion: externaldns.k8s.io/v1alpha1
|
||||
kind: DNSEndpoint
|
||||
metadata:
|
||||
name: cloudflared
|
||||
namespace: networking
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/target: "ipv4.${SECRET_DOAMIN}"
|
||||
spec:
|
||||
endpoints:
|
||||
- dnsName: "ipv4.${SECRET_DOAMIN}"
|
||||
recordType: CNAME
|
||||
targets: ["${SECRET_CLOUDFLARE_TUNNEL_ID}.cfargotunnel.com"]
|
||||
@@ -0,0 +1,102 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2beta1
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: &app cloudflared
|
||||
namespace: networking
|
||||
spec:
|
||||
interval: 15m
|
||||
chart:
|
||||
spec:
|
||||
chart: app-template
|
||||
version: 1.4.0
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bjw-s-charts
|
||||
namespace: flux-system
|
||||
maxHistory: 3
|
||||
install:
|
||||
createNamespace: true
|
||||
remediation:
|
||||
retries: 3
|
||||
upgrade:
|
||||
cleanupOnFail: true
|
||||
remediation:
|
||||
retries: 3
|
||||
uninstall:
|
||||
keepHistory: false
|
||||
values:
|
||||
controller:
|
||||
replicas: 1
|
||||
strategy: RollingUpdate
|
||||
annotations:
|
||||
reloader.stakater.com/auto: "true"
|
||||
image:
|
||||
repository: docker.io/cloudflare/cloudflared
|
||||
tag: 2023.5.0
|
||||
env:
|
||||
NO_AUTOUPDATE: "true"
|
||||
TUNNEL_CRED_FILE: /etc/cloudflared/creds/credentials.json
|
||||
TUNNEL_METRICS: 0.0.0.0:8080
|
||||
TUNNEL_TRANSPORT_PROTOCOL: auto
|
||||
TUNNEL_ID:
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: cloudflared-secret
|
||||
key: TUNNEL_ID
|
||||
args:
|
||||
- tunnel
|
||||
- --config
|
||||
- /etc/cloudflared/config/config.yaml
|
||||
- run
|
||||
- "$(TUNNEL_ID)"
|
||||
service:
|
||||
main:
|
||||
ports:
|
||||
http:
|
||||
port: 8080
|
||||
serviceMonitor:
|
||||
main:
|
||||
enabled: true
|
||||
endpoints:
|
||||
- port: http
|
||||
scheme: http
|
||||
path: /metrics
|
||||
interval: 1m
|
||||
scrapeTimeout: 30s
|
||||
probes:
|
||||
liveness: &probes
|
||||
enabled: true
|
||||
custom: true
|
||||
spec:
|
||||
httpGet:
|
||||
path: /ready
|
||||
port: http
|
||||
initialDelaySeconds: 0
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 1
|
||||
failureThreshold: 3
|
||||
readiness: *probes
|
||||
startup:
|
||||
enabled: false
|
||||
persistence:
|
||||
config:
|
||||
enabled: true
|
||||
type: configMap
|
||||
name: cloudflared-configmap
|
||||
subPath: config.yaml
|
||||
mountPath: /etc/cloudflared/config/config.yaml
|
||||
readOnly: true
|
||||
creds:
|
||||
enabled: true
|
||||
type: secret
|
||||
name: cloudflared-secret
|
||||
subPath: credentials.json
|
||||
mountPath: /etc/cloudflared/creds/credentials.json
|
||||
readOnly: true
|
||||
resources:
|
||||
requests:
|
||||
cpu: 5m
|
||||
memory: 10Mi
|
||||
limits:
|
||||
memory: 256Mi
|
||||
+3
-4
@@ -3,13 +3,12 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: networking
|
||||
resources:
|
||||
- ./dnsendpoint.yaml
|
||||
- ./secret.sops.yaml
|
||||
- ./helmrelease.yaml
|
||||
configMapGenerator:
|
||||
- name: cloudflare-ddns-configmap
|
||||
- name: cloudflared-configmap
|
||||
files:
|
||||
- ./cloudflare-ddns.sh
|
||||
- ./configs/config.yaml
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/substitute: disabled
|
||||
+7
-4
@@ -2,10 +2,12 @@
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: cluster-apps-cloudflare-ddns
|
||||
name: cluster-apps-cloudflared
|
||||
namespace: flux-system
|
||||
spec:
|
||||
path: ./kubernetes/apps/networking/cloudflare-ddns/app
|
||||
dependsOn:
|
||||
- name: cluster-apps-ingress-nginx
|
||||
path: ./kubernetes/apps/networking/cloudflared/app
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
@@ -13,7 +15,8 @@ spec:
|
||||
healthChecks:
|
||||
- apiVersion: helm.toolkit.fluxcd.io/v2beta1
|
||||
kind: HelmRelease
|
||||
name: cloudflare-ddns
|
||||
name: cloudflared
|
||||
namespace: networking
|
||||
interval: 30m
|
||||
timeout: 5m
|
||||
retryInterval: 1m
|
||||
timeout: 3m
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.5.0
|
||||
api-approved.kubernetes.io: "https://github.com/kubernetes-sigs/external-dns/pull/2007"
|
||||
creationTimestamp: null
|
||||
name: dnsendpoints.externaldns.k8s.io
|
||||
spec:
|
||||
group: externaldns.k8s.io
|
||||
names:
|
||||
kind: DNSEndpoint
|
||||
listKind: DNSEndpointList
|
||||
plural: dnsendpoints
|
||||
singular: dnsendpoint
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: DNSEndpointSpec defines the desired state of DNSEndpoint
|
||||
properties:
|
||||
endpoints:
|
||||
items:
|
||||
description: Endpoint is a high-level way of a connection between a service and an IP
|
||||
properties:
|
||||
dnsName:
|
||||
description: The hostname of the DNS record
|
||||
type: string
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Labels stores labels defined for the Endpoint
|
||||
type: object
|
||||
providerSpecific:
|
||||
description: ProviderSpecific stores provider specific config
|
||||
items:
|
||||
description: ProviderSpecificProperty holds the name and value of a configuration which is specific to individual DNS providers
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
recordTTL:
|
||||
description: TTL for the record
|
||||
format: int64
|
||||
type: integer
|
||||
recordType:
|
||||
description: RecordType type of record, e.g. CNAME, A, SRV, TXT etc
|
||||
type: string
|
||||
setIdentifier:
|
||||
description: Identifier to distinguish multiple records with the same name and type (e.g. Route53 records with routing policies other than 'simple')
|
||||
type: string
|
||||
targets:
|
||||
description: The targets the DNS record points to
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
status:
|
||||
description: DNSEndpointStatus defines the observed state of DNSEndpoint
|
||||
properties:
|
||||
observedGeneration:
|
||||
description: The generation observed by the external-dns controller.
|
||||
format: int64
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
@@ -2,7 +2,7 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2beta1
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: external-dns
|
||||
name: &app external-dns
|
||||
namespace: networking
|
||||
spec:
|
||||
interval: 15m
|
||||
@@ -26,8 +26,7 @@ spec:
|
||||
uninstall:
|
||||
keepHistory: false
|
||||
values:
|
||||
interval: 2m
|
||||
# logLevel: debug
|
||||
fullnameOverride: *app
|
||||
provider: cloudflare
|
||||
env:
|
||||
- name: CF_API_EMAIL
|
||||
@@ -41,10 +40,12 @@ spec:
|
||||
name: external-dns-secret
|
||||
key: api-key
|
||||
extraArgs:
|
||||
- --cloudflare-proxied
|
||||
- --annotation-filter=external-dns.alpha.kubernetes.io/target
|
||||
- --cloudflare-proxied
|
||||
- --crd-source-apiversion=externaldns.k8s.io/v1alpha1
|
||||
- --crd-source-kind=DNSEndpoint
|
||||
policy: sync
|
||||
sources: ["ingress"]
|
||||
sources: ["crd", "ingress"]
|
||||
txtPrefix: k8s.
|
||||
txtOwnerId: default
|
||||
domainFilters: ["${SECRET_DOMAIN}"]
|
||||
|
||||
@@ -3,5 +3,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: networking
|
||||
resources:
|
||||
- ./dnsendpoint-crd.yaml
|
||||
- ./secret.sops.yaml
|
||||
- ./helmrelease.yaml
|
||||
@@ -1 +0,0 @@
|
||||
173.245.48.0/20\,103.21.244.0/22\,103.22.200.0/22\,103.31.4.0/22\,141.101.64.0/18\,108.162.192.0/18\,190.93.240.0/20\,188.114.96.0/20\,197.234.240.0/22\,198.41.128.0/17\,162.158.0.0/15\,104.16.0.0/13\,104.24.0.0/14\,172.64.0.0/13\,131.0.72.0/22\,2400:cb00::/32\,2606:4700::/32\,2803:f800::/32\,2405:b500::/32\,2405:8100::/32\,2a06:98c0::/29\,2c0f:f248::/32
|
||||
@@ -32,7 +32,8 @@ spec:
|
||||
value: "${TIMEZONE}"
|
||||
service:
|
||||
annotations:
|
||||
metallb.universe.tf/loadBalancerIPs: "${METALLB_INGRESS_ADDR}"
|
||||
external-dns.alpha.kubernetes.io/hostname: "ipv4.${SECRET_DOMAIN}"
|
||||
loadBalancerIP: "${METALLB_INGRESS_ADDR}"
|
||||
externalTrafficPolicy: Local
|
||||
publishService:
|
||||
enabled: true
|
||||
@@ -44,28 +45,20 @@ spec:
|
||||
client-body-timeout: 120
|
||||
custom-http-errors: 400,401,403,404,500,502,503,504
|
||||
enable-brotli: "true"
|
||||
forwarded-for-header: "CF-Connecting-IP"
|
||||
hsts-max-age: "31449600"
|
||||
keep-alive: 120
|
||||
keep-alive-requests: 10000
|
||||
proxy-body-size: "100M"
|
||||
ssl-protocols: "TLSv1.3 TLSv1.2"
|
||||
use-forwarded-headers: "true"
|
||||
log-format-escape-json: "true"
|
||||
log-format-upstream: >-
|
||||
{"time": "$time_iso8601", "remote_addr": "$proxy_protocol_addr",
|
||||
"x_forwarded_for": "$proxy_add_x_forwarded_for", "request_id": "$req_id",
|
||||
"remote_user": "$remote_user", "bytes_sent": $bytes_sent, "request_time": $request_time,
|
||||
"status": $status, "vhost": "$host", "request_proto": "$server_protocol",
|
||||
"path": "$uri", "request_query": "$args", "request_length": $request_length,
|
||||
"duration": $request_time,"method": "$request_method", "http_referrer": "$http_referer",
|
||||
"http_user_agent": "$http_user_agent"}
|
||||
metrics:
|
||||
enabled: false
|
||||
enabled: true
|
||||
serviceMonitor:
|
||||
enabled: true
|
||||
namespace: networking
|
||||
namespaceSelector:
|
||||
any: true
|
||||
extraArgs:
|
||||
default-ssl-certificate: "networking/${SECRET_DOMAIN/./-}-production-tls"
|
||||
podAnnotations:
|
||||
configmap.reloader.stakater.com/reload: cloudflare-networks
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
@@ -78,14 +71,5 @@ spec:
|
||||
repository: ghcr.io/tarampampam/error-pages
|
||||
tag: 2.24.0
|
||||
extraEnvs:
|
||||
- name: TEMPLATE_NAME
|
||||
value: lost-in-space
|
||||
- name: SHOW_DETAILS
|
||||
value: "false"
|
||||
valuesFrom:
|
||||
# Cloudflare Networks
|
||||
# https://www.cloudflare.com/ips/
|
||||
- targetPath: controller.config.proxy-real-ip-cidr
|
||||
kind: ConfigMap
|
||||
name: cloudflare-networks
|
||||
valuesKey: cloudflare-networks.txt
|
||||
- { name: TEMPLATE_NAME, value: lost-in-space }
|
||||
- { name: SHOW_DETAILS, value: "false" }
|
||||
@@ -4,9 +4,3 @@ kind: Kustomization
|
||||
namespace: networking
|
||||
resources:
|
||||
- ./helmrelease.yaml
|
||||
configMapGenerator:
|
||||
- name: cloudflare-networks
|
||||
files:
|
||||
- ./cloudflare-networks.txt
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
@@ -3,7 +3,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./namespace.yaml
|
||||
- ./cloudflare-ddns/ks.yaml
|
||||
- ./external-dns/ks.yaml
|
||||
- ./ingress-nginx/ks.yaml
|
||||
- ./k8s-gateway/ks.yaml
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
terraform {
|
||||
|
||||
required_providers {
|
||||
cloudflare = {
|
||||
source = "cloudflare/cloudflare"
|
||||
version = "4.4.0"
|
||||
}
|
||||
http = {
|
||||
source = "hashicorp/http"
|
||||
version = "3.3.0"
|
||||
}
|
||||
sops = {
|
||||
source = "carlpett/sops"
|
||||
version = "0.7.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data "sops_file" "cloudflare_secrets" {
|
||||
source_file = "secret.sops.yaml"
|
||||
}
|
||||
|
||||
provider "cloudflare" {
|
||||
email = data.sops_file.cloudflare_secrets.data["cloudflare_email"]
|
||||
api_key = data.sops_file.cloudflare_secrets.data["cloudflare_apikey"]
|
||||
}
|
||||
|
||||
data "cloudflare_zones" "domain" {
|
||||
filter {
|
||||
name = data.sops_file.cloudflare_secrets.data["cloudflare_domain"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "cloudflare_zone_settings_override" "cloudflare_settings" {
|
||||
zone_id = lookup(data.cloudflare_zones.domain.zones[0], "id")
|
||||
settings {
|
||||
ssl = "strict"
|
||||
always_use_https = "on"
|
||||
min_tls_version = "1.2"
|
||||
opportunistic_encryption = "on"
|
||||
tls_1_3 = "zrt"
|
||||
automatic_https_rewrites = "on"
|
||||
universal_ssl = "on"
|
||||
browser_check = "on"
|
||||
challenge_ttl = 1800
|
||||
privacy_pass = "on"
|
||||
security_level = "medium"
|
||||
brotli = "on"
|
||||
minify {
|
||||
css = "on"
|
||||
js = "on"
|
||||
html = "on"
|
||||
}
|
||||
rocket_loader = "on"
|
||||
always_online = "off"
|
||||
development_mode = "off"
|
||||
http3 = "on"
|
||||
zero_rtt = "on"
|
||||
ipv6 = "on"
|
||||
websockets = "on"
|
||||
opportunistic_onion = "on"
|
||||
pseudo_ipv4 = "off"
|
||||
ip_geolocation = "on"
|
||||
email_obfuscation = "on"
|
||||
server_side_exclude = "on"
|
||||
hotlink_protection = "off"
|
||||
security_header {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data "http" "ipv4" {
|
||||
url = "http://ipv4.icanhazip.com"
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "ipv4" {
|
||||
name = "ipv4"
|
||||
zone_id = lookup(data.cloudflare_zones.domain.zones[0], "id")
|
||||
value = chomp(data.http.ipv4.response_body)
|
||||
proxied = true
|
||||
type = "A"
|
||||
ttl = 1
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "root" {
|
||||
name = data.sops_file.cloudflare_secrets.data["cloudflare_domain"]
|
||||
zone_id = lookup(data.cloudflare_zones.domain.zones[0], "id")
|
||||
value = "ipv4.${data.sops_file.cloudflare_secrets.data["cloudflare_domain"]}"
|
||||
proxied = true
|
||||
type = "CNAME"
|
||||
ttl = 1
|
||||
}
|
||||
@@ -9,7 +9,3 @@ creation_rules:
|
||||
key_groups:
|
||||
- age:
|
||||
- ${BOOTSTRAP_AGE_PUBLIC_KEY}
|
||||
- path_regex: terraform/.*\.sops\.ya?ml
|
||||
key_groups:
|
||||
- age:
|
||||
- ${BOOTSTRAP_AGE_PUBLIC_KEY}
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: cloudflare-ddns-secret
|
||||
namespace: networking
|
||||
type: Opaque
|
||||
stringData:
|
||||
CLOUDFLARE_EMAIL: "${BOOTSTRAP_CLOUDFLARE_EMAIL}"
|
||||
CLOUDFLARE_APIKEY: "${BOOTSTRAP_CLOUDFLARE_APIKEY}"
|
||||
CLOUDFLARE_RECORD_NAME: "ipv4.${BOOTSTRAP_CLOUDFLARE_DOMAIN}"
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: cloudflared-secret
|
||||
namespace: networking
|
||||
data:
|
||||
TUNNEL_ID: "${BOOTSTRAP_CLOUDFLARE_TUNNEL_ID}"
|
||||
credentials.json: |
|
||||
{
|
||||
"AccountTag": "${BOOTSTRAP_CLOUDFLARE_ACCOUNT_TAG}",
|
||||
"TunnelSecret": "${BOOTSTRAP_CLOUDFLARE_TUNNEL_SECRET}",
|
||||
"TunnelID": "${BOOTSTRAP_CLOUDFLARE_TUNNEL_ID}"
|
||||
}
|
||||
@@ -7,3 +7,4 @@ metadata:
|
||||
stringData:
|
||||
SECRET_DOMAIN: "${BOOTSTRAP_CLOUDFLARE_DOMAIN}"
|
||||
SECRET_CLOUDFLARE_EMAIL: "${BOOTSTRAP_CLOUDFLARE_EMAIL}"
|
||||
SECRET_CLOUDFLARE_TUNNEL_ID: "${BOOTSTRAP_CLOUDFLARE_TUNNEL_ID}"
|
||||
@@ -1,3 +0,0 @@
|
||||
cloudflare_email: "${BOOTSTRAP_CLOUDFLARE_EMAIL}"
|
||||
cloudflare_apikey: "${BOOTSTRAP_CLOUDFLARE_APIKEY}"
|
||||
cloudflare_domain: "${BOOTSTRAP_CLOUDFLARE_DOMAIN}"
|
||||
Reference in new issue
Block a user