[{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/tags/devops/","section":"Tags","summary":"","title":"Devops","type":"tags"},{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/tags/etcd/","section":"Tags","summary":"","title":"Etcd","type":"tags"},{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/tags/ha/","section":"Tags","summary":"","title":"Ha","type":"tags"},{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/tags/homelab/","section":"Tags","summary":"","title":"Homelab","type":"tags"},{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/tags/installation/","section":"Tags","summary":"","title":"Installation","type":"tags"},{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/tags/k3s/","section":"Tags","summary":"","title":"K3s","type":"tags"},{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/series/k3s-ha-%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80-%D0%B4%D0%BB%D1%8F-homelab/","section":"Series","summary":"","title":"K3s HA Кластер Для Homelab","type":"series"},{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/tags/kubernetes/","section":"Tags","summary":"","title":"Kubernetes","type":"tags"},{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/posts/","section":"Posts","summary":"","title":"Posts","type":"posts"},{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"2 ноября 2025","externalUrl":null,"permalink":"/","section":"Олег Казанин","summary":"","title":"Олег Казанин","type":"page"},{"content":"Инфраструктура готова: 5 VM работают, ОС настроена, порты открыты. Пора устанавливать K3s. Один curl-скрипт на каждую ноду - и через 15 минут у вас работающий HA-кластер.\nЗвучит слишком просто? Потому что сложная часть уже позади - в предыдущих статьях. Теперь осталось не перепутать флаги и порядок установки.\nРезультат: 5 нод в статусе Ready, etcd кластер 3/3 healthy, kubectl работает с локальной машины.\nДля кого это # Подходит:\nПрошёл статьи 1 и 2 (или имеешь готовые VM с настроенной ОС) Все 5 нод доступны по SSH Понимаешь разницу между master и worker Не подходит:\nVM ещё не созданы → статья 2 Не понимаешь зачем 3 master ноды → статья 1 Что понадобится # Компонент Значение K3s версия v1.31.4+k3s1 (или актуальная stable) Token Сгенерируем на первом шаге SSH доступ Ко всем 5 нодам Время ~15-20 минут Шаг 1: Сгенерировать token # Token - общий секрет для всех нод кластера. Без правильного token нода не присоединится.\nНа локальной машине:\n# Сгенерировать случайный token openssl rand -base64 32 Пример вывода:\nK10f8c9a7b6e5d4c3b2a1f0e9d8c7b6a5e4d3c2b1a0f9e8d7c6b5a4== Сохрани этот token - он понадобится для каждой ноды. Положи в менеджер паролей или временный файл.\n# Для удобства - сохранить в переменную (на время сессии) export K3S_TOKEN=\u0026#34;твой_сгенерированный_token\u0026#34; echo $K3S_TOKEN Шаг 2: Установить K3s на первую master ноду # Первая нода инициализирует etcd кластер. Она особенная - использует флаг --cluster-init.\nSSH на k3s-master-1:\nssh k3s@192.168.11.201 Установка:\n# Задать переменные export K3S_TOKEN=\u0026#34;твой_сгенерированный_token\u0026#34; export INSTALL_K3S_VERSION=\u0026#34;v1.31.4+k3s1\u0026#34; # Установить K3s curl -sfL https://get.k3s.io | sh -s - server \\ --cluster-init \\ --tls-san=192.168.11.201 \\ --disable=traefik \\ --disable=servicelb \\ --write-kubeconfig-mode=644 Разбор флагов:\nФлаг Зачем server Режим control plane (не agent) --cluster-init Ключевой! Инициализирует etcd. Только на первой ноде --tls-san=192.168.11.201 Добавить IP в сертификат API server --disable=traefik Отключить встроенный Traefik (установим свой через Helm) --disable=servicelb Отключить встроенный LB (установим MetalLB) --write-kubeconfig-mode=644 Разрешить чтение kubeconfig без sudo Установка займёт 1-2 минуты. K3s скачает бинарник (~50MB) и запустит все компоненты.\nПроверка # # 1. Статус сервиса sudo systemctl status k3s Ожидаемый результат:\n● k3s.service - Lightweight Kubernetes Loaded: loaded Active: active (running) since ... # 2. Статус ноды sudo k3s kubectl get nodes Ожидаемый результат:\nNAME STATUS ROLES AGE VERSION k3s-master-1 Ready control-plane,etcd,master 45s v1.31.4+k3s1 Checkpoint: Первая master работает # # Быстрая проверка sudo systemctl is-active k3s \u0026amp;\u0026amp; \\ sudo k3s kubectl get nodes | grep -q \u0026#34;Ready\u0026#34; \u0026amp;\u0026amp; \\ echo \u0026#34;✓ Master-1 готов\u0026#34; || echo \u0026#34;✗ Проблема\u0026#34; Если статус NotReady или сервис не запустился:\n# Смотреть логи sudo journalctl -u k3s -f --no-pager | tail -50 Ошибка в логах Причина Решение cgroup v1 is not supported Нужен cgroup v2 Вернись к статье 2, шаг 6.5 port 6443 already in use Что-то занимает порт sudo ss -tlnp | grep 6443 etcd failed to start Мало места на диске df -h, увеличь диск Шаг 3: Добавить вторую master ноду # Теперь присоединяем вторую master. Она подключается к существующему кластеру - без --cluster-init.\nSSH на k3s-master-2:\nssh k3s@192.168.11.202 Установка:\nexport K3S_TOKEN=\u0026#34;твой_сгенерированный_token\u0026#34; export INSTALL_K3S_VERSION=\u0026#34;v1.31.4+k3s1\u0026#34; curl -sfL https://get.k3s.io | sh -s - server \\ --server=https://192.168.11.201:6443 \\ --tls-san=192.168.11.202 \\ --disable=traefik \\ --disable=servicelb \\ --write-kubeconfig-mode=644 Ключевое отличие:\n❌ Нет --cluster-init - кластер уже инициализирован ✅ Есть --server=https://192.168.11.201:6443 - адрес существующего кластера Проверка # # На master-2 sudo k3s kubectl get nodes Ожидаемый результат:\nNAME STATUS ROLES AGE VERSION k3s-master-1 Ready control-plane,etcd,master 3m v1.31.4+k3s1 k3s-master-2 Ready control-plane,etcd,master 30s v1.31.4+k3s1 Две ноды - но кворума ещё нет. etcd требует большинство, а 2 из 3 - это ещё не \u0026ldquo;большинство от трёх\u0026rdquo;.\nШаг 4: Добавить третью master ноду # SSH на k3s-master-3:\nssh k3s@192.168.11.203 Установка (аналогично master-2):\nexport K3S_TOKEN=\u0026#34;твой_сгенерированный_token\u0026#34; export INSTALL_K3S_VERSION=\u0026#34;v1.31.4+k3s1\u0026#34; curl -sfL https://get.k3s.io | sh -s - server \\ --server=https://192.168.11.201:6443 \\ --tls-san=192.168.11.203 \\ --disable=traefik \\ --disable=servicelb \\ --write-kubeconfig-mode=644 Checkpoint: Control Plane HA готов # На любой master ноде:\n# 1. Все 3 master ноды Ready sudo k3s kubectl get nodes Ожидаемый результат:\nNAME STATUS ROLES AGE VERSION k3s-master-1 Ready control-plane,etcd,master 5m v1.31.4+k3s1 k3s-master-2 Ready control-plane,etcd,master 3m v1.31.4+k3s1 k3s-master-3 Ready control-plane,etcd,master 1m v1.31.4+k3s1 # 2. etcd кластер здоров sudo k3s kubectl exec -n kube-system \\ $(sudo k3s kubectl get pods -n kube-system -l component=etcd -o name | head -1) \\ -- etcdctl endpoint health --cluster Ожидаемый результат:\nhttps://192.168.11.201:2379 is healthy: successfully committed proposal: took = 2.1ms https://192.168.11.202:2379 is healthy: successfully committed proposal: took = 1.8ms https://192.168.11.203:2379 is healthy: successfully committed proposal: took = 2.3ms Теперь у вас настоящий HA. Можете остановить любую master ноду - кластер продолжит работать.\nТест отказоустойчивости (опционально) # Хотите убедиться, что HA работает? Проверьте:\n# С локальной машины - остановить master-2 ssh k3s@192.168.11.202 \u0026#34;sudo systemctl stop k3s\u0026#34; # Подождать 30-40 секунд, затем на master-1: ssh k3s@192.168.11.201 \u0026#34;sudo k3s kubectl get nodes\u0026#34; # master-2 станет NotReady, но кластер работает # Проверить etcd - 2/3 кворум есть ssh k3s@192.168.11.201 \u0026#34;sudo k3s kubectl exec -n kube-system \\ \\$(sudo k3s kubectl get pods -n kube-system -l component=etcd -o name | head -1) \\ -- etcdctl endpoint health --cluster\u0026#34; # 2 из 3 healthy - кворум есть # Вернуть master-2 ssh k3s@192.168.11.202 \u0026#34;sudo systemctl start k3s\u0026#34; Шаг 5: Добавить worker ноды # Worker ноды устанавливаются как agent - они не участвуют в etcd и не запускают control plane.\n5.1. Установить K3s agent на worker-1 # SSH на k3s-worker-1:\nssh k3s@192.168.11.210 Установка:\nexport K3S_TOKEN=\u0026#34;твой_сгенерированный_token\u0026#34; export INSTALL_K3S_VERSION=\u0026#34;v1.31.4+k3s1\u0026#34; curl -sfL https://get.k3s.io | sh -s - agent \\ --server=https://192.168.11.201:6443 Отличия от master:\nagent вместо server - режим worker Нет флагов --disable и --tls-san - они не нужны для worker Только --server - куда подключаться 5.2. Установить K3s agent на worker-2 # SSH на k3s-worker-2:\nssh k3s@192.168.11.211 Установка:\nexport K3S_TOKEN=\u0026#34;твой_сгенерированный_token\u0026#34; export INSTALL_K3S_VERSION=\u0026#34;v1.31.4+k3s1\u0026#34; curl -sfL https://get.k3s.io | sh -s - agent \\ --server=https://192.168.11.201:6443 Checkpoint: Все ноды в кластере # На любой master ноде:\nsudo k3s kubectl get nodes -o wide Ожидаемый результат:\nNAME STATUS ROLES AGE VERSION INTERNAL-IP k3s-master-1 Ready control-plane,etcd,master 10m v1.31.4+k3s1 192.168.11.201 k3s-master-2 Ready control-plane,etcd,master 8m v1.31.4+k3s1 192.168.11.202 k3s-master-3 Ready control-plane,etcd,master 6m v1.31.4+k3s1 192.168.11.203 k3s-worker-1 Ready \u0026lt;none\u0026gt; 2m v1.31.4+k3s1 192.168.11.210 k3s-worker-2 Ready \u0026lt;none\u0026gt; 1m v1.31.4+k3s1 192.168.11.211 Обрати внимание:\nMaster: роли control-plane,etcd,master Worker: роли \u0026lt;none\u0026gt; - только выполнение workloads Шаг 6: Настроить kubectl на локальной машине # Сейчас kubectl работает только на master нодах через sudo k3s kubectl. Настроим доступ с вашей рабочей машины.\n6.1. Скопировать kubeconfig # На локальной машине (не на ноде):\n# 1. Создать директорию mkdir -p ~/.kube # 2. Скопировать конфиг с master-1 scp k3s@192.168.11.201:/etc/rancher/k3s/k3s.yaml ~/.kube/config # 3. Заменить localhost на реальный IP sed -i \u0026#39;s/127.0.0.1/192.168.11.201/g\u0026#39; ~/.kube/config # Для macOS: # sed -i \u0026#39;\u0026#39; \u0026#39;s/127.0.0.1/192.168.11.201/g\u0026#39; ~/.kube/config # 4. Права доступа chmod 600 ~/.kube/config 6.2. Установить kubectl (если нет) # Linux:\ncurl -LO \u0026#34;https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl\u0026#34; sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl rm kubectl macOS:\nbrew install kubectl 6.3. Проверить подключение # # Версия kubectl version # Ноды kubectl get nodes # Все поды kubectl get pods -A Ожидаемый результат kubectl get pods -A:\nNAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-xxx 1/1 Running 0 10m kube-system local-path-provisioner-xxx 1/1 Running 0 10m kube-system metrics-server-xxx 1/1 Running 0 10m Если kubectl не подключается:\nСимптом Причина Решение connection refused k3s не запущен ssh k3s@192.168.11.201 \u0026quot;sudo systemctl status k3s\u0026quot; connection timeout Firewall блокирует Проверь UFW на master: sudo ufw status | grep 6443 certificate signed by unknown authority Неправильный kubeconfig Скопируй заново с master ноды 6.4. Настроить автодополнение (опционально) # # Bash echo \u0026#39;source \u0026lt;(kubectl completion bash)\u0026#39; \u0026gt;\u0026gt; ~/.bashrc echo \u0026#39;alias k=kubectl\u0026#39; \u0026gt;\u0026gt; ~/.bashrc echo \u0026#39;complete -o default -F __start_kubectl k\u0026#39; \u0026gt;\u0026gt; ~/.bashrc source ~/.bashrc # Zsh echo \u0026#39;source \u0026lt;(kubectl completion zsh)\u0026#39; \u0026gt;\u0026gt; ~/.zshrc source ~/.zshrc Теперь работает k get nodes и Tab-автодополнение.\nФинальная проверка # Полный чеклист работоспособности кластера:\necho \u0026#34;=== Проверка K3s HA кластера ===\u0026#34; echo -n \u0026#34;1. Все ноды Ready: \u0026#34; [ $(kubectl get nodes --no-headers | grep -c \u0026#34;Ready\u0026#34;) -eq 5 ] \u0026amp;\u0026amp; echo \u0026#34;✓ (5/5)\u0026#34; || echo \u0026#34;✗\u0026#34; echo -n \u0026#34;2. Master ноды: \u0026#34; kubectl get nodes --no-headers | grep -c \u0026#34;control-plane\u0026#34; | xargs -I {} echo \u0026#34;✓ ({}/3)\u0026#34; echo -n \u0026#34;3. Worker ноды: \u0026#34; kubectl get nodes --no-headers | grep -c \u0026#34;\u0026lt;none\u0026gt;\u0026#34; | xargs -I {} echo \u0026#34;✓ ({}/2)\u0026#34; echo -n \u0026#34;4. etcd healthy: \u0026#34; kubectl exec -n kube-system \\ $(kubectl get pods -n kube-system -l component=etcd -o name | head -1) \\ -- etcdctl endpoint health --cluster 2\u0026gt;/dev/null | grep -c \u0026#34;is healthy\u0026#34; | xargs -I {} echo \u0026#34;✓ ({}/3)\u0026#34; echo -n \u0026#34;5. CoreDNS Running: \u0026#34; kubectl get pods -n kube-system -l k8s-app=kube-dns --no-headers | grep -q \u0026#34;Running\u0026#34; \u0026amp;\u0026amp; echo \u0026#34;✓\u0026#34; || echo \u0026#34;✗\u0026#34; echo -n \u0026#34;6. Metrics Server Running: \u0026#34; kubectl get pods -n kube-system -l k8s-app=metrics-server --no-headers | grep -q \u0026#34;Running\u0026#34; \u0026amp;\u0026amp; echo \u0026#34;✓\u0026#34; || echo \u0026#34;✗\u0026#34; echo \u0026#34;\u0026#34; echo \u0026#34;=== Информация о кластере ===\u0026#34; kubectl cluster-info Ожидаемый результат:\n=== Проверка K3s HA кластера === 1. Все ноды Ready: ✓ (5/5) 2. Master ноды: ✓ (3/3) 3. Worker ноды: ✓ (2/2) 4. etcd healthy: ✓ (3/3) 5. CoreDNS Running: ✓ 6. Metrics Server Running: ✓ === Информация о кластере === Kubernetes control plane is running at https://192.168.11.201:6443 CoreDNS is running at https://192.168.11.201:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy Metrics-server is running at https://192.168.11.201:6443/api/v1/namespaces/kube-system/services/https:metrics-server:https/proxy Тестовый деплой # Убедимся, что кластер может запускать приложения:\n# 1. Создать тестовый под kubectl run nginx-test --image=nginx:alpine --port=80 # 2. Подождать запуска kubectl wait --for=condition=Ready pod/nginx-test --timeout=60s # 3. Проверить на какой ноде запустился kubectl get pod nginx-test -o wide Ожидаемый результат:\nNAME READY STATUS RESTARTS AGE IP NODE nginx-test 1/1 Running 0 30s 10.42.1.5 k3s-worker-1 Под запустился на worker ноде - как и должно быть.\n# 4. Проверить доступность изнутри кластера kubectl run -it --rm debug --image=busybox --restart=Never -- wget -qO- nginx-test Ожидаемый результат: HTML-страница nginx.\n# 5. Удалить тестовые ресурсы kubectl delete pod nginx-test Troubleshooting # Нода не присоединяется к кластеру # Симптом: После установки нода не появляется в kubectl get nodes.\nПричина Диагностика Решение Неправильный token Логи: sudo journalctl -u k3s-agent -f Проверь token, переустанови Firewall блокирует curl -k https://192.168.11.201:6443 Открой порт 6443 на masters DNS не резолвит ping k3s-master-1 Проверь /etc/hosts или DNS etcd не формирует кворум # Симптом: etcdctl endpoint health показывает unhealthy.\n# Проверить членов etcd sudo k3s kubectl exec -n kube-system \\ $(sudo k3s kubectl get pods -n kube-system -l component=etcd -o name | head -1) \\ -- etcdctl member list --write-out=table Причина Диагностика Решение Порты 2379-2380 закрыты sudo ufw status sudo ufw allow 2379:2380/tcp Нода недоступна по сети ping 192.168.11.20X Проверь сеть, UFW etcd ещё стартует uptime на ноде Подожди 2-3 минуты Поды не запускаются на workers # Симптом: Все поды на master нодах, workers пустые.\n# Проверить taints kubectl describe node k3s-worker-1 | grep Taints Если есть taints - убрать:\nkubectl taint nodes k3s-worker-1 node.kubernetes.io/not-ready:NoSchedule- Откат: удаление K3s # Если нужно начать заново:\nНа master ноде:\nsudo /usr/local/bin/k3s-uninstall.sh На worker ноде:\nsudo /usr/local/bin/k3s-agent-uninstall.sh Что удаляется:\nБинарники K3s Systemd сервисы Данные из /var/lib/rancher/k3s/ etcd данные (на masters) Контейнеры и образы ⚠️ Внимание: etcd снапшоты тоже удаляются. Если нужен бэкап:\n# Перед удалением - сохранить снапшоты sudo cp -r /var/lib/rancher/k3s/server/db/snapshots/ ~/k3s-backup/ Итог # Что сделано:\n✅ Сгенерирован token для кластера ✅ Установлен K3s на 3 master ноды с embedded etcd ✅ Добавлены 2 worker ноды ✅ Настроен kubectl на локальной машине ✅ Проверена работоспособность кластера Что имеем:\nHA Control Plane - выдерживает падение 1 master ноды 2 worker ноды для приложений kubectl доступ с локальной машины Встроенные компоненты: CoreDNS, metrics-server, local-path storage Что ещё не настроено (следующие статьи):\nLoadBalancer (MetalLB) - для доступа к сервисам извне Ingress Controller (Traefik) - для HTTP/HTTPS routing SSL сертификаты (cert-manager) - для автоматического HTTPS Мониторинг (Prometheus/Grafana) - для наблюдения за кластером Что дальше # Кластер готов, но пока он изолирован от внешнего мира. Чтобы запускать реальные приложения с доступом извне, нужны:\nMetalLB - выдаёт IP-адреса для LoadBalancer сервисов Traefik - маршрутизирует HTTP/HTTPS трафик cert-manager - автоматически получает SSL сертификаты Это темы для следующей серии статей.\nА пока можно:\nПоэкспериментировать с kubectl Задеплоить тестовые приложения Изучить как работает scheduling между нодами ","date":"2 ноября 2025","externalUrl":null,"permalink":"/posts/k3s-installation/","section":"Posts","summary":"Инфраструктура готова: 5 VM работают, ОС настроена, порты открыты. Пора устанавливать K3s. Один curl-скрипт на каждую ноду - и через 15 минут у вас работающий HA-кластер.","title":"Установить K3s HA кластер","type":"posts"},{"content":"","date":"21 октября 2025","externalUrl":null,"permalink":"/tags/debian/","section":"Tags","summary":"","title":"Debian","type":"tags"},{"content":"","date":"21 октября 2025","externalUrl":null,"permalink":"/tags/infrastructure/","section":"Tags","summary":"","title":"Infrastructure","type":"tags"},{"content":"","date":"21 октября 2025","externalUrl":null,"permalink":"/tags/proxmox/","section":"Tags","summary":"","title":"Proxmox","type":"tags"},{"content":"Архитектура спланирована, ресурсы посчитаны - пора создавать виртуальные машины. В этой статье подготовим 5 VM в Proxmox и настроим ОС так, чтобы K3s установился без сюрпризов.\nЗвучит просто? В теории - да. На практике: забытый swap, cgroup v1 вместо v2, закрытые порты firewall - и вы тратите час на отладку того, что должно было работать \u0026ldquo;из коробки\u0026rdquo;.\nРезультат: 5 VM (3 master + 2 worker) с Debian 12, настроенной сетью, отключённым swap и правильными параметрами ядра. SSH доступ работает, ноды видят друг друга.\nДля кого это # Подходит:\nПрочитал первую статью (или понимаешь архитектуру K3s HA) Есть Proxmox с 14+ vCPU и 56GB+ RAM свободных Умеешь работать в терминале Proxmox (или готов учиться) Не подходит:\nProxmox ещё не установлен - сначала разберись с ним Хочешь использовать LXC вместо VM - K3s в контейнерах работает, но с нюансами (не покрываем) Что понадобится # Компонент Значение Proxmox VE 7.x или 8.x Storage pool local-lvm или другой (минимум 200GB свободно) Сетевой bridge vmbr0 (или ваш) SSH-ключ Публичный ключ для доступа к VM ОС для VM Debian 12 cloud image Шаг 1: Скачать cloud image Debian 12 # Cloud image - готовый образ с поддержкой cloud-init. Не нужно проходить установщик вручную: задаёшь параметры (IP, пользователь, SSH-ключ) - VM стартует уже настроенной.\nНа Proxmox хосте (SSH или Shell в Web UI):\n# Перейти в директорию для образов cd /var/lib/vz/template/iso # Скачать Debian 12 cloud image wget https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2 # Проверить ls -lh debian-12-generic-amd64.qcow2 Ожидаемый результат:\n-rw-r--r-- 1 root root 521M ... debian-12-generic-amd64.qcow2 Если скачивание медленное: образ ~500MB, на слабом канале может занять время. Альтернатива - скачать на локальную машину и загрузить через Proxmox Web UI (Datacenter → Storage → Upload).\nШаг 2: Создать template VM # Template - шаблон VM, из которого будем клонировать все 5 нод. Настраиваем один раз, клонируем пять.\n2.1. Задать переменные # # Настрой под свою конфигурацию TEMPLATE_ID=9000 # ID для template (любой свободный) STORAGE=local-lvm # Твой storage pool BRIDGE=vmbr0 # Сетевой bridge SSH_KEY_PATH=~/.ssh/id_rsa.pub # Путь к публичному SSH-ключу Как узнать имя storage:\npvesm status Ожидаемый результат\nName Type Status Total Used Available % local dir active 229199360 9095552 220103808 3.97% local-lvm pool active 220103964 96 220103868 0.00% 2.2. Создать VM и импортировать диск # # 1. Создать пустую VM qm create $TEMPLATE_ID \\ --name debian-12-template \\ --memory 2048 \\ --cores 2 \\ --net0 virtio,bridge=$BRIDGE # 2. Импортировать скачанный образ как диск qm importdisk $TEMPLATE_ID \\ /var/lib/vz/template/iso/debian-12-generic-amd64.qcow2 \\ $STORAGE Ожидаемый результат:\nimporting disk \u0026#39;/var/lib/vz/template/iso/debian-12-generic-amd64.qcow2\u0026#39; to VM 9000 ... Successfully imported disk as \u0026#39;unused0:local-lvm:vm-9000-disk-0\u0026#39; 2.3. Настроить диск и загрузку # # 3. Подключить диск к VM qm set $TEMPLATE_ID \\ --scsihw virtio-scsi-pci \\ --scsi0 $STORAGE:vm-$TEMPLATE_ID-disk-0 # 4. Настроить загрузку и cloud-init qm set $TEMPLATE_ID \\ --boot c \\ --bootdisk scsi0 \\ --ide2 $STORAGE:cloudinit \\ --serial0 socket \\ --vga serial0 2.4. Настроить cloud-init # # 5. Пользователь, пароль, SSH-ключ qm set $TEMPLATE_ID \\ --ciuser k3s \\ --cipassword \u0026#34;ВашНадёжныйПароль\u0026#34; \\ --sshkeys $SSH_KEY_PATH \\ --ipconfig0 ip=dhcp # 6. Увеличить диск до 32GB (базовый размер для master) qm resize $TEMPLATE_ID scsi0 32G Замени:\nВашНадёжныйПароль - пароль для пользователя k3s (резервный доступ, если SSH не работает) $SSH_KEY_PATH - путь к твоему публичному ключу 2.5. Превратить в template # # 7. Конвертировать VM в template qm template $TEMPLATE_ID После этого VM 9000 станет шаблоном - её нельзя запустить, только клонировать.\nCheckpoint: Template создан # # Проверить что template существует qm list | grep template Ожидаемый результат:\n9000 debian-12-template stopped 2048 32.00 0 Если ошибка \u0026ldquo;disk import failed\u0026rdquo;:\nПроверь свободное место: pvesm status Проверь путь к образу: ls -l /var/lib/vz/template/iso/ Шаг 3: Клонировать master ноды # Теперь создаём 3 master ноды из template. Каждая получит свой IP, имя и ресурсы.\nTEMPLATE_ID=9000 # ───────────────────────────────────────────── # Master 1 # ───────────────────────────────────────────── qm clone $TEMPLATE_ID 201 --name k3s-master-1 --full qm set 201 --cores 2 --memory 8192 qm set 201 --ipconfig0 ip=192.168.11.201/24,gw=192.168.11.1 qm set 201 --nameserver 8.8.8.8 qm resize 201 scsi0 32G # ───────────────────────────────────────────── # Master 2 # ───────────────────────────────────────────── qm clone $TEMPLATE_ID 202 --name k3s-master-2 --full qm set 202 --cores 2 --memory 8192 qm set 202 --ipconfig0 ip=192.168.11.202/24,gw=192.168.11.1 qm set 202 --nameserver 8.8.8.8 qm resize 202 scsi0 32G # ───────────────────────────────────────────── # Master 3 # ───────────────────────────────────────────── qm clone $TEMPLATE_ID 203 --name k3s-master-3 --full qm set 203 --cores 2 --memory 8192 qm set 203 --ipconfig0 ip=192.168.11.203/24,gw=192.168.11.1 qm set 203 --nameserver 8.8.8.8 qm resize 203 scsi0 32G Параметры:\n--full - полное клонирование (не linked clone), VM независима от template --cores 2 --memory 8192 - 2 vCPU, 8GB RAM (как планировали) --ipconfig0 - статический IP через cloud-init --nameserver - DNS сервер (можешь указать свой) Адаптируй под свою сеть:\n192.168.11.0/24 → твоя подсеть 192.168.11.1 → твой gateway Шаг 4: Клонировать worker ноды # Workers получают больше ресурсов - здесь будут работать приложения.\n# ───────────────────────────────────────────── # Worker 1 # ───────────────────────────────────────────── qm clone $TEMPLATE_ID 210 --name k3s-worker-1 --full qm set 210 --cores 4 --memory 16384 qm set 210 --ipconfig0 ip=192.168.11.210/24,gw=192.168.11.1 qm set 210 --nameserver 8.8.8.8 qm resize 210 scsi0 50G # ───────────────────────────────────────────── # Worker 2 # ───────────────────────────────────────────── qm clone $TEMPLATE_ID 211 --name k3s-worker-2 --full qm set 211 --cores 4 --memory 16384 qm set 211 --ipconfig0 ip=192.168.11.211/24,gw=192.168.11.1 qm set 211 --nameserver 8.8.8.8 qm resize 211 scsi0 50G Отличия от master:\n4 vCPU вместо 2 16GB RAM вместо 8GB 50GB диск вместо 32GB Шаг 5: Запустить все VM # # Запустить все 5 VM for vmid in 201 202 203 210 211; do qm start $vmid echo \u0026#34;Запущена VM $vmid\u0026#34; sleep 3 done # Проверить статус qm list | grep k3s Ожидаемый результат:\n201 k3s-master-1 running 8192 32.00 12345 202 k3s-master-2 running 8192 32.00 12346 203 k3s-master-3 running 8192 32.00 12347 210 k3s-worker-1 running 16384 50.00 12348 211 k3s-worker-2 running 16384 50.00 12349 Checkpoint: VM работают # Подожди 1-2 минуты (cloud-init применяет настройки при первом запуске), затем проверь SSH:\n# Проверить доступность всех нод for ip in 192.168.11.201 192.168.11.202 192.168.11.203 192.168.11.210 192.168.11.211; do echo -n \u0026#34;Проверяю $ip... \u0026#34; ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no k3s@$ip \u0026#34;hostname\u0026#34; 2\u0026gt;/dev/null \u0026amp;\u0026amp; echo \u0026#34;OK\u0026#34; || echo \u0026#34;FAIL\u0026#34; done Ожидаемый результат:\nПроверяю 192.168.11.201... k3s-master-1 OK Проверяю 192.168.11.202... k3s-master-2 OK ... Если SSH не работает:\nСимптом Причина Решение Connection refused VM не загрузилась или SSH не запущен Открой консоль в Proxmox, проверь загрузку Connection timeout Неправильный IP или firewall Проверь IP в консоли: ip addr Permission denied Неправильный SSH-ключ Проверь ~/.ssh/authorized_keys на VM Host key verification failed Первое подключение Добавь -o StrictHostKeyChecking=no Шаг 6: Подготовить ОС на всех нодах # Теперь нужно настроить каждую ноду: обновить пакеты, отключить swap, настроить ядро. Команды одинаковые для всех 5 нод.\n6.1. Обновить систему # На каждой ноде (или через цикл):\n# Вариант 1: по одной ssh k3s@192.168.11.201 sudo apt update sudo apt upgrade -y sudo apt install -y curl wget vim htop iptables # Вариант 2: массово (с локальной машины) for ip in 192.168.11.{201..203} 192.168.11.{210..211}; do echo \u0026#34;=== Обновляю $ip ===\u0026#34; ssh k3s@$ip \u0026#34;sudo apt update \u0026amp;\u0026amp; sudo apt upgrade -y \u0026amp;\u0026amp; sudo apt install -y curl wget vim htop iptables\u0026#34; done 6.2. Отключить swap # Kubernetes не любит swap. При включённом swap поды ведут себя непредсказуемо - OOMKiller срабатывает не тогда, когда ожидаешь.\nНа всех нодах:\n# Отключить swap сейчас sudo swapoff -a # Отключить навсегда (закомментировать в fstab) sudo sed -i \u0026#39;/swap/s/^/#/\u0026#39; /etc/fstab # Проверить free -h | grep Swap Ожидаемый результат:\nSwap: 0B 0B 0B 6.3. Загрузить kernel-модули # K3s использует overlay filesystem и bridge netfilter. Без этих модулей - ошибки при старте.\nНа всех нодах:\n# Загрузить модули sudo modprobe overlay sudo modprobe br_netfilter # Настроить автозагрузку cat \u0026lt;\u0026lt;EOF | sudo tee /etc/modules-load.d/k3s.conf overlay br_netfilter EOF # Проверить lsmod | grep -E \u0026#39;overlay|br_netfilter\u0026#39; Ожидаемый результат:\noverlay 151552 0 br_netfilter 32768 0 6.4. Настроить sysctl # Параметры для сетевого взаимодействия между подами.\nНа всех нодах:\n# Создать конфиг cat \u0026lt;\u0026lt;EOF | sudo tee /etc/sysctl.d/k3s.conf net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 EOF # Применить sudo sysctl --system # Проверить sysctl net.ipv4.ip_forward net.bridge.bridge-nf-call-iptables Ожидаемый результат:\nnet.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-iptables = 1 6.5. Проверить cgroup v2 # Debian 12 по умолчанию использует cgroup v2 - просто проверим.\nmount | grep cgroup Ожидаемый результат (cgroup v2):\ncgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot) Если видишь tmpfs on /sys/fs/cgroup type tmpfs - это cgroup v1. Нужно включить v2:\n# Добавить параметр ядра sudo sed -i \u0026#39;s|^GRUB_CMDLINE_LINUX_DEFAULT=\u0026#34;\\(.*\\)\u0026#34;|GRUB_CMDLINE_LINUX_DEFAULT=\u0026#34;\\1 systemd.unified_cgroup_hierarchy=1\u0026#34;|\u0026#39; /etc/default/grub # Обновить GRUB sudo update-grub # Перезагрузить sudo reboot # После reboot проверить mount | grep cgroup2 Шаг 7: Настроить firewall # UFW - простой интерфейс к iptables. Откроем только нужные порты.\n7.1. На master нодах (201, 202, 203) # # Установить UFW sudo apt install -y ufw # Базовые правила sudo ufw default deny incoming sudo ufw default allow outgoing # SSH (чтобы не потерять доступ) sudo ufw allow 22/tcp # Kubernetes API sudo ufw allow 6443/tcp # etcd (между masters) sudo ufw allow 2379:2380/tcp # Kubelet sudo ufw allow 10250/tcp # Flannel VXLAN sudo ufw allow 8472/udp # Включить sudo ufw --force enable # Проверить sudo ufw status 7.2. На worker нодах (210, 211) # sudo apt install -y ufw sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp # SSH sudo ufw allow 10250/tcp # Kubelet sudo ufw allow 8472/udp # Flannel VXLAN sudo ufw --force enable sudo ufw status Шаг 8: Настроить /etc/hosts # Не обязательно, но удобно - ноды смогут обращаться друг к другу по имени.\nНа всех нодах:\ncat \u0026lt;\u0026lt;EOF | sudo tee -a /etc/hosts # K3s Cluster 192.168.11.201 k3s-master-1 192.168.11.202 k3s-master-2 192.168.11.203 k3s-master-3 192.168.11.210 k3s-worker-1 192.168.11.211 k3s-worker-2 EOF Проверить:\nping -c 1 k3s-master-2 Финальная проверка # Перед переходом к установке K3s убедись, что всё готово. Запусти на любой ноде:\necho \u0026#34;=== Проверка готовности ноды ===\u0026#34; echo -n \u0026#34;1. Swap отключён: \u0026#34; [ $(free | grep Swap | awk \u0026#39;{print $2}\u0026#39;) -eq 0 ] \u0026amp;\u0026amp; echo \u0026#34;✓\u0026#34; || echo \u0026#34;✗ ОШИБКА\u0026#34; echo -n \u0026#34;2. Модуль overlay: \u0026#34; lsmod | grep -q overlay \u0026amp;\u0026amp; echo \u0026#34;✓\u0026#34; || echo \u0026#34;✗ ОШИБКА\u0026#34; echo -n \u0026#34;3. Модуль br_netfilter: \u0026#34; lsmod | grep -q br_netfilter \u0026amp;\u0026amp; echo \u0026#34;✓\u0026#34; || echo \u0026#34;✗ ОШИБКА\u0026#34; echo -n \u0026#34;4. IP forwarding: \u0026#34; [ $(sysctl -n net.ipv4.ip_forward) -eq 1 ] \u0026amp;\u0026amp; echo \u0026#34;✓\u0026#34; || echo \u0026#34;✗ ОШИБКА\u0026#34; echo -n \u0026#34;5. bridge-nf-call-iptables: \u0026#34; [ $(sysctl -n net.bridge.bridge-nf-call-iptables) -eq 1 ] \u0026amp;\u0026amp; echo \u0026#34;✓\u0026#34; || echo \u0026#34;✗ ОШИБКА\u0026#34; echo -n \u0026#34;6. cgroup v2: \u0026#34; mount | grep -q \u0026#34;cgroup2\u0026#34; \u0026amp;\u0026amp; echo \u0026#34;✓\u0026#34; || echo \u0026#34;✗ ОШИБКА\u0026#34; echo -n \u0026#34;7. UFW активен: \u0026#34; sudo ufw status | grep -q \u0026#34;Status: active\u0026#34; \u0026amp;\u0026amp; echo \u0026#34;✓\u0026#34; || echo \u0026#34;✗ ОШИБКА\u0026#34; echo -n \u0026#34;8. Пинг k3s-master-1: \u0026#34; ping -c 1 -W 1 k3s-master-1 \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 \u0026amp;\u0026amp; echo \u0026#34;✓\u0026#34; || echo \u0026#34;✗ ОШИБКА\u0026#34; Ожидаемый результат:\n=== Проверка готовности ноды === 1. Swap отключён: ✓ 2. Модуль overlay: ✓ 3. Модуль br_netfilter: ✓ 4. IP forwarding: ✓ 5. bridge-nf-call-iptables: ✓ 6. cgroup v2: ✓ 7. UFW активен: ✓ 8. Пинг k3s-master-1: ✓ Если где-то ✗ - вернись к соответствующему шагу.\nTroubleshooting # Симптом Причина Решение VM не получает IP cloud-init не отработал Проверь консоль, жди 2-3 минуты, перезагрузи VM SSH connection refused sshd не запущен Открой консоль, проверь systemctl status ssh Swap не отключается Строка не закомментирована в fstab cat /etc/fstab, проверь swap строку, reboot cgroup v1 после reboot GRUB не обновился Проверь /proc/cmdline, повтори update-grub UFW блокирует всё Забыл разрешить SSH до включения Через консоль Proxmox: ufw allow 22/tcp Ноды не пингуются UFW или неправильный IP Проверь ip addr, проверь правила UFW Итог # Что сделано:\n✅ Скачан Debian 12 cloud image ✅ Создан template VM с cloud-init ✅ Склонированы 5 VM (3 master + 2 worker) ✅ Настроены статические IP ✅ Подготовлена ОС (swap, modules, sysctl, cgroup v2) ✅ Настроен firewall с нужными портами ✅ SSH работает на все ноды Что дальше:\n👉 Следующая статья: \u0026ldquo;Установить K3s HA кластер\u0026rdquo;\nТам мы:\nСгенерируем token для кластера Установим K3s на первую master ноду Добавим ещё 2 master ноды (HA) Подключим worker ноды Настроим kubectl Проверим работу кластера ","date":"21 октября 2025","externalUrl":null,"permalink":"/posts/k3s-infrastructure/","section":"Posts","summary":"Архитектура спланирована, ресурсы посчитаны - пора создавать виртуальные машины. Подготовим 5 VM в Proxmox и настроим ОС так, чтобы K3s установился без сюрпризов.","title":"Подготовить инфраструктуру для K3s в Proxmox","type":"posts"},{"content":"","date":"14 октября 2025","externalUrl":null,"permalink":"/tags/architecture/","section":"Tags","summary":"","title":"Architecture","type":"tags"},{"content":"Kubernetes слишком тяжёлый, Docker Swarm мёртв, а хочется нормальный кластер для экспериментов. Знакомо? K3s решает эту проблему - полноценный Kubernetes в бинарнике на 50MB вместо 1.5GB зависимостей. Но без правильного планирования вы получите нестабильную конструкцию, которая падает в самый неподходящий момент.\nВ этой статье разберём архитектуру K3s HA кластера: почему именно 3 master ноды, зачем embedded etcd и сколько ресурсов закладывать. В конце - готовый план для установки.\nРезультат: понимание архитектуры + таблица ресурсов + сетевая схема. Всё, что нужно перед тем, как создавать VM.\nДля кого это # Подходит:\nЗнаком с базовыми концепциями Kubernetes (pod, service, deployment) Есть Proxmox с 14+ vCPU и 56GB+ RAM Хочешь понять что устанавливать, прежде чем устанавливать Не подходит:\nНужна одна нода для экспериментов - достаточно docker-compose или K3s single-node Ищешь managed Kubernetes для бизнеса - смотри в сторону Yandex Cloud или VK Cloud Хочешь сразу команды без теории - переходи к статье 2 K3s vs Kubernetes: в чём разница # Kubernetes (K8s) - оркестратор контейнеров, стандарт индустрии. Добро пожаловать в enterprise, где для запуска трёх контейнеров нужно поддерживать шесть виртуальных машин.\nK3s - тот же Kubernetes, но кто-то в Rancher (теперь SUSE) задумался: \u0026ldquo;А что если выкинуть всё, что нужно только Сберу и Yandex Cloud?\u0026rdquo;\nKubernetes K3s Что выкинули:\nИнтеграции с облачными провайдерами (вы же не в VK Cloud) Legacy API (вы же не мигрируете кластер 2016 года) Встроенные драйверы хранилищ на все случаи жизни (вы же не используете 47 типов СХД) Альфа/бета-функции (нестабильные эксперименты) Что осталось: полноценный Kubernetes, сертифицированный CNCF (Cloud Native Computing Foundation - организация, которая решает, что считать \u0026ldquo;настоящим\u0026rdquo; Kubernetes). Все манифесты работают. Helm работает. kubectl работает. Ответы со StackOverflow работают.\nСравнение в цифрах # Характеристика Kubernetes K3s Размер ~1.5GB образы 50MB бинарник RAM на control plane ~2GB на ноду ~500MB на ноду Установка kubeadm, 10+ шагов один curl-скрипт etcd Отдельный кластер (3+ VM) Встроенный CNI Нужно устанавливать Flannel из коробки Совместимость 100% 100% \u0026ldquo;Но я потеряю гибкость!\u0026rdquo; - скажете вы. Да, вы не сможете заменить сетевой плагин Flannel без пересборки. Это критично примерно для одного проекта из тысячи, и ваш homelab в их число не входит.\nВердикт: для homelab K3s - очевидный выбор. Теряем 5% гибкости, получаем 90% простоты.\nЧто такое High Availability и зачем оно вам # HA (High Availability) - способность системы продолжать работу при отказе компонентов. Звучит как enterprise-термин для больших компаний? На практике это разница между \u0026ldquo;кластер упал в субботу, но я починил в понедельник\u0026rdquo; и \u0026ldquo;кластер сам пережил падение ноды, пока я спал\u0026rdquo;.\nБез HA (single node) # ┌─────────────────┐ │ K3s Master │ ← Единственная точка отказа │ + Worker │ └─────────────────┘ Нода упала → кластер мёртв → ваши сервисы недоступны С HA (3+ master nodes) # ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Master 1 │ │ Master 2 │ │ Master 3 │ │ + etcd │ │ + etcd │ │ + etcd │ └──────────┘ └──────────┘ └──────────┘ ↓ ↓ ↓ ┌──────────┐ ┌──────────┐ │ Worker 1 │ │ Worker 2 │ └──────────┘ └──────────┘ Одна master упала → кластер работает Один worker упал → поды переехали на другой Сколько master нод нужно # Вот тут начинается интересное. Интуиция подсказывает: одна нода - плохо, две - уже лучше. Логично? Логично. И неправильно.\nMaster нод Выдержит отказов Кворум Вердикт 1 0 1/1 Нет HA, но честно 2 0 Ловушка! ⛔ Хуже, чем 1 3 1 2/3 ✅ Минимум для HA 5 2 3/5 Для критичных систем Почему 2 master ноды хуже, чем 1 # etcd (база данных кластера, где хранится вообще всё) работает по принципу голосования. Чтобы записать данные, нужно согласие большинства нод. Не \u0026ldquo;хотя бы одной\u0026rdquo; - именно большинства.\nСчитаем:\n1 нода: большинство = 1. Упала - кластер мёртв. Честная игра, вы знали на что шли. 2 ноды: большинство = 2. Упала одна - кворума нет, кластер мёртв. Сюрприз! 3 ноды: большинство = 2. Одна упала - две оставшиеся продолжают работать. Это как договор, требующий подписи обоих директоров - заболел один, и компания парализована.\nС двумя нодами вы не получили отказоустойчивость. Вы удвоили количество точек отказа и назвали это \u0026ldquo;высокой доступностью\u0026rdquo;.\nПравило: или 1 нода (и честное понимание рисков), или 3+ (и настоящий HA). Двойка - ловушка для тех, кто не дочитал документацию.\nEmbedded etcd vs External etcd # etcd - распределённое key-value хранилище. Единственный источник истины для всего состояния Kubernetes: все объекты (поды, сервисы, секреты), конфигурации, сетевые политики. Без etcd кластер не работает. Точка.\nЕсть два варианта архитектуры:\nExternal etcd (классический Kubernetes) # Control Plane (3 VM) etcd кластер (3 VM) ┌────────────────┐ ┌──────────────┐ │ API Server │ │ etcd-1 │ │ Scheduler │ ──────────────\u0026gt;│ (только etcd)│ │ Controller │ └──────────────┘ └────────────────┘ ┌──────────────┐ ┌────────────────┐ │ etcd-2 │ │ API Server │ ──────────────\u0026gt;│ (только etcd)│ │ Scheduler │ └──────────────┘ │ Controller │ ┌──────────────┐ └────────────────┘ │ etcd-3 │ ┌────────────────┐ │ (только etcd)│ │ API Server │ ──────────────\u0026gt;└──────────────┘ │ Scheduler │ │ Controller │ └────────────────┘ Итого: 6 виртуальных машин Embedded etcd (K3s) # ┌─────────────────────────┐ │ K3s Master 1 │ │ ┌───────────────────┐ │ │ │ API + Scheduler │ │ │ │ + Controller │ │ │ └───────────────────┘ │ │ ┌───────────────────┐ │ │ │ etcd (встроенный) │◄─┼──┐ │ └───────────────────┘ │ │ └─────────────────────────┘ │ Raft protocol ┌─────────────────────────┐ │ (синхронизация) │ K3s Master 2 │ │ │ etcd ◄────────────────────┤ └─────────────────────────┘ │ ┌─────────────────────────┐ │ │ K3s Master 3 │ │ │ etcd ◄────────────────────┘ └─────────────────────────┘ Итого: 3 виртуальные машины Сравнение подходов # Критерий External etcd Embedded etcd Количество VM 6 (3 master + 3 etcd) 3 (всё вместе) Сложность настройки Высокая Один флаг --cluster-init Сложность обновления Отдельно etcd и K8s Одна команда Производительность Чуть лучше Достаточно для homelab Масштаб \u0026gt;500 нод До 100-200 нод Для homelab embedded etcd - очевидный выбор. Теряем 5-10% производительности etcd, экономим 3 VM и часы настройки.\n\u0026ldquo;А если мне понадобится масштаб?\u0026rdquo; - официально embedded etcd поддерживает до 100 нод и 5000 подов. Для homelab это как ограничение скорости 300 км/ч на велосипеде.\nЗачем отдельные worker ноды # Worker ноды - машины для запуска ваших приложений (подов). На них не запускаются компоненты control plane.\n\u0026ldquo;А можно запускать приложения прямо на master нодах?\u0026rdquo;\nТехнически - да. K3s не ставит ограничений на master ноды (в отличие от обычного Kubernetes). Но это плохая идея:\nControl plane должен быть стабильным. Ваше приложение съело всю память → API server упал → кластер недоступен. etcd чувствителен к диску. База данных на той же ноде создаёт I/O нагрузку → etcd тормозит → весь кластер тормозит. Изоляция отказов. Проблема с приложением не должна убивать control plane. 2 worker ноды - минимум для HA приложений:\nМожно запускать 2 реплики (на разных нодах) При падении одного worker\u0026rsquo;а второй держит нагрузку Легко добавить третью, четвёртую ноду потом Архитектура нашего кластера # Вот что мы будем строить:\nКлючевые моменты:\nВсе master ноды равны - нет \u0026ldquo;главной\u0026rdquo;, kubectl подключается к любой. etcd синхронизируется через Raft - алгоритм консенсуса, гарантирует согласованность данных. Workers знают только про API - они не подключаются к etcd напрямую. Flannel создаёт overlay-сеть - все поды получают IP из 10.42.0.0/16, видят друг друга. Планирование ресурсов # Таблица VM # Hostname VM ID IP vCPU RAM Disk Роль k3s-master-1 201 192.168.11.201 2 8GB 32GB Control Plane + etcd k3s-master-2 202 192.168.11.202 2 8GB 32GB Control Plane + etcd k3s-master-3 203 192.168.11.203 2 8GB 32GB Control Plane + etcd k3s-worker-1 210 192.168.11.210 4 16GB 50GB Workloads k3s-worker-2 211 192.168.11.211 4 16GB 50GB Workloads Итого - - 14 56GB 196GB - Почему именно такие ресурсы # Master ноды (2 vCPU / 8GB RAM / 32GB Disk):\nРеальное потребление в idle:\nAPI server: ~200-300MB RAM etcd: ~100-200MB RAM (растёт со временем) Scheduler + Controller: ~150MB RAM Системные поды: ~100-200MB RAM Итого: ~600-900MB используется \u0026ldquo;Зачем тогда 8GB?\u0026rdquo; - запас для burst-нагрузки. Когда вы деплоите 50 подов одновременно, API server временно съедает больше. etcd при большом кластере может вырасти до 1-2GB. Golang GC работает лучше с запасом памяти.\nWorker ноды (4 vCPU / 16GB RAM / 50GB Disk):\nЗдесь будут ваши приложения. При 16GB можно запустить:\n5-10 средних приложений (256MB-2GB каждое) Или 2-3 базы данных (PostgreSQL любит память) Или комбинацию 50GB диска - под образы контейнеров (10-20GB), логи (5-10GB), временные данные.\nМожно ли меньше? # Минимальная конфигурация (для экспериментов):\nMaster: 1 vCPU / 4GB RAM / 20GB Disk Worker: 2 vCPU / 8GB RAM / 30GB Disk Итого: 9 vCPU / 36GB RAM Риски:\nМедленная работа API server OOM killer при нагрузке Нет запаса для burst Для production-like homelab рекомендую таблицу выше. Комфортный запас стоит дешевле, чем отладка странных падений.\nСетевая схема # IP-адреса (адаптируй под свою сеть) # 192.168.11.0/24 - Локальная сеть 192.168.11.1 - Gateway (роутер) 192.168.11.201-203 - Master ноды 192.168.11.210-211 - Worker ноды 192.168.11.220-230 - Резерв для MetalLB (статья 2) Kubernetes внутренние сети (создаются автоматически) # 10.42.0.0/16 - Pod network (Flannel VXLAN overlay) 10.43.0.0/16 - Service network (ClusterIP) 10.43.0.10 - CoreDNS Порты между нодами # Порт Протокол Направление Назначение 6443 TCP Master ← Worker Kubernetes API 2379-2380 TCP Master ↔ Master etcd (client + peer) 10250 TCP Master ↔ All Kubelet API 8472 UDP All ↔ All Flannel VXLAN Требования к железу и софту # Железо (Proxmox хост) # Минимум:\nCPU: 14 vCPU свободных RAM: 56GB свободных Disk: 200GB на SSD Network: 1 Gbit Рекомендуется:\nCPU: 18+ vCPU (запас для приложений) RAM: 64GB+ (базы данных прожорливые) Disk: NVMe для etcd Network: 2.5 Gbit (для NFS, если будете использовать) Софт # Компонент Версия Proxmox VE 7.x или 8.x K3s v1.31+ (stable) ОС на нодах Debian 12 или Ubuntu 22.04+ Kernel 5.15+ (для cgroup v2) Итог # Что мы спроектировали:\n5 VM: 3 master + 2 worker K3s с embedded etcd (HA без лишних VM) Отказоустойчивость: выдерживает падение 1 master и любого worker Ресурсы: 14 vCPU / 56GB RAM / 196GB Disk Что НЕ входит в эту серию (отдельные статьи):\nLoadBalancer (MetalLB) Ingress (Traefik) SSL (cert-manager) Мониторинг (Prometheus/Grafana) Что дальше # 👉 \u0026ldquo;Подготовить инфраструктуру для K3s в Proxmox\u0026rdquo;\nТам мы:\nСоздадим template VM с Debian 12 Склонируем 5 VM с правильными ресурсами Настроим статические IP Подготовим ОС (swap, cgroup v2, firewall) ","date":"14 октября 2025","externalUrl":null,"permalink":"/posts/k3s-architecture/","section":"Posts","summary":"Kubernetes слишком тяжёлый, Docker Swarm мёртв, а хочется нормальный кластер для экспериментов. K3s решает эту проблему - полноценный Kubernetes в 50MB. Разберём архитектуру HA кластера без боли.","title":"K3s HA для homelab: архитектура без боли","type":"posts"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"}]