Compare commits
1 Commits
feature/ru
...
6df2665a22
| Author | SHA1 | Date | |
|---|---|---|---|
|
6df2665a22
|
@@ -5,4 +5,4 @@ indent_style = tab
|
||||
|
||||
[*.yaml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
indent_size = 4
|
||||
|
||||
4
.git-crypt/.gitattributes
vendored
4
.git-crypt/.gitattributes
vendored
@@ -1,4 +0,0 @@
|
||||
# Do not edit this file. To specify the files to encrypt, create your own
|
||||
# .gitattributes file in the directory where your files are.
|
||||
* !filter !diff
|
||||
*.gpg binary
|
||||
Binary file not shown.
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,2 +0,0 @@
|
||||
*.key filter=git-crypt diff=git-crypt
|
||||
secrets.yaml filter=git-crypt diff=git-crypt
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,2 @@
|
||||
.ipxe/
|
||||
rendered/
|
||||
configs/
|
||||
*.egg-info
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
default_install_hook_types:
|
||||
- pre-commit
|
||||
- commit-msg
|
||||
|
||||
default_stages:
|
||||
- pre-commit
|
||||
|
||||
repos:
|
||||
- repo: meta
|
||||
hooks:
|
||||
- id: check-hooks-apply
|
||||
- id: check-useless-excludes
|
||||
|
||||
- repo: builtin
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
- id: check-toml
|
||||
- id: check-added-large-files
|
||||
- id: check-merge-conflict
|
||||
- id: check-executables-have-shebangs
|
||||
|
||||
- repo: https://github.com/jmlrt/check-yamlschema
|
||||
rev: v0.0.7
|
||||
hooks:
|
||||
- id: check-yamlschema
|
||||
files: ^patches/.*\.yaml$
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: v3.1.0
|
||||
hooks:
|
||||
- id: prettier
|
||||
|
||||
- repo: https://github.com/crate-ci/typos
|
||||
rev: v1.40.0
|
||||
hooks:
|
||||
- id: typos
|
||||
|
||||
- repo: https://github.com/sirwart/ripsecrets
|
||||
rev: v0.1.11
|
||||
hooks:
|
||||
- id: ripsecrets-system
|
||||
|
||||
- repo: https://github.com/crate-ci/committed
|
||||
rev: v1.1.8
|
||||
hooks:
|
||||
- id: committed
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"bracketSpacing": false
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
secrets.yaml
|
||||
*.key
|
||||
73
README.md
73
README.md
@@ -1,73 +0,0 @@
|
||||
# Talos
|
||||
|
||||
To decrypt the secrets file:
|
||||
|
||||
```
|
||||
git-crypt unlock
|
||||
```
|
||||
|
||||
Generate the config files:
|
||||
|
||||
```bash
|
||||
talosctl gen config <cluster_name> https://<controlplane_ip>:6443 -f \
|
||||
--with-secrets secrets.yaml \
|
||||
--config-patch @<path_to_patch> \
|
||||
--config-patch-control-plane @<path_to_controlplane_patch> \
|
||||
--install-image factory.talos.dev/metal-installer/<schematic_id>:<version> \
|
||||
-o configs
|
||||
```
|
||||
|
||||
Set TALOSCONFIG:
|
||||
|
||||
```bash
|
||||
export TALOSCONFIG=$(realpath configs/talosconfig)
|
||||
```
|
||||
|
||||
Apply the configs for each node, use worker.yaml for worker nodes:
|
||||
|
||||
```bash
|
||||
talosctl apply-config --insecure --nodes <node_id> --file configs/controlplane.yaml
|
||||
```
|
||||
|
||||
Set endpoint to one of the nodes:
|
||||
|
||||
```bash
|
||||
talosctl config endpoint <node_ip>
|
||||
```
|
||||
|
||||
Bootstrap Kubernetes:
|
||||
|
||||
```bash
|
||||
talosctl -n <node_id> bootstrap
|
||||
```
|
||||
|
||||
Set endpoint to control plane:
|
||||
|
||||
```bash
|
||||
talosctl config endpoint <controlplane_ip>
|
||||
```
|
||||
|
||||
Get kubeconfig and set KUBECONFIG:
|
||||
|
||||
```bash
|
||||
talosctl -n 192.168.1.100 kubeconfig $PWD/configs/kubeconfig
|
||||
export KUBECONFIG=$(realpath configs/kubeconfig)
|
||||
```
|
||||
|
||||
For applying updated config to node:
|
||||
|
||||
```bash
|
||||
talosctl apply-config --nodes <node_id> --file configs/controlplane.yaml
|
||||
```
|
||||
|
||||
Upgrading talos or changing the schematic:
|
||||
|
||||
```bash
|
||||
talosctl upgrade --nodes <node_id> --image factory.talos.dev/metal-installer/<schematic_id>:<version>
|
||||
```
|
||||
|
||||
To upgrade kubernetes or inline manifests, first apply the updated controlplane configs, then run:
|
||||
|
||||
```bash
|
||||
talosctl upgrade-k8s
|
||||
```
|
||||
@@ -1,2 +0,0 @@
|
||||
style = "conventional"
|
||||
ignore_author_re = "Flux"
|
||||
2
config.yaml
Normal file
2
config.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
dhcp:
|
||||
tftpIp: 10.0.0.3
|
||||
8
nodes/_defaults.yaml
Normal file
8
nodes/_defaults.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
schematicID: !schematic "_schematic.yaml"
|
||||
arch: amd64
|
||||
talosVersion: v1.11.3
|
||||
kernelArgs: talos.platform=metal console=tty0 init_on_alloc=1 slab_nomerge pti=on consoleblank=0 nvme_core.io_timeout=4294967295 printk.devkmsg=on selinux=1 lockdown=confidentiality
|
||||
dns0: 1.1.1.1
|
||||
dns1: 8.8.8.8
|
||||
ntp: nl.pool.ntp.org
|
||||
install: false
|
||||
6
nodes/_schematic.yaml
Normal file
6
nodes/_schematic.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
customization:
|
||||
systemExtensions:
|
||||
officialExtensions:
|
||||
- siderolabs/iscsi-tools
|
||||
- siderolabs/util-linux-tools
|
||||
- siderolabs/intel-ucode
|
||||
3
nodes/production/_defaults.yaml
Normal file
3
nodes/production/_defaults.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
netmask: 255.255.252.0
|
||||
gateway: 10.0.0.1
|
||||
install: true
|
||||
3
nodes/production/helios.yaml
Normal file
3
nodes/production/helios.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
serial: 5CZ7NX2
|
||||
interface: enp2s0
|
||||
ip: 10.0.0.202
|
||||
3
nodes/production/hyperion.yaml
Normal file
3
nodes/production/hyperion.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
serial: F3PKRH2
|
||||
interface: enp3s0
|
||||
ip: 10.0.0.201
|
||||
3
nodes/production/selene.yaml
Normal file
3
nodes/production/selene.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
serial: J33CHY2
|
||||
interface: enp2s0
|
||||
ip: 10.0.0.203
|
||||
2
nodes/vm/_defaults.yaml
Normal file
2
nodes/vm/_defaults.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
netmask: 255.255.255.0
|
||||
gateway: 192.168.1.1
|
||||
4
nodes/vm/talos-vm.yaml
Normal file
4
nodes/vm/talos-vm.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
serial: talos-vm
|
||||
interface: enp1s0
|
||||
ip: 192.168.1.2
|
||||
install: true
|
||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
PyYAML==6.0.3
|
||||
requests==2.32.5
|
||||
@@ -1,53 +0,0 @@
|
||||
# yaml-language-server: $schema=../../schemas/cluster.json
|
||||
version:
|
||||
kubernetes: 1.34.1
|
||||
talos: 1.11.3
|
||||
|
||||
base:
|
||||
kernelArgs:
|
||||
- talos.platform=metal
|
||||
- console=tty0
|
||||
- init_on_alloc=1
|
||||
- init_on_free=1
|
||||
- slab_nomerge
|
||||
- pti=on
|
||||
- consoleblank=0
|
||||
- nvme_core.io_timeout=4294967295
|
||||
- printk.devkmsg=on
|
||||
- selinux=1
|
||||
- lockdown=confidentiality
|
||||
patches:
|
||||
all:
|
||||
- system/hostname.yaml
|
||||
- system/install-disk.yaml
|
||||
- system/network.yaml
|
||||
- networking/vip.yaml
|
||||
- networking/tailscale.yaml
|
||||
- networking/cilium.yaml
|
||||
- spegel.yaml
|
||||
- storage/longhorn.yaml
|
||||
- storage/longhorn/user-volume.yaml
|
||||
- storage/local-path-provisioner/user-volume.yaml
|
||||
- storage/limit-ephemeral.yaml
|
||||
- metrics/all.yaml
|
||||
controlPlane:
|
||||
- system/allow-control-plane-workloads.yaml
|
||||
- sops.yaml
|
||||
- flux/cluster-variables.yaml
|
||||
- metrics/control-plane.yaml
|
||||
- networking/gateway-api.yaml
|
||||
default:
|
||||
arch: amd64
|
||||
schematic: default.yaml
|
||||
network:
|
||||
dns:
|
||||
- 1.1.1.1
|
||||
- 8.8.8.8
|
||||
tailscale:
|
||||
server: https://headscale.huizinga.dev
|
||||
authKey:
|
||||
file: tailscale.key
|
||||
advertiseRoutes: true
|
||||
ntp: nl.pool.ntp.org
|
||||
install:
|
||||
auto: true
|
||||
@@ -1,16 +0,0 @@
|
||||
# yaml-language-server: $schema=../../schemas/cluster.json
|
||||
clusterEnv: staging
|
||||
controlPlaneIp: 192.168.1.100
|
||||
secretsFile: testing/secrets.yaml
|
||||
nodes:
|
||||
- testing/talos-vm
|
||||
|
||||
default:
|
||||
network:
|
||||
interface: enp1s0
|
||||
netmask: 255.255.255.0
|
||||
gateway: 192.168.1.1
|
||||
sops:
|
||||
file: testing/age.key
|
||||
install:
|
||||
disk: /dev/vda
|
||||
@@ -1,17 +0,0 @@
|
||||
# yaml-language-server: $schema=../../schemas/cluster.json
|
||||
clusterEnv: production
|
||||
controlPlaneIp: 10.0.2.1
|
||||
secretsFile: titan/secrets.yaml
|
||||
nodes:
|
||||
- titan/hyperion
|
||||
- titan/helios
|
||||
- titan/selene
|
||||
|
||||
default:
|
||||
network:
|
||||
netmask: 255.255.252.0
|
||||
gateway: 10.0.0.1
|
||||
sops:
|
||||
file: titan/age.key
|
||||
install:
|
||||
disk: /dev/sda
|
||||
@@ -1,6 +0,0 @@
|
||||
# yaml-language-server: $schema=../../../schemas/node.json
|
||||
type: controlPlane
|
||||
install:
|
||||
serial: talos-vm
|
||||
network:
|
||||
ip: 192.168.1.2
|
||||
@@ -1,7 +0,0 @@
|
||||
# yaml-language-server: $schema=../../../schemas/node.json
|
||||
type: controlPlane
|
||||
install:
|
||||
serial: 5CZ7NX2
|
||||
network:
|
||||
interface: enp2s0
|
||||
ip: 10.0.0.202
|
||||
@@ -1,7 +0,0 @@
|
||||
# yaml-language-server: $schema=../../../schemas/node.json
|
||||
type: controlPlane
|
||||
install:
|
||||
serial: F3PKRH2
|
||||
network:
|
||||
interface: enp3s0
|
||||
ip: 10.0.0.201
|
||||
@@ -1,7 +0,0 @@
|
||||
# yaml-language-server: $schema=../../../schemas/node.json
|
||||
type: controlPlane
|
||||
install:
|
||||
serial: J33CHY2
|
||||
network:
|
||||
interface: enp2s0
|
||||
ip: 10.0.0.203
|
||||
@@ -1,18 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
cluster:
|
||||
inlineManifests:
|
||||
- name: cluster-variables
|
||||
contents: |
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: flux-system
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cluster-variables
|
||||
namespace: flux-system
|
||||
data:
|
||||
cluster_env: {{ cluster.clusterEnv }}
|
||||
@@ -1,5 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
machine:
|
||||
kubelet:
|
||||
extraArgs:
|
||||
rotate-server-certificates: "true"
|
||||
@@ -1,5 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
cluster:
|
||||
extraManifests:
|
||||
- https://raw.githubusercontent.com/alex1989hu/kubelet-serving-cert-approver/main/deploy/standalone-install.yaml
|
||||
- https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
|
||||
@@ -1,12 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
machine:
|
||||
features:
|
||||
hostDNS:
|
||||
# This option is enabled by default and causes issues with cilium
|
||||
forwardKubeDNSToHost: false
|
||||
cluster:
|
||||
network:
|
||||
cni:
|
||||
name: none
|
||||
proxy:
|
||||
disabled: true
|
||||
@@ -1,4 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
cluster:
|
||||
extraManifests:
|
||||
- https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/standard-install.yaml
|
||||
@@ -1,8 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
apiVersion: v1alpha1
|
||||
kind: ExtensionServiceConfig
|
||||
name: tailscale
|
||||
environment:
|
||||
- TS_AUTHKEY={{ node.network.tailscale.authKey }}
|
||||
- TS_EXTRA_ARGS={% if node.network.tailscale.server %}--login-server {{ node.network.tailscale.server }} {% endif %}--advertise-tags=tag:cluster-{{ cluster.name }}
|
||||
- TS_ROUTES={% if node.network.tailscale.advertiseRoutes %}{{node.network.ip}}/{{ node.network.netmask | to_prefix }}{% endif %}
|
||||
@@ -1,7 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
machine:
|
||||
network:
|
||||
interfaces:
|
||||
- interface: "{{node.network.interface}}"
|
||||
vip:
|
||||
ip: "{{cluster.controlPlaneIp}}"
|
||||
@@ -1,18 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
cluster:
|
||||
inlineManifests:
|
||||
- name: sops-key
|
||||
contents: |
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: flux-system
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: sops-gpg
|
||||
namespace: flux-system
|
||||
data:
|
||||
age.agekey: |
|
||||
{{ node.sops | indent(6*2) }}
|
||||
@@ -1,8 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
machine:
|
||||
files:
|
||||
- path: /etc/cri/conf.d/20-customization.part
|
||||
op: create
|
||||
content: |
|
||||
[plugins."io.containerd.cri.v1.images"]
|
||||
discard_unpacked_layers = false
|
||||
@@ -1,6 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
apiVersion: v1alpha1
|
||||
kind: VolumeConfig
|
||||
name: EPHEMERAL
|
||||
provisioning:
|
||||
maxSize: 30GB
|
||||
@@ -1,9 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
apiVersion: v1alpha1
|
||||
kind: UserVolumeConfig
|
||||
name: local-path-provisioner
|
||||
provisioning:
|
||||
diskSelector:
|
||||
match: system_disk
|
||||
grow: true
|
||||
maxSize: 10GB
|
||||
@@ -1,11 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
machine:
|
||||
kubelet:
|
||||
extraMounts:
|
||||
- destination: /var/lib/longhorn
|
||||
type: bind
|
||||
source: /var/lib/longhorn
|
||||
options:
|
||||
- bind
|
||||
- rshared
|
||||
- rw
|
||||
@@ -1,9 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
apiVersion: v1alpha1
|
||||
kind: UserVolumeConfig
|
||||
name: longhorn
|
||||
provisioning:
|
||||
diskSelector:
|
||||
match: system_disk
|
||||
grow: true
|
||||
maxSize: 2000GB
|
||||
@@ -1,17 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
machine:
|
||||
# This is only needed on nodes that will have storage
|
||||
sysctls:
|
||||
vm.nr_hugepages: "1024"
|
||||
nodeLabels:
|
||||
openebs.io/engine: mayastor
|
||||
# This is needed on ALL nodes
|
||||
kubelet:
|
||||
extraMounts:
|
||||
- destination: /var/local
|
||||
type: bind
|
||||
source: /var/local
|
||||
options:
|
||||
- bind
|
||||
- rshared
|
||||
- rw
|
||||
@@ -1,3 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
cluster:
|
||||
allowSchedulingOnControlPlanes: true
|
||||
@@ -1,4 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
machine:
|
||||
network:
|
||||
hostname: "{{node.hostname}}"
|
||||
@@ -1,4 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
machine:
|
||||
install:
|
||||
disk: "{{node.install.disk}}"
|
||||
@@ -1,11 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.11/website/content/v1.11/schemas/config.schema.json
|
||||
machine:
|
||||
network:
|
||||
interfaces:
|
||||
- interface: "{{node.network.interface}}"
|
||||
dhcp: false
|
||||
addresses:
|
||||
- "{{node.network.ip}}"
|
||||
routes:
|
||||
- network: 0.0.0.0/0
|
||||
gateway: "{{node.network.gateway}}"
|
||||
@@ -1,8 +0,0 @@
|
||||
customization:
|
||||
systemExtensions:
|
||||
officialExtensions:
|
||||
- siderolabs/iscsi-tools
|
||||
- siderolabs/util-linux-tools
|
||||
- siderolabs/intel-ucode
|
||||
- siderolabs/i915
|
||||
- siderolabs/tailscale
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,23 +1,25 @@
|
||||
{% set httpUrl = "http://192.168.1.1:8000" -%}
|
||||
#!ipxe
|
||||
|
||||
dhcp
|
||||
|
||||
echo Starting ${serial}
|
||||
|
||||
:start
|
||||
goto node_${serial} || exit
|
||||
# Is a known serial is set, execute that
|
||||
# If an unknown serial is set, exit
|
||||
# If no serial is set, ask the user
|
||||
goto node_${serial} || shell
|
||||
# Default behavior (non install mode) is to exit iPXE script
|
||||
|
||||
{% for cluster in clusters%}
|
||||
{% for node in cluster.nodes %}
|
||||
{%- if node.install.serial -%}
|
||||
# {{ cluster.name }}/{{ node.hostname }}
|
||||
:node_{{ node.install.serial }}
|
||||
{% set ipArg = "ip=" ~ [node.network.ip, "" , node.network.gateway, node.network.netmask, node.hostname, node.network.interface, "", node.network.dns[0], node.network.dns[1], node.ntp]|join(":") -%}
|
||||
{{ range datasource "nodes" }}
|
||||
{{- if .install }}
|
||||
# {{ .filename }}
|
||||
:node_{{ .serial }}
|
||||
{{- $ipArg := printf "ip=%s::%s:%s:%s:%s::%s:%s:%s" .ip .gateway .netmask .hostname .interface .dns0 .dns1 .ntp }}
|
||||
{{- $kernelArgs := printf "%s %s" $ipArg .kernelArgs }}
|
||||
imgfree
|
||||
kernel https://pxe.factory.talos.dev/image/{{ node.schematic }}/v{{ cluster.version.talos }}/kernel-{{ node.arch }} {{ ipArg }} {{ node.kernelArgs|join(" ") }} {% if node.install.auto %}talos.config={{httpUrl}}/configs/{{cluster.name}}/{{node.hostname}}.yaml{% endif +%}
|
||||
initrd https://pxe.factory.talos.dev/image/{{ node.schematic }}/v{{ cluster.version.talos }}/initramfs-{{ node.arch }}.xz
|
||||
kernel https://pxe.factory.talos.dev/image/{{ .schematicID }}/{{ .talosVersion }}/kernel-{{ .arch }} {{ $kernelArgs }}
|
||||
initrd https://pxe.factory.talos.dev/image/{{ .schematicID }}/{{ .talosVersion }}/initramfs-{{ .arch }}.xz
|
||||
boot
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% set tftpIp = "192.168.1.1" -%}
|
||||
{{ $tftpIp := (ds "config").dhcp.tftpIp -}}
|
||||
|
||||
enable-tftp
|
||||
tftp-root=/tftproot
|
||||
@@ -9,9 +9,9 @@ dhcp-vendorclass=UEFI,PXEClient:Arch:00007
|
||||
dhcp-vendorclass=UEFI64,PXEClient:Arch:00009
|
||||
|
||||
# 1st stage: pxe rom boot on ipxe
|
||||
dhcp-boot=net:BIOS,ipxe.pxe,{{ tftpIp }},{{ tftpIp }}
|
||||
dhcp-boot=net:UEFI,ipxe.efi,{{ tftpIp }},{{ tftpIp }}
|
||||
dhcp-boot=net:UEFI64,ipxe.efi,{{ tftpIp }},{{ tftpIp }}
|
||||
dhcp-boot=net:BIOS,ipxe.pxe,{{ $tftpIp }},{{ $tftpIp }}
|
||||
dhcp-boot=net:UEFI,ipxe.efi,{{ $tftpIp }},{{ $tftpIp }}
|
||||
dhcp-boot=net:UEFI64,ipxe.efi,{{ $tftpIp }},{{ $tftpIp }}
|
||||
|
||||
# Based on logic in https://gist.github.com/robinsmidsrod/4008017
|
||||
# iPXE sends a 175 option, checking suboptions
|
||||
@@ -30,11 +30,11 @@ tag-if=set:ipxe-ok,tag:ipxe-http,tag:ipxe-https
|
||||
|
||||
# these create option 43 cruft, which is required in proxy mode
|
||||
# TFTP IP is required on all dhcp-boot lines (unless dnsmasq itself acts as tftp server?)
|
||||
pxe-service=tag:!ipxe-ok,X86PC,PXE,undionly.kpxe,{{ tftpIp }}
|
||||
pxe-service=tag:!ipxe-ok,IA32_EFI,PXE,snponlyx32.efi,{{ tftpIp }}
|
||||
pxe-service=tag:!ipxe-ok,BC_EFI,PXE,snponly.efi,{{ tftpIp }}
|
||||
pxe-service=tag:!ipxe-ok,X86-64_EFI,PXE,snponly.efi,{{ tftpIp }}
|
||||
pxe-service=tag:!ipxe-ok,X86PC,PXE,undionly.kpxe,{{ $tftpIp }}
|
||||
pxe-service=tag:!ipxe-ok,IA32_EFI,PXE,snponlyx32.efi,{{ $tftpIp }}
|
||||
pxe-service=tag:!ipxe-ok,BC_EFI,PXE,snponly.efi,{{ $tftpIp }}
|
||||
pxe-service=tag:!ipxe-ok,X86-64_EFI,PXE,snponly.efi,{{ $tftpIp }}
|
||||
|
||||
# later match overrides previous, keep ipxe script last
|
||||
# server address must be non zero, but can be anything as long as iPXE script is not fetched over TFTP
|
||||
dhcp-boot=tag:ipxe-ok,boot.ipxe,,{{ tftpIp }}
|
||||
dhcp-boot=tag:ipxe-ok,boot.ipxe,,{{ $tftpIp }}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
CONFIGS={{ root }}/configs
|
||||
|
||||
TALOSCONFIG=${CONFIGS}/talosconfig
|
||||
rm -f ${CONFIGS}
|
||||
|
||||
# Generate the configuration for each node
|
||||
{% for cluster in clusters %}
|
||||
{% for node in cluster.nodes -%}
|
||||
talosctl gen config {{ cluster.name }} https://{{ cluster.controlPlaneIp }}:6443 -f \
|
||||
--with-secrets {{ cluster.secretsFile }} \
|
||||
--talos-version v{{ cluster.version.talos }} \
|
||||
--kubernetes-version v{{ cluster.version.kubernetes }} \
|
||||
--output-types {{ node.type }} \
|
||||
--install-image factory.talos.dev/metal-installer/{{ node.schematic }}:v{{ cluster.version.talos }} \
|
||||
{% for patch in node.patches.all -%}
|
||||
{# The double call to tojson is needed to properly escape the patch (object -> json -> string) -#}
|
||||
--config-patch {{ patch|tojson|tojson }} \
|
||||
{% endfor -%}
|
||||
{% for patch in node.patches.controlPlane -%}
|
||||
--config-patch-control-plane {{ patch|tojson|tojson }} \
|
||||
{% endfor -%}
|
||||
--with-docs=false \
|
||||
--with-examples=false \
|
||||
-o ${CONFIGS}/{{ cluster.name }}/{{ node.hostname }}.yaml
|
||||
{% endfor %}
|
||||
|
||||
# Generate the talosconfig file for each cluster
|
||||
talosctl gen config {{ cluster.name }} https://{{ cluster.controlPlaneIp }}:6443 -f \
|
||||
--with-secrets {{ cluster.secretsFile }} \
|
||||
--output-types talosconfig \
|
||||
-o ${CONFIGS}/{{ cluster.name }}/talosconfig
|
||||
|
||||
# Create merged talosconfig
|
||||
talosctl config --talosconfig=${CONFIGS}/{{ cluster.name }}/talosconfig endpoint {{ cluster.controlPlaneIp }}
|
||||
talosctl config --talosconfig=${TALOSCONFIG} merge ${CONFIGS}/{{ cluster.name }}/talosconfig
|
||||
{% endfor %}
|
||||
@@ -1,2 +0,0 @@
|
||||
export TALOSCONFIG={{ root }}/configs/talosconfig
|
||||
export KUBECONFIG={{ clusters|map(attribute='name')|kubeconfig|join(":") }}
|
||||
96
tools/merge
Executable file
96
tools/merge
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Adapted from: https://enix.io/en/blog/pxe-talos/
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import json
|
||||
import pathlib
|
||||
|
||||
import requests
|
||||
import yaml
|
||||
|
||||
|
||||
@functools.cache
|
||||
def get_schematic_id(schematic: str):
|
||||
"""Lookup the schematic id associated with a given schematic"""
|
||||
r = requests.post("https://factory.talos.dev/schematics", data=schematic)
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
return data["id"]
|
||||
|
||||
|
||||
def schematic_constructor(directory: pathlib.Path):
|
||||
"""Load specified schematic file and get the assocatied schematic id"""
|
||||
|
||||
def constructor(loader: yaml.SafeLoader, node: yaml.nodes.ScalarNode):
|
||||
filename = str(loader.construct_scalar(node))
|
||||
try:
|
||||
schematic = directory.joinpath(filename).read_text()
|
||||
return get_schematic_id(schematic)
|
||||
except Exception:
|
||||
raise yaml.MarkedYAMLError("Failed to load schematic", node.start_mark)
|
||||
|
||||
return constructor
|
||||
|
||||
|
||||
def get_loader(directory: pathlib.Path):
|
||||
"""Add special constructors to yaml loader"""
|
||||
loader = yaml.SafeLoader
|
||||
loader.add_constructor("!schematic", schematic_constructor(directory))
|
||||
|
||||
return loader
|
||||
|
||||
|
||||
@functools.cache
|
||||
def get_defaults(directory: pathlib.Path, root: pathlib.Path):
|
||||
"""Compute the defaults from the provided directory and parents."""
|
||||
try:
|
||||
with open(directory.joinpath("_defaults.yaml")) as fyaml:
|
||||
yml_data = yaml.load(fyaml, Loader=get_loader(directory))
|
||||
except OSError:
|
||||
yml_data = {}
|
||||
|
||||
# Stop recursion when reaching root directory
|
||||
if directory != root:
|
||||
return get_defaults(directory.parent, root) | yml_data
|
||||
else:
|
||||
return yml_data
|
||||
|
||||
|
||||
def walk_files(root: pathlib.Path):
|
||||
"""Get all files that do not start with and underscore"""
|
||||
for dirpath, _dirnames, filenames in root.walk():
|
||||
for fn in filenames:
|
||||
if not fn.startswith("_"):
|
||||
yield dirpath.joinpath(fn)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("directory", type=pathlib.Path)
|
||||
parser.add_argument("-f", "--filter")
|
||||
args = parser.parse_args()
|
||||
|
||||
data = []
|
||||
for fullname in walk_files(args.directory):
|
||||
filename = (
|
||||
str(fullname.relative_to(args.directory).parent) + "/" + fullname.stem
|
||||
)
|
||||
|
||||
if args.filter is not None and not filename.startswith(args.filter):
|
||||
continue
|
||||
|
||||
with open(fullname) as fyaml:
|
||||
yml_data = yaml.load(fyaml, Loader=get_loader(fullname.parent))
|
||||
yml_data = get_defaults(fullname.parent, args.directory) | yml_data
|
||||
yml_data["hostname"] = fullname.stem
|
||||
yml_data["filename"] = filename
|
||||
data.append(yml_data)
|
||||
|
||||
# Dump everything to json
|
||||
print(json.dumps(data))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
11
tools/render
Executable file
11
tools/render
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
ROOT=$(git rev-parse --show-toplevel)
|
||||
RENDERED=${ROOT}/rendered
|
||||
TEMPLATES=${ROOT}/templates
|
||||
|
||||
${ROOT}/tools/merge ./nodes > ${RENDERED}/nodes.json
|
||||
|
||||
gomplate --input-dir ${TEMPLATES} --output-dir ${RENDERED} \
|
||||
-d nodes=file://${RENDERED}/nodes.json \
|
||||
-d config=${ROOT}/config.yaml \
|
||||
@@ -6,7 +6,6 @@ IPXE_VERSION=b41bda4413bf286d7b7a449bc05e1531da1eec2e
|
||||
IPXE_BIN=(bin/ipxe.pxe bin-x86_64-efi/ipxe.efi)
|
||||
|
||||
IPXE_DIR=${ROOT}/.ipxe/ipxe-${IPXE_VERSION}
|
||||
HTTP_URL=$(cat ${ROOT}/config.yaml | yq .server.httpUrl)
|
||||
|
||||
function download_ipxe() {
|
||||
base_dir=$(dirname ${IPXE_DIR})
|
||||
@@ -26,8 +25,7 @@ function patch_ipxe() {
|
||||
#!ipxe
|
||||
|
||||
dhcp
|
||||
chain ${HTTP_URL}/boot.ipxe || shell
|
||||
# chain boot.ipxe || shell
|
||||
chain boot.ipxe || shell
|
||||
EOF
|
||||
|
||||
cd - > /dev/null
|
||||
@@ -46,7 +44,6 @@ function build_ipxe() {
|
||||
|
||||
function render() {
|
||||
${ROOT}/tools/render
|
||||
${ROOT}/rendered/generate_configs.sh
|
||||
}
|
||||
|
||||
function host_tftp() {
|
||||
@@ -67,30 +64,8 @@ function host_tftp() {
|
||||
sudo in.tftpd --verbosity 100 --permissive -L --secure ${TFTP_DIR}
|
||||
}
|
||||
|
||||
function host_http() {
|
||||
HTTP_DIR=$(mktemp --tmpdir -d http.XXX)
|
||||
chmod 755 ${HTTP_DIR}
|
||||
function cleanup() {
|
||||
rm -rf ${HTTP_DIR}
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
ln -s ${ROOT}/rendered/boot.ipxe ${HTTP_DIR}
|
||||
for bin in "${IPXE_BIN[@]}"; do
|
||||
path=${IPXE_DIR}/src/${bin}
|
||||
ln -s ${path} ${HTTP_DIR}
|
||||
done
|
||||
|
||||
ln -s ${ROOT}/configs ${HTTP_DIR}
|
||||
|
||||
echo "Starting http"
|
||||
cd ${HTTP_DIR}
|
||||
python -m http.server 8000
|
||||
cd -
|
||||
}
|
||||
|
||||
download_ipxe
|
||||
patch_ipxe
|
||||
build_ipxe
|
||||
render
|
||||
host_http
|
||||
host_tftp
|
||||
13
tools/vm
13
tools/vm
@@ -3,9 +3,9 @@ set -euo pipefail
|
||||
ROOT=$(git rev-parse --show-toplevel)
|
||||
|
||||
VM_NAME="talos-vm"
|
||||
VCPUS="6"
|
||||
RAM_MB="16384"
|
||||
DISK_GB="100"
|
||||
VCPUS="2"
|
||||
RAM_MB="2048"
|
||||
DISK_GB="10"
|
||||
NETWORK=talos
|
||||
CONNECTION="qemu:///system"
|
||||
|
||||
@@ -21,7 +21,7 @@ function define_network() {
|
||||
<ip address="192.168.1.1" netmask="255.255.255.0">
|
||||
<dhcp>
|
||||
<range start="192.168.1.2" end="192.168.1.254"/>
|
||||
<bootp file='http://192.168.1.1:8000/ipxe.pxe'/>
|
||||
<bootp file='ipxe.pxe'/>
|
||||
</dhcp>
|
||||
</ip>
|
||||
</network>
|
||||
@@ -111,12 +111,13 @@ function delete() {
|
||||
virsh --connect="${CONNECTION}" destroy "${VM_NAME}"
|
||||
fi
|
||||
virsh --connect="${CONNECTION}" undefine "${VM_NAME}" --remove-all-storage
|
||||
else
|
||||
echo "VM doest not exists"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
if [[ $(virsh --connect="${CONNECTION}" net-list --all | grep -c "${NETWORK}") > "0" ]]; then
|
||||
if [[ $(virsh --connect="${CONNECTION}" list | grep -c "${VM_NAME}") > "0" ]]; then
|
||||
virsh --connect="${CONNECTION}" net-destroy "${NETWORK}"
|
||||
fi
|
||||
virsh --connect="${CONNECTION}" net-undefine "${NETWORK}"
|
||||
fi
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user