From de0ed1c70a67208626cd60652d6f0fccd98cd7b9 Mon Sep 17 00:00:00 2001 From: Devin Buhl Date: Tue, 4 Jul 2023 11:36:58 -0400 Subject: [PATCH] feat!: Rewrite configure script in ansible (#822) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: smol changes Signed-off-by: Devin Buhl * feat!: Rewrite configure script in ansible Signed-off-by: Devin Buhl * fix: add comment for real path Signed-off-by: Devin Buhl * feat: verification is done Signed-off-by: Devin Buhl * fix: do not need net common Signed-off-by: Devin Buhl * chore: clean up old comments Signed-off-by: Devin Buhl * chore: clean up old comments Signed-off-by: Devin Buhl * feat: finish up ansible host generation and more Signed-off-by: Devin Buhl * fix: backup/restore sops config between tasks Signed-off-by: Devin Buhl * chore: clean up test comments Signed-off-by: Devin Buhl * fix: use ansible template on template Signed-off-by: Devin Buhl * Update template/vars/config.sample.yaml Co-authored-by: Manuel Rรผger * Update template/tasks/verify_cli.yaml * chore: update readme Signed-off-by: Devin Buhl * chore: update readme Signed-off-by: Devin Buhl * Update README.md Co-authored-by: Manuel Rรผger * fix: move bcrypt logic to template Signed-off-by: Devin Buhl * fix: derp Signed-off-by: Devin Buhl --------- Signed-off-by: Devin Buhl Co-authored-by: Manuel Rรผger --- .config.sample.env | 99 ---- .envrc | 2 - .gitattributes | 1 - .taskfiles/AnsibleTasks.yaml | 91 ++++ .taskfiles/AnsibleTasks.yml | 76 --- .../{ClusterTasks.yml => ClusterTasks.yaml} | 0 .vscode/settings.json | 8 +- README.md | 30 +- Taskfile.yml => Taskfile.yaml | 22 +- ansible.cfg => ansible/ansible.cfg | 6 +- .../kubernetes/{kubernetes.yml => main.yaml} | 0 .../master/{kubernetes.yml => main.yaml} | 0 .../worker/{kubernetes.yml => main.yaml} | 0 ...allation.yml => cluster-installation.yaml} | 10 +- .../{cluster-nuke.yml => cluster-nuke.yaml} | 2 +- ...uster-prepare.yml => cluster-prepare.yaml} | 0 ...cluster-reboot.yml => cluster-reboot.yaml} | 0 ...uster-upgrade.yml => cluster-upgrade.yaml} | 0 .../tasks/{cilium.yml => cilium.yaml} | 0 .../tasks/{coredns.yml => coredns.yaml} | 0 .../playbooks/tasks/{cruft.yml => cruft.yaml} | 0 ...e_containers.yml => stale_containers.yaml} | 0 .../custom-coredns-helmchart.yaml.j2 | 2 +- .../{requirements.yml => requirements.yaml} | 8 +- configure | 482 ------------------ .../kube-system/coredns/app/helmrelease.yaml | 91 ++++ .../coredns/app/kustomization.yaml | 6 + kubernetes/apps/kube-system/coredns/ks.yaml | 16 + .../apps/kube-system/kustomization.yaml | 1 + .../apps/system-upgrade/kustomization.yaml | 2 +- template/configure.yaml | 84 +++ template/defaults/extras.yaml | 2 + template/defaults/templates.yaml | 44 ++ template/tasks/verify_age.yaml | 22 + template/tasks/verify_cli.yaml | 8 + template/tasks/verify_cloudflare.yaml | 34 ++ template/tasks/verify_github.yaml | 30 ++ template/tasks/verify_net.yaml | 94 ++++ .../templates/.sops.yaml.j2 | 4 +- template/templates/ansible/hosts.yaml.j2 | 20 + template/templates/ansible/node.sops.yaml.j2 | 2 + .../templates/ansible/supplemental.yaml.j2 | 6 + .../cert-manager-secret.sops.yaml.j2 | 2 +- .../cloudflared-secret.sops.yaml.j2 | 14 + .../kubernetes/cluster-secrets.sops.yaml.j2 | 10 + .../kubernetes/cluster-settings.yaml.j2 | 14 + .../templates/kubernetes/cluster.yaml.j2 | 2 +- .../external-dns-secret.sops.yaml.j2 | 2 +- .../github-webhook-token-secret.sops.yaml.j2 | 2 +- .../grafana-admin-secret.sops.yaml.j2 | 2 +- .../kube-prometheus-stack-helmrelease.yaml.j2 | 5 +- .../weave-gitops-secret.sops.yaml.j2 | 2 +- template/vars/.gitignore | 1 + template/vars/config.sample.yaml | 59 +++ tmpl/ansible/supplemental.yml | 5 - tmpl/kubernetes/cloudflared-secret.sops.yaml | 14 - tmpl/kubernetes/cluster-secrets.sops.yaml | 10 - tmpl/kubernetes/flux/cluster-settings.yaml | 13 - 58 files changed, 698 insertions(+), 764 deletions(-) delete mode 100644 .config.sample.env create mode 100644 .taskfiles/AnsibleTasks.yaml delete mode 100644 .taskfiles/AnsibleTasks.yml rename .taskfiles/{ClusterTasks.yml => ClusterTasks.yaml} (100%) rename Taskfile.yml => Taskfile.yaml (72%) rename ansible.cfg => ansible/ansible.cfg (87%) rename ansible/inventory/group_vars/kubernetes/{kubernetes.yml => main.yaml} (100%) rename ansible/inventory/group_vars/master/{kubernetes.yml => main.yaml} (100%) rename ansible/inventory/group_vars/worker/{kubernetes.yml => main.yaml} (100%) rename ansible/playbooks/{cluster-installation.yml => cluster-installation.yaml} (88%) rename ansible/playbooks/{cluster-nuke.yml => cluster-nuke.yaml} (96%) rename ansible/playbooks/{cluster-prepare.yml => cluster-prepare.yaml} (100%) rename ansible/playbooks/{cluster-reboot.yml => cluster-reboot.yaml} (100%) rename ansible/playbooks/{cluster-upgrade.yml => cluster-upgrade.yaml} (100%) rename ansible/playbooks/tasks/{cilium.yml => cilium.yaml} (100%) rename ansible/playbooks/tasks/{coredns.yml => coredns.yaml} (100%) rename ansible/playbooks/tasks/{cruft.yml => cruft.yaml} (100%) rename ansible/playbooks/tasks/{stale_containers.yml => stale_containers.yaml} (100%) rename ansible/{requirements.yml => requirements.yaml} (100%) delete mode 100755 configure create mode 100644 kubernetes/apps/kube-system/coredns/app/helmrelease.yaml create mode 100644 kubernetes/apps/kube-system/coredns/app/kustomization.yaml create mode 100644 kubernetes/apps/kube-system/coredns/ks.yaml create mode 100644 template/configure.yaml create mode 100644 template/defaults/extras.yaml create mode 100644 template/defaults/templates.yaml create mode 100644 template/tasks/verify_age.yaml create mode 100644 template/tasks/verify_cli.yaml create mode 100644 template/tasks/verify_cloudflare.yaml create mode 100644 template/tasks/verify_github.yaml create mode 100644 template/tasks/verify_net.yaml rename tmpl/.sops.yaml => template/templates/.sops.yaml.j2 (69%) create mode 100644 template/templates/ansible/hosts.yaml.j2 create mode 100644 template/templates/ansible/node.sops.yaml.j2 create mode 100644 template/templates/ansible/supplemental.yaml.j2 rename tmpl/kubernetes/cert-manager-secret.sops.yaml => template/templates/kubernetes/cert-manager-secret.sops.yaml.j2 (69%) create mode 100644 template/templates/kubernetes/cloudflared-secret.sops.yaml.j2 create mode 100644 template/templates/kubernetes/cluster-secrets.sops.yaml.j2 create mode 100644 template/templates/kubernetes/cluster-settings.yaml.j2 rename tmpl/kubernetes/flux/cluster.yaml => template/templates/kubernetes/cluster.yaml.j2 (87%) rename tmpl/kubernetes/external-dns-secret.sops.yaml => template/templates/kubernetes/external-dns-secret.sops.yaml.j2 (68%) rename tmpl/kubernetes/github-webhook-token-secret.sops.yaml => template/templates/kubernetes/github-webhook-token-secret.sops.yaml.j2 (68%) rename tmpl/kubernetes/grafana-admin-secret.sops.yaml => template/templates/kubernetes/grafana-admin-secret.sops.yaml.j2 (68%) rename kubernetes/apps/monitoring/kube-prometheus-stack/app/helmrelease.yaml => template/templates/kubernetes/kube-prometheus-stack-helmrelease.yaml.j2 (97%) rename tmpl/kubernetes/weave-gitops-secret.sops.yaml => template/templates/kubernetes/weave-gitops-secret.sops.yaml.j2 (61%) create mode 100644 template/vars/.gitignore create mode 100644 template/vars/config.sample.yaml delete mode 100644 tmpl/ansible/supplemental.yml delete mode 100644 tmpl/kubernetes/cloudflared-secret.sops.yaml delete mode 100644 tmpl/kubernetes/cluster-secrets.sops.yaml delete mode 100644 tmpl/kubernetes/flux/cluster-settings.yaml diff --git a/.config.sample.env b/.config.sample.env deleted file mode 100644 index ccbaeb64..00000000 --- a/.config.sample.env +++ /dev/null @@ -1,99 +0,0 @@ -# -# Cluster related variables -# - -# The repo you created from this template -# e.g. https://github.com/onedr0p/home-cluster -export BOOTSTRAP_GIT_REPOSITORY="" - -# To enable Flux to update your cluster on `git push` set the following to one of: -# `generated` - this will generate a token and print it in the logs -# Set this to any other string and it will be used for the secret -export BOOTSTRAP_FLUX_GITHUB_WEBHOOK_SECRET="generated" # NOTE: Must only contain alphanumeric characters and dashes - -# The Weave GitOps dashboard admin password -# `generated` - this will generate a token and print it in the logs -# Set this to any other string and it will be used for the secret -export BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD="generated" # NOTE: Must only contain alphanumeric characters and dashes - -# The Grafana admin password -# `generated` - this will generate a token and print it in the logs -# Set this to any other string and it will be used for the secret -export BOOTSTRAP_GRAFANA_ADMIN_PASSWORD="generated" # NOTE: Must only contain alphanumeric characters and dashes - -# Age Public Key - string should start with age -# e.g. age15uzrw396e67z9wdzsxzdk7ka0g2gr3l460e0slaea563zll3hdfqwqxdta -export BOOTSTRAP_AGE_PUBLIC_KEY="" - -# Choose your timezone -# e.g. America/New_York -export BOOTSTRAP_TIMEZONE="Etc/UTC" - -# The email you want to be associated with the ACME account -export BOOTSTRAP_ACME_EMAIL="" - -# Choose one of your cloudflare domains -# e.g. onedr0p.com -export BOOTSTRAP_CLOUDFLARE_DOMAIN="" -# Your global Cloudflare API Token (not API Key) -export BOOTSTRAP_CLOUDFLARE_APITOKEN="" - -# 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 -export BOOTSTRAP_CLOUDFLARE_ACCOUNT_TAG="" -export BOOTSTRAP_CLOUDFLARE_TUNNEL_SECRET="" -export BOOTSTRAP_CLOUDFLARE_TUNNEL_ID="" - -# The load balancer IP for k8s_gateway, choose a available IP in your nodes network that is not being used -export BOOTSTRAP_K8S_GATEWAY_ADDR="" -# The load balancer IP for ingress-nginx, choose a available IP in your nodes network that is not being used -export BOOTSTRAP_INGRESS_NGINX_ADDR="" -# The IP address to use with kube-vip, choose a available IP in your nodes network that is not being used -export BOOTSTRAP_KUBE_VIP_ADDR="" -# Choose your cluster or service cidrs -# Leave this unchanged unless you know what you are doing -export BOOTSTRAP_CLUSTER_CIDR="10.42.0.0/16" -export BOOTSTRAP_SERVICE_CIDR="10.43.0.0/16" - -# -# Ansible related variables -# - -# -# Default prefixes for hostnames assigned by Ansible -# These are unused on nodes where BOOTSTRAP_ANSIBLE_HOSTNAME_ is provided -# - -export BOOTSTRAP_ANSIBLE_DEFAULT_CONTROL_NODE_HOSTNAME_PREFIX="k8s-" # NOTE: Must only contain alphanumeric characters and dashes -export BOOTSTRAP_ANSIBLE_DEFAULT_NODE_HOSTNAME_PREFIX="k8s-" # NOTE: Must only contain alphanumeric characters and dashes - -# -# Ansible hosts - repeat this block as many times as you need, -# incrementing the last digit on the variable name for each node -# - -# IP Address to the node -# That doesn't conflict with any other IP addresses here -# e.g. 192.168.1.200 -export BOOTSTRAP_ANSIBLE_HOST_ADDR_0="" -# User Ansible will log into the nodes -export BOOTSTRAP_ANSIBLE_SSH_USERNAME_0="" # NOTE: Must only contain alphanumeric characters and dashes -# Password Ansible will use to escalate to sudo -export BOOTSTRAP_ANSIBLE_SUDO_PASSWORD_0="" # NOTE: Must only contain alphanumeric characters and dashes -# Set this node as a control node (true/false) -export BOOTSTRAP_ANSIBLE_CONTROL_NODE_0="" -# Optional: Set the hostname of the node, if set this will override the *_HOSTNAME_PREFIX vars above -export BOOTSTRAP_ANSIBLE_HOSTNAME_0="" - -# export BOOTSTRAP_ANSIBLE_HOST_ADDR_1="" -# export BOOTSTRAP_ANSIBLE_SSH_USERNAME_1="" # NOTE: Must only contain alphanumeric characters and dashes -# export BOOTSTRAP_ANSIBLE_SUDO_PASSWORD_1="" # NOTE: Must only contain alphanumeric characters and dashes -# export BOOTSTRAP_ANSIBLE_CONTROL_NODE_1="" -# export BOOTSTRAP_ANSIBLE_HOSTNAME_1="" - -# export BOOTSTRAP_ANSIBLE_HOST_ADDR_2="" -# export BOOTSTRAP_ANSIBLE_SSH_USERNAME_2="" # NOTE: Must only contain alphanumeric characters and dashes -# export BOOTSTRAP_ANSIBLE_SUDO_PASSWORD_2="" # NOTE: Must only contain alphanumeric characters and dashes -# export BOOTSTRAP_ANSIBLE_CONTROL_NODE_2="" -# export BOOTSTRAP_ANSIBLE_HOSTNAME_2="" diff --git a/.envrc b/.envrc index 76c51a41..e146bb1d 100644 --- a/.envrc +++ b/.envrc @@ -1,6 +1,4 @@ #shellcheck disable=SC2148,SC2155 export KUBECONFIG=$(expand_path ./kubeconfig) -export ANSIBLE_CONFIG=$(expand_path ./ansible.cfg) -export ANSIBLE_HOST_KEY_CHECKING="False" export K8S_AUTH_KUBECONFIG=$(expand_path ./kubeconfig) export SOPS_AGE_KEY_FILE=$(expand_path ~/.config/sops/age/keys.txt) diff --git a/.gitattributes b/.gitattributes index 07392c5c..07f507f7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,4 @@ * text=auto eol=lf -*.yml.j2 linguist-language=YAML *.yaml.j2 linguist-language=YAML *.sops.* diff=sopsdiffer *.sops.toml linguist-language=JSON diff --git a/.taskfiles/AnsibleTasks.yaml b/.taskfiles/AnsibleTasks.yaml new file mode 100644 index 00000000..055776ad --- /dev/null +++ b/.taskfiles/AnsibleTasks.yaml @@ -0,0 +1,91 @@ +--- +version: "3" + +env: + K8S_AUTH_KUBECONFIG: "{{.ROOT_DIR}}/kubeconfig" + +vars: + ANSIBLE_PLAYBOOK_DIR: "{{.ANSIBLE_DIR}}/playbooks" + ANSIBLE_INVENTORY_DIR: "{{.ANSIBLE_DIR}}/inventory" + +tasks: + + init: + desc: Install / Upgrade Ansible galaxy deps + dir: "{{.ANSIBLE_DIR}}" + cmds: + - pip3 install --user --requirement requirements.txt + - ansible-galaxy install -r requirements.yaml --roles-path ~/.ansible/roles --force + - ansible-galaxy collection install -r requirements.yaml --collections-path ~/.ansible/collections --force + + list: + desc: List all the hosts + dir: "{{.ANSIBLE_DIR}}" + cmds: + - ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml --list-hosts + + prepare: + desc: Prepare all the k8s nodes for running k3s + dir: "{{.ANSIBLE_DIR}}" + cmds: + - ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-prepare.yaml + env: + ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg" + + install: + desc: Install Kubernetes on the nodes + dir: "{{.ANSIBLE_DIR}}" + cmds: + - ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-installation.yaml + env: + ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg" + + upgrade: + desc: Upgrade Kubernetes on the nodes (currently this only upgrades kube-vip) + dir: "{{.ANSIBLE_DIR}}" + cmds: + - ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-upgrade.yaml + env: + ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg" + + nuke: + desc: Uninstall Kubernetes on the nodes + dir: "{{.ANSIBLE_DIR}}" + interactive: true + cmds: + - ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-nuke.yaml + - task: force-reboot + env: + ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg" + + ping: + desc: Ping all the hosts + dir: "{{.ANSIBLE_DIR}}" + cmds: + - ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml --one-line -m 'ping' + env: + ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg" + + uptime: + desc: Uptime of all the hosts + dir: "{{.ANSIBLE_DIR}}" + cmds: + - ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml --one-line -a 'uptime' + env: + ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg" + + force-reboot: + desc: Reboot all the k8s nodes + dir: "{{.ANSIBLE_DIR}}" + cmds: + - ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-reboot.yaml + env: + ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg" + + force-poweroff: + desc: Shutdown all the k8s nodes + dir: "{{.ANSIBLE_DIR}}" + cmds: + - ansible kubernetes -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yaml -a '/usr/bin/systemctl poweroff' --become + env: + ANSIBLE_CONFIG: "{{.ANSIBLE_DIR}}/ansible.cfg" diff --git a/.taskfiles/AnsibleTasks.yml b/.taskfiles/AnsibleTasks.yml deleted file mode 100644 index 97a33e34..00000000 --- a/.taskfiles/AnsibleTasks.yml +++ /dev/null @@ -1,76 +0,0 @@ ---- -version: "3" - -env: - ANSIBLE_CONFIG: "{{.ROOT_DIR}}/ansible.cfg" - K8S_AUTH_KUBECONFIG: "{{.ROOT_DIR}}/kubeconfig" - -vars: - ANSIBLE_PLAYBOOK_DIR: "{{.ANSIBLE_DIR}}/playbooks" - ANSIBLE_INVENTORY_DIR: "{{.ANSIBLE_DIR}}/inventory" - -tasks: - - init: - desc: Install / Upgrade Ansible galaxy deps - dir: "{{.ANSIBLE_DIR}}" - cmds: - - pip3 install --user --requirement requirements.txt - - ansible-galaxy install -r requirements.yml --roles-path ~/.ansible/roles --force - - ansible-galaxy collection install -r requirements.yml --collections-path ~/.ansible/collections --force - - list: - desc: List all the hosts - dir: "{{.ANSIBLE_DIR}}" - cmds: - - ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yml --list-hosts - - prepare: - desc: Prepare all the k8s nodes for running k3s - dir: "{{.ANSIBLE_DIR}}" - cmds: - - ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-prepare.yml - - install: - desc: Install Kubernetes on the nodes - dir: "{{.ANSIBLE_DIR}}" - cmds: - - ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-installation.yml - - upgrade: - desc: Upgrade Kubernetes on the nodes (currently this only upgrades kube-vip) - dir: "{{.ANSIBLE_DIR}}" - cmds: - - ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-upgrade.yml - - nuke: - desc: Uninstall Kubernetes on the nodes - dir: "{{.ANSIBLE_DIR}}" - interactive: true - cmds: - - ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-nuke.yml - - task: force-reboot - - ping: - desc: Ping all the hosts - dir: "{{.ANSIBLE_DIR}}" - cmds: - - ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yml --one-line -m 'ping' - - uptime: - desc: Uptime of all the hosts - dir: "{{.ANSIBLE_DIR}}" - cmds: - - ansible all -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yml --one-line -a 'uptime' - - force-reboot: - desc: Reboot all the k8s nodes - dir: "{{.ANSIBLE_DIR}}" - cmds: - - ansible-playbook -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yml {{.ANSIBLE_PLAYBOOK_DIR}}/cluster-reboot.yml - - force-poweroff: - desc: Shutdown all the k8s nodes - dir: "{{.ANSIBLE_DIR}}" - cmds: - - ansible kubernetes -i {{.ANSIBLE_INVENTORY_DIR}}/hosts.yml -a '/usr/bin/systemctl poweroff' --become diff --git a/.taskfiles/ClusterTasks.yml b/.taskfiles/ClusterTasks.yaml similarity index 100% rename from .taskfiles/ClusterTasks.yml rename to .taskfiles/ClusterTasks.yaml diff --git a/.vscode/settings.json b/.vscode/settings.json index 33a015e9..1f28dc79 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,13 +1,13 @@ { "files.associations": { "*.json5": "jsonc", - "**/ansible/**/*.yml": "ansible", - "**/ansible/**/*.sops.yml": "yaml", - "**/ansible/**/inventory/**/*.yml": "yaml", + "**/ansible/**/*.yaml": "ansible", + "**/ansible/**/*.sops.yaml": "yaml", + "**/ansible/**/inventory/**/*.yaml": "yaml", "**/kubernetes/**/*.sops.toml": "plaintext" }, "yaml.schemas": { - "ansible": "ansible/*.yml", + "ansible": "ansible/*.yaml", "Kubernetes": "kubernetes/*.yaml" }, "editor.bracketPairColorization.enabled": true, diff --git a/README.md b/README.md index 29e91de4..df4d239a 100644 --- a/README.md +++ b/README.md @@ -79,9 +79,9 @@ 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/), [cloudflared](https://github.com/cloudflare/cloudflared), [cilium-cli](https://github.com/cilium/cilium-cli), [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/), [sops v3](https://github.com/mozilla/sops), [yq v4](https://github.com/mikefarah/yq) + - Required: [age](https://github.com/FiloSottile/age), [ansible](https://www.ansible.com), [flux](https://toolkit.fluxcd.io/), [cloudflared](https://github.com/cloudflare/cloudflared), [go-task](https://github.com/go-task/task), [direnv](https://github.com/direnv/direnv), [jq](https://stedolan.github.io/jq/), [kubectl](https://kubernetes.io/docs/tasks/tools/), [python-pip3](https://pypi.org/project/pip/), [sops v3](https://github.com/getsops/sops) - - 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) 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. @@ -170,30 +170,22 @@ In order to expose services to the internet you will need to create a [Cloudflar ### ๐Ÿ“„ Configuration -๐Ÿ“ The `.config.env` file contains necessary configuration that is needed by Ansible and Flux. +๐Ÿ“ The `template/vars/config.yaml` 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 configuration file and start filling out all the variables. **All are required** unless otherwise noted in the comments. ```sh - cp .config.sample.env .config.env + cp template/vars/config.sample.yaml template/vars/config.yaml ``` -2. Once that is done, verify the configuration is correct by running: - - ```sh - task verify - ``` - -3. If you do not encounter any errors run start having the script wire up the templated files and place them where they need to be. +2. Once done run the following command which will verify and generate the files needed to continue ```sh task configure ``` -โš ๏ธ This will print out the clear-text passwords for Grafana and Weave Gitops if you had them set to `generated` in your `.config.env`. Take note of these, you'll need them to log into the applications. - ### โšก Preparing Ubuntu Server with Ansible ๐Ÿ“ Here we will be running an Ansible Playbook to prepare Ubuntu server for running a Kubernetes cluster. @@ -276,14 +268,14 @@ In order to expose services to the internet you will need to create a [Cloudflar ```sh task cluster:verify # โ–บ checking prerequisites - # โœ” kubectl 1.21.5 >=1.18.0-0 - # โœ” Kubernetes 1.21.5+k3s1 >=1.16.0-0 + # โœ” kubectl 1.27.3 >=1.18.0-0 + # โœ” Kubernetes 1.27.3+k3s1 >=1.16.0-0 # โœ” prerequisites checks passed ``` 2. Push you changes to git - ๐Ÿ“ **Verify** all the `*.sops.yaml` and `*.sops.yml` files under the `./ansible`, and `./kubernetes` directories are **encrypted** with SOPS + ๐Ÿ“ **Verify** all the `*.sops.yaml` and `*.sops.yaml` files under the `./ansible`, and `./kubernetes` directories are **encrypted** with SOPS ```sh git add -A @@ -456,7 +448,7 @@ To enable Renovate on your repository, click the 'Configure' button over at thei Flux is pull-based by design meaning it will periodically check your git repository for changes, using a webhook you can enable Flux to update your cluster on `git push`. In order to configure Github to send `push` events from your repository to the Flux webhook receiver you will need two things: -1. Webhook URL - Your webhook receiver will be deployed on `https://flux-webhook.${BOOTSTRAP_CLOUDFLARE_DOMAIN}/hook/:hookId`. In order to find out your hook id you can run the following command: +1. Webhook URL - Your webhook receiver will be deployed on `https://flux-webhook.${bootstrap_cloudflare_domain}/hook/:hookId`. In order to find out your hook id you can run the following command: ```sh kubectl -n flux-system get receiver/github-receiver @@ -476,7 +468,7 @@ Flux is pull-based by design meaning it will periodically check your git reposit sops -d ./kubernetes/apps/flux-system/addons/webhooks/github/secret.sops.yaml | yq .stringData.token ``` - **Note:** Don't forget to update the `BOOTSTRAP_FLUX_GITHUB_WEBHOOK_SECRET` variable in your `.config.env` file so it matches the generated secret if applicable + **Note:** Don't forget to update the `bootstrap_flux_github_webhook_token` variable in the `config.yaml` file so it matches the generated secret if applicable Now that you have the webhook url and secret, it's time to set everything up on the Github repository side. Navigate to the settings of your repository on Github, under "Settings/Webhooks" press the "Add webhook" button. Fill in the webhook url and your secret. diff --git a/Taskfile.yml b/Taskfile.yaml similarity index 72% rename from Taskfile.yml rename to Taskfile.yaml index 81d32fc6..86a78748 100644 --- a/Taskfile.yml +++ b/Taskfile.yaml @@ -2,18 +2,17 @@ version: "3" vars: - KUBERNETES_DIR: "{{.ROOT_DIR}}/kubernetes" + TEMPLATE_DIR: "{{.ROOT_DIR}}/template" ANSIBLE_DIR: "{{.ROOT_DIR}}/ansible" - -dotenv: [".config.env"] + KUBERNETES_DIR: "{{.ROOT_DIR}}/kubernetes" env: KUBECONFIG: "{{.ROOT_DIR}}/kubeconfig" SOPS_AGE_KEY_FILE: ~/.config/sops/age/keys.txt includes: - ansible: .taskfiles/AnsibleTasks.yml - cluster: .taskfiles/ClusterTasks.yml + ansible: .taskfiles/AnsibleTasks.yaml + cluster: .taskfiles/ClusterTasks.yaml tasks: init: @@ -35,21 +34,14 @@ tasks: fluxcd/tap/flux go-task/tap/go-task helm - ipcalc jq kubernetes-cli kustomize sops stern - weaveworks/tap/gitops - yq - - verify: - desc: Verify env settings - cmds: - - ./configure --verify configure: - desc: Configure repository from env settings + desc: Configure repository from Ansible vars + dir: "{{.TEMPLATE_DIR}}" cmds: - - ./configure + - ansible-playbook configure.yaml diff --git a/ansible.cfg b/ansible/ansible.cfg similarity index 87% rename from ansible.cfg rename to ansible/ansible.cfg index d7864b5a..021bd030 100644 --- a/ansible.cfg +++ b/ansible/ansible.cfg @@ -6,10 +6,10 @@ stdout_callback = yaml force_valid_group_names = ignore # File/Directory settings log_path = ~/.ansible/ansible.log -inventory = ./ansible/inventory -roles_path = ~/.ansible/roles:./ansible/roles +inventory = ./inventory +roles_path = ~/.ansible/roles:./roles collections_path = ~/.ansible/collections -remote_tmp = /tmp +remote_tmp = ~/.ansible/tmp local_tmp = ~/.ansible/tmp # Fact Caching settings fact_caching = jsonfile diff --git a/ansible/inventory/group_vars/kubernetes/kubernetes.yml b/ansible/inventory/group_vars/kubernetes/main.yaml similarity index 100% rename from ansible/inventory/group_vars/kubernetes/kubernetes.yml rename to ansible/inventory/group_vars/kubernetes/main.yaml diff --git a/ansible/inventory/group_vars/master/kubernetes.yml b/ansible/inventory/group_vars/master/main.yaml similarity index 100% rename from ansible/inventory/group_vars/master/kubernetes.yml rename to ansible/inventory/group_vars/master/main.yaml diff --git a/ansible/inventory/group_vars/worker/kubernetes.yml b/ansible/inventory/group_vars/worker/main.yaml similarity index 100% rename from ansible/inventory/group_vars/worker/kubernetes.yml rename to ansible/inventory/group_vars/worker/main.yaml diff --git a/ansible/playbooks/cluster-installation.yml b/ansible/playbooks/cluster-installation.yaml similarity index 88% rename from ansible/playbooks/cluster-installation.yml rename to ansible/playbooks/cluster-installation.yaml index 2d9a5f26..fff784db 100644 --- a/ansible/playbooks/cluster-installation.yml +++ b/ansible/playbooks/cluster-installation.yaml @@ -29,7 +29,7 @@ k3s_state: installed - name: Kubeconfig - ansible.builtin.include_tasks: tasks/kubeconfig.yml + ansible.builtin.include_tasks: tasks/kubeconfig.yaml - name: Wait for custom manifests to rollout when: @@ -58,20 +58,20 @@ - k3s_primary_control_node - (k3s_server_manifests_templates | length > 0 or k3s_server_manifests_urls | length > 0) - ansible.builtin.include_tasks: tasks/coredns.yml + ansible.builtin.include_tasks: tasks/coredns.yaml - name: Cilium when: - k3s_primary_control_node - (k3s_server_manifests_templates | length > 0 or k3s_server_manifests_urls | length > 0) - ansible.builtin.include_tasks: tasks/cilium.yml + ansible.builtin.include_tasks: tasks/cilium.yaml - name: Cruft when: k3s_primary_control_node - ansible.builtin.include_tasks: tasks/cruft.yml + ansible.builtin.include_tasks: tasks/cruft.yaml - name: Stale Containers - ansible.builtin.include_tasks: tasks/stale_containers.yml + ansible.builtin.include_tasks: tasks/stale_containers.yaml vars: stale_containers_state: enabled diff --git a/ansible/playbooks/cluster-nuke.yml b/ansible/playbooks/cluster-nuke.yaml similarity index 96% rename from ansible/playbooks/cluster-nuke.yml rename to ansible/playbooks/cluster-nuke.yaml index 0d5c2cc5..c1f5bbfe 100644 --- a/ansible/playbooks/cluster-nuke.yml +++ b/ansible/playbooks/cluster-nuke.yaml @@ -63,7 +63,7 @@ k3s_state: uninstalled - name: Stale Containers - ansible.builtin.include_tasks: tasks/stale_containers.yml + ansible.builtin.include_tasks: tasks/stale_containers.yaml vars: stale_containers_state: disabled diff --git a/ansible/playbooks/cluster-prepare.yml b/ansible/playbooks/cluster-prepare.yaml similarity index 100% rename from ansible/playbooks/cluster-prepare.yml rename to ansible/playbooks/cluster-prepare.yaml diff --git a/ansible/playbooks/cluster-reboot.yml b/ansible/playbooks/cluster-reboot.yaml similarity index 100% rename from ansible/playbooks/cluster-reboot.yml rename to ansible/playbooks/cluster-reboot.yaml diff --git a/ansible/playbooks/cluster-upgrade.yml b/ansible/playbooks/cluster-upgrade.yaml similarity index 100% rename from ansible/playbooks/cluster-upgrade.yml rename to ansible/playbooks/cluster-upgrade.yaml diff --git a/ansible/playbooks/tasks/cilium.yml b/ansible/playbooks/tasks/cilium.yaml similarity index 100% rename from ansible/playbooks/tasks/cilium.yml rename to ansible/playbooks/tasks/cilium.yaml diff --git a/ansible/playbooks/tasks/coredns.yml b/ansible/playbooks/tasks/coredns.yaml similarity index 100% rename from ansible/playbooks/tasks/coredns.yml rename to ansible/playbooks/tasks/coredns.yaml diff --git a/ansible/playbooks/tasks/cruft.yml b/ansible/playbooks/tasks/cruft.yaml similarity index 100% rename from ansible/playbooks/tasks/cruft.yml rename to ansible/playbooks/tasks/cruft.yaml diff --git a/ansible/playbooks/tasks/stale_containers.yml b/ansible/playbooks/tasks/stale_containers.yaml similarity index 100% rename from ansible/playbooks/tasks/stale_containers.yml rename to ansible/playbooks/tasks/stale_containers.yaml diff --git a/ansible/playbooks/templates/custom-coredns-helmchart.yaml.j2 b/ansible/playbooks/templates/custom-coredns-helmchart.yaml.j2 index 7eb17869..fb576e59 100644 --- a/ansible/playbooks/templates/custom-coredns-helmchart.yaml.j2 +++ b/ansible/playbooks/templates/custom-coredns-helmchart.yaml.j2 @@ -17,7 +17,7 @@ spec: image: repository: registry.k8s.io/coredns/coredns tag: v1.10.1 - replicaCount: 3 + replicaCount: 1 service: # Choose the 10th IP address from the start of the service-cidr clusterIP: {{ k3s_server['service-cidr'] | ansible.utils.nthhost(10) }} diff --git a/ansible/requirements.yml b/ansible/requirements.yaml similarity index 100% rename from ansible/requirements.yml rename to ansible/requirements.yaml index d68df8fa..6c47fe8c 100644 --- a/ansible/requirements.yml +++ b/ansible/requirements.yaml @@ -1,15 +1,15 @@ --- collections: - - name: community.general - version: 7.1.0 - - name: community.sops - version: 1.6.4 - name: ansible.posix version: 1.5.4 - name: ansible.utils version: 2.10.3 + - name: community.general + version: 7.1.0 - name: kubernetes.core version: 2.4.0 + - name: community.sops + version: 1.6.4 roles: - name: xanmanning.k3s src: https://github.com/PyratLabs/ansible-role-k3s.git diff --git a/configure b/configure deleted file mode 100755 index 3479ba1a..00000000 --- a/configure +++ /dev/null @@ -1,482 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o pipefail - -# shellcheck disable=SC2155 -export PROJECT_DIR=$(git rev-parse --show-toplevel) - -# shellcheck disable=SC2155 -export SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt - -# shellcheck disable=SC1091 -source "${PROJECT_DIR}/.config.env" - -show_help() { -cat << EOF -Usage: $(basename "$0") - -h, --help Display help - --verify Verify .config.env settings -EOF -} - -main() { - local verify= - parse_command_line "$@" - if [[ "${verify}" == 1 ]]; then - verify_start - verify_binaries - verify_master_count - verify_ansible_hosts - verify_lbs - verify_kubevip - verify_cluster_service_cidrs - verify_age - verify_git_repository - verify_cloudflare - verify_success - else - # generate sops configuration file - envsubst < "${PROJECT_DIR}/tmpl/.sops.yaml" \ - > "${PROJECT_DIR}/.sops.yaml" - # generate cluster settings - envsubst < "${PROJECT_DIR}/tmpl/kubernetes/flux/cluster-settings.yaml" \ - > "${PROJECT_DIR}/kubernetes/flux/vars/cluster-settings.yaml" - envsubst < "${PROJECT_DIR}/tmpl/kubernetes/flux/cluster.yaml" \ - > "${PROJECT_DIR}/kubernetes/flux/config/cluster.yaml" - # generate secrets - envsubst < "${PROJECT_DIR}/tmpl/kubernetes/cluster-secrets.sops.yaml" \ - > "${PROJECT_DIR}/kubernetes/flux/vars/cluster-secrets.sops.yaml" - sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/flux/vars/cluster-secrets.sops.yaml" - 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/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" - 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" - # generate ansible settings - envsubst < "${PROJECT_DIR}/tmpl/ansible/supplemental.yml" \ - > "${PROJECT_DIR}/ansible/inventory/group_vars/kubernetes/supplemental.yml" - # generate ansible hosts file and secrets - generate_ansible_hosts - generate_ansible_host_secrets - setup_github_webhook - setup_weave_gitops - setup_grafana_admin - setup_prometheus_endpoints - success - fi -} - -parse_command_line() { - while :; do - case "${1:-}" in - -h|--help) - show_help - exit - ;; - --verify) - verify=1 - ;; - *) - break - ;; - esac - - shift - done - if [[ -z "$verify" ]]; then - verify=0 - fi -} - -_has_binary() { - command -v "${1}" >/dev/null 2>&1 || { - _log "ERROR(${FUNCNAME[0]})" "${1} is not installed or not found in \$PATH" - exit 1 - } - _log "INFO(${FUNCNAME[0]})" "Found CLI tool ${1} and it is in \$PATH" -} - -_has_optional_envar() { - local option="${1}" - # shellcheck disable=SC2015 - [[ "${!option}" == "" ]] && { - _log "WARN" "Unset optional variable ${option}" - } || { - _log "INFO(${FUNCNAME[0]})" "Found variable '${option}' with value '${!option}'" - } -} - -_has_envar() { - local option="${1}" - local secret="${2:-false}" - local value= - # shellcheck disable=SC2015 - if [[ "${!option}" == "" ]]; then - _log "ERROR(${FUNCNAME[0]})" "Unset variable ${option}" - exit 1 - fi - value="${!option}" - if [[ $secret == "true" ]]; then - value="***" - fi - _log "INFO(${FUNCNAME[0]})" "Found variable '${option}' with value '${value}'" -} - -_has_valid_ip() { - local ip="${1}" - local variable_name="${2}" - if ! ipcalc "${ip}" | awk 'BEGIN{FS=":"; is_invalid=0} /^INVALID/ {is_invalid=1; print $1} END{exit is_invalid}' >/dev/null 2>&1; then - _log "INFO(${FUNCNAME[0]})" "Variable '${variable_name}' has an invalid IP address '${ip}'" - exit 1 - else - _log "INFO(${FUNCNAME[0]})" "Variable '${variable_name}' has a valid IP address '${ip}'" - fi -} - -verify_age() { - _has_envar "BOOTSTRAP_AGE_PUBLIC_KEY" - _has_envar "SOPS_AGE_KEY_FILE" - if [[ ! "$BOOTSTRAP_AGE_PUBLIC_KEY" =~ ^age.* ]]; then - _log "ERROR(${FUNCNAME[0]})" "BOOTSTRAP_AGE_PUBLIC_KEY does not start with age" - exit 1 - else - _log "INFO(${FUNCNAME[0]})" "Age public key is in the correct format" - fi - if [[ ! -f ~/.config/sops/age/keys.txt ]]; then - _log "ERROR(${FUNCNAME[0]})" "Unable to find Age file keys.txt in ~/.config/sops/age" - exit 1 - else - _log "INFO(${FUNCNAME[0]})" "Found Age public key '${BOOTSTRAP_AGE_PUBLIC_KEY}'" - fi -} - -verify_binaries() { - _has_binary "age" - _has_binary "ansible" - _has_binary "envsubst" - _has_binary "flux" - _has_binary "git" - _has_binary "gitops" - _has_binary "ipcalc" - _has_binary "jq" - _has_binary "pip3" - _has_binary "sops" - _has_binary "ssh" - _has_binary "task" - _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" - exit 1 - fi - if ! [[ "$(yq --version)" =~ 4\.[0-9]+\.[0-9]+ ]]; then - _log "ERROR(${FUNCNAME[0]})" "Incompatible yq version, make sure you are using the latest release of github.com/mikefarah/yq" - exit 1 - fi -} - -verify_kubevip() { - _has_envar "BOOTSTRAP_KUBE_VIP_ADDR" - _has_valid_ip "${BOOTSTRAP_KUBE_VIP_ADDR}" "BOOTSTRAP_KUBE_VIP_ADDR" -} - -verify_lbs() { - #TODO: Validate IPs aren't already in use with arp - _has_envar "BOOTSTRAP_K8S_GATEWAY_ADDR" - _has_envar "BOOTSTRAP_INGRESS_NGINX_ADDR" - _has_valid_ip "${BOOTSTRAP_K8S_GATEWAY_ADDR}" "BOOTSTRAP_K8S_GATEWAY_ADDR" - _has_valid_ip "${BOOTSTRAP_INGRESS_NGINX_ADDR}" "BOOTSTRAP_INGRESS_NGINX_ADDR" -} - -verify_cluster_service_cidrs() { - #TODO: Validate input is a CIDR range - _has_envar "BOOTSTRAP_CLUSTER_CIDR" - _has_envar "BOOTSTRAP_SERVICE_CIDR" -} - -verify_git_repository() { - _has_envar "BOOTSTRAP_GIT_REPOSITORY" - export GIT_TERMINAL_PROMPT=0 - pushd "$(mktemp -d)" >/dev/null 2>&1 - [ "$(git ls-remote "${BOOTSTRAP_GIT_REPOSITORY}" 2> /dev/null)" ] || { - _log "ERROR(${FUNCNAME[0]})" "Unable to find the remote Git repository '${BOOTSTRAP_GIT_REPOSITORY}'" - exit 1 - } - popd >/dev/null 2>&1 - export GIT_TERMINAL_PROMPT=1 -} - -verify_master_count() { - local master_node_count= - master_node_count=0 - for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do - node_id=$(echo "${var}" | awk -F"_" '{print $5}') - node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}" - if [[ "${!node_control}" == "true" ]]; then - master_node_count=$((master_node_count+1)) - fi - done - # Check for existance of master nodes and that their count is not an even number - if [[ ${master_node_count} -eq 0 || $((master_node_count%2)) -eq 0 ]]; then - _log "ERROR(${FUNCNAME[0]})" "You must have 1, 3 or an odd number of master nodes >=3 inorder for etcd to have quorum" - exit 1 - fi - _log "INFO(${FUNCNAME[0]})" "Verified control plane node count" -} - -verify_cloudflare() { - local errors= - local account_zone= - _has_envar "BOOTSTRAP_CLOUDFLARE_APITOKEN" "true" - _has_envar "BOOTSTRAP_CLOUDFLARE_DOMAIN" "true" - _has_envar "BOOTSTRAP_ACME_EMAIL" "true" - # Try to retrieve zone information from Cloudflare's API - account_zone=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=${BOOTSTRAP_CLOUDFLARE_DOMAIN}&status=active" \ - -H "Authorization: Bearer ${BOOTSTRAP_CLOUDFLARE_APITOKEN}" \ - -H "Content-Type: application/json" - ) - if [[ "$(echo "${account_zone}" | jq ".success")" == "true" ]]; then - _log "INFO(${FUNCNAME[0]})" "Verified Cloudflare Account and Zone information" - else - errors=$(echo "${account_zone}" | jq -c ".errors") - _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 "Authorization: Bearer ${BOOTSTRAP_CLOUDFLARE_APITOKEN}" \ - -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() { - local node_id= - local node_addr= - local node_username= - local node_password= - local node_control= - local node_hostname= - local default_control_node_prefix= - local default_worker_node_prefix= - default_control_node_prefix="BOOTSTRAP_ANSIBLE_DEFAULT_CONTROL_NODE_HOSTNAME_PREFIX" - default_worker_node_prefix="BOOTSTRAP_ANSIBLE_DEFAULT_NODE_HOSTNAME_PREFIX" - _has_optional_envar "${default_control_node_prefix}" - _has_optional_envar "${default_worker_node_prefix}" - for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do - node_id=$(echo "${var}" | awk -F"_" '{print $5}') - node_addr="BOOTSTRAP_ANSIBLE_HOST_ADDR_${node_id}" - node_username="BOOTSTRAP_ANSIBLE_SSH_USERNAME_${node_id}" - node_password="BOOTSTRAP_ANSIBLE_SUDO_PASSWORD_${node_id}" - node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}" - node_hostname="BOOTSTRAP_ANSIBLE_HOSTNAME_${node_id}" - _has_envar "${node_addr}" - _has_envar "${node_username}" - _has_envar "${node_password}" "true" - _has_envar "${node_control}" - _has_optional_envar "${node_hostname}" - if [[ "${!node_addr}" == "${BOOTSTRAP_KUBE_VIP_ADDR}" ]]; then - _log "ERROR(${FUNCNAME[0]})" "The kube-vip IP '${BOOTSTRAP_KUBE_VIP_ADDR}' should not be the same as the IP for node '${!node_addr}'" - exit 1 - fi - if [[ "${!node_addr}" == "${BOOTSTRAP_K8S_GATEWAY_ADDR}" ]]; then - _log "ERROR(${FUNCNAME[0]})" "The k8s-gateway load balancer IP '${BOOTSTRAP_K8S_GATEWAY_ADDR}' should not be the same as the IP for node '${!node_addr}'" - exit 1 - fi - if [[ "${!node_addr}" == "${BOOTSTRAP_INGRESS_NGINX_ADDR}" ]]; then - _log "ERROR(${FUNCNAME[0]})" "The ingress load balancer IP '${BOOTSTRAP_INGRESS_NGINX_ADDR}' should not be the same as the IP for node '${!node_addr}'" - exit 1 - fi - if ssh -q -o BatchMode=yes -o ConnectTimeout=5 "${!node_username}"@"${!var}" "true"; then - _log "INFO(${FUNCNAME[0]})" "SSH into host '${!var}' with username '${!node_username}' was successfull" - else - _log "ERROR(${FUNCNAME[0]})" "SSH into host '${!var}' with username '${!node_username}'was NOT successful, did you copy over your SSH key?" - exit 1 - fi - done -} - -verify_start() { - _log "INFO(${FUNCNAME[0]})" "Starting verification of .config.env, please wait..." -} - -verify_success() { - _log "INFO(${FUNCNAME[0]})" "All checks passed!" - _log "INFO(${FUNCNAME[0]})" "Run the script without --verify to template all the files out" - exit 0 -} - -generate_ansible_host_secrets() { - local node_id= - local node_username= - local node_password= - local node_hostname= - local node_control= - default_control_node_prefix=${BOOTSTRAP_ANSIBLE_DEFAULT_CONTROL_NODE_HOSTNAME_PREFIX:-k8s-} - default_worker_node_prefix=${BOOTSTRAP_ANSIBLE_DEFAULT_NODE_HOSTNAME_PREFIX:-k8s-} - for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do - node_id=$(echo "${var}" | awk -F"_" '{print $5}') - node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}" - if [[ "${!node_control}" == "true" ]]; then - node_hostname="BOOTSTRAP_ANSIBLE_HOSTNAME_${node_id}" - host_key="${!node_hostname:-${default_control_node_prefix}}" - if [ "${host_key}" == "${default_control_node_prefix}" ]; then - node_hostname=${default_control_node_prefix}${node_id} - else - node_hostname=${!node_hostname} - fi - else - node_hostname="BOOTSTRAP_ANSIBLE_HOSTNAME_${node_id}" - host_key="${!node_hostname:-${default_worker_node_prefix}}" - if [ "${host_key}" == "${default_worker_node_prefix}" ]; then - node_hostname=${default_worker_node_prefix}${node_id} - else - node_hostname=${!node_hostname} - fi - fi - { - node_username="BOOTSTRAP_ANSIBLE_SSH_USERNAME_${node_id}" - node_password="BOOTSTRAP_ANSIBLE_SUDO_PASSWORD_${node_id}" - printf "kind: Secret\n" - printf "ansible_user: %s\n" "${!node_username}" - printf "ansible_become_pass: %s\n" "${!node_password}" - } > "${PROJECT_DIR}/ansible/inventory/host_vars/${node_hostname}.sops.yml" - sops --encrypt --in-place "${PROJECT_DIR}/ansible/inventory/host_vars/${node_hostname}.sops.yml" - done -} - -generate_ansible_hosts() { - local worker_node_count= - default_control_node_prefix=${BOOTSTRAP_ANSIBLE_DEFAULT_CONTROL_NODE_HOSTNAME_PREFIX:-k8s-} - default_worker_node_prefix=${BOOTSTRAP_ANSIBLE_DEFAULT_NODE_HOSTNAME_PREFIX:-k8s-} - { - printf -- "---\n" - printf "kubernetes:\n" - printf " children:\n" - printf " master:\n" - printf " hosts:\n" - master_node_count=0 - worker_node_count=0 - for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do - node_id=$(echo "${var}" | awk -F"_" '{print $5}') - node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}" - if [[ "${!node_control}" == "true" ]]; then - master_node_count=$((master_node_count+1)) - node_hostname="BOOTSTRAP_ANSIBLE_HOSTNAME_${node_id}" - host_key="${!node_hostname:-${default_control_node_prefix}}" - if [ "${host_key}" == "${default_control_node_prefix}" ]; then - node_hostname=${default_control_node_prefix}${node_id} - else - node_hostname=${!node_hostname} - fi - printf " %s:\n" "${node_hostname}" - printf " ansible_host: %s\n" "${!var}" - else - worker_node_count=$((worker_node_count+1)) - fi - done - if [[ ${worker_node_count} -gt 0 ]]; then - printf " worker:\n" - printf " hosts:\n" - for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do - node_id=$(echo "${var}" | awk -F"_" '{print $5}') - node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}" - if [[ "${!node_control}" == "false" ]]; then - node_hostname="BOOTSTRAP_ANSIBLE_HOSTNAME_${node_id}" - host_key="${!node_hostname:-${default_worker_node_prefix}}" - if [ "${host_key}" == "${default_worker_node_prefix}" ]; then - node_hostname=${default_worker_node_prefix}${node_id} - else - node_hostname=${!node_hostname} - fi - printf " %s:\n" "${node_hostname}" - printf " ansible_host: %s\n" "${!var}" - fi - done - fi - } > "${PROJECT_DIR}/ansible/inventory/hosts.yml" -} - -setup_prometheus_endpoints() { - yq --inplace 'del(.spec.values.kubeControllerManager.endpoints[])' \ - "${PROJECT_DIR}/kubernetes/apps/monitoring/kube-prometheus-stack/app/helmrelease.yaml" - for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do - node_id=$(echo "${var}" | awk -F"_" '{print $5}') - node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}" - if [[ "${!node_control}" == "true" ]]; then - node_addr="BOOTSTRAP_ANSIBLE_HOST_ADDR_${node_id}" - _log "INFO(${FUNCNAME[0]})" "Setting up Prometheus endpoint for '${!node_addr}'" - yq --inplace ".spec.values.kubeControllerManager.endpoints += \"${!node_addr}\"" \ - "${PROJECT_DIR}/kubernetes/apps/monitoring/kube-prometheus-stack/app/helmrelease.yaml" - fi - done -} - -setup_github_webhook() { - _has_envar "BOOTSTRAP_FLUX_GITHUB_WEBHOOK_SECRET" - WEBHOOK_SECRET="${BOOTSTRAP_FLUX_GITHUB_WEBHOOK_SECRET}" - if [[ "${WEBHOOK_SECRET}" == "generated" ]]; then - WEBHOOK_SECRET="$(openssl rand -hex 12)" - fi - export BOOTSTRAP_FLUX_GITHUB_WEBHOOK_SECRET="${WEBHOOK_SECRET}" - _log "INFO(${FUNCNAME[0]})" "Using GitHub Token '${WEBHOOK_SECRET}' for Flux" - envsubst < "${PROJECT_DIR}/tmpl/kubernetes/github-webhook-token-secret.sops.yaml" \ - > "${PROJECT_DIR}/kubernetes/apps/flux-system/addons/webhooks/github/secret.sops.yaml" - sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/flux-system/addons/webhooks/github/secret.sops.yaml" -} - -setup_weave_gitops() { - _has_envar "BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD" - WEAVE_GITOPS_ADMIN_PASSWORD="${BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD}" - if [[ "${WEAVE_GITOPS_ADMIN_PASSWORD}" == "generated" ]]; then - WEAVE_GITOPS_ADMIN_PASSWORD="$(openssl rand -hex 12)" - fi - export BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD="${WEAVE_GITOPS_ADMIN_PASSWORD}" - _log "INFO(${FUNCNAME[0]})" "Using admin password '${WEAVE_GITOPS_ADMIN_PASSWORD}' for Weave Gitops" - # Convert password to bcrypt hash - # shellcheck disable=SC2155 - export BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD="$(echo -n "${BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD}" | gitops get bcrypt-hash)" - envsubst < "${PROJECT_DIR}/tmpl/kubernetes/weave-gitops-secret.sops.yaml" \ - > "${PROJECT_DIR}/kubernetes/apps/flux-system/weave-gitops/app/secret.sops.yaml" - sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/flux-system/weave-gitops/app/secret.sops.yaml" -} - -setup_grafana_admin() { - _has_envar "BOOTSTRAP_GRAFANA_ADMIN_PASSWORD" - GRAFANA_ADMIN_PASSWORD="${BOOTSTRAP_GRAFANA_ADMIN_PASSWORD}" - if [[ "${GRAFANA_ADMIN_PASSWORD}" == "generated" ]]; then - GRAFANA_ADMIN_PASSWORD="$(openssl rand -hex 12)" - fi - export BOOTSTRAP_GRAFANA_ADMIN_PASSWORD="${GRAFANA_ADMIN_PASSWORD}" - _log "INFO(${FUNCNAME[0]})" "Using password '${GRAFANA_ADMIN_PASSWORD}' for Grafana" - envsubst < "${PROJECT_DIR}/tmpl/kubernetes/grafana-admin-secret.sops.yaml" \ - > "${PROJECT_DIR}/kubernetes/apps/monitoring/grafana/app/secret.sops.yaml" - sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/monitoring/grafana/app/secret.sops.yaml" -} - -success() { - _log "INFO(${FUNCNAME[0]})" "All files have been templated, proceed to the next steps outlined in the README" - exit 0 -} - -_log() { - local type="${1}" - local msg="${2}" - printf 'timestamp="%s" type="%s" message="%s"\n' "$(date)" "${type}" "${msg}" -} - -main "$@" diff --git a/kubernetes/apps/kube-system/coredns/app/helmrelease.yaml b/kubernetes/apps/kube-system/coredns/app/helmrelease.yaml new file mode 100644 index 00000000..335640ab --- /dev/null +++ b/kubernetes/apps/kube-system/coredns/app/helmrelease.yaml @@ -0,0 +1,91 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + name: coredns + namespace: kube-system +spec: + interval: 30m + chart: + spec: + chart: coredns + version: 1.24.1 + sourceRef: + kind: HelmRepository + name: coredns + namespace: flux-system + maxHistory: 2 + install: + createNamespace: true + remediation: + retries: 3 + upgrade: + cleanupOnFail: true + remediation: + retries: 3 + uninstall: + keepHistory: false + values: + fullnameOverride: coredns + image: + repository: registry.k8s.io/coredns/coredns + tag: v1.10.1 + replicaCount: 1 + service: + clusterIP: "${COREDNS_ADDR}" + serviceAccount: + create: true + deployment: + annotations: + reloader.stakater.com/auto: "true" + servers: + - zones: + - zone: . + scheme: dns:// + use_tcp: true + port: 53 + plugins: + - name: log + - name: errors + - name: health + configBlock: |- + lameduck 5s + - name: ready + - name: kubernetes + parameters: cluster.local in-addr.arpa ip6.arpa + configBlock: |- + pods insecure + fallthrough in-addr.arpa ip6.arpa + ttl 30 + - name: prometheus + parameters: 0.0.0.0:9153 + - name: forward + parameters: . /etc/resolv.conf + - name: cache + parameters: 30 + - name: loop + - name: reload + - name: loadbalance + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - key: node-role.kubernetes.io/control-plane + operator: Exists + effect: NoSchedule + - key: node-role.kubernetes.io/master + operator: Exists + effect: NoSchedule + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + app.kubernetes.io/instance: coredns diff --git a/kubernetes/apps/kube-system/coredns/app/kustomization.yaml b/kubernetes/apps/kube-system/coredns/app/kustomization.yaml new file mode 100644 index 00000000..1c3fdb04 --- /dev/null +++ b/kubernetes/apps/kube-system/coredns/app/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: kube-system +resources: + - ./helmrelease.yaml diff --git a/kubernetes/apps/kube-system/coredns/ks.yaml b/kubernetes/apps/kube-system/coredns/ks.yaml new file mode 100644 index 00000000..5c2415cd --- /dev/null +++ b/kubernetes/apps/kube-system/coredns/ks.yaml @@ -0,0 +1,16 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: cluster-apps-coredns + namespace: flux-system +spec: + path: ./kubernetes/apps/kube-system/coredns/app + prune: true + sourceRef: + kind: GitRepository + name: home-kubernetes + wait: false # no flux ks dependents + interval: 30m + retryInterval: 1m + timeout: 5m diff --git a/kubernetes/apps/kube-system/kustomization.yaml b/kubernetes/apps/kube-system/kustomization.yaml index 626924aa..860ff1b8 100644 --- a/kubernetes/apps/kube-system/kustomization.yaml +++ b/kubernetes/apps/kube-system/kustomization.yaml @@ -4,6 +4,7 @@ kind: Kustomization resources: - ./namespace.yaml - ./cilium/ks.yaml + - ./coredns/ks.yaml - ./local-path-provisioner/ks.yaml - ./metrics-server/ks.yaml - ./reloader/ks.yaml diff --git a/kubernetes/apps/system-upgrade/kustomization.yaml b/kubernetes/apps/system-upgrade/kustomization.yaml index 78ca97cb..7e5f85e1 100644 --- a/kubernetes/apps/system-upgrade/kustomization.yaml +++ b/kubernetes/apps/system-upgrade/kustomization.yaml @@ -5,5 +5,5 @@ resources: - ./namespace.yaml # NOTE: Only enable system-upgrade-controller if you also update the version of k3s in the following file # otherwise if you run ansible against an already provisioned cluster you might downgrade it - # https://github.com/onedr0p/flux-cluster-template/blob/main/ansible/inventory/group_vars/kubernetes/k3s.yml + # https://github.com/onedr0p/flux-cluster-template/blob/main/ansible/inventory/group_vars/kubernetes/main.yaml # - ./system-upgrade-controller/ks.yaml diff --git a/template/configure.yaml b/template/configure.yaml new file mode 100644 index 00000000..2003b023 --- /dev/null +++ b/template/configure.yaml @@ -0,0 +1,84 @@ +--- +- name: Cluster Installation + hosts: localhost + connection: local + vars_files: + - vars/config.yaml + - defaults/templates.yaml + - defaults/extras.yaml + tasks: + - name: Get absolute path to this Git repository # noqa: command-instead-of-module + ansible.builtin.command: git rev-parse --show-toplevel + changed_when: false + check_mode: false + register: repository_path + failed_when: repository_path.rc != 0 + + - name: Verify configuration + ansible.builtin.include_tasks: tasks/verify_{{ task }}.yaml + loop: [age, cli, net, cloudflare, github] + loop_control: + loop_var: task + + - name: Ensure template directories exist + ansible.builtin.file: + path: "{{ repository_path.stdout }}/{{ item.dest | dirname }}" + state: directory + mode: "0755" + loop: "{{ templates }}" + + - name: Template out non-encrypted files + ansible.builtin.template: + src: "templates/{{ item.src }}" + dest: "{{ repository_path.stdout }}/{{ item.dest }}" + mode: "0755" + loop: "{{ templates | selectattr('encrypt', 'equalto', false) | list }}" + + # https://github.com/ansible-collections/community.sops/issues/153 + - name: Backup sops configuration file + ansible.builtin.copy: + src: "{{ repository_path.stdout }}/.sops.yaml" + dest: "{{ repository_path.stdout }}/.sops.yaml.orig" + mode: "0755" + - name: Remove sops configuration file + ansible.builtin.file: + path: "{{ repository_path.stdout }}/.sops.yaml" + state: absent + + - name: Template out encrypted files + community.sops.sops_encrypt: + path: "{{ repository_path.stdout }}/{{ item.dest }}" + encrypted_regex: ^(data|stringData)$ + age: ["{{ bootstrap_age_public_key }}"] + content_yaml: "{{ lookup('ansible.builtin.template', 'templates/' + item.src) | from_yaml }}" + mode: "0755" + force: true + loop: "{{ templates | selectattr('encrypt', 'equalto', true) | list }}" + + - name: Ensure Ansible inventory directory exists + ansible.builtin.file: + path: "{{ repository_path.stdout }}/ansible/inventory/host_vars" + state: directory + mode: "0755" + + - name: Template out node secrets + community.sops.sops_encrypt: + path: "{{ repository_path.stdout }}/ansible/inventory/host_vars/{{ item.name }}.sops.yaml" + age: ["{{ bootstrap_age_public_key }}"] + content_yaml: "{{ lookup('ansible.builtin.template', 'templates/ansible/node.sops.yaml.j2', template_vars=dict(password=item.password)) | from_yaml }}" + mode: "0755" + force: true + loop: "{{ bootstrap_hosts.master + bootstrap_hosts.worker | default([]) }}" + loop_control: + label: "{{ item.address }}" + + # https://github.com/ansible-collections/community.sops/issues/153 + - name: Restore sops configuration file + ansible.builtin.copy: + src: "{{ repository_path.stdout }}/.sops.yaml.orig" + dest: "{{ repository_path.stdout }}/.sops.yaml" + mode: "0755" + - name: Remove backup sops configuration file + ansible.builtin.file: + path: "{{ repository_path.stdout }}/.sops.yaml.orig" + state: absent diff --git a/template/defaults/extras.yaml b/template/defaults/extras.yaml new file mode 100644 index 00000000..7a7ecb9d --- /dev/null +++ b/template/defaults/extras.yaml @@ -0,0 +1,2 @@ +--- +bootstrap_coredns_addr: "{{ bootstrap_service_cidr | ansible.utils.nthhost(10) }}" diff --git a/template/defaults/templates.yaml b/template/defaults/templates.yaml new file mode 100644 index 00000000..c897ec3b --- /dev/null +++ b/template/defaults/templates.yaml @@ -0,0 +1,44 @@ +--- +templates: + # Root + - src: .sops.yaml.j2 + dest: ./.sops.yaml + encrypt: false + # Ansible dir + - src: ansible/supplemental.yaml.j2 + dest: ./ansible/inventory/group_vars/kubernetes/supplemental.yaml + encrypt: false + - src: ansible/hosts.yaml.j2 + dest: ./ansible/hosts.yaml + encrypt: false + # Kubernetes dir + - src: kubernetes/kube-prometheus-stack-helmrelease.yaml.j2 + dest: ./kubernetes/apps/monitoring/kube-prometheus-stack/app/helmrelease.yaml + encrypt: false + - src: kubernetes/cert-manager-secret.sops.yaml.j2 + dest: ./kubernetes/apps/cert-manager/cert-manager/issuers/secret.sops.yaml + encrypt: true + - src: kubernetes/cloudflared-secret.sops.yaml.j2 + dest: ./kubernetes/apps/networking/cloudflared/app/secret.sops.yaml + encrypt: true + - src: kubernetes/cluster-secrets.sops.yaml.j2 + dest: ./kubernetes/flux/vars/cluster-secrets.sops.yaml + encrypt: true + - src: kubernetes/cluster-settings.yaml.j2 + dest: ./kubernetes/flux/vars/cluster-settings.yaml + encrypt: false + - src: kubernetes/cluster.yaml.j2 + dest: ./kubernetes/flux/config/cluster.yaml + encrypt: false + - src: kubernetes/external-dns-secret.sops.yaml.j2 + dest: ./kubernetes/apps/networking/external-dns/app/secret.sops.yaml + encrypt: true + - src: kubernetes/github-webhook-token-secret.sops.yaml.j2 + dest: ./kubernetes/apps/flux-system/addons/webhooks/github/secret.sops.yaml + encrypt: true + - src: kubernetes/grafana-admin-secret.sops.yaml.j2 + dest: ./kubernetes/apps/monitoring/grafana/app/secret.sops.yaml + encrypt: true + - src: kubernetes/weave-gitops-secret.sops.yaml.j2 + dest: ./kubernetes/apps/flux-system/weave-gitops/app/secret.sops.yaml + encrypt: true diff --git a/template/tasks/verify_age.yaml b/template/tasks/verify_age.yaml new file mode 100644 index 00000000..03a0d9fd --- /dev/null +++ b/template/tasks/verify_age.yaml @@ -0,0 +1,22 @@ +--- +- name: Query age key file + ansible.builtin.stat: + path: ~/.config/sops/age/keys.txt + register: result + +- name: Check if age key file exists + ansible.builtin.assert: + that: [result.stat.exists] + success_msg: Age file ~/.config/sops/age/keys.txt exists + fail_msg: Age file ~/.config/sops/age/keys.txt does not exist + +- name: Query age key file contents + ansible.builtin.set_fact: + age_contents: "{{ lookup('file', '~/.config/sops/age/keys.txt') }}" + +- name: Check if age public keys match + ansible.builtin.assert: + that: + - "'{{ bootstrap_age_public_key }}' in age_contents" + success_msg: Age public key {{ bootstrap_age_public_key }} exists + fail_msg: Age public key {{ bootstrap_age_public_key }} does not exist diff --git a/template/tasks/verify_cli.yaml b/template/tasks/verify_cli.yaml new file mode 100644 index 00000000..a081767a --- /dev/null +++ b/template/tasks/verify_cli.yaml @@ -0,0 +1,8 @@ +--- +- name: Check for required CLI tools + ansible.builtin.command: "command -v {{ item }}" + loop: [age, flux, git, pip3, sops, task] + changed_when: false + check_mode: false + register: result + failed_when: result.rc != 0 and result.rc != 127 diff --git a/template/tasks/verify_cloudflare.yaml b/template/tasks/verify_cloudflare.yaml new file mode 100644 index 00000000..ad240a91 --- /dev/null +++ b/template/tasks/verify_cloudflare.yaml @@ -0,0 +1,34 @@ +--- +- name: Query Cloudflare zone + ansible.builtin.uri: + url: "https://api.cloudflare.com/client/v4/zones?name={{ bootstrap_cloudflare_domain }}&status=active" + headers: + Authorization: "Bearer {{ bootstrap_cloudflare_token }}" + Content-Type: application/json + timeout: 5 + return_content: true + body_format: json + register: result + +- name: Check if Cloudflare zone exists + ansible.builtin.assert: + that: ["result.json.success == true"] + success_msg: "Cloudflare zone {{ bootstrap_cloudflare_domain }} exists" + fail_msg: "Cloudflare zone {{ bootstrap_cloudflare_domain }} does not exist" + +- name: Query Cloudflared tunnel + ansible.builtin.uri: + url: "https://api.cloudflare.com/client/v4/accounts/{{ bootstrap_cloudflare_account_tag }}/cfd_tunnel/{{ bootstrap_cloudflare_tunnel_id }}" + headers: + Authorization: "Bearer {{ bootstrap_cloudflare_token }}" + Content-Type: application/json + timeout: 5 + return_content: true + body_format: json + register: result + +- name: Check if Cloudflared tunnel exists + ansible.builtin.assert: + that: ["result.json.success == true"] + success_msg: "Cloudflared tunnel {{ bootstrap_cloudflare_tunnel_id }} exists" + fail_msg: "Cloudflared tunnel {{ bootstrap_cloudflare_tunnel_id }} does not exist" diff --git a/template/tasks/verify_github.yaml b/template/tasks/verify_github.yaml new file mode 100644 index 00000000..d33609a7 --- /dev/null +++ b/template/tasks/verify_github.yaml @@ -0,0 +1,30 @@ +--- +- name: Query Github username + ansible.builtin.uri: + url: "https://api.github.com/users/{{ bootstrap_github_username }}" + timeout: 5 + return_content: true + body_format: json + register: result + +- name: Check if username exists + ansible.builtin.assert: + that: + - "result.json.login == '{{ bootstrap_github_username }}'" + success_msg: "Github user {{ bootstrap_github_username }} exists" + fail_msg: "Github user {{ bootstrap_github_username }} does not exist" + +- name: Query Github repo + ansible.builtin.uri: + url: "https://api.github.com/repos/{{ bootstrap_github_username }}/{{ bootstrap_github_repository_name }}" + timeout: 5 + return_content: true + body_format: json + register: result + +- name: Check if repo exists + ansible.builtin.assert: + that: + - "result.json.full_name == '{{ bootstrap_github_username }}/{{ bootstrap_github_repository_name }}'" + success_msg: "Github repo {{ bootstrap_github_username }}/{{ bootstrap_github_repository_name }} exists" + fail_msg: "Github repo {{ bootstrap_github_username }}/{{ bootstrap_github_repository_name }} does not exist" diff --git a/template/tasks/verify_net.yaml b/template/tasks/verify_net.yaml new file mode 100644 index 00000000..c39f2d78 --- /dev/null +++ b/template/tasks/verify_net.yaml @@ -0,0 +1,94 @@ +--- +- name: Verify master node count + ansible.builtin.assert: + that: + - "{{ bootstrap_hosts.master | length > 0 }}" + - "{{ bootstrap_hosts.master | length is odd }}" + success_msg: "Master node count {{ bootstrap_hosts.master | length }} is correct." + fail_msg: "Master node count {{ bootstrap_hosts.master | length }} is not greater than 0 or is not odd." + +- name: Verify node CIDR + ansible.builtin.assert: + that: ["{{ bootstrap_node_cidr is ansible.utils.ipv4 }}"] + success_msg: "Node CIDR {{ bootstrap_node_cidr }} is valid." + fail_msg: "Node CIDR {{ bootstrap_node_cidr }} is invalid." + +- name: Verify cluster CIDR + ansible.builtin.assert: + that: ["{{ bootstrap_cluster_cidr is ansible.utils.ipv4 }}"] + success_msg: "Cluster CIDR {{ bootstrap_cluster_cidr }} is valid." + fail_msg: "Cluster CIDR {{ bootstrap_cluster_cidr }} is invalid." + +- name: Verify service CIDR + ansible.builtin.assert: + that: ["{{ bootstrap_service_cidr is ansible.utils.ipv4 }}"] + success_msg: "Service CIDR {{ bootstrap_service_cidr }} is valid." + fail_msg: "Service CIDR {{ bootstrap_service_cidr }} is invalid." + +- name: Verify k8s_gateway + ansible.builtin.assert: + that: ["{{ bootstrap_k8s_gateway_addr is ansible.utils.ipv4 }}"] + success_msg: "k8s_gateway address {{ bootstrap_k8s_gateway_addr }} is valid." + fail_msg: "k8s_gateway address {{ bootstrap_k8s_gateway_addr }} is invalid." + +- name: Verify k8s_gateway in node CIDR + ansible.builtin.assert: + that: ["{{ bootstrap_node_cidr | ansible.utils.network_in_usable(bootstrap_k8s_gateway_addr) }}"] + success_msg: "k8s_gateway address {{ bootstrap_k8s_gateway_addr }} is within {{ bootstrap_node_cidr }}." + fail_msg: "k8s_gateway address {{ bootstrap_k8s_gateway_addr }} is not within {{ bootstrap_node_cidr }}." + +- name: Verify ingress-nginx + ansible.builtin.assert: + that: ["{{ bootstrap_ingress_nginx_addr is ansible.utils.ipv4 }}"] + success_msg: "ingress-nginx address {{ bootstrap_ingress_nginx_addr }} is valid." + fail_msg: "ingress-nginx address {{ bootstrap_ingress_nginx_addr }} is invalid." + +- name: Verify ingress-nginx in node CIDR + ansible.builtin.assert: + that: ["{{ bootstrap_node_cidr | ansible.utils.network_in_usable(bootstrap_ingress_nginx_addr) }}"] + success_msg: "ingress-nginx address {{ bootstrap_ingress_nginx_addr }} is within {{ bootstrap_node_cidr }}." + fail_msg: "ingress-nginx address {{ bootstrap_ingress_nginx_addr }} is not within {{ bootstrap_node_cidr }}." + +- name: Verify kube-vip + ansible.builtin.assert: + that: ["{{ bootstrap_kube_vip_addr is ansible.utils.ipv4 }}"] + success_msg: "kube-vip address {{ bootstrap_kube_vip_addr }} is valid." + fail_msg: "kube-vip address {{ bootstrap_kube_vip_addr }} is invalid." + +- name: Verify kube-vip in node CIDR + ansible.builtin.assert: + that: ["{{ bootstrap_node_cidr | ansible.utils.network_in_usable(bootstrap_kube_vip_addr) }}"] + success_msg: "kube-vip address {{ bootstrap_kube_vip_addr }} is within {{ bootstrap_node_cidr }}." + fail_msg: "kube-vip address {{ bootstrap_kube_vip_addr }} is not within {{ bootstrap_node_cidr }}." + +- name: Verify nodes are not the same IPs as k8s_gateway, ingress-nginx or kube-vip + ansible.builtin.assert: + that: + - "{{ item.address not in (bootstrap_k8s_gateway_addr, bootstrap_ingress_nginx_addr, bootstrap_kube_vip_addr) }}" + success_msg: "Node address {{ item.address }} is different than k8s_gateway, ingress-nginx or kube-vip." + fail_msg: "Node address {{ item.address }} is not different than k8s_gateway, ingress-nginx or kube-vip." + quiet: true + loop: "{{ bootstrap_hosts.master + bootstrap_hosts.worker | default([]) }}" + loop_control: + label: "{{ item.address }}" + +- name: Verify nodes are in node CIDR + ansible.builtin.assert: + that: ["{{ bootstrap_node_cidr | ansible.utils.network_in_usable(item.address) }}"] + success_msg: "Node address {{ item.address }} is within {{ bootstrap_node_cidr }}." + fail_msg: "Node address {{ item.address }} is not within {{ bootstrap_node_cidr }}." + quiet: true + loop: "{{ bootstrap_hosts.master + bootstrap_hosts.worker | default([]) }}" + loop_control: + label: "{{ item.address }}" + +- name: Verify SSH port is reachable + ansible.builtin.wait_for: + host: "{{ item.address }}" + port: 22 + search_regex: OpenSSH + timeout: 10 + connection: local + loop: "{{ bootstrap_hosts.master + bootstrap_hosts.worker | default([]) }}" + loop_control: + label: "{{ item.address }}" diff --git a/tmpl/.sops.yaml b/template/templates/.sops.yaml.j2 similarity index 69% rename from tmpl/.sops.yaml rename to template/templates/.sops.yaml.j2 index e00c74f9..16a3a247 100644 --- a/tmpl/.sops.yaml +++ b/template/templates/.sops.yaml.j2 @@ -4,8 +4,8 @@ creation_rules: encrypted_regex: "^(data|stringData)$" key_groups: - age: - - ${BOOTSTRAP_AGE_PUBLIC_KEY} + - "{{ bootstrap_age_public_key }}" - path_regex: ansible/.*\.sops\.ya?ml key_groups: - age: - - ${BOOTSTRAP_AGE_PUBLIC_KEY} + - "{{ bootstrap_age_public_key }}" diff --git a/template/templates/ansible/hosts.yaml.j2 b/template/templates/ansible/hosts.yaml.j2 new file mode 100644 index 00000000..d555d51e --- /dev/null +++ b/template/templates/ansible/hosts.yaml.j2 @@ -0,0 +1,20 @@ +#jinja2: trim_blocks: True, lstrip_blocks: True +--- +kubernetes: + children: + master: + hosts: + {% for item in bootstrap_hosts.master %} + {{ item.name }}: + ansible_user: {{ item.username }} + ansible_host: {{ item.address }} + {% endfor %} + {% if bootstrap_hosts.worker | default([]) | length > 0 %} + worker: + hosts: + {% for item in bootstrap_hosts.worker %} + {{ item.name }}: + ansible_user: {{ item.username }} + ansible_host: {{ item.address }} + {% endfor %} + {% endif %} diff --git a/template/templates/ansible/node.sops.yaml.j2 b/template/templates/ansible/node.sops.yaml.j2 new file mode 100644 index 00000000..e538fd2e --- /dev/null +++ b/template/templates/ansible/node.sops.yaml.j2 @@ -0,0 +1,2 @@ +--- +ansible_become_pass: "{{ password }}" diff --git a/template/templates/ansible/supplemental.yaml.j2 b/template/templates/ansible/supplemental.yaml.j2 new file mode 100644 index 00000000..55e8771b --- /dev/null +++ b/template/templates/ansible/supplemental.yaml.j2 @@ -0,0 +1,6 @@ +--- +timezone: "{{ bootstrap_timezone }}" +coredns_addr: "{{ bootstrap_coredns_addr }}" +kube_vip_addr: "{{ bootstrap_kube_vip_addr }}" +cluster_cidr: "{{ bootstrap_cluster_cidr }}" +service_cidr: "{{ bootstrap_service_cidr }}" diff --git a/tmpl/kubernetes/cert-manager-secret.sops.yaml b/template/templates/kubernetes/cert-manager-secret.sops.yaml.j2 similarity index 69% rename from tmpl/kubernetes/cert-manager-secret.sops.yaml rename to template/templates/kubernetes/cert-manager-secret.sops.yaml.j2 index e36d65bc..18b1db7b 100644 --- a/tmpl/kubernetes/cert-manager-secret.sops.yaml +++ b/template/templates/kubernetes/cert-manager-secret.sops.yaml.j2 @@ -5,4 +5,4 @@ metadata: name: cert-manager-secret namespace: cert-manager stringData: - api-token: "${BOOTSTRAP_CLOUDFLARE_APITOKEN}" + api-token: "{{ bootstrap_cloudflare_token }}" diff --git a/template/templates/kubernetes/cloudflared-secret.sops.yaml.j2 b/template/templates/kubernetes/cloudflared-secret.sops.yaml.j2 new file mode 100644 index 00000000..ad63f1ef --- /dev/null +++ b/template/templates/kubernetes/cloudflared-secret.sops.yaml.j2 @@ -0,0 +1,14 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: cloudflared-secret + namespace: networking +stringData: + TUNNEL_ID: "{{ bootstrap_cloudflare_tunnel_id }}" + credentials.json: | + { + "AccountTag": "{{ bootstrap_cloudflare_account_tag }}", + "TunnelSecret": "{{ bootstrap_cloudflare_tunnel_secret }}", + "TunnelID": "{{ bootstrap_cloudflare_tunnel_id }}" + } diff --git a/template/templates/kubernetes/cluster-secrets.sops.yaml.j2 b/template/templates/kubernetes/cluster-secrets.sops.yaml.j2 new file mode 100644 index 00000000..54f10d93 --- /dev/null +++ b/template/templates/kubernetes/cluster-secrets.sops.yaml.j2 @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: cluster-secrets + namespace: flux-system +stringData: + SECRET_DOMAIN: "{{ bootstrap_cloudflare_domain }}" + SECRET_ACME_EMAIL: "{{ bootstrap_acme_email }}" + SECRET_CLOUDFLARE_TUNNEL_ID: "{{ bootstrap_cloudflare_tunnel_id }}" diff --git a/template/templates/kubernetes/cluster-settings.yaml.j2 b/template/templates/kubernetes/cluster-settings.yaml.j2 new file mode 100644 index 00000000..58955eb2 --- /dev/null +++ b/template/templates/kubernetes/cluster-settings.yaml.j2 @@ -0,0 +1,14 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cluster-settings + namespace: flux-system +data: + TIMEZONE: "{{ bootstrap_timezone }}" + COREDNS_ADDR: "{{ bootstrap_coredns_addr }}" + K8S_GATEWAY_ADDR: "{{ bootstrap_k8s_gateway_addr }}" + INGRESS_NGINX_ADDR: "{{ bootstrap_ingress_nginx_addr }}" + KUBE_VIP_ADDR: "{{ bootstrap_kube_vip_addr }}" + CLUSTER_CIDR: "{{ bootstrap_cluster_cidr }}" + SERVICE_CIDR: "{{ bootstrap_service_cidr }}" diff --git a/tmpl/kubernetes/flux/cluster.yaml b/template/templates/kubernetes/cluster.yaml.j2 similarity index 87% rename from tmpl/kubernetes/flux/cluster.yaml rename to template/templates/kubernetes/cluster.yaml.j2 index 8d42e24b..6b6cb15f 100644 --- a/tmpl/kubernetes/flux/cluster.yaml +++ b/template/templates/kubernetes/cluster.yaml.j2 @@ -8,7 +8,7 @@ spec: interval: 30m ref: branch: main - url: "${BOOTSTRAP_GIT_REPOSITORY}" + url: "https://github.com/{{ bootstrap_github_username }}/{{ bootstrap_github_repository_name }}.git" ignore: | # exclude all /* diff --git a/tmpl/kubernetes/external-dns-secret.sops.yaml b/template/templates/kubernetes/external-dns-secret.sops.yaml.j2 similarity index 68% rename from tmpl/kubernetes/external-dns-secret.sops.yaml rename to template/templates/kubernetes/external-dns-secret.sops.yaml.j2 index fd509728..7d62527d 100644 --- a/tmpl/kubernetes/external-dns-secret.sops.yaml +++ b/template/templates/kubernetes/external-dns-secret.sops.yaml.j2 @@ -5,4 +5,4 @@ metadata: name: external-dns-secret namespace: networking stringData: - api-token: "${BOOTSTRAP_CLOUDFLARE_APITOKEN}" + api-token: "{{ bootstrap_cloudflare_token }}" diff --git a/tmpl/kubernetes/github-webhook-token-secret.sops.yaml b/template/templates/kubernetes/github-webhook-token-secret.sops.yaml.j2 similarity index 68% rename from tmpl/kubernetes/github-webhook-token-secret.sops.yaml rename to template/templates/kubernetes/github-webhook-token-secret.sops.yaml.j2 index 58b3f916..4a63b880 100644 --- a/tmpl/kubernetes/github-webhook-token-secret.sops.yaml +++ b/template/templates/kubernetes/github-webhook-token-secret.sops.yaml.j2 @@ -5,4 +5,4 @@ metadata: name: github-webhook-token-secret namespace: flux-system stringData: - token: "${BOOTSTRAP_FLUX_GITHUB_WEBHOOK_SECRET}" + token: "{{ bootstrap_flux_github_webhook_token }}" diff --git a/tmpl/kubernetes/grafana-admin-secret.sops.yaml b/template/templates/kubernetes/grafana-admin-secret.sops.yaml.j2 similarity index 68% rename from tmpl/kubernetes/grafana-admin-secret.sops.yaml rename to template/templates/kubernetes/grafana-admin-secret.sops.yaml.j2 index f739c21e..faf4db4f 100644 --- a/tmpl/kubernetes/grafana-admin-secret.sops.yaml +++ b/template/templates/kubernetes/grafana-admin-secret.sops.yaml.j2 @@ -6,4 +6,4 @@ metadata: namespace: monitoring stringData: admin-user: admin - admin-password: "${BOOTSTRAP_GRAFANA_ADMIN_PASSWORD}" + admin-password: "{{ bootstrap_grafana_admin_password }}" diff --git a/kubernetes/apps/monitoring/kube-prometheus-stack/app/helmrelease.yaml b/template/templates/kubernetes/kube-prometheus-stack-helmrelease.yaml.j2 similarity index 97% rename from kubernetes/apps/monitoring/kube-prometheus-stack/app/helmrelease.yaml rename to template/templates/kubernetes/kube-prometheus-stack-helmrelease.yaml.j2 index ca386e30..1d12948e 100644 --- a/kubernetes/apps/monitoring/kube-prometheus-stack/app/helmrelease.yaml +++ b/template/templates/kubernetes/kube-prometheus-stack-helmrelease.yaml.j2 @@ -1,3 +1,4 @@ +#jinja2: trim_blocks: True, lstrip_blocks: True --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease @@ -88,7 +89,9 @@ spec: kubeControllerManager: enabled: true endpoints: &cp - - 127.0.0.1 # Replaced by configure + {% for item in bootstrap_hosts.master %} + - {{ item.address }} + {% endfor %} serviceMonitor: metricRelabelings: # Remove duplicate metrics diff --git a/tmpl/kubernetes/weave-gitops-secret.sops.yaml b/template/templates/kubernetes/weave-gitops-secret.sops.yaml.j2 similarity index 61% rename from tmpl/kubernetes/weave-gitops-secret.sops.yaml rename to template/templates/kubernetes/weave-gitops-secret.sops.yaml.j2 index 519e95af..a5bf1f00 100644 --- a/tmpl/kubernetes/weave-gitops-secret.sops.yaml +++ b/template/templates/kubernetes/weave-gitops-secret.sops.yaml.j2 @@ -7,4 +7,4 @@ metadata: type: Opaque stringData: username: admin - password: "${BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD}" + password: "{{ bootstrap_weave_gitops_admin_password | password_hash('bcrypt') }}" diff --git a/template/vars/.gitignore b/template/vars/.gitignore new file mode 100644 index 00000000..5b6b0720 --- /dev/null +++ b/template/vars/.gitignore @@ -0,0 +1 @@ +config.yaml diff --git a/template/vars/config.sample.yaml b/template/vars/config.sample.yaml new file mode 100644 index 00000000..7ea807cb --- /dev/null +++ b/template/vars/config.sample.yaml @@ -0,0 +1,59 @@ +--- +# +# Bootstrap configuration - This file is gitignored +# + +# Github username (e.g. onedr0p) +bootstrap_github_username: +# Github repository (e.g. flux-cluster-template) +bootstrap_github_repository_name: +# Age Public Key (e.g. age15uzrw396e67z9wdzsxzdk7ka0g2gr3l460e0slaea563zll3hdfqwqxdta) +bootstrap_age_public_key: +# Choose your timezone (e.g. America/New_York) +bootstrap_timezone: Etc/UTC +# Email you want to be associated with the ACME account (used for TLS certificates via letsencrypt.org) +bootstrap_acme_email: + +# Flux github webhook token (openssl rand -hex 12) +bootstrap_flux_github_webhook_token: +# Grafana admin password (openssl rand -hex 12) +bootstrap_grafana_admin_password: +# Weave GitOps dashboard password (openssl rand -hex 12) +bootstrap_weave_gitops_admin_password: + +# Cloudflare domain +bootstrap_cloudflare_domain: +# Cloudflare API Token (not API Key) +bootstrap_cloudflare_token: +# Cloudflared Account Tag (cat ~/.cloudflared/*.json | jq -r .AccountTag) +bootstrap_cloudflare_account_tag: +# Cloudflared Tunnel Secret (cat ~/.cloudflared/*.json | jq -r .TunnelSecret) +bootstrap_cloudflare_tunnel_secret: +# Cloudflared Tunnel ID (cat ~/.cloudflared/*.json | jq -r .TunnelID) +bootstrap_cloudflare_tunnel_id: + +# CIDR your nodes are on (e.g. 192.168.1.0/24) +bootstrap_node_cidr: +# Load balancer IP for k8s_gateway, choose an available IP in your nodes network that is not being used +bootstrap_k8s_gateway_addr: +# Load balancer IP for ingress-nginx, choose an available IP in your nodes network that is not being used +bootstrap_ingress_nginx_addr: +# IP address to use with kube-vip, choose an available IP in your nodes network that is not being used +bootstrap_kube_vip_addr: +# Choose your cluster and service cidrs, leave these unchanged unless you know what you are doing +bootstrap_cluster_cidr: 10.42.0.0/16 +bootstrap_service_cidr: 10.43.0.0/16 + +# Node information +bootstrap_hosts: + # Use only 1, 3 or more odd master nodes, recommended is 3 + master: + # - name: kube0 + # address: + # username: + # password: + worker: + # - name: kube1 + # address: + # username: + # password: diff --git a/tmpl/ansible/supplemental.yml b/tmpl/ansible/supplemental.yml deleted file mode 100644 index 042310cd..00000000 --- a/tmpl/ansible/supplemental.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -timezone: "${BOOTSTRAP_TIMEZONE}" -kube_vip_addr: "${BOOTSTRAP_KUBE_VIP_ADDR}" -cluster_cidr: "${BOOTSTRAP_CLUSTER_CIDR}" -service_cidr: "${BOOTSTRAP_SERVICE_CIDR}" diff --git a/tmpl/kubernetes/cloudflared-secret.sops.yaml b/tmpl/kubernetes/cloudflared-secret.sops.yaml deleted file mode 100644 index 7027e757..00000000 --- a/tmpl/kubernetes/cloudflared-secret.sops.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: cloudflared-secret - namespace: networking -stringData: - TUNNEL_ID: "${BOOTSTRAP_CLOUDFLARE_TUNNEL_ID}" - credentials.json: | - { - "AccountTag": "${BOOTSTRAP_CLOUDFLARE_ACCOUNT_TAG}", - "TunnelSecret": "${BOOTSTRAP_CLOUDFLARE_TUNNEL_SECRET}", - "TunnelID": "${BOOTSTRAP_CLOUDFLARE_TUNNEL_ID}" - } diff --git a/tmpl/kubernetes/cluster-secrets.sops.yaml b/tmpl/kubernetes/cluster-secrets.sops.yaml deleted file mode 100644 index db3baf55..00000000 --- a/tmpl/kubernetes/cluster-secrets.sops.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: cluster-secrets - namespace: flux-system -stringData: - SECRET_DOMAIN: "${BOOTSTRAP_CLOUDFLARE_DOMAIN}" - SECRET_ACME_EMAIL: "${BOOTSTRAP_ACME_EMAIL}" - SECRET_CLOUDFLARE_TUNNEL_ID: "${BOOTSTRAP_CLOUDFLARE_TUNNEL_ID}" diff --git a/tmpl/kubernetes/flux/cluster-settings.yaml b/tmpl/kubernetes/flux/cluster-settings.yaml deleted file mode 100644 index 6e156bc8..00000000 --- a/tmpl/kubernetes/flux/cluster-settings.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: cluster-settings - namespace: flux-system -data: - TIMEZONE: "${BOOTSTRAP_TIMEZONE}" - K8S_GATEWAY_ADDR: "${BOOTSTRAP_K8S_GATEWAY_ADDR}" - INGRESS_NGINX_ADDR: "${BOOTSTRAP_INGRESS_NGINX_ADDR}" - KUBE_VIP_ADDR: "${BOOTSTRAP_KUBE_VIP_ADDR}" - CLUSTER_CIDR: "${BOOTSTRAP_CLUSTER_CIDR}" - SERVICE_CIDR: "${BOOTSTRAP_SERVICE_CIDR}"