Акция Панель управления ispmanager для VDS — первый месяц бесплатно
до 31.07.2026 Подробнее
Выберите продукт

k0s на VDS: минималистичный Kubernetes с ingress, CNI и хранилищем

Пошагово поднимем лёгкий k0s Kubernetes на VDS: подготовим ОС и firewall, выберем CNI и MTU, настроим динамическое хранилище и развернём ingress-nginx без внешнего балансировщика. В конце — грабли, апгрейды, бэкапы и базовая безопасность.
k0s на VDS: минималистичный Kubernetes с ingress, CNI и хранилищем

Лёгкие дистрибутивы Kubernetes спроектированы для простоты и экономии ресурсов. k0s — один из самых «компактных» вариантов: единый бинарник, встроенный containerd, разумные дефолты. На небольшом VDS это позволяет получить полноценный кластер без громоздких установщиков и сложных зависимостей — отличный вариант для pet-проектов, staging, edge и даже аккуратного продакшна.

В этой инструкции мы развернём k0s на VDS, настроим CNI, выберем практичное динамическое хранилище и поднимем ingress без внешнего балансировщика (через hostPort/hostNetwork). Параллельно разберём firewall, версии ядра, MTU, типовые ошибки и апгрейд.

Когда k0s уместен на VDS

k0s хорош, когда нужно получить «настоящий» Kubernetes, но без лишнего веса и долгой притирки компонентов. Он:

  • быстро устанавливается (единый бинарник, auto-bootstrapping control plane);
  • экономно расходует CPU/RAM (важно на небольших тарифах VDS);
  • совместим с привычной экосистемой: Helm, CSI/CNI, ingress-контроллеры;
  • подходит для single-node и простого масштабирования до нескольких узлов.

Если вам нужен минимальный, но полноценный Kubernetes на одном или паре серверов, k0s обычно проще и стабильнее, чем самостоятельный kubeadm с ручной сборкой компонентов.

План работ

Мы пройдём следующие шаги:

  1. Подготовим VDS: OS, sysctl, firewall, порты и swap.
  2. Установим k0s (single-node controller+worker на одном сервере).
  3. Выберем CNI и настроим MTU.
  4. Добавим динамическое хранилище для PVC (local-path/OpenEBS).
  5. Развернём ingress-nginx без внешнего LB (hostPort).
  6. Проверим деплой с тестовым сервисом и Ingress.
  7. Обсудим апгрейды, бэкапы и масштабирование до 2–3 узлов.

Требования и подготовка VDS

Минимальные ресурсы

  • CPU: 2 vCPU (минимум), 4 vCPU комфортнее;
  • RAM: 4 ГБ минимально, 8 ГБ комфортнее;
  • Диск: 20–40 ГБ для базового кластера, SSD.

Рекомендуемые ОС: Ubuntu 22.04/24.04 LTS или Debian 12. Ядро с поддержкой cgroup v2 и nftables (по умолчанию есть в современных LTS).

Подготовка системы

Обновления и базовые пакеты:

sudo apt update
sudo apt -y upgrade
sudo apt -y install ca-certificates curl gnupg lsof jq ufw

Отключите swap (Kubernetes этого требует):

sudo swapoff -a
sudo sed -ri '/\sswap\s/s/^/#/' /etc/fstab

Сетевые sysctl для корректной работы CNI (мост и пересылка):

# /etc/sysctl.d/99-kubernetes.conf
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
sudo sysctl --system

Желательно убедиться, что загружены модули ядра для мостов и vxlan (если выберете Flannel или kube-router):

lsmod | egrep 'br_netfilter|vxlan'

Если пусто — загрузите:

echo br_netfilter | sudo tee /etc/modules-load.d/k8s.conf
echo vxlan | sudo tee -a /etc/modules-load.d/k8s.conf
sudo modprobe br_netfilter
sudo modprobe vxlan

Firewall и порты

Базовый набор для single-node с ingress на 80/443 и kube-router/Flannel:

  • 22/tcp — SSH;
  • 6443/tcp — Kubernetes API (нужен для join/администрирования);
  • 10250/tcp — kubelet (внутренний, обычно открыт локально);
  • 8472/udp — Flannel VXLAN (или иные порты для выбранного CNI);
  • 80/tcp и 443/tcp — для ingress;
  • 30000–32767/tcp,udp — NodePort (если будете использовать).
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 6443/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 8472/udp
sudo ufw enable

Если выберете Cilium — проверьте требования к портам и возможностям ядра (eBPF). Для Calico/Flannel — убедитесь, что UDP для оверлея не блокируется провайдером.

Порты и UFW для k0s-кластера с ingress

Установка k0s (single-node)

Штатный установщик k0s — это скрипт, который скачивает/обновляет бинарник:

curl -sSLf https://get.k0s.sh | sudo sh

Поставим контроллер и воркер на один узел:

sudo k0s install controller --single
sudo k0s start

Проверим статус:

sudo k0s status

Получим kubeconfig и настроим kubectl:

sudo mkdir -p /root/.kube
sudo cp /var/lib/k0s/pki/admin.conf /root/.kube/config
sudo chown root:root /root/.kube/config
kubectl get nodes -o wide

Через пару минут узел должен перейти в Ready.

Выбор и настройка CNI

k0s поддерживает несколько CNI. Для VDS практичны:

  • kube-router — простой, быстрый, без «излишеств»;
  • Flannel — «классика» для оверлея VXLAN;
  • Cilium — eBPF, продвинутые политики, но требует более внимательной проверки ядра/MTU.

Сконфигурировать провайдер можно через файл кластера. Базовый пример с kube-router и заданной MTU (важно на облачных сетях с меньшим MTU):

# k0s.yaml
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
  name: vds-k0s
spec:
  network:
    provider: kuberouter
    mtu: 1450
  kubeProxy:
    mode: iptables

Применение конфига при установке с нуля:

sudo k0s stop
sudo k0s install controller --single --config k0s.yaml
sudo k0s start

Если меняете CNI на работающем кластере — планируйте короткое окно: изменение сетевого провайдера затрагивает все Pod-сети. Для Cilium дополнительно может потребоваться настройка eBPF (разрешение forwarding, корректная MTU, BPF FS).

Динамическое хранилище (Storage)

Для stateful-приложений нужны PVC с динамическим провиженингом. На одном VDS комфортнее всего:

  • local-path-provisioner — простой провиженер, создающий PV в локальной файловой системе;
  • OpenEBS LocalPV (hostpath/LVM) — гибче, удобно задавать директории/диски.

Минимальная стратегия — local-path. После установки провиженера назначьте его классом по умолчанию. Пример StorageClass (если используете local-path-provisioner):

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-path
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: rancher.io/local-path
volumeBindingMode: WaitForFirstConsumer

Если хотите жёстко контролировать путь хранения, подойдёт OpenEBS LocalPV hostpath: он позволяет указать директорию для томов, например /var/lib/k0s/localpv. Для продакшна на одном узле используйте регулярные бэкапы PV (rsync или снапшоты LVM — зависит от реализации).

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Ingress без внешнего балансировщика

На одиночном VDS обычно нет managed LoadBalancer. Самые практичные схемы:

  • ingress-nginx с hostPort 80/443 на самом узле;
  • ingress-nginx с hostNetwork=true;
  • или внешний Nginx на «хосте» и проксирование в Service NodePort (требует отдельного сервисного Nginx и больше ручной поддержки).

Рассмотрим вариант с hostPort (самый «чистый» для одного узла):

kubectl create namespace ingress-nginx
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx --set controller.hostPort.enabled=true --set controller.hostPort.ports.http=80 --set controller.hostPort.ports.https=443 --set controller.service.type=ClusterIP --set controller.kind=DaemonSet

Через DaemonSet контроллер будет слушать 80/443 на узле. Если кластер станет многонодовым, все узлы с контроллером будут открывать 80/443 — обычно достаточно оставить метки и nodeSelector, чтобы ограничить узел(-ы) приёма трафика. Для выбора между Nginx/Traefik/HAProxy посмотрите наш обзор вариантов ingress-контроллеров.

Далее — пробный Ingress-объект. Сначала деплоим echo-сервис:

kubectl create namespace demo
kubectl -n demo create deployment echo --image=nginxdemos/hello
kubectl -n demo expose deployment echo --port=80 --target-port=80

Теперь Ingress (замените example.com на ваш домен и укажите A-запись на IP VDS; при необходимости — регистрация доменов):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echo
  namespace: demo
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "20m"
spec:
  ingressClassName: nginx
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: echo
            port:
              number: 80

Проверьте доступность по HTTP. Для HTTPS используйте cert-manager или заранее подготовленный секрет TLS. Если нужен проверенный коммерческий сертификат, оформите SSL-сертификаты. Пример с TLS-секретом:

apiVersion: v1
kind: Secret
metadata:
  name: echo-tls
  namespace: demo
type: kubernetes.io/tls
data:
  tls.crt: BASE64_CERT
  tls.key: BASE64_KEY
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echo
  namespace: demo
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - example.com
    secretName: echo-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: echo
            port:
              number: 80

Проверка ingress-nginx и демо-сервиса в k0s

В многонодовом сценарии удобно поставить MetalLB в режиме L2 и использовать Service типа LoadBalancer для ingress-nginx. На одиночном VDS hostPort/hostNetwork остаётся самым простым и надёжным вариантом.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Масштабирование: добавляем worker-узлы

k0s упрощает join: создайте токен для воркеров на контроллере и выполните установку на новых узлах.

# На контроллере:
sudo k0s token create --role=worker --expiry=24h

На новом узле установите k0s бинарник и выполните:

sudo k0s install worker --token <скопированный_токен>
sudo k0s start

Через минуту узел появится в kubectl get nodes. Проверьте MTU и firewall между узлами для вашего CNI. Если узлы в разных сетях — удобно связать их через туннель, например WireGuard; мы разбирали практику поддержания связи в статье про роуминг и keepalive.

Апгрейды k0s и кластера

Обновление k0s по месту:

curl -sSLf https://get.k0s.sh | sudo K0S_VERSION=<target> sh
sudo k0s stop
sudo k0s start
k0s version
kubectl version --short

При минорных апгрейдах соблюдайте совместимость мажорных версий Kubernetes и CRD ваших компонентов (ingress, CSI/CNI). Рекомендуются «мелкие» ступени (например, 1.28 → 1.29), предварительный бэкап и проверка на staging.

Бэкапы и восстановление

На single-node кластере критичны:

  • снимки etcd;
  • бэкапы PV (в зависимости от выбранного провиженера: файловые копии, снапшоты LVM или экспорт).

Снимок etcd с контроллера:

sudo k0s etcd snapshot save /var/lib/k0s/etcd-snap-$(date +%F-%H%M).db
ls -lh /var/lib/k0s/

Храните бэкапы вне узла (объектное хранилище или другой сервер). Регулярно тестируйте восстановление — хотя бы на временном узле.

Наблюдаемость и базовый SRE-минимум

  • metrics-server для kubectl top и HPA;
  • логирование: fluent-bit → централизованное хранилище или локально в journald с ротацией;
  • алертинг: минимум health-checks на API-сервер и HTTP 200 на ingress-домены.

Проверьте лимиты контейнеров: выставляйте resources.requests/limits, иначе одно приложение может «съесть» всю RAM/CPU узла. Для ingress-nginx задайте разумные таймауты (proxy-read-timeout, proxy-body-size) через аннотации/ConfigMap.

Частые проблемы и решения

  • Pod в статусе CrashLoopBackOff: проверьте kubectl logs, ресурсы, образ, переменные окружения.
  • Распадается сеть между узлами: проверьте MTU, открыты ли порты CNI, не режет ли провайдер UDP.
  • Ingress 404/502: верен ли ingressClassName (обычно nginx), совпадает ли host, существует ли Service/Endpoints.
  • DNS не резолвит: статус CoreDNS, проверка kube-dns Service, сетевой плагин.
  • Проблемы с TLS: корректен ли секрет, совпадают ли CN/SAN и домен, нет ли лишних переносов при base64.

Продакшн-минимум для VDS-кластера

  • Отдельный системный пользователь и SSH-ключи, fail2ban/защита SSH.
  • Автообновления безопасности ОС и перезагрузка ядра в плановое окно.
  • Мониторинг доступности API-сервера, ingress-доменов, диска и inode.
  • Регулярные бэкапы etcd и PV, проверка восстановления.
  • Ресурсные запросы/лимиты, Readiness/Liveness пробы в ваших Deployment.
  • Разделение namespace, RBAC для сервисных аккаунтов, секреты через Secret/External Secrets.

Что дальше

Для нескольких узлов: MetalLB (L2) + Service LoadBalancer для ingress-nginx; Cilium eBPF для сетевых политик; OpenEBS LVM для предсказуемого локального хранения; cert-manager для автоматизации TLS; GitOps и Helm-чарты для повторяемых деплоев. Для миграций доменов и TLS-практик также будет полезна статья о HSTS и 301.

k0s даёт современный Kubernetes-опыт без перегруза — особенно на VDS. С правильным выбором CNI, storage и ingress ваш кластер будет достаточно лёгким для небольших бюджетов и достаточно гибким для роста.

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину

Ошибка mount: wrong fs type, bad option, bad superblock в Debian/Ubuntu может означать и простую опечатку в имени раздела, и пробл ...
Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление

Если XFS-раздел внезапно стал доступен только для чтения, а сервер ушёл в emergency mode, главное — не спешить. Разберём безопасны ...
Debian/Ubuntu: как исправить Failed to fetch при apt update OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить Failed to fetch при apt update

Ошибка Failed to fetch при apt update в Debian и Ubuntu обычно связана не с самим APT, а с DNS, сетью, зеркалом, прокси, временем ...