Пошаговый гайдз по развёртыванию кластера Kubernetes на bare-metal VPS с kubeadm, Calico, MetalLB и Longhorn. Окончательный результат — рабочий multi-node кластер с ingress и persistent storage за 60–120 минут.
0
Статья была полезной?
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…
Зачем K8s на VPS?
Вы получите рабочий кластер Kubernetes на собственных VPS без облачных провайдеров: контрол-плейн, сетевой плагин, ingress с MetalLB и дисковое хранилище. Время выполнения: 60–120 минут для трёх узлов при наличии стабильного интернета и прав root.
Что вы изучите
Установка kubeadm/kubelet/kubectl версии Kubernetes 1.31 (2026) и containerd 1.7 (2024).
Настройка сетевого плагина Calico 3.26 (2025) для bare-metal.
Развёртывание ingress с ingress-nginx 1.13 (2025) и MetalLB 0.14 (2025).
Организация persistent storage: local-path-provisioner для тестов и Longhorn 1.6 (2025) для продакшена.
Базовые меры безопасности: RBAC, NetworkPolicy, pod security admission и kube-bench.
Требования
ОС: Ubuntu 22.04 LTS (2022) или Ubuntu 24.04 (2024). Проверено на Debian 12 (2023).
Kubernetes: kubeadm/kubelet/kubectl 1.31.0 (релиз 2026) — используйте одну версию на всех узлах.
containerd 1.7.x (релиз 2024). Размер образов control-plane ~200–400 MB, image pull ~до 1 GB при первом запуске.
Минимум ОЗУ: control plane 4 GB, worker node 2 GB. CPU: control plane 2 vCPU, worker 1 vCPU. Рекомендуется 8 GB RAM для стабильной работы с Longhorn.
Порты: 6443 (kube-apiserver), 2379-2380 (etcd если локально), 10250 (kubelet), 30000-32767 (NodePort), 80/443 для ingress.
Права root на всех VPS, доступ по SSH между узлами.
Шаг 1: kubeadm init
Цель: подготовить узел control-plane и инициализировать кластер с kubeadm 1.31.0 и containerd 1.7. Проверки и приведение системы к требуемому состоянию.
# Отключите swap
sudo swapoff -a
# Удалите запись swap из /etc/fstab
sudo sed -i.bak '/swap/d' /etc/fstab
# Установите зависимости и containerd 1.7.x (пример для Ubuntu 22.04)
sudo apt-get update -y && sudo apt-get install -y ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update -y
sudo apt-get install -y containerd.io=1.7.0-1
# Генерируем дефолтный конфиг containerd и перезапускаем
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
Пояснение: swap должен быть отключён — kubelet откажется запускаться с активным swap. containerd 1.7 совместим с Kubernetes 1.31 на момент 2025–2026.
... [init] using Kubernetes version: v1.31.0
[preflight] Running pre-flight checks
[certs] Generated CA certificate and key
[certs] apiserver certificate signed
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kube-apiserver to be healthy: ...
Your Kubernetes control-plane has initialized successfully!
You should now deploy a pod network to the cluster.
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 10.0.0.5:6443 --token --discovery-token-ca-cert-hash sha256:
Типовая ошибка: swap включён
Error: [preflight] Some fatal errors occurred:
[ERROR Swap]: swap is enabled; production deployments should disable swap
Fix: sudo swapoff -a && remove swap line from /etc/fstab
Ещё одна ошибка: CRI not found
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR CRI]: container runtime is not running: output from systemctl status containerd: ...
Fix: убедитесь, что containerd запущен: sudo systemctl restart containerd && sudo systemctl status containerd
Шаг 2: сетевой плагин
Цель: установить Calico 3.26 (релиз 2025) для маршрутизации Pod-to-Pod и реализации NetworkPolicy. В примере используется CIDR 192.168.0.0/16, совместимый с kubeadm init выше.
# Установка Calico (версия 3.26)
kubectl apply -f https://docs.projectcalico.org/v3.26/manifests/calico.yaml
# Проверка
kubectl get pods -n kube-system -l k8s-app=calico-node
Ожидаемый вывод:
NAME READY STATUS RESTARTS AGE
calico-node-abcde 1/1 Running 0 30s
calico-node-fghij 1/1 Running 0 30s
calico-kube-controllers-12345 1/1 Running 0 30s
Типовая ошибка: DaemonSet не разворачивается (ImagePullBackOff или CrashLoopBackOff). Возможные причины и фиксы:
Error: ImagePullBackOff
Fix: проверьте доступность реестра и правильность версии образа. Если VPS за прокси, настройте /etc/systemd/system/containerd.service.d/http-proxy.conf
Error: CrashLoopBackOff
Fix: проверьте логи: kubectl logs -n kube-system daemonset/calico-node -c calico-node
Частая причина: отсутствующие sysctl для bridge. Убедитесь, что включено:
sudo modprobe br_netfilter
sudo sysctl -w net.bridge.bridge-nf-call-iptables=1
sudo sysctl -w net.ipv4.ip_forward=1
# Для постоянности добавьте в /etc/sysctl.d/99-kubernetes.conf
Шаг 3: ingress
Цель: обеспечить доступ к сервисам извне с помощью ingress-nginx 1.13 (2025) и MetalLB 0.14 (2025) как провайдера LoadBalancer для bare-metal.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.96.200.1 192.0.2.100 80:30080/TCP,443:30443/TCP 2m
metallb-controller ClusterIP 10.96.0.10 7472/TCP 1m
Типовая ошибка: MetalLB не назначает IP
Problem: EXTERNAL-IP remains <pending>
Fix: Убедитесь, что IP-пул доступен в той же L2 сети, где находятся VPS, либо настройте BGP (требует роутера). На VPS провайдера спросите, разрешён ли ARP для дополнительных адресов.
Типовая ошибка: ingress-nginx CrashLoopBackOff после установки
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
Fix: проверьте, что порт 80/443 не занят на хосте. На bare-metal ingress-nginx использует hostPort или DaemonSet; конфликт с локальным nginx решается остановкой локального сервиса или настройкой NodePort.
Скриншот kubectl get svc с External-IP, выделенным MetalLB
Шаг 4: storage
Цель: предоставить динамическое PersistentVolume на bare-metal. Два варианта: lightweight для тестов — local-path-provisioner; production — Longhorn 1.6 (2025).
# Вариант A: local-path-provisioner (легковесный, для dev)
kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
kubectl get storageclass
# Вариант B: Longhorn 1.6 (рекомендуется для продакшена на нескольких дисках)
kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.6.0/deploy/longhorn.yaml
# После установки зайдите в UI Longhorn через Service type=LoadBalancer (используя MetalLB IP)
Ожидаемый вывод для local-path:
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE AGE
local-path (default) rancher.io/local-path Delete WaitForFirstConsumer 5m
Ожидаемый вывод для Longhorn:
kubectl -n longhorn-system get pods
NAME READY STATUS RESTARTS AGE
longhorn-driver-deployer-xxxxx 1/1 Running 0 3m
longhorn-manager-xxxxx 2/2 Running 0 3m
longhorn-ui-xxxxx 1/1 Running 0 3m
Типовая ошибка: PVC остаётся в Pending
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
data-pvc Pending ----- ----- ----- local-path 2m
Fix: Проверьте StorageClass по умолчанию (kubectl get storageclass). Для local-path убедитесь, что nodeSelector в DaemonSet совпадает с узлом, где есть диск. Для Longhorn проверьте, что на каждом узле есть доступные диски и longhorn-manager в статусе Running.
Скриншот интерфейса Longhorn UI с перечнем томов
Когда K8s избыточен?
Используйте Kubernetes, когда у вас несколько микросервисов (обычно больше 3—5), требуется автоматическое масштабирование, управление конфигурацией, и отказоустойчивость. На VPS с маленькими ресурсами K8s часто слишком тяжёл: контроль-плейн должен работать минимум 4 GB RAM и 2 vCPU для стабильности, каждый kubelet потребляет ~50–150 MB, система добавляет оверхед сетевого плагина и CSI. Для простого сайта с одной базой данных и одним HTTP-сервисом лучше использовать systemd + nginx или Docker Compose — это зачастую экономнее и проще в сопровождении.
Конкретные признаки избыточности:
Меньше 3 сервисов и низкая нагрузка (до ~100 RPS).
Ограничение бюджета по ОЗУ: суммарно доступно меньше 6 GB для всех VPS.
Требуется минимальное время отклика без сложности K8s-операций и обновлений.
Что с безопасностью?
Подход: многоуровневый. Базовые шаги для bare-metal VPS кластеров — включить RBAC, NetworkPolicy, PodSecurity admission, ограничить доступ к kube-apiserver, настроить TLS для всего трафика и использовать audit logging. Ниже — конкретные команды и рекомендации.
# Включите PodSecurity в namespace, пример для strict-политики
kubectl label namespace default pod-security.kubernetes.io/enforce=baseline
# Установите kube-bench для проверки соответствия CIS
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl logs job.kube-bench -n default
Результат kube-bench — примеры проблем и исправления (усечённый вывод):
[INFO] 1.1 - Master Node Security: OK
[WARN] 1.5 - Ensure that the etcd data directory permissions are set to 700: WARNING
[PASS] 4.1 - Ensure that the kubelet certificate authorities file permissions are set to 0644: PASS
Fix: Для etcd chmod 700 /var/lib/etcd && chown etcd:etcd /var/lib/etcd
Другие важные шаги:
Ограничьте доступ к API по IP или VPN. На bare-metal используйте firewall (ufw/iptables) и проброс портов только для доверенных IP.
Используйте NetworkPolicy (Calico поддерживает) для сегментации трафика: запрещайте межсервисные соединения по умолчанию и открывайте только необходимое.
Регулярно обновляйте Kubernetes и CNI. План обновлений: каждые 3–6 месяцев, патчи безопасности — как только доступны.
Шифруйте etcd: если etcd на той же машине, включите TLS и резервное копирование конфигурации, храните ключи отдельно.
Полезные команды для аудита и мониторинга:
# Проверить версию компонентов
kubectl version --short
# Проверить доступные токены/сертификаты
kubectl get secrets -n kube-system
# Просмотр NetworkPolicy
kubectl get networkpolicy --all-namespaces
Инструменты для мониторинга: Prometheus (версия 2.40, 2025), Grafana 9.x (2025). Для логов: EFK/Opensearch. Для проверки конфигурации используй kube-bench и kube-hunter.
Какой минимальный набор ресурсов нужен для рабочего кластера?
Минимальный набор для тестового кластера: один control-plane с 4 GB RAM и 2 vCPU и один worker с 2 GB RAM и 1 vCPU. Для production рекомендуется минимум три control-plane узла с 4–8 GB RAM и 2–4 vCPU каждый, а также несколько worker узлов в зависимости от нагрузки. Control plane потребляет дополнительно место для журналов и образов: планируйте не менее 20–30 GB дискового пространства. Longhorn требует нескольких GB на каждом узле для реплик томов.
Что делать, если worker не присоединяется к кластеру?
Проверьте токен и discovery-token-ca-cert-hash, выданные командой kubeadm init. На worker выполните команду join и смотрите ошибки: если ошибка "x509: certificate signed by unknown authority", проверьте корректность хэша SHA256. Если соединение прерывается, проверьте сетевые правила: доступ по TCP 6443 от worker к control plane должен быть открыт. Также убедитесь, что время синхронизировано (ntpd/chrony) — расхождение времени может вызвать TLS-ошибки.
Зачем MetalLB на VPS?
В облаке провайдер предоставляет тип Service=LoadBalancer. На bare-metal такой возможности нет, потому MetalLB реализует функциональность LoadBalancer на уровне L2 (ARP) или BGP. MetalLB позволяет назначать внешние IP адреса из пула и работает с ingress-nginx: это даёт стабильный внешний IP для сервисов и UI (например, Longhorn UI). Для L2 требуется управление ARP в вашей сети и свободный пул IP, обычно выделяемый провайдером.
Когда нужно обновлять Kubernetes и как это делать?
Обновления безопасности — как только доступно критическое исправление. Плановые обновления делайте один раз в 3–6 месяцев и тестируйте на staging. Используйте kubeadm upgrade plan и kubeadm upgrade apply v1.X.Y для control plane, затем обновите kubelet/kubectl на каждом узле и перезапустите kubelet. Всегда делайте бэкап etcd перед обновлением и проверяйте совместимость CNI/CSI плагинов с целевой версией.
Какие ещё ресурсы читать?
Документация проектов: официальный kubeadm (kubernetes.io), Calico (projectcalico.org), MetalLB (metallb.universe.tf) и Longhorn (longhorn.io). Для практик безопасности используйте CIS Kubernetes Benchmark и инструменты kube-bench/kube-hunter. См. также материалы в разделе DevOps и примеры контейнеризации в Docker.
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…