Skip to content

Repository files navigation

Local Lab

Open in GitHub Codespaces

buildtalosproxmoxlicense

Personal infrastructure-as-code repository: два Kubernetes-кластера на Talos поверх Proxmox, управляемые через Terraform (bootstrap) и ArgoCD (deploy).

Состояние: скелет. Смотри SERVICES.md для списка сервисов и текущей фазы.


Архитектура

 ┌─────────────────────────────────────┐
│ Tailscale mesh │
│ (overlay для всех нод/сайтов) │
└──────────┬──────────────┬───────────┘
│ │
┌──────────────────────┴──┐ ┌────┴───────────────────┐
│ ОФИС (office-prod) │ │ ДОМ (home-prod) │
│ 3 × Proxmox host │ │ 1 × Proxmox host │
│ │ │ │
│ ┌─ Talos VM (kaluga) │ │ ┌─ Talos VM (beast) │
│ ├─ Talos VM (s-tropez)│ │ │ single-node │
│ └─ Talos VM (courch.) │ │ │ CP + worker │
│ │ │ └────────────────────│
│ 3 mixed CP+worker │ │ │
│ etcd quorum: 3/3 │ │ Хранение: local-path │
│ Хранение: Longhorn │ │ Назначение: lab + HA │
│ │ │ для умного дома │
│ ┌─────────────────┐ │ │ │
│ │ ArgoCD │───┼──────┼──→ управляет home-prod │
│ │ (hub-and- │ │ │ через kubeconfig │
│ │ spoke) │ │ │ │
│ └─────────────────┘ │ │ │
└─────────────────────────┘ └────────────────────────┘
▲ ▲
│ │
git push ───────→ ArgoCD reconcile loop
(всё деплоится из этого репо)

Принципы

  • GitOps — состояние кластеров описано в этом репо, ArgoCD непрерывно синхронизирует
  • Talos Linux в Proxmox VM — иммутабельная ОС только для Kubernetes, минимум attack surface
  • Hub-and-spoke ArgoCD — один инстанс на office-prod управляет обоими кластерами через зарегистрированные kubeconfig'и
  • Расширяемость — поднять lab-кластер (k3s/k0s/RKE2 на Ubuntu/OpenSUSE) для экспериментов = добавить папку terraform/clusters/lab-X/ и опционально kubernetes/lab-X/, основная архитектура не меняется

Кластеры

КластерСайтНодыOS / k8sНазначение
office-prodОфис, 3 Proxmox-хоста (kaluga, saint-tropez, courchevel)3 × Talos VM, mixed CP+workerTalosProduction: prod-сервисы, GitOps хаб
home-prodДом, 1 Proxmox-хост (beast)1 × Talos VM, single-node CP+workerTalosHA, личные эксперименты, ad-hoc
lab-*По мере надобностиk3s / k0s / RKE2 / etcЭксперименты, обучение

Хардварная инвентаризация — hardware/.


Стек

Bootstrap (вне кластера)

  • Terraform — провижининг VM на Proxmox + bootstrap Talos через talosctl
  • Tailscale — mesh между всеми нодами и клиентами (личный tailnet)
  • Headscale — координационный сервер Tailscale (живёт отдельно на Hetzner-VM, не в этом репо)

Кластерная база (день 1, ставится на каждый prod-кластер)

  • Cilium — CNI (сеть подов, NetworkPolicy, eBPF)
  • Longhorn — CSI распределённое хранилище (только office-prod)
  • cert-manager — авто-обновление TLS (Let's Encrypt)
  • Traefik — Ingress controller
  • ArgoCD — GitOps деплой (hub на office-prod)

Расширения (добавляются по мере необходимости)

External Secrets / Sealed Secrets, Velero (backup в S3/MinIO), ExternalDNS, Renovate Bot, CloudNativePG (Postgres operator), kube-prometheus-stack + Loki + Grafana Alloy.

Полный список с обоснованиями — SERVICES.md.


Структура репозитория

local-lab/
├── terraform/ # Bootstrap слой (вне k8s)
│ ├── modules/
│ │ ├── proxmox-vm/ # Универсальный модуль VM на Proxmox
│ │ │ # (любая ОС: Talos / Ubuntu / OpenSUSE)
│ │ └── talos-cluster/ # Bootstrap Talos: talosctl genconfig/apply/bootstrap
│ └── clusters/
│ ├── office-prod/ # tf-stack для office-prod
│ └── home-prod/ # tf-stack для home-prod
│
├── kubernetes/ # Что внутри кластеров (через ArgoCD)
│ ├── office-prod/
│ │ ├── bootstrap/ # ArgoCD App-of-Apps: точка входа
│ │ ├── infrastructure/ # Cilium, Longhorn, cert-manager, Traefik, ArgoCD
│ │ └── apps/ # Homepage, Nextcloud, Jellyfin, Paperless, и т.д.
│ └── home-prod/
│ ├── bootstrap/
│ ├── infrastructure/ # минимум: Cilium, cert-manager, Traefik
│ └── apps/ # пусто (Home Assistant — отдельная HAOS VM)
│
├── docker/ # Сервисы вне Kubernetes — папка на сервис
│ ├── homepage/ # дашборд: compose.yaml + config/ + secrets.sops.yaml
│ ├── imm-bridge/ # доступ к IMM сервера pve-local-l-01
│ └── ilo-bridge/ # доступ к iLO сервера pve-local-l-02
├── hardware/ # Инвентаризация железа
├── SERVICES.md # Карта сервисов и фаз миграции
└── README.md

Конвенция содержимого папки сервиса

В kubernetes/<cluster>/{infrastructure,apps}/<service>/ плоско лежит:

  • application.yaml — ArgoCD Application (обязательный), ссылается на upstream Helm-чарт + values
  • values.yaml — Helm values, если большие (опционально)
  • secret.yamlExternalSecret или SealedSecret манифесты (опционально)
  • любые дополнительные манифесты (IngressRoute, NetworkPolicy, и т.п.)

Без base/ и overlays/ — каждый сервис деплоится в один кластер, Kustomize-оверрайды не нужны.


Сеть

  • Офис:192.168.20.0/24
  • Дом:10.0.1.0/24
  • Tailscale tailnet:100.64.0.0/10 (overlay)
  • Headscale: на отдельной Hetzner-VM (вне этого репо)
  • Доступ к сервисам — через Tailscale + Traefik Ingress, без публичных IP

Workflow

Поднять кластер с нуля (office-prod)

  1. cd terraform/clusters/office-prod && terraform apply — создаёт 3 Talos VM на Proxmox-хостах + bootstrap кластер
  2. Получить kubeconfig из output
  3. Установить ArgoCD одной командой (helm install)
  4. Применить kubernetes/office-prod/bootstrap/root.yaml — ArgoCD дальше сам подтянет всю инфру и приложения из репо

Добавить сервис

  1. Создать папку kubernetes/<cluster>/apps/<service>/
  2. Положить application.yaml (ArgoCD Application с Helm chart reference)
  3. git commit && git push
  4. ArgoCD заметит и применит автоматически

Поднять lab-кластер (эксперимент)

  1. Создать модуль terraform/modules/<distro>-cluster/ (если ещё нет)
  2. Создать terraform/clusters/lab-<name>/ с tf-стеком
  3. (Опц.) Зарегистрировать новый кластер в ArgoCD на office-prod через Cluster ресурс

Proxmox API-токен для Terraform

Провайдер bpg/proxmox аутентифицируется в Proxmox по API-токену. Endpoint и токен каждого кластера лежат в secret.auto.tfvars рядом со стейтом (файл под .gitignore, в репо не попадает), провайдер читает их через var.proxmox_api_endpoint / var.proxmox_api_token.

1. Создать пользователя и токен

На любой ноде Proxmox-кластера (root-сессия):

# пользователь под Terraform (realm pve = встроенный)
pveum user add terraform@pve
# токен с отключённым privilege separation: токен наследует права пользователя
pveum user token add terraform@pve terraform --privsep 0

token addодин раз выведет секрет вида terraform@pve!terraform=xxxxxxxx-xxxx-... — сохрани сразу, повторно он не показывается.

2. Выдать права

Для провижининга VM (создание, диски, cloud-init, сеть) достаточно роли PVEAdmin:

pveum acl modify / --users terraform@pve --roles PVEAdmin

⚠️Подвох:PVEAdmin не содержит Sys.Modify, а он обязателен для скачивания образа по URL (proxmox_download_file → API query-url-metadata). Без него terraform apply падает на загрузке Talos-образа с HTTP 403 — Permission check failed. Добавляем ровно эту привилегию отдельной ролью (least-privilege, не расширяя до PVESysAdmin/Administrator):

pveum role add TerraformDownload --privs "Sys.Modify"
pveum acl modify / --users terraform@pve --roles TerraformDownload

3. Прописать в стейте

В secret.auto.tfvars каждого стейта (terraform/live/<cluster>/<stack>/):

proxmox_api_endpoint="https://<proxmox-ip>:8006/"proxmox_api_token="terraform@pve!terraform=xxxxxxxx-xxxx-..."

4. Проверить

# эффективные права токена — должны включать Sys.Modify
pveum user token permissions terraform@pve terraform | grep Sys.Modify
# живой тест metadata-запроса: ожидаем HTTP 200, не 403
curl -sk -o /dev/null -w "%{http_code}\n" \
-H "Authorization: PVEAPIToken=terraform@pve!terraform=xxxxxxxx-xxxx-..." \
--data-urlencode "url=https://factory.talos.dev/<...>.raw.gz" \
--data-urlencode "verify-certificates=0" -G \
"https://<proxmox-ip>:8006/api2/json/nodes/<node>/query-url-metadata"

Установка кластера с нуля (pve-local-l)

Пошаговый runbook для реального кластера pve-local-l (3 CP + 3 worker, Talos + Cilium Gateway API + Longhorn). Три шага неизбежно ручные — это bootstrap-«семя» (инфраструктуры ещё нет / ArgoCD не ставит сам себя / нужно посадить первый Application). Всё остальное ArgoCD доводит сам.

Слой 0 — предпосылки на Proxmox

  • образ Talos с extensions (iscsi-tools, util-linux-tools) залит в local:import/
  • registry-зеркала 10.0.1.50:5000-5002 подняты и прогреты (в Talos skipFallback: true — без них кластер не соберётся)
  • ZFS-пул tank для data-дисков Longhorn

Слой 1 — Terraform (VM + диски + Talos + Cilium)

cd terraform/live/pve-local-l/talos-k8s-3c-3w
terraform init
terraform apply

Закладывай ~10 мин: etcd проходит через learner-гонку и самособирается (поды control-plane могут повисеть в ContainerCreating — это ожидаемо, не ошибка).

Достать доступы:

mkdir -p ~/.kube
terraform output -raw kubeconfig >~/.kube/local-lab.yaml
terraform output -raw talosconfig >~/.talosconfig
export KUBECONFIG=~/.kube/local-lab.yaml

Слой 2 — ArgoCD (единственная ручная установка чарта)

helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm install argocd argo/argo-cd -n argocd --create-namespace \
--version <pin> \
-f gitops/pve-local-l/bootstrap/argocd-values.yaml

argocd-values.yaml уводит redis с ecr-public.aws.com (нет в registry-зеркалах) на docker.io. Версию чарта запинь через --version (helm search repo argo/argo-cd --versions).

Слой 3 — посадить App-of-Apps

kubectl apply -f gitops/pve-local-l/bootstrap/root-app.yaml

Слой 4 — дальше ArgoCD сам

Подтягивает из репозитория: metallb → metrics-server → longhorn → cilium-gateway → homepage. Между приложениями нет жёсткого порядка — ArgoCD реконсилит до сходимости (~несколько минут после первого git push reconcile-задержки).

kubectl get applications -n argocd -w

Проверки после сходимости

kubectl get nodes # 6 Ready (3 CP + 3 worker)
kubectl get gatewayclass # cilium
kubectl get gateway -n gateway # homelab: PROGRAMMED=True, есть ADDRESS из MetalLB-пула
kubectl get storageclass # longhorn

Дальнейшие этапы — ArgoCD bootstrap (kvt-lab / pve-klg-p-02)

После terraform apply (VM + Talos + Cilium развёрнуты) кластер пуст. Дальше ставится ArgoCD и сажается App-of-Apps. Порядок строгий: ArgoCD ставится первым (это helm install), App-of-Apps применяется уже работающим ArgoCD — не наоборот.

Предусловие: bootstrap-файлы для klg пока не созданы (есть только у pve-local-l). Создай по образцу gitops/pve-local-l/:

  • gitops/pve-klg-p-02/bootstrap/argocd-values.yaml — overrides ArgoCD-чарта. У pve-local-l тут redis уводится на registry-зеркало 10.0.1.50; у klg сеть другая и registry-зеркала пока отключены — правь под свою.
  • gitops/pve-klg-p-02/bootstrap/root-app.yaml — App-of-Apps, path: gitops/pve-klg-p-02/argocd.
  • gitops/pve-klg-p-02/argocd/ — манифесты приложений, которые подтянет ArgoCD.

Слой 2 — ArgoCD (единственная ручная установка чарта)

export KUBECONFIG=~/.kube/kvt-lab/config
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm install argocd argo/argo-cd -n argocd --create-namespace \
--version <pin> \
-f gitops/pve-klg-p-02/bootstrap/argocd-values.yaml

Слой 3 — посадить App-of-Apps

kubectl apply -f gitops/pve-klg-p-02/bootstrap/root-app.yaml

Слой 4 — дальше ArgoCD сам

Реконсилит всё из gitops/pve-klg-p-02/argocd до сходимости.

kubectl get applications -n argocd -w

DevContainer

Репозиторий настроен под DevPod / VS Code DevContainers. Открой в VS Code → Reopen in Container, либо:

devpod up . --id . --provider . --dotfiles https://github.com/CosmDandy/dotfiles-devpod.git

В девконтейнер будут установлены: Terraform, talosctl, kubectl, helm, k9s, gitleaks (для pre-commit hook).


Безопасность

  • Pre-commit hook gitleaks — блокирует случайные секреты в коммитах
  • .gitignore исключает: *.env, *.tfvars (кроме *.example), *.key, *.pem, kubeconfig, talosconfig, secrets/, .claude/
  • Все секреты в кластерах — через External Secrets Operator или SealedSecrets (без plaintext в репо)
  • Сертификаты — через cert-manager + Let's Encrypt (DNS challenge, без публичного 443)

About

Multi-cluster Kubernetes as code: Talos on Proxmox, reconciled by Flux and Argo CD

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages