Для учебного сценария достаточно одного Linux-узла с ролью K3s server. На нем запустятся Kubernetes API, планировщик, контроллеры и приложение. Agent-узлы добавляются, когда нужно проверить распределение Pod или подготовить кластер к нескольким рабочим узлам.
В статье развернем HTTP-приложение через Deployment, создадим внутренний Service, опубликуем его по домену через Ingress и Traefik, подключим PersistentVolumeClaim и проверим сохранность файла после пересоздания Pod. В конце выполним RollingUpdate, проверим новую версию и покажем откат через kubectl rollout undo.
Команды ниже используют переменные-заглушки для версии K3s, адресов и образов. Перед запуском зафиксируйте версию K3s, ОС, архитектуру процессора, сетевую схему, StorageClass и состав встроенных компонентов.
Короткий ответ: что развернем в K3s
K3s сохраняет привычную модель Kubernetes: контейнер работает в Pod, Deployment поддерживает нужное число реплик, Service дает стабильную внутреннюю точку доступа, Ingress маршрутизирует HTTP-запросы по домену, а PVC запрашивает постоянное хранилище.
Итоговая цепочка будет выглядеть так: DNS указывает на внешний адрес узла, Traefik принимает запрос на порту 80 или 443, объект Ingress выбирает Service, Service направляет трафик в готовый Pod. Запись приложения попадает в каталог, подключенный через PVC, а физически хранится в StorageClass и связанном PersistentVolume.
Итоговая схема кластера и приложения
- K3s server управляет Kubernetes API и состоянием кластера.
- K3s agent запускает рабочие Pod и подключается к server. Для одноузлового стенда agent не обязателен.
- containerd скачивает образы и запускает контейнеры.
- Deployment описывает приложение, образ, реплики, ресурсы и probes.
- Service связывает запросы с Pod по label selector.
- Ingress описывает маршрут по host и path.
- Traefik принимает внешний HTTP/HTTPS-трафик и обрабатывает объект Ingress.
- PersistentVolumeClaim запрашивает том заданного размера и монтирует его в контейнер.
В типовой установке K3s часто присутствуют Traefik и local-path-provisioner. Фактический состав зависит от параметров установки и версии, поэтому проверяйте его командами kubectl get pods -A, kubectl get ingressclass и kubectl get storageclass.
Что будет проверено в конце
- Все нужные узлы имеют статус
Ready. - Deployment поддерживает две готовые реплики приложения.
- ReadinessProbe и livenessProbe возвращают успешный результат.
- Service доступен внутри кластера.
- Ingress содержит правильный host, backend и ingress class.
- Домен указывает на внешний адрес, а порты 80 и 443 доступны через firewall.
- PVC получает статус
Bound, файл сохраняется после удаления Pod. - Новая версия проходит rolling update, а предыдущая версия доступна для отката.
K3s и полноразмерный Kubernetes: какие различия важны на практике
K3s - это облегченная сертифицированная дистрибуция Kubernetes. Пользователь работает с теми же базовыми API-объектами: Pod, Deployment, Service, Ingress, ConfigMap, Secret и PersistentVolumeClaim. Отличия заметны в способе установки, составе компонентов и количестве решений, которые администратор принимает вручную.
Архитектура control plane и worker nodes подробно разобрана в руководстве по архитектуре Kubernetes и ключевым объектам API. Для K3s эта модель сохраняется, но многие компоненты упакованы в единый сценарий управления.
Что K3s упрощает
| Область | Практическое отличие K3s |
|---|---|
| Установка | Server и agent устанавливаются через единый механизм, а системный сервис запускается через systemd. |
| Компоненты | Основные части control plane поставляются согласованным набором. containerd используется как контейнерный runtime. |
| Datastore | Для небольшого одноузлового сценария можно использовать встроенное хранилище состояния. Для HA выбирают embedded etcd или внешний datastore. |
| Ingress | Traefik часто устанавливается как встроенный компонент, если его не отключить при установке. |
| Хранилище | local-path-provisioner позволяет быстро создать локальный PersistentVolume без отдельной CSI-системы. |
| kubectl | На server доступна команда k3s kubectl. Обычный клиент kubectl работает через kubeconfig. |
Главное преимущество для небольшого проекта дает сокращение начальной настройки. Манифесты Kubernetes при этом не превращаются в отдельный формат: Deployment, Service и Ingress описываются стандартным YAML.
Какие компромиссы появляются
- Один server с локальным datastore не обеспечивает отказоустойчивость control plane. При его остановке уже запущенные контейнеры могут продолжить работу, но кластер теряет возможность нормально принимать изменения и планировать новые Pod.
- Добавление agent-узла не создает High Availability. Для embedded etcd нужен отдельный план кворума, обычно с тремя server-узлами, либо внешний datastore.
- local-path хранит данные на конкретном диске и узле. Перезапуск Pod на другом узле может закончиться невозможностью смонтировать том.
- Встроенный Traefik удобен для HTTP-сервисов, но сложная маршрутизация, нестандартные сетевые политики и единый ingress для разных кластеров потребуют отдельного проектирования.
- Backup состояния K3s и backup PVC решают разные задачи. Копия datastore не заменяет копию данных приложения.
Когда K3s подходит, а когда нужен другой вариант
| Сценарий | Оценка | Причина |
|---|---|---|
| Лаборатория на одной VM | Подходит | Минимум компонентов, быстрый запуск, стандартные Kubernetes-манифесты. |
| Edge-узел с ограниченными ресурсами | Часто подходит | Компактный control plane и небольшой объем ручной настройки. |
| Небольшое внутреннее приложение | Подходит при наличии backup | Ingress, Service и PVC закрывают базовые задачи, если риски локального storage приемлемы. |
| Крупный многокомандный кластер | Нужна отдельная оценка | Потребуются HA, RBAC, NetworkPolicy, observability, CSI и формализованный процесс обновления. |
| Жесткие требования к отказоустойчивости данных | Локального K3s недостаточно | Нужно внешнее или распределенное хранилище, резервирование дисков и проверенный restore. |
Минимальная конфигурация и подготовка Linux-узлов
Для этого примера подойдет одна Linux-VM с 2 vCPU и 4 ГБ RAM. Это ориентир для K3s и небольшого nginx-контейнера, а не универсальная норма. База данных, сборщики логов, мониторинг и несколько реплик потребуют отдельного расчета.
Если нужен отдельный тестовый узел, VDS или VPS можно создать в облачной инфраструктуре Timeweb Cloud. Выбирайте ресурсы по фактическому числу Pod, объему storage и запасу на обновление.
Роли server и agent-узлов
- Server хранит состояние кластера, обслуживает API, запускает scheduler и controller manager. В одноузловом сценарии он может одновременно запускать workload.
- Agent получает назначения от server, запускает Pod и сообщает их состояние. На agent нет полного control plane.
- Несколько server нужны для отказоустойчивого control plane. Схему quorum, datastore и резервное копирование нужно выбрать до установки.
Для проверки планирования можно использовать один server и один agent. Чтобы Kubernetes не размещал пользовательские Pod на server, задайте taint при установке или позже через kubectl taint nodes. Без taint server обычно остается доступным для обычных workload.
Сеть, имена узлов и firewall
- Задайте уникальные hostname: например,
k3s-server-1иk3s-agent-1. - Проверьте, что узлы видят друг друга по внутренним адресам и корректно разрешают имена.
- Синхронизируйте время через настроенный NTP-клиент. Расхождение времени ломает TLS и усложняет анализ событий.
- Разрешите TCP-подключение к Kubernetes API на порту
6443между agent и server. - Откройте TCP-порты
80и443на внешнем адресе, если Traefik публикует HTTP и HTTPS. - Разрешите сетевой трафик, который нужен выбранному backend CNI. Для Flannel список портов зависит от режима VXLAN или WireGuard.
На VPS проверьте одновременно firewall операционной системы, правила облачной сети и таблицы NAT. На bare metal добавьте проверку маршрутизатора и проброса портов.
Фиксация версии и параметров установки
Создайте короткий файл с параметрами до запуска установщика:
K3S_VERSION=vX.Y.Z+k3sN
SERVER_NAME=k3s-server-1
AGENT_NAME=k3s-agent-1
SERVER_API_ENDPOINT=SERVER_API_ADDRESS_WITH_PORT
INGRESS=traefik
STORAGE_CLASS=local-path
Вместо vX.Y.Z+k3sN укажите релиз, который прошел проверку в вашем окружении. Запишите версию Linux, архитектуру CPU, режим datastore, CNI, ingress-контроллер и StorageClass. Если подключаетесь к API по DNS-имени, добавьте это имя в TLS SAN при установке server.
Как установить K3s на server и agent
Ниже используется локальный файл install-k3s.sh. Получите его по принятому в вашей организации каналу, проверьте контрольную сумму и сохраните рядом с журналом установки. Такой подход позволяет не менять версию из-за плавающего содержимого установщика.
Установка первого K3s server
На первом Linux-узле задайте проверенную версию и запустите server:
export K3S_VERSION='vX.Y.Z+k3sN'
sudo env INSTALL_K3S_VERSION=$K3S_VERSION sh ./install-k3s.sh server --node-name k3s-server-1 --write-kubeconfig-mode 640
sudo systemctl enable --now k3s
sudo systemctl status k3s --no-pager
sudo k3s kubectl get nodes -o wide
Если Traefik нужен в примере, не добавляйте параметр --disable=traefik. Для внешнего datastore или embedded etcd параметры выбираются отдельно. Один server без дополнительных флагов подходит для лабораторного запуска, но не создает HA.
При проблеме с запуском смотрите журнал сервиса:
sudo journalctl -u k3s -n 100 --no-pager
Команда sudo k3s kubectl get nodes должна показать server в статусе Ready. Если API не отвечает, сначала проверяйте systemd и journal, затем состояние локального firewall.
Подключение agent-узла к кластеру
На server получите join-токен:
sudo cat /var/lib/rancher/k3s/server/node-token
Токен дает право присоединиться к кластеру. Не отправляйте его в чат, репозиторий или публичный issue. На agent задайте API endpoint server и токен:
export K3S_VERSION='vX.Y.Z+k3sN'
export K3S_URL='SERVER_API_ENDPOINT'
export K3S_TOKEN='PASTE_NODE_TOKEN'
sudo env K3S_URL=$K3S_URL K3S_TOKEN=$K3S_TOKEN INSTALL_K3S_VERSION=$K3S_VERSION sh ./install-k3s.sh agent --node-name k3s-agent-1
sudo systemctl enable --now k3s-agent
sudo systemctl status k3s-agent --no-pager
В K3S_URL укажите адрес Kubernetes API server с протоколом и портом 6443. Адрес должен быть доступен с agent по маршруту, который вы проверили заранее.
На server проверьте регистрацию:
kubectl get nodes -o wide
kubectl describe node k3s-agent-1
Новый узел сначала может находиться в состоянии NotReady, пока не завершится настройка сетевых компонентов. Если статус не меняется, проверьте token, API endpoint, hostname и межузловые порты.
Настройка kubectl и первичная проверка
На server kubeconfig обычно хранится в /etc/rancher/k3s/k3s.yaml. Скопируйте его текущему пользователю:
mkdir -p $HOME/.kube
sudo cp /etc/rancher/k3s/k3s.yaml $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
chmod 600 $HOME/.kube/config
export KUBECONFIG=$HOME/.kube/config
kubectl version
kubectl get nodes
kubectl get pods -A
kubectl get namespaces
kubectl get events -A --sort-by=.lastTimestamp
В kubeconfig для удаленного управления замените loopback-адрес API на сетевой endpoint server и убедитесь, что имя входит в TLS SAN. Для базовой проверки API можно выполнить:
kubectl get --raw=/readyz
Ошибка подключения к API указывает на kubeconfig, адрес или firewall. Ошибки в системных Pod требуют отдельной проверки через kubectl get pods -A, kubectl describe pod и журнал конкретного контейнера.
Если Kubernetes нужен впервые, базовые команды собраны в практическом руководстве по запуску сервисов с минимальной конфигурацией.
Развертывание приложения через Deployment и Service
В качестве приложения возьмем nginx с закрепленным тегом образа. Для рабочего сервиса замените его на образ из вашего registry и используйте версию или digest, который можно однозначно повторить.
Namespace и Deployment
Создайте файл web.yaml с Namespace, PVC, Deployment и Service:
apiVersion: v1
kind: Namespace
metadata:
name: demo
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: web-data
namespace: demo
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: demo
labels:
app: web
spec:
replicas: 2
revisionHistoryLimit: 5
progressDeadlineSeconds: 600
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.27.1-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 3
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
volumeMounts:
- name: web-data
mountPath: /usr/share/nginx/html/data
volumes:
- name: web-data
persistentVolumeClaim:
claimName: web-data
---
apiVersion: v1
kind: Service
metadata:
name: web
namespace: demo
spec:
selector:
app: web
ports:
- name: http
port: 80
targetPort: http
type: ClusterIP
Labels в spec.template.metadata.labels должны совпадать с spec.selector.matchLabels и selector Service. Если selector не находит Pod, Deployment может работать, а Service останется без endpoints.
В примере две реплики и maxUnavailable: 0 оставляют старый Pod в работе, пока новый не пройдет readinessProbe. Это требует свободных ресурсов для дополнительного Pod.
Практические шаблоны Deployment, Service, Ingress, ConfigMap и Secrets собраны в руководстве по деплою сервисов в Kubernetes.
Readiness и liveness probes
- readinessProbe определяет, можно ли отправлять трафик в Pod. При ошибке Pod остается запущенным, но исключается из endpoints Service.
- livenessProbe обнаруживает зависший процесс. После нескольких неудач kubelet перезапускает контейнер.
Для nginx путь / подходит как учебная проверка. Для API лучше использовать отдельный endpoint, который отвечает после загрузки конфигурации и обязательных зависимостей. Проверка должна быть короткой и не выполнять тяжелый запрос к базе при каждом вызове.
Service и проверка приложения внутри кластера
Сначала убедитесь, что Pod работают и Service получил endpoints:
kubectl apply -f web.yaml
kubectl -n demo get deploy,pod,svc,pvc
kubectl -n demo get endpoints web
kubectl -n demo rollout status deployment/web
Для локальной проверки без Ingress используйте port-forward:
kubectl -n demo port-forward service/web 8080:80
curl -I 127.0.0.1:8080
Ожидаемый результат, HTTP-ответ со статусом 200 или другой успешный код вашего приложения. Если endpoints пуст, проверьте labels, readinessProbe и состояние контейнеров.
Публикация приложения через K3s Ingress и Traefik
Service, NodePort и Ingress: что выбрать
| Тип | Назначение | Когда использовать |
|---|---|---|
| ClusterIP | Внутренний адрес Service | Связь сервисов внутри кластера. Это вариант для основного примера. |
| NodePort | Порт на каждом узле | Прямая публикация без отдельного HTTP-маршрутизатора или временная диагностика. |
| Ingress | Маршрутизация HTTP/HTTPS по host и path | Публикация веб-приложений через общий ingress-контроллер. |
Ingress не заменяет Service. Он передает запрос в Service, а тот выбирает Pod по labels. Для TCP-сервисов вроде PostgreSQL обычно нужен другой способ публикации.
Настройка Ingress для Traefik
Проверьте, что Traefik и ingress class доступны:
kubectl -n kube-system get pods -l app.kubernetes.io/name=traefik
kubectl -n kube-system get service traefik
kubectl get ingressclass
Создайте файл web-ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
namespace: demo
spec:
ingressClassName: traefik
rules:
- host: app.example.test
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
Примените объект и проверьте его состояние:
kubectl apply -f web-ingress.yaml
kubectl -n demo get ingress web
kubectl -n demo describe ingress web
kubectl -n demo get events --sort-by=.lastTimestamp
В describe проверьте ingress class, host, backend и Events. Если адрес не появился, это не всегда означает ошибку: на bare metal или обычном VPS контроллер может принимать трафик через IP узла без заполнения внешнего адреса объекта.
DNS, порты 80/443 и TLS
Создайте A-запись для app.example.test, которая указывает на внешний IP узла или балансировщика. Затем проверьте:
dig +short app.example.test
nc -vz PUBLIC_IP 80
nc -vz PUBLIC_IP 443
openssl s_client -connect PUBLIC_IP:443 -servername app.example.test
Для HTTPS создайте TLS Secret из сертификата и ключа:
kubectl -n demo create secret tls web-tls --cert=server.crt --key=server.key
Добавьте в Ingress секцию:
tls:
- hosts:
- app.example.test
secretName: web-tls
Сертификат можно выпускать через выбранный ACME-контроллер или корпоративный PKI. Проверьте автоматическое продление заранее. Для VPS убедитесь, что порты 80 и 443 открыты в правилах провайдера и ОС. На bare metal проверьте NAT до узла, где Traefik принимает соединения.
Persistent storage: подключение PVC и проверка сохранности данных
StorageClass, PersistentVolume и PersistentVolumeClaim
StorageClass описывает способ динамического создания томов. PersistentVolume представляет выделенный ресурс хранения. PersistentVolumeClaim - заявка приложения на объем и режим доступа.
Перед применением манифеста проверьте имя StorageClass:
kubectl get storageclass
kubectl get persistentvolume
kubectl -n demo get pvc
В типовой K3s-установке часто встречается StorageClass local-path. Если в вашем кластере имя другое, замените значение storageClassName. Если StorageClass отсутствует, PVC останется в состоянии Pending, пока вы не добавите provisioner или не создадите PV вручную.
Монтирование PVC в приложение
В манифесте PVC запрашивает 1 ГБ и режим ReadWriteOnce. Deployment монтирует заявку в /usr/share/nginx/html/data. Файлы в этом каталоге не зависят от временной файловой системы контейнера.
Проверьте связь PVC и Pod:
kubectl -n demo get pvc web-data
kubectl -n demo get pv
kubectl -n demo describe pod -l app=web
Если контейнер запускается от непривилегированного пользователя, проверьте права на каталог. Для production добавьте подходящий securityContext, например fsGroup, только после проверки UID контейнера и поведения выбранного storage-драйвера.
Ограничения локального хранилища K3s
- local-path создает том на локальном диске конкретного узла.
- Перемещение Pod на другой узел может быть невозможно, если у PV есть node affinity к исходному узлу.
ReadWriteOnceобычно разрешает запись одному узлу. Это не следует трактовать как универсальное ограничение ровно на один Pod.- Отказ диска или удаление каталога на узле может привести к потере данных.
- Масштабирование stateful-приложения требует проверки совместимости с несколькими репликами.
Для нескольких узлов используйте CSI-драйвер и подходящее сетевое хранилище, например NFS или внешний NAS. Проверьте задержки, блокировки, права доступа и поведение при потере связи. Резервное копирование должно выполняться независимо от того, локальный это том или сетевой.
Тест восстановления данных
Запишите файл в PVC, удалите текущий Pod и проверьте файл в новом Pod:
POD=$(kubectl -n demo get pod -l app=web -o jsonpath='{.items[0].metadata.name}')
kubectl -n demo exec $POD -- sh -c 'printf storage-ok > /usr/share/nginx/html/data/healthcheck.txt'
kubectl -n demo exec $POD -- cat /usr/share/nginx/html/data/healthcheck.txt
kubectl -n demo delete pod $POD
kubectl -n demo rollout status deployment/web
NEW_POD=$(kubectl -n demo get pod -l app=web -o jsonpath='{.items[0].metadata.name}')
kubectl -n demo exec $NEW_POD -- cat /usr/share/nginx/html/data/healthcheck.txt
Последняя команда должна вывести storage-ok. Проверка доказывает, что PVC повторно монтируется после пересоздания Pod. Она не заменяет backup и полноценный restore-тест на отдельной инфраструктуре.
Безопасное обновление релиза без простоя или с минимальным риском
Подготовка перед обновлением
- Проверьте текущий rollout:
kubectl -n demo rollout status deployment/web. - Убедитесь, что обе реплики готовы и в кластере есть ресурсы для дополнительного Pod.
- Заранее скачайте и проверьте новый образ.
- Используйте неизменяемый тег или digest, а не плавающий тег вроде
latest. - Проверьте совместимость формата данных и миграций базы.
- Создайте backup PVC и зафиксируйте команду отката.
Для stateful-приложения контейнерный rollback не отменяет миграцию схемы базы. Изменения данных нужно планировать отдельно.
RollingUpdate и порядок замены Pod
В примере две реплики, maxUnavailable: 0 и maxSurge: 1. Kubernetes создает дополнительный Pod с новым образом, ждет успешной readinessProbe и только после этого уменьшает число старых Pod.
Полное отсутствие простоя требует нескольких условий: минимум две готовые реплики, запас CPU и RAM, корректная readinessProbe, рабочий Service и совместимость старой и новой версии при параллельном запуске. Один Pod с PVC может получить короткое окно недоступности даже при стратегии RollingUpdate.
Запустите обновление:
kubectl -n demo set image deployment/web web=nginx:1.27.2-alpine
kubectl -n demo rollout status deployment/web --timeout=5m
kubectl -n demo get pods -o wide
В production подставляйте образ из своего registry и проверенный immutable tag или digest. Тег nginx в примере нужен для демонстрации механики, а не как универсальный способ поставки.
Проверка новой версии и наблюдение за rollout
kubectl -n demo get deployment web
kubectl -n demo get pods
kubectl -n demo describe deployment web
kubectl -n demo logs deployment/web --all-containers=true --tail=100
kubectl -n demo get events --sort-by=.lastTimestamp
kubectl -n demo get ingress web
Проверьте HTTP-ответ через Ingress, отсутствие ошибок в логах, состояние endpoints и сохранность тестового файла. Для production добавьте наблюдение за кодами 4xx и 5xx, latency, перезапусками контейнеров, CPU, RAM, диском и сроком действия TLS-сертификатов.
Откат к предыдущему релизу
Если новый Pod не проходит readinessProbe или приложение отвечает ошибками, остановите дальнейшее изменение трафика и изучите историю:
kubectl -n demo rollout history deployment/web
kubectl -n demo rollout undo deployment/web
kubectl -n demo rollout status deployment/web --timeout=5m
kubectl -n demo get pods
Если нужно вернуть конкретную ревизию, укажите ее номер через --to-revision. После отката повторно проверьте Service, Ingress, логи и данные PVC. Для приложений с базой данных проверьте совместимость старого бинарника с текущей схемой.
Стратегии rolling update, blue-green и canary, а также миграция stateful-нагрузок разобраны в практическом плане перехода от монолита к микросервисам.
Диагностика: что проверить, если приложение не работает
Проверяйте цепочку последовательно: узел, Pod, контейнер, Service, Ingress, DNS и firewall, затем storage. Не начинайте с DNS, если Pod не получил статус Ready.
Pod не запускается или перезапускается
| Состояние | Проверка | Частая причина |
|---|---|---|
| Pending | kubectl -n demo describe pod POD_NAME | Нет ресурсов, PVC не привязан, node affinity или taint не позволяют выбрать узел. |
| CrashLoopBackOff | kubectl -n demo logs POD_NAME --previous | Процесс завершается, неверная конфигурация, отсутствует Secret или приложение не может открыть каталог. |
| ImagePullBackOff | kubectl -n demo describe pod POD_NAME | Ошибка имени образа, закрытый registry, неверный imagePullSecret или недоступный DNS. |
| Pod Ready, но трафика нет | kubectl -n demo get endpoints web | Неверный selector Service или readinessProbe исключила Pod. |
Соберите события и логи:
kubectl -n demo get pods -o wide
kubectl -n demo describe pod POD_NAME
kubectl -n demo logs POD_NAME --all-containers=true --tail=200
kubectl -n demo get events --sort-by=.lastTimestamp
Ingress создан, но домен недоступен
- Проверьте наличие Traefik и его Service в namespace
kube-system. - Сверьте
ingressClassNameс выводомkubectl get ingressclass. - Проверьте host и path в
kubectl -n demo describe ingress web. - Убедитесь, что Service имеет endpoints.
- Проверьте внешний адрес Traefik и доступность TCP-портов 80 и 443.
- Проверьте DNS-командой
dig +short app.example.test. - Для HTTPS проверьте имя TLS Secret и срок действия сертификата.
Если Service доступен через port-forward, а Ingress не работает, проблема находится в Traefik, host, DNS, firewall или TLS. Если Service тоже не отвечает, вернитесь к selector и readinessProbe.
PVC имеет статус Pending или не монтируется
kubectl -n demo get pvc
kubectl -n demo describe pvc web-data
kubectl get pv
kubectl get storageclass
kubectl -n demo describe pod POD_NAME
Pending часто означает отсутствующий StorageClass, несовпадение access mode, нехватку свободного места или отсутствие provisioner. Если PVC привязан, но Pod не стартует, изучите Events Pod и проверьте права на mountPath.
Для local-path проверьте, на каком узле создан PV и куда Kubernetes пытается поместить Pod. Перенос на другой узел без доступа к исходному диску не решает проблему. Для многузловой схемы заранее выберите CSI или NFS с понятной политикой восстановления.
Что добавить перед использованием K3s в production
Учебный кластер показывает механику Kubernetes, но production требует отдельного набора процессов. Практические критерии для промышленного кластера собраны в руководстве по проектированию и управлению production-ready Kubernetes.
Резервное копирование и восстановление
- Для datastore сохраняйте snapshots или резервные копии способом, который соответствует выбранному режиму K3s: SQLite, embedded etcd или внешний datastore.
- PVC копируйте отдельно. Для базы данных используйте согласованный backup, а не простое копирование открытых файлов.
- Храните версии манифестов, Secrets и параметров установки в защищенном хранилище.
- Проводите restore-тест. Архив без проверки восстановления не дает подтверждения работоспособности backup.
Безопасность доступа
- Защитите kubeconfig server и join-токен правами файловой системы и менеджером секретов.
- Выдавайте пользователям минимальные права через RBAC.
- Не публикуйте Kubernetes API в интернет без необходимости; ограничьте доступ сетевыми правилами и VPN.
- Не храните пароли в открытом YAML. Используйте Secrets и контролируйте, кто может их читать.
- Регулярно обновляйте ОС, K3s, контейнерные образы и ingress-контроллер.
- Добавьте сетевые политики, если приложения должны быть изолированы друг от друга.
Наблюдаемость и план обновления
Минимальный набор сигналов включает состояние nodes и Pod, загрузку CPU и RAM, свободное место на дисках, число рестартов, ошибки приложения, latency, доступность Ingress и срок действия TLS-сертификатов. Для PVC контролируйте заполнение томов и ошибки монтирования.
Зафиксируйте процедуру обновления K3s: совместимость версий Kubernetes API, порядок обновления server и agent, backup datastore, тестовый кластер, окно работ и критерии отката. Обновление control plane и обновление образа приложения - разные операции, их не стоит смешивать в один неконтролируемый шаг.
Итоговый чек-лист развертывания K3s
Используйте список как короткую шпаргалку перед передачей кластера в эксплуатацию:
- Зафиксирована версия K3s, версия Linux, архитектура CPU и сетевой endpoint API.
- Подготовлены hostname, DNS, синхронизация времени и firewall.
- Установлен K3s server, сервис
k3sзапущен. - При необходимости добавлены agent-узлы, каждый имеет статус
Ready. - Настроен kubeconfig с правами доступа
600. - Проверены системные Pod и события кластера.
- Применены Namespace, PVC, Deployment и Service.
- Deployment имеет нужное число готовых реплик.
- Service имеет endpoints и отвечает при внутренней проверке.
- Traefik и IngressClass доступны, Ingress указывает на правильный Service.
- DNS направляет домен на внешний адрес, порты 80 и 443 открыты.
- TLS Secret создан, сертификат проверен и имеет план продления.
- PVC получил статус
Bound, тестовый файл пережил пересоздание Pod. - Выполнен контролируемый rollout новой версии.
- Проверены логи, Events, HTTP-ответ и сохранность данных.
- Команда
kubectl rollout undoпроверена или записана в аварийную процедуру. - Для production подготовлены backup datastore, backup PVC, RBAC, Secrets, мониторинг и план обновления K3s.
Минимальный набор команд для финальной проверки
kubectl get nodes -o wide
kubectl get pods -A
kubectl -n demo get deployment,pod,service,ingress,pvc
kubectl -n demo get endpoints web
kubectl -n demo get events --sort-by=.lastTimestamp
kubectl -n demo rollout status deployment/web
kubectl -n demo describe ingress web
kubectl -n demo describe pvc web-data
dig +short app.example.test
nc -vz PUBLIC_IP 80
nc -vz PUBLIC_IP 443
Готовый результат - узлы в статусе Ready, рабочие реплики Deployment, endpoints Service, корректный Ingress, привязанный PVC и доступ приложения по домену. Если один из пунктов не выполнен, возвращайтесь к соответствующему звену цепочки, не меняя сразу несколько компонентов.