Skip to content

Commit

Permalink
feat: add talos support (#1192)
Browse files Browse the repository at this point in the history
Signed-off-by: Devin Buhl <devin@buhl.casa>
  • Loading branch information
onedr0p authored Jan 19, 2024
1 parent cec3212 commit 91d8b84
Show file tree
Hide file tree
Showing 33 changed files with 537 additions and 42 deletions.
2 changes: 1 addition & 1 deletion .github/renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@
"matchStrings": [
// Example:
// k3s_release_version: "v1.27.3+k3s1"
"datasource=(?<datasource>\\S+) depName=(?<depName>\\S+)( versioning=(?<versioning>\\S+))?\n.*?\"(?<currentValue>.*)\"\n",
"datasource=(?<datasource>\\S+) depName=(?<depName>\\S+)( versioning=(?<versioning>\\S+))?( extractVersion=(?<extractVersion>\\S+))?\n.*?\"(?<currentValue>.*)\"\n",
// Example:
// - https://github.com/rancher/system-upgrade-controller/releases/download/v0.11.0/crd.yaml
"datasource=(?<datasource>\\S+) depName=(?<depName>\\S+)( versioning=(?<versioning>\\S+))?\n.*?-\\s(.*?)\/(?<currentValue>[^/]+)\/[^/]+\n",
Expand Down
55 changes: 55 additions & 0 deletions .github/tests/config-talos.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
ci_test: true

bootstrap_distribution: talos
bootstrap_github_username: onedr0p
bootstrap_github_repository_name: flux-cluster-template
bootstrap_github_repository_branch: main
bootstrap_age_public_key: $BOOTSTRAP_AGE_PUBLIC_KEY
bootstrap_timezone: Etc/UTC
bootstrap_acme_email: fake
bootstrap_acme_production_enabled: false
bootstrap_flux_github_webhook_token: fake
bootstrap_cloudflare_domain: fake
bootstrap_cloudflare_token: fake
bootstrap_cloudflare_account_tag: fake
bootstrap_cloudflare_tunnel_secret: fake
bootstrap_cloudflare_tunnel_id: fake
bootstrap_node_cidr: 10.10.10.0/24
bootstrap_kube_api_addr: 10.10.10.254
bootstrap_kube_api_hostname: fake
bootstrap_k8s_gateway_addr: 10.10.10.253
bootstrap_external_ingress_addr: 10.10.10.252
bootstrap_internal_ingress_addr: 10.10.10.251
bootstrap_cilium_loadbalancer_mode: dsr
bootstrap_ipv6_enabled: false
bootstrap_cluster_cidr: 10.42.0.0/16
bootstrap_service_cidr: 10.43.0.0/16
bootstrap_local_storage_path: /var/openebs/local
bootstrap_nodes:
master:
- name: k8s-0
address: 10.10.10.100
username: fake
diskSerial: fake
- name: k8s-1
address: 10.10.10.101
username: fake
diskSerial: fake
- name: k8s-2
address: 10.10.10.102
username: fake
diskSerial: fake
worker:
- name: k8s-3
address: 10.10.10.103
username: fake
diskSerial: fake
- name: k8s-4
address: 10.10.10.104
username: fake
diskSerial: fake
- name: k8s-5
address: 10.10.10.105
username: fake
diskSerial: fake
8 changes: 8 additions & 0 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jobs:
- k3s-ipv4
- k3s-ipv6
- k3s-no-kube-vip
- talos
addon-files: ["addons"]
steps:
- name: Checkout
Expand Down Expand Up @@ -112,6 +113,13 @@ jobs:
shell: bash
run: task configure --yes

- name: Run Talos configure
if: ${{ steps.config-env.outputs.distribution == 'talos' }}
shell: bash
run: |
task talos:gensecret --yes
task talos:genconfig
- name: Run Ansible lint
if: ${{ steps.config-env.outputs.distribution == 'k3s' || steps.config-env.outputs.distribution == 'k0s' }}
shell: bash
Expand Down
1 change: 1 addition & 0 deletions .taskfiles/K0s/Taskfile.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
---
# yaml-language-server: $schema=https://taskfile.dev/schema.json
version: "3"

env:
Expand Down
72 changes: 72 additions & 0 deletions .taskfiles/Talos/Taskfile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
# yaml-language-server: $schema=https://taskfile.dev/schema.json
version: "3"

vars:
TALOS_DIR: "{{.ROOT_DIR}}/kubernetes/talos"
TALHELPER_SECRET_FILE: "{{.TALOS_DIR}}/talhelper.sops.yaml"
TALHELPER_CONFIG_FILE: "{{.TALOS_DIR}}/talconfig.yaml"

tasks:

gensecret:
desc: Generate talos secret
prompt: This will overwrite the existing secret... continue?
dir: "{{.TALOS_DIR}}"
cmds:
- talhelper gensecret > {{.TALHELPER_SECRET_FILE}}
- task: :sops:.encrypt-file
vars:
file: "{{.TALHELPER_SECRET_FILE}}"
preconditions:
- { msg: "Missing talhelper config file", sh: "test -f {{.TALHELPER_CONFIG_FILE}}" }

genconfig:
desc: Generate talos config
dir: "{{.TALOS_DIR}}"
cmd: talhelper genconfig
preconditions:
- { msg: "Missing talhelper config file", sh: "test -f {{.TALHELPER_CONFIG_FILE}}" }

apply-config:
desc: Apply talos config on a node
dir: "{{.TALOS_DIR}}"
cmd: talhelper gencommand apply --extra-flags=--insecure | bash

bootstrap:
desc: Bootstrap the talos cluster
dir: "{{.TALOS_DIR}}"
cmd: talhelper gencommand bootstrap | bash

kubeconfig:
desc: Generate talos kubeconfig
prompt: This will overwrite the existing kubeconfig... continue?
dir: "{{.TALOS_DIR}}"
cmd: talosctl kubeconfig {{.ROOT_DIR}} --force

apply-extras:
desc: Apply extras
dir: "{{.TALOS_DIR}}"
cmds:
- kubectl --kubeconfig {{.KUBECONFIG_FILE}} kustomize --enable-helm ./cni | kubectl apply --kubeconfig {{.KUBECONFIG_FILE}} --server-side --filename -
- kubectl --kubeconfig {{.KUBECONFIG_FILE}} kustomize --enable-helm ./kubelet-csr-approver | kubectl apply --kubeconfig {{.KUBECONFIG_FILE}} --server-side --filename -
preconditions:
- { msg: "Missing kubeconfig", sh: "test -f {{.KUBECONFIG_FILE}}" }

upgrade-talos:
desc: Upgrade talos on a node
cmd: talosctl --nodes {{.node}} upgrade --image {{.image}} --preserve=true --reboot-mode=powercycle
vars:
image: '{{ or .image (fail "Argument (image) is required") }}'
node: '{{ or .node (fail "Argument (node) is required") }}'
preconditions:
- { msg: "Node not found", sh: "talosctl --nodes {{.node}} get machineconfig" }

upgrade-k8s:
desc: Upgrade k8s on a node
cmd: talosctl --nodes {{.node}} upgrade-k8s --to {{.to}}
vars:
node: '{{ or .node (fail "Argument (node) is required") }}'
to: '{{ or .to (fail "Argument (to) is required") }}'
preconditions:
- { msg: "Node not found", sh: "talosctl --nodes {{.node}} get machineconfig" }
1 change: 1 addition & 0 deletions .taskfiles/Workstation/Archfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ moreutils
sops
stern-bin
talhelper-bin
talosctl
2 changes: 2 additions & 0 deletions .taskfiles/Workstation/Brewfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
tap "fluxcd/tap"
tap "go-task/tap"
tap "k0sproject/tap"
tap "siderolabs/talos"
brew "age"
brew "cloudflared"
brew "direnv"
Expand All @@ -16,4 +17,5 @@ brew "moreutils"
brew "sops"
brew "stern"
brew "talhelper"
brew "talosctl"
brew "yq"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Deploy a Kubernetes cluster backed by Flux

Welcome to my highly opinionated template for deploying a single Kubernetes ([k3s](https://k3s.io) or [k0s](https://github.com/k0sproject/k0s)) cluster with [Ansible](https://www.ansible.com) and using [Flux](https://toolkit.fluxcd.io) to manage its state.
Welcome to my opinionated and extendable template for deploying a single Kubernetes cluster with [k0s](https://github.com/k0sproject/k0s), [k3s](https://k3s.io) or [Talos](https://github.com/siderolabs/talos) backed by [Flux](https://fluxcd.io/flux/) to manage its state.

## 👋 Introduction

Expand Down
1 change: 1 addition & 0 deletions Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ includes:
repository:
aliases: ["repo"]
taskfile: .taskfiles/Repository/Taskfile.yaml
talos: .taskfiles/Talos/Taskfile.yaml
sops: .taskfiles/Sops/Taskfile.yaml
workstation: .taskfiles/Workstation/Taskfile.yaml

Expand Down
15 changes: 11 additions & 4 deletions bootstrap/tasks/validation/cli.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
- name: Check if required CLI tools are present
ansible.builtin.shell: |
command -v {{ item }} >/dev/null 2>&1
ansible.builtin.shell: command -v {{ item }} >/dev/null 2>&1
loop: ["age", "cloudflared", "flux", "sops", "jq", "kubeconform", "kustomize"]
changed_when: false
check_mode: false
Expand All @@ -10,10 +9,18 @@

- name: Check if required CLI tools are present for k0s
when: bootstrap_distribution == "k0s"
ansible.builtin.shell: |
command -v {{ item }} >/dev/null 2>&1
ansible.builtin.shell: command -v {{ item }} >/dev/null 2>&1
loop: ["k0sctl"]
changed_when: false
check_mode: false
register: result
failed_when: result.rc != 0 and result.rc != 127

- name: Check if required CLI tools are present for talos
when: bootstrap_distribution == "talos"
ansible.builtin.shell: command -v {{ item }} >/dev/null 2>&1
loop: ["talhelper", "talosctl"]
changed_when: false
check_mode: false
register: result
failed_when: result.rc != 0 and result.rc != 127
28 changes: 15 additions & 13 deletions bootstrap/tasks/validation/net.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
---
- name: Set reachable address
ansible.builtin.set_fact:
current_address: "{{ item.external_address | default(item.address) }}"
loop: "{{ bootstrap_nodes.master + bootstrap_nodes.worker | default([]) }}"
loop_control:
label: "{{ item.address }}"

- name: Check if master node count is odd
ansible.builtin.assert:
that:
Expand Down Expand Up @@ -161,7 +154,6 @@
fail_msg: Node address {{ item.address }} is not within {{ bootstrap_node_cidr }}.
quiet: true
loop: "{{ bootstrap_nodes.master + bootstrap_nodes.worker | default([]) }}"
when: item.external_address is not defined
loop_control:
label: "{{ item.address }}"

Expand Down Expand Up @@ -193,14 +185,24 @@
fail_msg: All node names are not unique.
quiet: true

- name: Check if nodes SSH ports are reachable
when: not ci_test | default(false)
- name: Check if SSH ports are reachable
when: (not ci_test | default(false)) and (not bootstrap_distribution == "talos")
ansible.builtin.wait_for:
host: "{{ current_address }}"
host: "{{ item.address }}"
port: 22
search_regex: OpenSSH
timeout: 10
connection: local
loop: "{{ bootstrap_nodes.master + bootstrap_nodes.worker | default([]) }}"
loop_control:
label: "{{ current_address }}"
label: "{{ item.address }}"

- name: Check if Talos ports are reachable
when: (not ci_test | default(false)) and (bootstrap_distribution == "talos")
ansible.builtin.wait_for:
host: "{{ item.address }}"
port: 50000
timeout: 10
connection: local
loop: "{{ bootstrap_nodes.master + bootstrap_nodes.worker | default([]) }}"
loop_control:
label: "{{ item.address }}"
2 changes: 1 addition & 1 deletion bootstrap/tasks/validation/vars.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

- name: Check if bootstrap distribution is valid
ansible.builtin.assert:
that: bootstrap_distribution in ['k0s', 'k3s']
that: bootstrap_distribution in ['k0s', 'k3s', 'talos']
success_msg: Distribution {{ bootstrap_distribution }} is valid
fail_msg: Distribution {{ bootstrap_distribution }} is not valid

Expand Down
5 changes: 5 additions & 0 deletions bootstrap/templates/.sops.yaml.j2
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
---
creation_rules:
- # IMPORTANT: This rule MUST be above the others
path_regex: talos/.*\.sops\.ya?ml
key_groups:
- age:
- "#{ bootstrap_age_public_key }#"
- path_regex: kubernetes/.*\.sops\.ya?ml
encrypted_regex: "^(data|stringData)$"
key_groups:
Expand Down
8 changes: 0 additions & 8 deletions bootstrap/templates/ansible/inventory/hosts.yaml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,15 @@ kubernetes:
#% for item in bootstrap_nodes.master %#
"#{ item.name }#":
ansible_user: "#{ item.username }#"
#% if item.external_address is defined %#
ansible_host: "#{ item.external_address }#"
#% else %#
ansible_host: "#{ item.address }#"
#% endif %#
#% endfor %#
#% if bootstrap_nodes.worker | default([]) | length > 0 %#
worker:
hosts:
#% for item in bootstrap_nodes.worker %#
"#{ item.name }#":
ansible_user: "#{ item.username }#"
#% if item.external_address is defined %#
ansible_host: "#{ item.external_address }#"
#% else %#
ansible_host: "#{ item.address }#"
#% endif %#
#% endfor %#
#% endif %#
#% endif %#
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#% if bootstrap_distribution == "talos" %#
---
apiVersion: helm.toolkit.fluxcd.io/v2beta2
kind: HelmRelease
metadata:
name: kubelet-csr-approver
spec:
interval: 30m
chart:
spec:
chart: kubelet-csr-approver
version: 1.0.6
sourceRef:
kind: HelmRepository
name: postfinance
namespace: flux-system
install:
remediation:
retries: 3
upgrade:
cleanupOnFail: true
remediation:
retries: 3
uninstall:
keepHistory: false
values:
providerRegex: |
^k(m|w)\d\d?$
#% endif %#
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#% if bootstrap_distribution == "talos" %#
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./helmrelease.yaml
#% endif %#
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#% if bootstrap_distribution == "talos" %#
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: &app kubelet-csr-approver
namespace: flux-system
spec:
targetNamespace: kube-system
commonMetadata:
labels:
app.kubernetes.io/name: *app
path: ./kubernetes/apps/kube-system/kubelet-csr-approver/app
prune: false # never should be deleted
sourceRef:
kind: GitRepository
name: home-kubernetes
wait: false
interval: 30m
retryInterval: 1m
timeout: 5m
#% endif %#
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ resources:
#% if bootstrap_distribution == "k3s" %#
- ./coredns/ks.yaml
#% endif %#
#% if bootstrap_distribution == "talos" %#
- ./kubelet-csr-approver/ks.yaml
#% endif %#
- ./metrics-server/ks.yaml
#% if bootstrap_distribution == "k0s" and spegel.enabled | default(false) %#
#% if (bootstrap_distribution == "k0s" or bootstrap_distribution == "talos") and spegel.enabled | default(false) %#
- ./spegel/ks.yaml
#% endif %#
Loading

0 comments on commit 91d8b84

Please sign in to comment.