MAATRIX / Блог / Как установить и настроить k3s на VPS

Как установить и настроить k3s на VPS

Как установить и настроить k3s на VPS

MAATRIX

Полноценный Kubernetes на VPS с двумя гигабайтами памяти не заводится: один kube-apiserver съедает больше, чем есть у машины. k3s решает ту же задачу одним бинарником на ~70 МБ, внутри которого уже лежат containerd, CoreDNS и Traefik. Разберём, как выглядит k3s установка на VPS от подготовки системы до приложения с HTTPS — с командами, текстами ошибок и граблями арендованной машины.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое k3s и что он тянет за собой

k3s — дистрибутив Kubernetes от SUSE, сертифицированный CNCF. Это не урезанная копия: те же манифесты, kubectl и Helm-чарты. Отличие в упаковке: вместо пяти сервисов и внешнего etcd — один бинарник и один юнит systemd, а внутри собрано то, что ставят обычно отдельно:

КомпонентЧто делаетКак отключить
flannel (VXLAN)сеть подов, 10.42.0.0/16--flannel-backend=none
CoreDNSDNS кластера на 10.43.0.10--disable=coredns
Traefik v3Ingress-контроллер на 80/443--disable=traefik
local-path-provisionerPVC в /var/lib/rancher/k3s/storage--disable=local-storage

Главное отличие: состояние лежит не в etcd, а в SQLite через слой kine — файл /var/lib/rancher/k3s/server/db/state.db. Это экономит сотни мегабайт, но означает одно: отказоустойчивого control-plane на SQLite не бывает. Для HA нужен встроенный etcd: --cluster-init и три сервера.

Готовим VPS: виртуализация, cgroup, swap и порты

До установки проверьте тип виртуализации и версию cgroup. На OpenVZ и большинстве LXC-контейнеров k3s либо не стартует, либо ведёт себя непредсказуемо: нет своего ядра, не грузятся overlay и br_netfilter.

systemd-detect-virt
stat -fc %T /sys/fs/cgroup/

Первая должна ответить kvm, qemu или none; openvz или lxc — берите другой сервер. Вторая — cgroup2fs: на Ubuntu 24.04, Debian 12/13 и AlmaLinux 9/10 так из коробки, tmpfs означает cgroup v1 с худшими лимитами.

Swap выключаем: kubelet считает память без его учёта, и вытеснение подов становится случайным. Часы синхронизируйте через timedatectl set-ntp true — сертификаты кластера завязаны на время.

swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab
hostnamectl set-hostname k3s-uk-1

Уникальное имя хоста задавайте до установки: машины разворачивают из готового образа, и две ноды приезжают с одинаковым ubuntu-2204 — выстрелит это при добавлении воркера. Дальше фаервол:

ufw allow 22/tcp
ufw allow 6443/tcp
ufw allow 80,443/tcp
ufw allow from 10.42.0.0/16 to any
ufw allow from 10.43.0.0/16 to any
ufw --force enable

Две последние строки критичны и их постоянно забывают: без подсетей подов и сервисов ufw режет внутрикластерный трафик, и в логах появляется dial tcp 10.43.0.10:53: i/o timeout. Выглядит как «сломался CoreDNS», хотя сломан фаервол.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть k3s

Установка сервера: config.yaml до запуска, а не после

Типовая инструкция предлагает curl -sfL https://get.k3s.io | sh - и разбираться потом. На VPS правильнее сначала положить конфиг: тогда первый запуск выпишет сертификаты с нужными именами.

mkdir -p /etc/rancher/k3s
cat >/etc/rancher/k3s/config.yaml <<'EOF'
node-name: k3s-uk-1
write-kubeconfig-mode: "0600"
tls-san:
  - 185.203.11.42
  - k3s.example.com
disable:
  - metrics-server
EOF

Файл принимает имена флагов без двух дефисов. tls-san — дополнительные адреса в сертификате API-сервера: публичный IP и домен. metrics-server выключайте, если не нужен kubectl top: минус около 60 МБ. Версию не оставляйте на самотёк:

curl -s https://update.k3s.io/v1-release/channels | jq -r '.data[] | select(.name=="stable") | .latest'
curl -sfL https://get.k3s.io | INSTALL_K3S_CHANNEL=stable sh -

Первая ответит вроде v1.33.4+k3s1; нужна конкретная — передайте её в INSTALL_K3S_VERSION. Скрипт положит бинарник в /usr/local/bin/k3s, симлинки kubectl, crictl, ctr и юнит k3s.service. До состояния Ready на 2 vCPU — около 40 секунд.

k3s kubectl get nodes -o wide
NAME       STATUS   ROLES                  AGE   VERSION        INTERNAL-IP   CONTAINER-RUNTIME
k3s-uk-1   Ready    control-plane,master   62s   v1.33.4+k3s1   10.0.0.5      containerd://2.0.5-k3s2

Самопроверка k3s check-config скажет, чего не хватает в ядре провайдера. Где что лежит: данные и БД — /var/lib/rancher/k3s/, kubeconfig — /etc/rancher/k3s/k3s.yaml, токен воркеров — /var/lib/rancher/k3s/server/node-token; YAML из /var/lib/rancher/k3s/server/manifests/ применяется при старте сам. По памяти: на тестовом VPS 2 vCPU / 2 ГБ free -m показывает порядка 600 МБ в покое, из них ~500 МБ — сам k3s; без Traefik и metrics-server — 430 МБ.

kubeconfig: доступ к кластеру снаружи и ошибка x509

На сервере проще работать через k3s kubectl. Если запустить голый kubectl, встретите классику:

The connection to the server localhost:8080 was refused - did you specify the right host or port?

kubectl просто не знает, где кластер, и идёт на localhost:8080. Лечится копией конфига — sudo install -o "$USER" -g "$USER" -m 600 /etc/rancher/k3s/k3s.yaml ~/.kube/config. Частый совет выставить write-kubeconfig-mode: "0644" вредный: в файле сертификат уровня cluster-admin, и 644 отдаёт полный доступ к кластеру любому пользователю машины. Чтобы управлять с ноутбука, конфиг забирают и подменяют адрес:

ssh root@185.203.11.42 cat /etc/rancher/k3s/k3s.yaml | sed 's/127.0.0.1/185.203.11.42/' > ~/.kube/k3s-uk.yaml
chmod 600 ~/.kube/k3s-uk.yaml && export KUBECONFIG=~/.kube/k3s-uk.yaml

И здесь вылезает ошибка, из-за которой кластер часто сносят заново:

Unable to connect to the server: tls: failed to verify certificate: x509: certificate is valid for 10.43.0.1, 127.0.0.1, 10.0.0.5, ::1, not 185.203.11.42

Сертификат выписан на внутренние адреса, а вы стучитесь по публичному — от этого и спасает tls-san. Добавьте адрес и выполните systemctl restart k3s; если ошибка осталась, старый сертификат никуда не делся — удалите его:

rm -f /var/lib/rancher/k3s/server/tls/serving-kube-apiserver.{crt,key}
systemctl restart k3s

Корневой CA не меняется, скопированный kubeconfig останется рабочим. И про безопасность: открытый в интернет 6443 будут сканировать — ограничьте источник через ufw allow from 203.0.113.7 to any port 6443 proto tcp либо ходите SSH-туннелем ssh -N -L 6443:127.0.0.1:6443 root@185.203.11.42.

Воркер-ноды: как соединить несколько VPS в один кластер

Токен лежит в /var/lib/rancher/k3s/server/node-token, вид у него такой: K10c9f3...::server:1a2b3c.... На втором VPS:

curl -sfL https://get.k3s.io | K3S_URL=https://185.203.11.42:6443 \
  K3S_TOKEN='K10c9f3...::server:1a2b3c...' sh -s - agent \
  --node-ip 91.198.174.12 --node-external-ip 91.198.174.12

Флаги --node-ip и --node-external-ip обязательны, когда ноды в разных дата-центрах: иначе агент объявит серверу приватный адрес внутренней сети, и поды на разных нодах не свяжутся. Дальше две ошибки из journalctl -u k3s-agent -f:

level=error msg="Failed to validate connection to cluster at https://185.203.11.42:6443: Get \"https://185.203.11.42:6443/cacerts\": dial tcp 185.203.11.42:6443: i/o timeout"

Это фаервол: 6443 закрыт для IP агента, откройте его адресно. Вторая ошибка — следствие клонирования VPS из снапшота:

Node password rejected, duplicate hostname or contents of '/etc/rancher/node/password' may not match server node-passwd entry

k3s привязывает пароль ноды к имени, а у вас две машины с одинаковым hostname. Лечение — уникальное имя и снос пароля на агенте и записи на сервере:

hostnamectl set-hostname k3s-uk-2
rm -f /etc/rancher/node/password
kubectl -n kube-system delete secret k3s-uk-2.node-password.k3s
systemctl restart k3s-agent

Порты кластера: 6443/tcp на серверы, 8472/udp между нодами (VXLAN flannel), 10250/tcp (метрики kubelet), 2379-2380/tcp между серверами при etcd, 51820/udp при WireGuard. И главное про ноды в разных ДЦ: flannel в режиме VXLAN не шифрует трафик — поды общаются по интернету открытым текстом. Ставьте первый сервер сразу со строкой flannel-backend: wireguard-native в config.yaml, на лету режим не переключается; плата — 10–15% пропускной способности. Следите за MTU: VXLAN отъедает 50 байт от кадра, и симптом просевшего MTU — зависающие TLS-рукопожатия при живом ping, проверка ping -M do -s 1372 91.198.174.12.

Первое приложение: Ingress, TLS, диск и реестр образов

Traefik уже слушает 80 и 443 через ServiceLB, свой балансировщик не нужен. Тег cert-manager сверьте с актуальным релизом.

kubectl create deployment web --image=nginx:1.29-alpine --replicas=2
kubectl expose deployment web --port=80
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.18.2/cert-manager.yaml

Выпускающий центр и ингресс одним манифестом:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef: {name: letsencrypt-prod}
    solvers: [{http01: {ingress: {class: traefik}}}]
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
  annotations: {cert-manager.io/cluster-issuer: letsencrypt-prod}
spec:
  ingressClassName: traefik
  tls: [{hosts: [app.example.com], secretName: web-tls}]
  rules:
    - host: app.example.com
      http:
        paths:
          - {path: /, pathType: Prefix, backend: {service: {name: web, port: {number: 80}}}}

Через минуту kubectl get certificate покажет READY True. Если Falsekubectl describe challenge: почти всегда A-запись ещё не указывает на IP ноды либо закрыт 80-й порт, без которого HTTP-01 не пройдёт.

Диск: StorageClass local-path работает из коробки, данные ложатся в /var/lib/rancher/k3s/storage/. Ограничение существенное — том привязан к ноде, только ReadWriteOnce, репликации нет: потеряли ноду, потеряли данные. Для нескольких нод — Longhorn.

Реестр образов — частая внезапная проблема при установке с российского адреса:

Failed to pull image "nginx:1.29-alpine": failed to resolve reference "docker.io/library/nginx:1.29-alpine": unexpected status from HEAD request to https://registry-1.docker.io/v2/library/nginx/manifests/1.29-alpine: 403 Forbidden

Docker Hub отдаёт 403 на диапазоны российских провайдеров. Лечится зеркалом в /etc/rancher/k3s/registries.yaml; после правки обязателен systemctl restart k3s — файл читается только при старте.

mirrors:
  docker.io:
    endpoint:
      - "https://mirror.gcr.io"

На ноде в Лондоне или Нью-Йорке этой возни нет: Docker Hub, ghcr.io и quay.io отдают образы напрямую. Из эксплуатации помните: обновление — повторный запуск установщика, сначала серверы, потом агенты; бэкап — k3s etcd-snapshot save или копия state.db на остановленном сервисе; чистка — k3s crictl rmi --prune, сам containerd образы не удаляет.

Какой сервер взять под k3s в MAATRIX

У k3s жёсткий пол: control-plane в покое занимает 500–600 МБ. На VPS с 1 ГБ на поды остаётся 300–400 МБ, и первая же сборка или миграция БД закончится OOMKilled с кодом 137.

СценарийКонфигурацияЧто реально помещается
Изучить, тестовый стенд2 vCPU / 2 ГБ / 30 ГБ NVMek3s и 3–5 лёгких подов
Один боевой узел4 vCPU / 8 ГБ / 80 ГБ NVMe15–25 подов: БД, кэш, 2–3 приложения, раннер CI
Сервер и два воркера4/8 ГБ + 2 × 2/4 ГБразнос нагрузки, обновление нод без простоя
HA control-plane3 × 4 vCPU / 8 ГБ / 80 ГБвстроенный etcd, переживает падение одной ноды

Три уточнения. Диск обязательно NVMe: SQLite и etcd упираются в задержку fsync, на медленном хранилище API-сервер сыплет etcdserver: request timed out. Объём берите с запасом — 20 ГБ уходят за пару месяцев деплоев на слои образов и логи в /var/log/pods. И не растягивайте HA-тройку по странам: etcd плохо переносит RTT выше 20–30 мс между членами кворума.

По локации для k3s мы обычно советуем UK, Лондон: 10–20 мс до европейских точек обмена, GDPR-периметр для клиентов из ЕС и чистый IP — образы из Docker Hub, ghcr.io и quay.io тянутся без 403 и зеркал, Let's Encrypt проходит HTTP-01 без сюрпризов. FR даёт то же для континентальной Европы, US в Нью-Йорке — если в кластере есть обращения к зарубежным ИИ-API, RU — когда данные обязаны лежать в России по 152-ФЗ. Оплата — картами РФ, по СБП, криптой или токеном MAAT.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть k3s

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Можно ли поставить k3s на VPS с 1 ГБ RAM?

Технически да, кластер поднимется. Но control-plane заберёт 500–600 МБ, и на контейнеры останется меньше половины гигабайта. Рабочий минимум — 2 ГБ, боевой — 4 ГБ.

k3s — настоящий Kubernetes?

Да, сертифицированный CNCF: те же манифесты, kubectl, Helm и операторы. Отличия в упаковке — один бинарник вместо набора сервисов и SQLite вместо etcd по умолчанию.

Как удалить k3s начисто?

Запустите /usr/local/bin/k3s-uninstall.sh на сервере или /usr/local/bin/k3s-agent-uninstall.sh на агенте. Скрипт удалит и /var/lib/rancher/k3s вместе с данными PVC — сначала сделайте копию нужного.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.