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+worker | Talos | Production: prod-сервисы, GitOps хаб |
| home-prod | Дом, 1 Proxmox-хост (beast) | 1 × Talos VM, single-node CP+worker | Talos | HA, личные эксперименты, ad-hoc |
| lab-* | По мере надобности | — | k3s / k0s / RKE2 / etc | Эксперименты, обучение |
Хардварная инвентаризация — hardware/.
- Terraform — провижининг VM на Proxmox + bootstrap Talos через
talosctl - Tailscale — mesh между всеми нодами и клиентами (личный tailnet)
- Headscale — координационный сервер Tailscale (живёт отдельно на Hetzner-VM, не в этом репо)
- 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— ArgoCDApplication(обязательный), ссылается на upstream Helm-чарт + valuesvalues.yaml— Helm values, если большие (опционально)secret.yaml—ExternalSecretили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
cd terraform/clusters/office-prod && terraform apply— создаёт 3 Talos VM на Proxmox-хостах + bootstrap кластер- Получить
kubeconfigиз output - Установить ArgoCD одной командой (
helm install) - Применить
kubernetes/office-prod/bootstrap/root.yaml— ArgoCD дальше сам подтянет всю инфру и приложения из репо
- Создать папку
kubernetes/<cluster>/apps/<service>/ - Положить
application.yaml(ArgoCD Application с Helm chart reference) git commit && git push- ArgoCD заметит и применит автоматически
- Создать модуль
terraform/modules/<distro>-cluster/(если ещё нет) - Создать
terraform/clusters/lab-<name>/с tf-стеком - (Опц.) Зарегистрировать новый кластер в ArgoCD на office-prod через
Clusterресурс
Провайдер bpg/proxmox аутентифицируется в Proxmox по API-токену. Endpoint и токен каждого кластера лежат в secret.auto.tfvars рядом со стейтом (файл под .gitignore, в репо не попадает), провайдер читает их через var.proxmox_api_endpoint / var.proxmox_api_token.
На любой ноде Proxmox-кластера (root-сессия):
# пользователь под Terraform (realm pve = встроенный)
pveum user add terraform@pve
# токен с отключённым privilege separation: токен наследует права пользователя
pveum user token add terraform@pve terraform --privsep 0token addодин раз выведет секрет вида terraform@pve!terraform=xxxxxxxx-xxxx-... — сохрани сразу, повторно он не показывается.
Для провижининга VM (создание, диски, cloud-init, сеть) достаточно роли PVEAdmin:
pveum acl modify / --users terraform@pve --roles PVEAdminPVEAdmin не содержит 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В secret.auto.tfvars каждого стейта (terraform/live/<cluster>/<stack>/):
proxmox_api_endpoint="https://<proxmox-ip>:8006/"proxmox_api_token="terraform@pve!terraform=xxxxxxxx-xxxx-..."# эффективные права токена — должны включать 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"Пошаговый runbook для реального кластера pve-local-l (3 CP + 3 worker, Talos + Cilium Gateway API + Longhorn). Три шага неизбежно ручные — это bootstrap-«семя» (инфраструктуры ещё нет / ArgoCD не ставит сам себя / нужно посадить первый Application). Всё остальное ArgoCD доводит сам.
- образ Talos с extensions (
iscsi-tools,util-linux-tools) залит вlocal:import/ - registry-зеркала
10.0.1.50:5000-5002подняты и прогреты (в TalosskipFallback: true— без них кластер не соберётся) - ZFS-пул
tankдля data-дисков Longhorn
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.yamlhelm 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.yamlargocd-values.yaml уводит redis с ecr-public.aws.com (нет в registry-зеркалах) на docker.io. Версию чарта запинь через --version (helm search repo argo/argo-cd --versions).
kubectl apply -f gitops/pve-local-l/bootstrap/root-app.yamlПодтягивает из репозитория: metallb → metrics-server → longhorn → cilium-gateway → homepage. Между приложениями нет жёсткого порядка — ArgoCD реконсилит до сходимости (~несколько минут после первого git push reconcile-задержки).
kubectl get applications -n argocd -wkubectl 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После 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.
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.yamlkubectl apply -f gitops/pve-klg-p-02/bootstrap/root-app.yamlРеконсилит всё из gitops/pve-klg-p-02/argocd до сходимости.
kubectl get applications -n argocd -wРепозиторий настроен под 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)