370 lines
19 KiB
Markdown
370 lines
19 KiB
Markdown
---
|
||
title: "K3s HA для homelab: архитектура без боли"
|
||
date: 2025-10-14
|
||
draft: false
|
||
description: "Полноценный Kubernetes в бинарнике на 50MB вместо 1.5GB зависимостей. Разбираем архитектуру K3s HA кластера: почему именно 3 master ноды, зачем embedded etcd и сколько ресурсов закладывать."
|
||
tags: ["kubernetes", "k3s", "homelab", "proxmox", "architecture", "ha", "devops"]
|
||
series: ["K3s HA кластер для homelab"]
|
||
series_order: 1
|
||
---
|
||
|
||
Kubernetes слишком тяжёлый, Docker Swarm мёртв, а хочется нормальный кластер для экспериментов. Знакомо? K3s решает эту проблему - полноценный Kubernetes в бинарнике на 50MB вместо 1.5GB зависимостей. Но без правильного планирования вы получите нестабильную конструкцию, которая падает в самый неподходящий момент.
|
||
|
||
В этой статье разберём архитектуру K3s HA кластера: почему именно 3 master ноды, зачем embedded etcd и сколько ресурсов закладывать. В конце - готовый план для установки.
|
||
|
||
**Результат:** понимание архитектуры + таблица ресурсов + сетевая схема. Всё, что нужно перед тем, как создавать VM.
|
||
|
||
---
|
||
|
||
## Для кого это
|
||
|
||
**Подходит:**
|
||
- Знаком с базовыми концепциями Kubernetes (pod, service, deployment)
|
||
- Есть Proxmox с 14+ vCPU и 56GB+ RAM
|
||
- Хочешь понять *что* устанавливать, прежде чем устанавливать
|
||
|
||
**Не подходит:**
|
||
- Нужна одна нода для экспериментов - достаточно docker-compose или K3s single-node
|
||
- Ищешь managed Kubernetes для бизнеса - смотри в сторону Yandex Cloud или VK Cloud
|
||
- Хочешь сразу команды без теории - переходи к статье 2
|
||
|
||
---
|
||
|
||
## K3s vs Kubernetes: в чём разница
|
||
|
||
**Kubernetes (K8s)** - оркестратор контейнеров, стандарт индустрии. Добро пожаловать в enterprise, где для запуска трёх контейнеров нужно поддерживать шесть виртуальных машин.
|
||
|
||
**K3s** - тот же Kubernetes, но кто-то в Rancher (теперь SUSE) задумался: "А что если выкинуть всё, что нужно только Сберу и Yandex Cloud?"
|
||
|
||

|
||

|
||
|
||
|
||
**Что выкинули:**
|
||
|
||
- Интеграции с облачными провайдерами (вы же не в VK Cloud)
|
||
- Legacy API (вы же не мигрируете кластер 2016 года)
|
||
- Встроенные драйверы хранилищ на все случаи жизни (вы же не используете 47 типов СХД)
|
||
- Альфа/бета-функции (нестабильные эксперименты)
|
||
|
||
**Что осталось:** полноценный Kubernetes, сертифицированный CNCF (Cloud Native Computing Foundation - организация, которая решает, что считать "настоящим" Kubernetes). Все манифесты работают. Helm работает. kubectl работает. Ответы со StackOverflow работают.
|
||
|
||
### Сравнение в цифрах
|
||
|
||
| Характеристика | Kubernetes | K3s |
|
||
|----------------|------------|-----|
|
||
| Размер | ~1.5GB образы | 50MB бинарник |
|
||
| RAM на control plane | ~2GB на ноду | ~500MB на ноду |
|
||
| Установка | kubeadm, 10+ шагов | один curl-скрипт |
|
||
| etcd | Отдельный кластер (3+ VM) | Встроенный |
|
||
| CNI | Нужно устанавливать | Flannel из коробки |
|
||
| Совместимость | 100% | 100% |
|
||
|
||
*"Но я потеряю гибкость!"* - скажете вы. Да, вы не сможете заменить сетевой плагин Flannel без пересборки. Это критично примерно для одного проекта из тысячи, и ваш homelab в их число не входит.
|
||
|
||
**Вердикт:** для homelab K3s - очевидный выбор. Теряем 5% гибкости, получаем 90% простоты.
|
||
|
||
---
|
||
|
||
## Что такое High Availability и зачем оно вам
|
||
|
||
**HA (High Availability)** - способность системы продолжать работу при отказе компонентов. Звучит как enterprise-термин для больших компаний? На практике это разница между "кластер упал в субботу, но я починил в понедельник" и "кластер сам пережил падение ноды, пока я спал".
|
||
|
||
### Без 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 нод нужно
|
||
|
||
Вот тут начинается интересное. Интуиция подсказывает: одна нода - плохо, две - уже лучше. Логично? Логично. И неправильно.
|
||
|
||
| Master нод | Выдержит отказов | Кворум | Вердикт |
|
||
|------------|------------------|--------|---------|
|
||
| 1 | 0 | 1/1 | Нет HA, но честно |
|
||
| 2 | 0 | **Ловушка!** | ⛔ Хуже, чем 1 |
|
||
| 3 | 1 | 2/3 | ✅ Минимум для HA |
|
||
| 5 | 2 | 3/5 | Для критичных систем |
|
||
|
||
### Почему 2 master ноды хуже, чем 1
|
||
|
||
etcd (база данных кластера, где хранится вообще всё) работает по принципу голосования. Чтобы записать данные, нужно согласие большинства нод. Не "хотя бы одной" - именно большинства.
|
||
|
||
Считаем:
|
||
|
||
- **1 нода:** большинство = 1. Упала - кластер мёртв. Честная игра, вы знали на что шли.
|
||
- **2 ноды:** большинство = 2. Упала одна - кворума нет, кластер мёртв. Сюрприз!
|
||
- **3 ноды:** большинство = 2. Одна упала - две оставшиеся продолжают работать.
|
||
|
||
Это как договор, требующий подписи обоих директоров - заболел один, и компания парализована.
|
||
|
||
С двумя нодами вы не получили отказоустойчивость. Вы удвоили количество точек отказа и назвали это "высокой доступностью".
|
||
|
||

|
||
|
||
**Правило:** или 1 нода (и честное понимание рисков), или 3+ (и настоящий HA). Двойка - ловушка для тех, кто не дочитал документацию.
|
||
|
||
---
|
||
|
||
## Embedded etcd vs External etcd
|
||
|
||
**etcd** - распределённое key-value хранилище. Единственный источник истины для всего состояния Kubernetes: все объекты (поды, сервисы, секреты), конфигурации, сетевые политики. Без etcd кластер не работает. Точка.
|
||
|
||
Есть два варианта архитектуры:
|
||
|
||
### External etcd (классический Kubernetes)
|
||
|
||
```
|
||
Control Plane (3 VM) etcd кластер (3 VM)
|
||
┌────────────────┐ ┌──────────────┐
|
||
│ API Server │ │ etcd-1 │
|
||
│ Scheduler │ ──────────────>│ (только etcd)│
|
||
│ Controller │ └──────────────┘
|
||
└────────────────┘ ┌──────────────┐
|
||
┌────────────────┐ │ etcd-2 │
|
||
│ API Server │ ──────────────>│ (только etcd)│
|
||
│ Scheduler │ └──────────────┘
|
||
│ Controller │ ┌──────────────┐
|
||
└────────────────┘ │ etcd-3 │
|
||
┌────────────────┐ │ (только etcd)│
|
||
│ API Server │ ──────────────>└──────────────┘
|
||
│ 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 |
|
||
| Масштаб | >500 нод | До 100-200 нод |
|
||
|
||
**Для homelab embedded etcd - очевидный выбор.** Теряем 5-10% производительности etcd, экономим 3 VM и часы настройки.
|
||
|
||
*"А если мне понадобится масштаб?"* - официально embedded etcd поддерживает до 100 нод и 5000 подов. Для homelab это как ограничение скорости 300 км/ч на велосипеде.
|
||
|
||
---
|
||
|
||
## Зачем отдельные worker ноды
|
||
|
||
**Worker ноды** - машины для запуска ваших приложений (подов). На них не запускаются компоненты control plane.
|
||
|
||
*"А можно запускать приложения прямо на master нодах?"*
|
||
|
||
Технически - да. K3s не ставит ограничений на master ноды (в отличие от обычного Kubernetes). Но это плохая идея:
|
||
|
||
- **Control plane должен быть стабильным.** Ваше приложение съело всю память → API server упал → кластер недоступен.
|
||
- **etcd чувствителен к диску.** База данных на той же ноде создаёт I/O нагрузку → etcd тормозит → весь кластер тормозит.
|
||
- **Изоляция отказов.** Проблема с приложением не должна убивать control plane.
|
||
|
||
**2 worker ноды - минимум для HA приложений:**
|
||
- Можно запускать 2 реплики (на разных нодах)
|
||
- При падении одного worker'а второй держит нагрузку
|
||
- Легко добавить третью, четвёртую ноду потом
|
||
|
||
---
|
||
|
||
## Архитектура нашего кластера
|
||
|
||
Вот что мы будем строить:
|
||
|
||

|
||
|
||
**Ключевые моменты:**
|
||
|
||
1. **Все master ноды равны** - нет "главной", kubectl подключается к любой.
|
||
2. **etcd синхронизируется через Raft** - алгоритм консенсуса, гарантирует согласованность данных.
|
||
3. **Workers знают только про API** - они не подключаются к etcd напрямую.
|
||
4. **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):**
|
||
|
||
Реальное потребление в idle:
|
||
- API server: ~200-300MB RAM
|
||
- etcd: ~100-200MB RAM (растёт со временем)
|
||
- Scheduler + Controller: ~150MB RAM
|
||
- Системные поды: ~100-200MB RAM
|
||
- **Итого:** ~600-900MB используется
|
||
|
||
*"Зачем тогда 8GB?"* - запас для burst-нагрузки. Когда вы деплоите 50 подов одновременно, API server временно съедает больше. etcd при большом кластере может вырасти до 1-2GB. Golang GC работает лучше с запасом памяти.
|
||
|
||
**Worker ноды (4 vCPU / 16GB RAM / 50GB Disk):**
|
||
|
||
Здесь будут ваши приложения. При 16GB можно запустить:
|
||
- 5-10 средних приложений (256MB-2GB каждое)
|
||
- Или 2-3 базы данных (PostgreSQL любит память)
|
||
- Или комбинацию
|
||
|
||
50GB диска - под образы контейнеров (10-20GB), логи (5-10GB), временные данные.
|
||
|
||
### Можно ли меньше?
|
||
|
||
**Минимальная конфигурация (для экспериментов):**
|
||
- Master: 1 vCPU / 4GB RAM / 20GB Disk
|
||
- Worker: 2 vCPU / 8GB RAM / 30GB Disk
|
||
- **Итого:** 9 vCPU / 36GB RAM
|
||
|
||
**Риски:**
|
||
- Медленная работа API server
|
||
- OOM killer при нагрузке
|
||
- Нет запаса для burst
|
||
|
||
Для production-like homelab рекомендую таблицу выше. Комфортный запас стоит дешевле, чем отладка странных падений.
|
||
|
||
---
|
||
|
||
## Сетевая схема
|
||
|
||
### 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 хост)
|
||
|
||
**Минимум:**
|
||
- CPU: 14 vCPU свободных
|
||
- RAM: 56GB свободных
|
||
- Disk: 200GB на SSD
|
||
- Network: 1 Gbit
|
||
|
||
**Рекомендуется:**
|
||
- CPU: 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) |
|
||
|
||
## Итог
|
||
|
||
**Что мы спроектировали:**
|
||
- 5 VM: 3 master + 2 worker
|
||
- K3s с embedded etcd (HA без лишних VM)
|
||
- Отказоустойчивость: выдерживает падение 1 master и любого worker
|
||
- Ресурсы: 14 vCPU / 56GB RAM / 196GB Disk
|
||
|
||
**Что НЕ входит в эту серию** (отдельные статьи):
|
||
- LoadBalancer (MetalLB)
|
||
- Ingress (Traefik)
|
||
- SSL (cert-manager)
|
||
- Мониторинг (Prometheus/Grafana)
|
||
|
||
---
|
||
|
||
## Что дальше
|
||
|
||
**👉 "Подготовить инфраструктуру для K3s в Proxmox"**
|
||
|
||
Там мы:
|
||
- Создадим template VM с Debian 12
|
||
- Склонируем 5 VM с правильными ресурсами
|
||
- Настроим статические IP
|
||
- Подготовим ОС (swap, cgroup v2, firewall) |