Kubernetes на минималках: поднимаем k3s

kubernetesk3sdevopsself-hosting

Kubernetes — мощный инструмент, но у него репутация монстра, который жрёт ресурсы и требует целой команды для поддержки. Отчасти это справедливо для полноразмерных кластеров на kubeadm. Но есть k3s — дистрибутив Kubernetes от Rancher, который умещается в один бинарник на 70 МБ и отлично работает на VPS с 2 ГБ RAM. Я использую его для self-hosted проектов, и за полтора года ни разу не пожалел.

Почему k3s

Kubernetes бывает разный. Вот чем k3s отличается от стандартной установки:

  • Один бинарник — никаких отдельных etcd, kube-scheduler, kube-controller-manager. Всё в одном процессе. Вместо etcd по умолчанию используется SQLite (для single-node) или встроенный etcd (для HA).
  • Минимальные ресурсы — серверная нода потребляет ~500 МБ RAM. Для сравнения, куберовый control plane на kubeadm — от 2 ГБ.
  • Батарейки в комплекте — из коробки идут Traefik (ingress controller), CoreDNS, local-path-provisioner (persistent volumes), metrics-server. Не нужно ставить полдюжины аддонов сразу после установки.
  • Полная совместимость — это сертифицированный Kubernetes. Все манифесты, Helm-чарты и операторы работают без изменений.

Архитектура Kubernetes: control plane, worker nodes и основные компоненты

Установка

Установка k3s — одна команда. Серьёзно:

curl -sfL https://get.k3s.io | sh -

Через 30 секунд у вас работающий кластер. Kubeconfig лежит в /etc/rancher/k3s/k3s.yaml, а kubectl уже в PATH.

# Проверяем, что кластер работает
sudo kubectl get nodes
# NAME      STATUS   ROLES                  AGE   VERSION
# vps-01    Ready    control-plane,master   45s   v1.29.3+k3s1

sudo kubectl get pods -A
# Traefik, CoreDNS, metrics-server — всё запущено

Для удобства настроим доступ без sudo:

mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
export KUBECONFIG=~/.kube/config

Если хотите управлять кластером с локальной машины, скопируйте kubeconfig и замените 127.0.0.1 на IP сервера:

scp user@vps:/etc/rancher/k3s/k3s.yaml ~/.kube/k3s-config
sed -i 's/127.0.0.1/YOUR_VPS_IP/' ~/.kube/k3s-config
export KUBECONFIG=~/.kube/k3s-config

Деплоим первое приложение

Развернём простое веб-приложение. Для этого нужны три ресурса: Deployment, Service и Ingress.

Deployment

# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
  labels:
    app: demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
        - name: app
          image: nginx:1.25-alpine
          ports:
            - containerPort: 80
          resources:
            requests:
              memory: "64Mi"
              cpu: "50m"
            limits:
              memory: "128Mi"
              cpu: "200m"
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 3
            periodSeconds: 5

Service

# app-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: demo-app
spec:
  selector:
    app: demo
  ports:
    - port: 80
      targetPort: 80

Ingress

# app-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-app
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: websecure
    traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
spec:
  rules:
    - host: demo.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: demo-app
                port:
                  number: 80
  tls:
    - hosts:
        - demo.example.com
      secretName: demo-tls

Применяем:

kubectl apply -f app-deployment.yaml
kubectl apply -f app-service.yaml
kubectl apply -f app-ingress.yaml

# Проверяем статус
kubectl get pods
kubectl get svc
kubectl get ingress

Структура кластера k3s: single-node setup с Traefik и приложением

Traefik как Ingress Controller

k3s ставит Traefik из коробки. Это удобно, но конфигурация по умолчанию довольно минимальна. Для Let’s Encrypt нужно подправить настройки.

Traefik в k3s управляется через HelmChartConfig:

# traefik-config.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    additionalArguments:
      - "--certificatesresolvers.letsencrypt.acme.email=you@example.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/data/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
    ports:
      websecure:
        tls:
          enabled: true
    logs:
      access:
        enabled: true
kubectl apply -f traefik-config.yaml
# Traefik перезапустится автоматически

Helm: пакетный менеджер для Kubernetes

Вручную писать манифесты для каждого приложения — не масштабируется. Helm решает эту проблему: это пакетный менеджер, который позволяет устанавливать приложения из готовых чартов с кастомизацией через values.

# Установка Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# Добавляем репозиторий
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

# Ищем чарт
helm search repo bitnami/postgresql

# Устанавливаем PostgreSQL
helm install my-db bitnami/postgresql 
  --set auth.postgresPassword=secretpass 
  --set primary.persistence.size=10Gi 
  --namespace databases 
  --create-namespace

Для продакшена лучше хранить values в файле и версионировать:

# postgres-values.yaml
auth:
  postgresPassword: secretpass
  database: myapp

primary:
  persistence:
    size: 10Gi
  resources:
    requests:
      memory: 256Mi
      cpu: 100m
    limits:
      memory: 512Mi
      cpu: 500m

metrics:
  enabled: true
helm install my-db bitnami/postgresql -f postgres-values.yaml -n databases --create-namespace

Persistent Volumes

k3s из коробки поставляет local-path-provisioner — StorageClass, который создаёт PV на локальном диске ноды. Для single-node это идеально.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 5Gi

Данные хранятся в /opt/local-path-provisioner/ на ноде. Для продакшена стоит настроить бэкапы этой директории.

Если нужно что-то серьёзнее — Longhorn (тоже от Rancher) даёт репликацию, снепшоты и бэкапы в S3. Ставится одной командой:

kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.6.0/deploy/longhorn.yaml

Мониторинг

k3s ставит metrics-server автоматически. Базовые метрики доступны через kubectl:

# Потребление ресурсов нодами
kubectl top nodes

# Потребление ресурсов подами
kubectl top pods -A

# Подробнее по конкретному namespace
kubectl top pods -n default --sort-by=memory

Для полноценного мониторинга я ставлю kube-prometheus-stack через Helm:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install monitoring prometheus-community/kube-prometheus-stack 
  --namespace monitoring 
  --create-namespace 
  --set prometheus.prometheusSpec.retention=30d 
  --set grafana.adminPassword=admin

Это даёт Prometheus, Grafana и Alertmanager с преднастроенными дашбордами для Kubernetes. На VPS с 4 ГБ RAM стек мониторинга занимает около 500 МБ — терпимо.

Полезные команды на каждый день

# Статус всех ресурсов в namespace
kubectl get all -n default

# Описание пода (события, причины ошибок)
kubectl describe pod <pod-name>

# Логи пода (follow, последние 50 строк)
kubectl logs -f --tail=50 <pod-name>

# Зайти в контейнер
kubectl exec -it <pod-name> -- /bin/sh

# Перезапустить deployment (rolling restart)
kubectl rollout restart deployment/<name>

# Откатиться на предыдущую ревизию
kubectl rollout undo deployment/<name>

# Отслеживать статус деплоя
kubectl rollout status deployment/<name>

Итог

k3s снижает порог входа в Kubernetes до минимума. Один VPS, одна команда для установки — и у вас полноценный кластер с ingress-контроллером, storage provisioner и метриками. Для self-hosted проектов, домашних лабораторий и даже небольших продакшен-сред — это оптимальный выбор. А если потребуется масштабирование, k3s поддерживает HA-кластер из нескольких нод через встроенный etcd. Но это тема для отдельной статьи.

© 2026 Terminal Notes. Built with SvelteKit.