feat!: add mandatory cloudflare tunnel support (#716)

Co-authored-by: Devin Buhl <onedr0p@users.noreply.github.com>
This commit is contained in:
Steven KreitzerandDevin Buhl authored and GitHub committed 2023-05-04 19:39:22 -04:00
1 parent b917eccb76
commit 145f575fbb
34 files changed
+352 -395

No files matched your search

+8 -1
View File
@@ -21,9 +21,16 @@ export BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD="generated" # NOTE: Must only conta
export BOOTSTRAP_CLOUDFLARE_DOMAIN="" export BOOTSTRAP_CLOUDFLARE_DOMAIN=""
# The email you use to sign into Cloudflare with # The email you use to sign into Cloudflare with
export BOOTSTRAP_CLOUDFLARE_EMAIL="" export BOOTSTRAP_CLOUDFLARE_EMAIL=""
# Your global Cloudflare API Key # Your global Cloudflare API Key (not API token)
export BOOTSTRAP_CLOUDFLARE_APIKEY="" 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 # 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 # You don't need many IPs, just choose 10 IPs to start with
# e.g. 192.168.1.220-192.168.1.230 # e.g. 192.168.1.220-192.168.1.230
-2
View File
@@ -5,7 +5,5 @@ area/github:
- ".github/**/*" - ".github/**/*"
area/kubernetes: area/kubernetes:
- "kubernetes/**/*" - "kubernetes/**/*"
area/terraform:
- "terraform/**/*"
area/templates: area/templates:
- "tmpl/**/*" - "tmpl/**/*"
-6
View File
@@ -16,10 +16,6 @@
color: "72ccf3" color: "72ccf3"
description: >- description: >-
Changes made in the tmpl directory Changes made in the tmpl directory
- name: area/terraform
color: "72ccf3"
description: >-
Changes made in the terraform directory
# Renovate # Renovate
- name: renovate/ansible - name: renovate/ansible
color: "ffc300" color: "ffc300"
@@ -31,8 +27,6 @@
color: "ffc300" color: "ffc300"
- name: renovate/helm - name: renovate/helm
color: "ffc300" color: "ffc300"
- name: renovate/terraform
color: "ffc300"
# Semantic Type # Semantic Type
- name: type/patch - name: type/patch
color: "FFEC19" color: "FFEC19"
-2
View File
@@ -12,8 +12,6 @@ categories:
labels: ["area/github"] labels: ["area/github"]
- title: "Ansible" - title: "Ansible"
labels: ["area/ansible"] labels: ["area/ansible"]
- title: "Terraform"
labels: ["area/terraform"]
- title: "Maintenance" - title: "Maintenance"
labels: ["docs"] labels: ["docs"]
version-resolver: version-resolver:
-4
View File
@@ -25,10 +25,6 @@
"matchDatasources": ["galaxy", "galaxy-collection"], "matchDatasources": ["galaxy", "galaxy-collection"],
"addLabels": ["renovate/ansible"] "addLabels": ["renovate/ansible"]
}, },
{
"matchDatasources": ["terraform-provider"],
"addLabels": ["renovate/terraform"]
},
{ {
"matchDatasources": ["github-releases", "github-tags"], "matchDatasources": ["github-releases", "github-tags"],
"addLabels": ["renovate/github-release"] "addLabels": ["renovate/github-release"]
-19
View File
@@ -35,7 +35,6 @@
"semanticCommitType": "feat", "semanticCommitType": "feat",
"semanticCommitScope": "helm" "semanticCommitScope": "helm"
}, },
{ {
"matchDatasources": ["helm"], "matchDatasources": ["helm"],
"matchUpdateTypes": ["patch"], "matchUpdateTypes": ["patch"],
@@ -53,30 +52,12 @@
"semanticCommitType": "feat", "semanticCommitType": "feat",
"semanticCommitScope": "ansible" "semanticCommitScope": "ansible"
}, },
{ {
"matchDatasources": ["galaxy", "galaxy-collection"], "matchDatasources": ["galaxy", "galaxy-collection"],
"matchUpdateTypes": ["patch"], "matchUpdateTypes": ["patch"],
"semanticCommitType": "fix", "semanticCommitType": "fix",
"semanticCommitScope": "ansible" "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"], "matchDatasources": ["github-releases", "github-tags"],
"matchUpdateTypes": ["major"], "matchUpdateTypes": ["major"],
-4
View File
@@ -11,7 +11,3 @@ kubeconfig
*.key *.key
# Ansible # Ansible
xanmanning.k3s* xanmanning.k3s*
# Terraform
.terraform
.terraform.tfstate*
terraform.tfstate*
-4
View File
@@ -8,7 +8,3 @@ repos:
- --config-file - --config-file
- .yamllint.yaml - .yamllint.yaml
id: yamllint id: yamllint
- repo: https://github.com/gruntwork-io/pre-commit
rev: v0.1.21
hooks:
- id: terraform-fmt
-22
View File
@@ -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}}
-1
View File
@@ -8,7 +8,6 @@
"signageos.signageos-vscode-sops", "signageos.signageos-vscode-sops",
"will-stone.in-any-case", "will-stone.in-any-case",
"EditorConfig.editorconfig", "EditorConfig.editorconfig",
"HashiCorp.terraform",
"PKief.material-icon-theme", "PKief.material-icon-theme",
] ]
} }
-1
View File
@@ -4,7 +4,6 @@
"**/ansible/**/*.yml": "ansible", "**/ansible/**/*.yml": "ansible",
"**/ansible/**/*.sops.yml": "yaml", "**/ansible/**/*.sops.yml": "yaml",
"**/ansible/**/inventory/**/*.yml": "yaml", "**/ansible/**/inventory/**/*.yml": "yaml",
"**/terraform/**/*.tf": "terraform",
"**/kubernetes/**/*.sops.toml": "plaintext" "**/kubernetes/**/*.sops.toml": "plaintext"
}, },
"yaml.schemas": { "yaml.schemas": {
+54 -63
View File
@@ -1,8 +1,8 @@
# Template for deploying k3s backed by Flux # 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 ## 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)_ _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 ## 📝 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._ **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 ### 📚 Reading material
@@ -48,10 +43,10 @@ First and foremost some experience in debugging/troubleshooting problems **and a
### 💻 Systems ### 💻 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. - 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. - 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. 📍 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. 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. 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. 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` - Ensure `pip3` is working on your command line by running `pip3 --version`
4. [Homebrew] Install [go-task](https://github.com/go-task/task) 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 ### 🔐 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 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`... 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). 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/). 📍 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 ### 📄 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. 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 # 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 ### 🔹 GitOps with Flux
📍 Here we will be installing [flux](https://toolkit.fluxcd.io/) after some quick bootstrap steps. 📍 Here we will be installing [flux](https://toolkit.fluxcd.io/) after some quick bootstrap steps.
@@ -389,7 +375,7 @@ task cluster:resources
### 🌐 DNS ### 🌐 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. [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. 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! Now if nothing is working, that is expected. This is DNS after all!
### 🤖 Renovatebot ### 🤖 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: 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. - 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. - 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> <details>
<summary>Expand to read guide on adding Flux SSH authentication</summary> <summary>Expand to read guide on adding Flux SSH authentication</summary>
1. Generate new SSH key: 1. Generate new SSH key:
```sh ```sh
ssh-keygen -t ecdsa -b 521 -C "github-deploy-key" -f ./kubernetes/bootstrap/github-deploy.key -q -P "" 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 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: 3. Create sops secret in `./kubernetes/bootstrap/github-deploy-key.sops.yaml` with the contents of:
```yaml ```yaml
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
@@ -487,15 +471,15 @@ The benefits of a public repository include:
github.com ecdsa-sha2-nistp256 ... github.com ecdsa-sha2-nistp256 ...
github.com ssh-rsa ... github.com ssh-rsa ...
``` ```
4. Encrypt secret: 4. Encrypt secret:
```sh ```sh
sops --encrypt --in-place ./kubernetes/bootstrap/github-deploy-key.sops.yaml sops --encrypt --in-place ./kubernetes/bootstrap/github-deploy-key.sops.yaml
``` ```
5. Apply secret to cluster: 5. Apply secret to cluster:
```sh ```sh
sops --decrypt ./kubernetes/bootstrap/github-deploy-key.sops.yaml | kubectl apply -f - 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 ```yaml
apiVersion: source.toolkit.fluxcd.io/v1beta2 apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository kind: GitRepository
@@ -511,16 +495,16 @@ The benefits of a public repository include:
secretRef: secretRef:
name: github-deploy-key name: github-deploy-key
``` ```
7. Commit and push changes 7. Commit and push changes
8. Force flux to reconcile your changes 8. Force flux to reconcile your changes
```sh ```sh
task cluster:reconcile task cluster:reconcile
``` ```
9. Verify git repository is now using SSH: 9. Verify git repository is now using SSH:
```sh ```sh
task cluster:gitrepositories 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> </details>
### 💨 Kubernetes Dashboard ### 💨 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. 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. 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. 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. 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. 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. 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
View File
@@ -4,7 +4,6 @@ version: "3"
vars: vars:
KUBERNETES_DIR: "{{.ROOT_DIR}}/kubernetes" KUBERNETES_DIR: "{{.ROOT_DIR}}/kubernetes"
ANSIBLE_DIR: "{{.ROOT_DIR}}/ansible" ANSIBLE_DIR: "{{.ROOT_DIR}}/ansible"
TERRAFORM_DIR: "{{.ROOT_DIR}}/terraform"
dotenv: [".config.env"] dotenv: [".config.env"]
@@ -16,10 +15,8 @@ includes:
ansible: .taskfiles/AnsibleTasks.yml ansible: .taskfiles/AnsibleTasks.yml
cluster: .taskfiles/ClusterTasks.yml cluster: .taskfiles/ClusterTasks.yml
precommit: .taskfiles/PrecommitTasks.yml precommit: .taskfiles/PrecommitTasks.yml
terraform: .taskfiles/TerraformTasks.yml
tasks: tasks:
init: init:
desc: Initialize workstation dependencies with Brew desc: Initialize workstation dependencies with Brew
cmds: cmds:
@@ -33,6 +30,7 @@ tasks:
DEPS: >- DEPS: >-
age age
ansible ansible
cloudflare/cloudflare/cloudflared
direnv direnv
fluxcd/tap/flux fluxcd/tap/flux
go-task/tap/go-task go-task/tap/go-task
@@ -45,8 +43,6 @@ tasks:
prettier prettier
sops sops
stern stern
terraform
tflint
weaveworks/tap/gitops weaveworks/tap/gitops
yamllint yamllint
yq yq
Vendored
+21 -11
View File
@@ -51,15 +51,9 @@ main() {
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/cert-manager-secret.sops.yaml" \ envsubst < "${PROJECT_DIR}/tmpl/kubernetes/cert-manager-secret.sops.yaml" \
> "${PROJECT_DIR}/kubernetes/apps/cert-manager/cert-manager/issuers/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" 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" \ envsubst < "${PROJECT_DIR}/tmpl/kubernetes/cloudflared-secret.sops.yaml" \
> "${PROJECT_DIR}/kubernetes/apps/networking/cloudflare-ddns/app/secret.sops.yaml" > "${PROJECT_DIR}/kubernetes/apps/networking/cloudflared/app/secret.sops.yaml"
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/networking/cloudflare-ddns/app/secret.sops.yaml" sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/networking/cloudflared/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"
# generate ansible settings # generate ansible settings
envsubst < "${PROJECT_DIR}/tmpl/ansible/kube-vip.yml" \ envsubst < "${PROJECT_DIR}/tmpl/ansible/kube-vip.yml" \
> "${PROJECT_DIR}/ansible/inventory/group_vars/kubernetes/kube-vip.yml" > "${PROJECT_DIR}/ansible/inventory/group_vars/kubernetes/kube-vip.yml"
@@ -229,7 +223,6 @@ verify_binaries() {
_has_binary "sops" _has_binary "sops"
_has_binary "ssh" _has_binary "ssh"
_has_binary "task" _has_binary "task"
_has_binary "terraform"
_has_binary "yq" _has_binary "yq"
if ! [[ "$(sops --version)" =~ 3\.[0-9]+\.[0-9]+ ]]; then 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" _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() { verify_cloudflare() {
local account_zone=
local errors= local errors=
local account_zone=
_has_envar "BOOTSTRAP_CLOUDFLARE_APIKEY" "true" _has_envar "BOOTSTRAP_CLOUDFLARE_APIKEY" "true"
_has_envar "BOOTSTRAP_CLOUDFLARE_DOMAIN" "true" _has_envar "BOOTSTRAP_CLOUDFLARE_DOMAIN" "true"
_has_envar "BOOTSTRAP_CLOUDFLARE_EMAIL" "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}" _log "ERROR(${FUNCNAME[0]})" "Unable to get Cloudflare Account and Zone information ${errors}"
exit 1 exit 1
fi 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() { 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,13 +3,12 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
namespace: networking namespace: networking
resources: resources:
- ./dnsendpoint.yaml
- ./secret.sops.yaml - ./secret.sops.yaml
- ./helmrelease.yaml - ./helmrelease.yaml
configMapGenerator: configMapGenerator:
- name: cloudflare-ddns-configmap - name: cloudflared-configmap
files: files:
- ./cloudflare-ddns.sh - ./configs/config.yaml
generatorOptions: generatorOptions:
disableNameSuffixHash: true disableNameSuffixHash: true
annotations:
kustomize.toolkit.fluxcd.io/substitute: disabled
@@ -2,10 +2,12 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1 apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization kind: Kustomization
metadata: metadata:
name: cluster-apps-cloudflare-ddns name: cluster-apps-cloudflared
namespace: flux-system namespace: flux-system
spec: spec:
path: ./kubernetes/apps/networking/cloudflare-ddns/app dependsOn:
- name: cluster-apps-ingress-nginx
path: ./kubernetes/apps/networking/cloudflared/app
prune: true prune: true
sourceRef: sourceRef:
kind: GitRepository kind: GitRepository
@@ -13,7 +15,8 @@ spec:
healthChecks: healthChecks:
- apiVersion: helm.toolkit.fluxcd.io/v2beta1 - apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease kind: HelmRelease
name: cloudflare-ddns name: cloudflared
namespace: networking namespace: networking
interval: 30m 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 apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease kind: HelmRelease
metadata: metadata:
name: external-dns name: &app external-dns
namespace: networking namespace: networking
spec: spec:
interval: 15m interval: 15m
@@ -26,8 +26,7 @@ spec:
uninstall: uninstall:
keepHistory: false keepHistory: false
values: values:
interval: 2m fullnameOverride: *app
# logLevel: debug
provider: cloudflare provider: cloudflare
env: env:
- name: CF_API_EMAIL - name: CF_API_EMAIL
@@ -41,10 +40,12 @@ spec:
name: external-dns-secret name: external-dns-secret
key: api-key key: api-key
extraArgs: extraArgs:
- --cloudflare-proxied
- --annotation-filter=external-dns.alpha.kubernetes.io/target - --annotation-filter=external-dns.alpha.kubernetes.io/target
- --cloudflare-proxied
- --crd-source-apiversion=externaldns.k8s.io/v1alpha1
- --crd-source-kind=DNSEndpoint
policy: sync policy: sync
sources: ["ingress"] sources: ["crd", "ingress"]
txtPrefix: k8s. txtPrefix: k8s.
txtOwnerId: default txtOwnerId: default
domainFilters: ["${SECRET_DOMAIN}"] domainFilters: ["${SECRET_DOMAIN}"]
@@ -3,5 +3,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
namespace: networking namespace: networking
resources: resources:
- ./dnsendpoint-crd.yaml
- ./secret.sops.yaml - ./secret.sops.yaml
- ./helmrelease.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}" value: "${TIMEZONE}"
service: service:
annotations: annotations:
metallb.universe.tf/loadBalancerIPs: "${METALLB_INGRESS_ADDR}" external-dns.alpha.kubernetes.io/hostname: "ipv4.${SECRET_DOMAIN}"
loadBalancerIP: "${METALLB_INGRESS_ADDR}"
externalTrafficPolicy: Local externalTrafficPolicy: Local
publishService: publishService:
enabled: true enabled: true
@@ -44,28 +45,20 @@ spec:
client-body-timeout: 120 client-body-timeout: 120
custom-http-errors: 400,401,403,404,500,502,503,504 custom-http-errors: 400,401,403,404,500,502,503,504
enable-brotli: "true" enable-brotli: "true"
forwarded-for-header: "CF-Connecting-IP"
hsts-max-age: "31449600" hsts-max-age: "31449600"
keep-alive: 120 keep-alive: 120
keep-alive-requests: 10000 keep-alive-requests: 10000
proxy-body-size: "100M" proxy-body-size: "100M"
ssl-protocols: "TLSv1.3 TLSv1.2" 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: metrics:
enabled: false enabled: true
serviceMonitor:
enabled: true
namespace: networking
namespaceSelector:
any: true
extraArgs: extraArgs:
default-ssl-certificate: "networking/${SECRET_DOMAIN/./-}-production-tls" default-ssl-certificate: "networking/${SECRET_DOMAIN/./-}-production-tls"
podAnnotations:
configmap.reloader.stakater.com/reload: cloudflare-networks
resources: resources:
requests: requests:
cpu: 10m cpu: 10m
@@ -78,14 +71,5 @@ spec:
repository: ghcr.io/tarampampam/error-pages repository: ghcr.io/tarampampam/error-pages
tag: 2.24.0 tag: 2.24.0
extraEnvs: extraEnvs:
- name: TEMPLATE_NAME - { name: TEMPLATE_NAME, value: lost-in-space }
value: lost-in-space - { name: SHOW_DETAILS, value: "false" }
- 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
@@ -4,9 +4,3 @@ kind: Kustomization
namespace: networking namespace: networking
resources: resources:
- ./helmrelease.yaml - ./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 kind: Kustomization
resources: resources:
- ./namespace.yaml - ./namespace.yaml
- ./cloudflare-ddns/ks.yaml
- ./external-dns/ks.yaml - ./external-dns/ks.yaml
- ./ingress-nginx/ks.yaml - ./ingress-nginx/ks.yaml
- ./k8s-gateway/ks.yaml - ./k8s-gateway/ks.yaml
-93
View File
@@ -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
}
-4
View File
@@ -9,7 +9,3 @@ creation_rules:
key_groups: key_groups:
- age: - age:
- ${BOOTSTRAP_AGE_PUBLIC_KEY} - ${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: stringData:
SECRET_DOMAIN: "${BOOTSTRAP_CLOUDFLARE_DOMAIN}" SECRET_DOMAIN: "${BOOTSTRAP_CLOUDFLARE_DOMAIN}"
SECRET_CLOUDFLARE_EMAIL: "${BOOTSTRAP_CLOUDFLARE_EMAIL}" SECRET_CLOUDFLARE_EMAIL: "${BOOTSTRAP_CLOUDFLARE_EMAIL}"
SECRET_CLOUDFLARE_TUNNEL_ID: "${BOOTSTRAP_CLOUDFLARE_TUNNEL_ID}"
-3
View File
@@ -1,3 +0,0 @@
cloudflare_email: "${BOOTSTRAP_CLOUDFLARE_EMAIL}"
cloudflare_apikey: "${BOOTSTRAP_CLOUDFLARE_APIKEY}"
cloudflare_domain: "${BOOTSTRAP_CLOUDFLARE_DOMAIN}"