oakazanin/public/index.json

2 lines
60 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[{"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"}]