Kubernetes на VPS: минимальный кластер с k3s
k3s — лёгкая дистрибуция Kubernetes от Rancher Labs, требующая всего 512 МБ RAM. Идеальна для изучения K8s и запуска небольших production-кластеров на VPS от 4 ГБ RAM.
Установка k3s (Master нода)
curl -sfL https://get.k3s.io | sh -
systemctl status k3s
# Проверить кластер
kubectl get nodes
kubectl get pods -AДобавление Worker ноды
# Получить токен на Master
cat /var/lib/rancher/k3s/server/node-token
# На Worker ноде
curl -sfL https://get.k3s.io | K3S_URL=https://MASTER_IP:6443 K3S_TOKEN=TOKEN sh -Деплой приложения
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginx:alpine
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
selector:
app: webapp
ports:
- port: 80
targetPort: 80
type: LoadBalancerkubectl apply -f deployment.yaml
kubectl get pods
kubectl get servicesHelm: пакетный менеджер K8s
# Установить Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Установить приложение из Helm Chart (например, cert-manager)
helm repo add jetstack https://charts.jetstack.io
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set installCRDs=trueIngress + авто-SSL
# Traefik (входит в k3s по умолчанию)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: webapp-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- app.yourdomain.com
secretName: webapp-tls
rules:
- host: app.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp-service
port:
number: 80Разбор реальных ошибок и статусов подов
Три статуса пода закрывают почти все вопросы новичков в Kubernetes. Разберём, что означает каждый и как найти причину через kubectl describe.
Pod завис в состоянии Pending
kubectl describe pod webapp-7d9f8c-abcde
Events:
Warning FailedScheduling 12s default-scheduler 0/1 nodes are available: 1 Insufficient memory.Планировщик не может найти ноду, где хватает запрошенных ресурсов из resources.requests. Решение: уменьшить requests.memory в манифесте, добавить worker-ноду или проверить, не заняты ли ресурсы другими подами через kubectl describe node.
CrashLoopBackOff
kubectl get pods
NAME READY STATUS RESTARTS AGE
webapp-7d9f8c-abcde 0/1 CrashLoopBackOff 6 4mКонтейнер стартует и сразу падает, Kubernetes перезапускает его с экспоненциальной задержкой. Причина почти всегда в самом приложении: смотрите kubectl logs webapp-7d9f8c-abcde --previous — флаг --previous обязателен, иначе увидите логи уже нового упавшего процесса, а не предыдущего.
ImagePullBackOff
Events:
Warning Failed 8s kubelet Failed to pull image "myrepo/app:v2": rpc error: code = Unknown desc = Error response from daemon: pull access denied for myrepo/app, repository does not exist or may require 'docker login'Либо опечатка в имени образа/теге, либо образ приватный и на ноде не настроен imagePullSecrets. Создайте секрет командой kubectl create secret docker-registry regcred --docker-server=... --docker-username=... --docker-password=... и укажите его в spec.imagePullSecrets.
k3s vs другие лёгкие дистрибутивы
| Критерий | k3s | MicroK8s | Полный kubeadm |
|---|---|---|---|
| Минимум RAM | 512 MB | 540 MB | 2 GB на control-plane |
| База данных состояния | SQLite (или etcd для HA) | dqlite | etcd |
| Установка одной командой | Есть | Есть (snap) | Нет, несколько шагов |
Когда k3s не подходит
- Проект умещается в Docker Compose или Docker Swarm — оверхед Kubernetes не окупается на масштабе 1-2 сервисов.
- Команда не знакома с понятиями Kubernetes и нет времени на обучение — лучше начать с Docker Swarm.
- Нужна строгая сертифицированная upstream-сборка Kubernetes для комплаенса — k3s заменяет часть компонентов (Traefik, servicelb, local-path-provisioner) на свои облегчённые версии, для некоторых аудитов это придётся отключать.
- VPS с менее чем 1 ГБ RAM — даже минимальный k3s съедает существенную часть памяти, для веб-сайта хватит обычного стека без оркестрации.
- Нужно планирование задач на GPU со специфичными device plugins производителя — их придётся настраивать вручную, готовой интеграции в k3s нет.
Проверка результата
# Все ноды в состоянии Ready
kubectl get nodes -o wide
# Все системные поды запущены
kubectl get pods -A | grep -v Running
# HTTP-ответ через Ingress
curl -I https://app.yourdomain.com
# Статус выпуска сертификата cert-manager
kubectl get certificate -A
kubectl describe certificate webapp-tlsЕсли команда grep -v Running вернула хоть одну строку (кроме заголовка) — какой-то системный под не поднялся, разбирайтесь через kubectl describe pod в соответствующем неймспейсе. Перед продакшн-использованием кластера настройте внешний мониторинг — он покажет падение сервиса даже если сам Kubernetes считает под живым.