17-kubernetes — Kubernetes (k3s + kubectl + helm)
Ставит лёгкий Kubernetes-дистрибутив k3s, ждёт готовности узла, копирует доступ (kubeconfig) деплой-пользователю, ставит Helm и открывает нужные порты в файрволе. Поддерживает одиночный сервер и HA-кластер из нескольких серверов. ☐ опциональный.
Зачем нужен
Kubernetes (сокращённо «k8s») — это система оркестрации контейнеров: она сама запускает ваши приложения-контейнеры на серверах, перезапускает упавшие, держит нужное число копий (реплик), обновляет их без простоя и распределяет нагрузку. Вы описываете «что должно работать», а Kubernetes следит, чтобы так и было.
k3s — это официальный облегчённый дистрибутив Kubernetes (сертифицирован CNCF), собранный в один бинарник. Он идеально подходит для одного продакшен-сервера: внутри уже есть containerd (среда запуска контейнеров), поэтому Docker не требуется. При этом это полноценный Kubernetes — те же kubectl, манифесты и Helm.
Модуль ставит k3s, консольный клиент kubectl (внутри k3s), пакетный менеджер Helm (устанавливает готовые приложения в кластер «одной командой», как apt для Kubernetes), настраивает доступ и файрвол — и даёт команду mitdev k8s deploy для развёртывания ваших контейнеров.
Когда включать и когда не нужен
- Включайте, если приложения поставляются как Docker-образы и вы хотите катить их с автоперезапуском, репликами и обновлением без простоя; или планируете отказоустойчивый кластер из нескольких серверов.
- Не нужен, если приложение проще запускать через PM2/Docker Compose — Kubernetes добавляет сложность, которая оправдана не всегда.
- Важно про nginx: если на сервере уже установлен nginx, k3s ставится с отключённым traefik (см. ниже) — публикация приложений идёт через nginx.
Зависимости и требования
- Отдельных модулей mitdev формально не требует, но:
- если установлен модуль user — kubeconfig копируется деплой-пользователю (
DEPLOY_USER); - если установлен nginx — traefik в k3s отключается, приложения публикуются через nginx.
- если установлен модуль user — kubeconfig копируется деплой-пользователю (
- Нужен доступ в интернет: k3s ставится скриптом
https://get.k3s.io, Helm — официальным скриптом сraw.githubusercontent.com. - Для HA-кластера (несколько серверов) — приватная сеть между узлами и открытые кластерные порты (модуль открывает их сам для указанных пиров).
Три режима кластера
Режим выбирается переменной K8S_CLUSTER_MODE (её задаёт мастер установки):
| Режим | Что это | Когда |
|---|---|---|
single |
один самостоятельный сервер (по умолчанию) | обычный одиночный сервер |
init |
первый сервер HA-кластера, поднимает встроенный etcd | когда нужен отказоустойчивый кластер |
join |
дополнительный сервер, присоединяется к существующему кластеру | второй, третий и т. д. узлы |
etcd («embedded etcd») — это встроенная в k3s распределённая база, где хранится всё состояние кластера; в HA-режиме она реплицируется между серверами, поэтому кластер переживает отказ узла. Для кворума etcd нужно нечётное число серверов (обычно 3).
Режим join требует двух параметров, которые даёт первый узел командой mitdev k8s token:
K8S_SERVER_URL— адрес видаhttps://<ip-первого-узла>:6443;K8S_TOKEN— секретный токен присоединения.
Ещё одна переменная — K8S_PEERS (список IP остальных серверов кластера): по ним модуль точечно открывает кластерные порты в файрволе.
Что именно делает
Пошагово, в порядке выполнения module_install:
- Ставит k3s (канал stable) в выбранном режиме. Если k3s уже установлен и запущен — шаг пропускается. Формируется строка запуска:
single→server;init→server --cluster-init(поднимает встроенный etcd);join→server --server <K8S_SERVER_URL>(проверяет наличиеK8S_SERVER_URLиK8S_TOKEN).
- Если обнаружен nginx (
state_done nginxили служба активна) — к строке запуска добавляется--disable traefik. traefik — это встроенный в k3s веб-балансировщик (ingress-контроллер), который сам занимает порты 80 и 443; nginx хочет те же порты, поэтому их «драка» устраняется отключением traefik. Публикация приложений тогда идёт через nginx. - Ждёт готовности узла (
_k8s_wait_node_ready): до 30 попыток с интервалом 4 секунды (до ~2 минут) опрашиваетkubectl get nodes, пока узел не перейдёт в состояние Ready (готов принимать поды). - Копирует kubeconfig деплой-пользователю (если задан
DEPLOY_USER): создаёт/home/<user>/.kube(700), кладёт/etc/rancher/k3s/k3s.yamlв~/.kube/config(600, владелец — деплой-пользователь). kubeconfig — это файл с адресом кластера и ключами доступа; с нимkubectlработает от имени пользователя без sudo. - Ставит Helm официальным скриптом в
/usr/local/bin/helm(если ещё не установлен). - Открывает порты в файрволе (если UFW активен):
6443/tcp— API-сервер Kubernetes;10.42.0.0/16— сеть подов (pod — минимальная единица запуска, один или несколько контейнеров);10.43.0.0/16— сеть сервисов (внутренние виртуальные адреса служб);- для каждого пира из
K8S_PEERSдополнительно (нужно для HA):2379:2380/tcp(etcd),10250/tcp(kubelet — агент на узле),8472/udp(flannel VXLAN — сетевой туннель между узлами).
- Если режим
init— печатает подсказку: токен присоединения берётся командойmitdev k8s token. - Верификация и
state_mark.
Файлы, службы и порты
| Объект | Значение | Примечание |
|---|---|---|
| Служба systemd | k3s (или k3s-agent) |
автозапуск включён |
Порт 6443/tcp |
API-сервер Kubernetes | доступ kubectl и присоединение узлов |
Порт 2379-2380/tcp |
etcd | только HA, только между пирами |
Порт 10250/tcp |
kubelet | только HA, только между пирами |
Порт 8472/udp |
flannel VXLAN | только HA, только между пирами |
Сеть 10.42.0.0/16 |
поды | внутренняя |
Сеть 10.43.0.0/16 |
сервисы | внутренняя |
/usr/local/bin/helm |
Helm | пакетный менеджер |
/etc/rancher/k3s/k3s.yaml |
kubeconfig (root) | исходный файл доступа |
/home/<DEPLOY_USER>/.kube/config |
kubeconfig деплой-пользователя | 600 |
/var/lib/rancher/k3s/server/node-token |
токен присоединения (режимы init/join) | только root |
/usr/local/bin/k3s-uninstall.sh |
штатный деинсталлятор k3s | ставится вместе с k3s |
/var/lib/mitdev/k8s/<app>.yaml |
манифесты приложений mitdev k8s deploy |
— |
Учётные данные
Отдельных паролей модуль не сохраняет в /root/.mitdev-credentials. Доступ к кластеру даёт kubeconfig:
- для root —
/etc/rancher/k3s/k3s.yaml(используется автоматически черезk3s kubectl); - для деплой-пользователя —
~/.kube/config(права600).
Секрет присоединения новых узлов к кластеру — токен в /var/lib/rancher/k3s/server/node-token (читается только root). Его показывает mitdev k8s token.
Настройка
Эти переменные собирает мастер установки (их нет в config/defaults.conf):
| Переменная | Значения | По умолчанию | На что влияет | Когда задаётся |
|---|---|---|---|---|
K8S_CLUSTER_MODE |
single / init / join |
single |
режим узла (одиночный / первый в кластере / присоединяемый) | в мастере при выборе одиночного или кластерного сценария |
K8S_SERVER_URL |
https://<ip>:6443 |
— | адрес первого узла кластера | только в режиме join |
K8S_TOKEN |
строка-токен | — | секрет присоединения к кластеру | только в режиме join |
K8S_PEERS |
список IP через пробел | пусто | адреса других серверов кластера — для них открываются кластерные порты | в HA-сценарии |
K8S_SERVER_URL и K8S_TOKEN для режима join вы берёте с первого узла командой mitdev k8s token.
Как переопределить настройки
Обычно эти переменные задаются интерактивно в мастере установки при выборе кластерного сценария. Их можно передать и явно перед запуском (флаг -E сохраняет окружение при sudo):
# первый узел HA-кластера
K8S_CLUSTER_MODE=init sudo -E ./install.sh
# присоединяемый узел
K8S_CLUSTER_MODE=join \
K8S_SERVER_URL=https://10.8.0.1:6443 \
K8S_TOKEN=<токен-с-первого-узла> \
K8S_PEERS="10.8.0.1 10.8.0.2" \
sudo -E ./install.sh
Как пользоваться
Режим single — одиночный сервер
Ничего дополнительно делать не нужно: после установки узел готов, деплойте приложения (см. ниже).
Режим init + join — HA-кластер по шагам
Узел 1 (первый сервер, режим init):
# при установке выбран режим init (или K8S_CLUSTER_MODE=init)
# после установки получите параметры присоединения:
sudo mitdev k8s token
# выведет: URL: https://<ip-узла-1>:6443 и Токен: <строка>
Узел 2 и далее (режим join): запустите установку с параметрами, полученными на узле 1:
K8S_CLUSTER_MODE=join \
K8S_SERVER_URL=https://<ip-узла-1>:6443 \
K8S_TOKEN=<токен-с-узла-1> \
K8S_PEERS="<ip-узла-1> <ip-узла-3>" \
sudo -E ./install.sh
Проверка кластера (на любом узле):
sudo mitdev k8s nodes # все узлы должны быть Ready
sudo mitdev k8s status
Для кворума etcd держите нечётное число серверов (3 — типичный минимум для HA).
Добавить ещё один узел
Повторите шаг «join» на новом сервере с тем же URL и токеном (токен всегда можно переполучить на первом узле через mitdev k8s token). Не забудьте добавить IP нового узла в K8S_PEERS на нём (и при желании открыть порты для него на других узлах).
Развернуть приложение — mitdev k8s deploy
sudo mitdev k8s deploy <имя> <образ> [порт] [домен] [реплики]
<имя>— латиница-kebab (напримерweb), по RFC 1123;<образ>— Docker-образ, напримерghcr.io/org/app:latest;[порт]— порт внутри контейнера (по умолчанию спрашивается, типовое3000);[домен]— если указан, приложение публикуется наружу (через traefik или nginx); пусто — доступно только внутри кластера;[реплики]— число копий (по умолчанию2).
Пример:
sudo mitdev k8s deploy web ghcr.io/org/app:latest 3000 app.example.com 3
Что происходит: рендерится манифест Deployment + Service в /var/lib/mitdev/k8s/web.yaml, применяется kubectl apply, ожидается раскатка (rollout status, до 180 с). Манифест включает podAntiAffinity — правило, которое старается разнести реплики по разным узлам кластера: падение одного сервера уносит максимум одну копию, остальные продолжают обслуживать трафик. Также заданы проверки готовности/живости (readiness/liveness probes) и плавное обновление (rolling update без простоя). Если задан домен: при включённом traefik создаётся Ingress (правило маршрутизации HTTP по домену), при nginx — сайт nginx на выделенный NodePort сервиса (с предложением выпустить SSL через certbot).
Управлять кластером через kubectl
От root — через встроенный клиент:
sudo k3s kubectl get pods -A
От деплой-пользователя — обычный kubectl (kubeconfig уже лежит в ~/.kube/config):
kubectl get pods
kubectl get nodes
Удобные обёртки mitdev:
sudo mitdev k8s status # версия, узлы, поды, приложения mitdev
sudo mitdev k8s nodes # узлы (get nodes -o wide)
sudo mitdev k8s pods [ns] # поды (всех или одного namespace)
sudo mitdev k8s services # сервисы
sudo mitdev k8s logs <app> # логи приложения (follow)
sudo mitdev k8s apply <файл.yaml>
Проверка, что всё работает
module_verify считает модуль успешным, если: команда k3s есть, служба k3s активна, узел в состоянии Ready, и установлен helm.
Ручные проверки:
# версия и служба
sudo k3s --version
systemctl status k3s
# узел(ы) должны быть Ready
sudo k3s kubectl get nodes
# системные поды (kube-system) в Running
sudo k3s kubectl get pods -A
# Helm установлен
helm version
# общая диагностика mitdev
sudo mitdev doctor
Типовые задачи
- Получить токен и URL для присоединения узла:
sudo mitdev k8s token - Развернуть приложение с публикацией на домен:
sudo mitdev k8s deploy web ghcr.io/org/app:latest 3000 app.example.com 2 - Обновить образ приложения — повторите
deployс новым тегом образа (пройдёт rolling update):sudo mitdev k8s deploy web ghcr.io/org/app:v2 3000 app.example.com 2 - Посмотреть логи приложения:
sudo mitdev k8s logs web - Удалить одно приложение (Deployment/Service/Ingress + сайт nginx, если был):
sudo mitdev k8s delete web - Удалить все приложения mitdev, но оставить кластер:
sudo mitdev k8s delete-all - Установить готовое приложение через Helm (пример):
helm repo add bitnami https://charts.bitnami.com/bitnami helm install my-redis bitnami/redis
Частые ошибки
| Симптом | Причина | Что сделать |
|---|---|---|
| nginx не стартует после установки k3s | traefik из k3s занял порты 80/443 | k3s должен ставиться с --disable traefik — переустановите модуль, когда nginx уже установлен, либо снимите traefik; смотрите journalctl -u nginx |
| Узел долго не Ready (больше 2 минут) | не скачались системные образы, проблемы с сетью/диском | sudo k3s kubectl describe node; journalctl -u k3s -n 100; проверьте интернет и место на диске |
mitdev k8s token пишет «токен не найден» |
узел не сервер кластера (не режим init) | токен есть только на серверах, поднятых в режиме init |
Узел join не присоединяется |
закрыт 6443, неверный токен/URL, разные версии k3s | проверьте доступность https://<узел-1>:6443, сверьте токен, откройте порты для пиров |
| Приложение развёрнуто, но недоступно по домену | не задан домен, нет ни traefik, ни nginx | укажите домен при deploy; при nginx на хосте публикация идёт через него, при traefik — через ingress |
| Реплики оказались на одном узле | podAntiAffinity — «мягкое» правило (preferred) | это ожидаемо, если узлов мало; при достаточном числе узлов они разнесутся |
Безопасность и продакшен
Модуль уже закрывает: k3s работает через containerd без Docker, kubeconfig деплой-пользователя имеет права 600, порты открываются точечно (API — всем, кластерные — только пирам из K8S_PEERS), traefik отключается при конфликте с nginx.
Остаётся на клиенте:
- Порт 6443 (API-сервер) — не открывайте его в интернет шире необходимого. UFW открывает
6443/tcp; ограничьте источник до доверенных сетей/пиров, если API не должен быть публичным. - kubeconfig — секрет. Держите
~/.kube/configи/etc/rancher/k3s/k3s.yamlс правами600и не копируйте на чужие машины. - Для HA держите нечётное число серверов (кворум etcd) и приватную сеть между узлами.
- Ограничивайте ресурсы подов (в шаблоне уже заданы
requests/limits) и следите за обновлениями образов.
Откат и удаление
- Авто-откат при падении установки (
module_rollback): запускает штатныйk3s-uninstall.sh(если есть) и удаляетhelm. mitdev remove kubernetes(то же, чтоmitdev k8s delete-cluster): запускает официальный/usr/local/bin/k3s-uninstall.sh, который сносит весь узел — все поды, рабочие нагрузки, хранилище containerd и состояние кластера (etcd/sqlite). Дополнительно удаляются Helm, kubeconfig деплой-пользователя и правила файрвола, открытые модулем. Это и есть команда «удалить кластер и все поды».- Флаг
--purgeздесь ничего сверх этого не добавляет — деинсталлятор k3s и так удаляет данные кластера.
См. также
- ../KUBERNETES.md — подробное руководство по Kubernetes в mitdev.
- ../HA.md — отказоустойчивость и кластеры.
- ../COMMANDS.md — все подкоманды
mitdev k8s. - ../MODULES.md — краткий обзор всех модулей.