Kubernetes в домашней лаборатории обычно пугает тремя вещами: десятком компонентов, требованием к памяти и сложной установкой. K3s решает это одним бинарником и systemd-службой: control plane, containerd, CNI и базовые дополнения уже внутри. Ниже — установка на один узел, проверка рабочим приложением, постоянное хранилище, второй узел и обслуживание без магии.

Что такое k3s и чем он отличается

K3s — сертифицированный дистрибутив Kubernetes от Rancher, собранный в один исполняемый файл. Из стандартной поставки убрали тяжёлые и необязательные компоненты, заменили etcd на SQLite по умолчанию, а облачные контроллеры и CSI-плагины оставили подключаемыми. В комплекте идут CoreDNS, metrics-server, локальный провижионер хранилища local-path, балансировщик ServiceLB и ingress-контроллер Traefik. Для домашней лаборатории это готовый набор: поставил — и можно запускать поды.

Важно понимать границы: один сервер — это не отказоустойчивый кластер. SQLite-база и единственный control plane означают простой при перезагрузке. Для HA нужны три сервера и встроенный etcd, но дома чаще достаточно одного узла и резервной копии состояния.

Требования и установка

Минимально достаточно 2 ядер, 2 ГБ памяти и 20 ГБ диска; на практике control plane с несколькими подами комфортно живёт при 4 ГБ. Поддерживаются x86_64, arm64 и armhf, поэтому подойдёт и мини-ПК, и Raspberry Pi. Установка занимает минуту: скрипт скачивает бинарник, создаёт службу и запускает её.

curl -sfL https://get.k3s.io | sh -
sudo systemctl status k3s --no-pager
sudo k3s kubectl get nodes -o wide
sudo k3s kubectl get pods -A

Kubeconfig по умолчанию лежит в /etc/rancher/k3s/k3s.yaml и доступен только root. Чтобы работать обычным пользователем, скопируйте файл в домашний каталог и замените 127.0.0.1 на адрес сервера — иначе kubectl с другой машины будет искать API локально.

mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER:$USER ~/.kube/config
sed -i 's/127.0.0.1/192.168.1.50/' ~/.kube/config

Проверьте, что kubectl видит кластер. Если команда ругается на сертификат, убедитесь, что в конфиге именно IP или DNS-имя сервера, а не localhost.

Настройка через config.yaml

Параметры установки удобно хранить в /etc/rancher/k3s/config.yaml: так их видно в git и не нужно вспоминать флаги. Для дома разумно сразу зафиксировать адрес узла и отключить лишнее, если вы планируете ставить свой ingress.

write-kubeconfig-mode: "0644"
node-ip: 192.168.1.50
disable:
  - traefik
  - servicelb
cluster-cidr: 10.42.0.0/16
service-cidr: 10.43.0.0/16

После правки перезапустите службу. Не меняйте cluster-cidr и service-cidr на работающем кластере: поды и сервисы получат несогласованные адреса, и понадобится переустановка. Если оставляете Traefik, порты 80 и 443 будут заняты им; если отключаете — ставьте ingress-nginx или Caddy отдельно.

Первое приложение и проверка

Начните с простого Deployment и NodePort: это проверит, что планировщик, сеть и kube-proxy работают. Образ nginx:alpine небольшой, поэтому стартует быстро даже на слабом железе.

kubectl create deployment web --image=nginx:alpine
kubectl scale deployment web --replicas=2
kubectl expose deployment web --port=80 --type=NodePort
kubectl get pods,svc -o wide

В выводе service найдите порт вида 30080 и откройте http://192.168.1.50:30080. Если страница не открывается, проверьте, что поды в статусе Running, а не CrashLoopBackOff, и что порт не блокирует локальный firewall. Дальше удобнее описывать ресурсы в YAML и применять через kubectl apply -f.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: whoami
          image: traefik/whoami
          ports:
            - containerPort: 80

Хранилище и ingress

Local-path создаёт каталог на узле и отдаёт его поду через PersistentVolumeClaim. Этого достаточно для домашних сервисов, но данные привязаны к конкретному узлу: для базы с репликацией лучше смотреть на Longhorn или внешний NFS.

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

Для доступа по имени хоста установите ingress-контроллер и опишите Ingress. Не забудьте добавить запись в /etc/hosts или локальный DNS, иначе браузер не найдёт whoami.lab.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/deploy.yaml
kubectl get pods -n ingress-nginx
kubectl get ingress

Для маршрутизации по имени хоста опишите Ingress. Сохраните манифест в web-ingress.yaml и примените через kubectl apply.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
spec:
  ingressClassName: nginx
  rules:
    - host: whoami.lab
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80

Проверка через curl с заголовком Host помогает отделить проблему DNS от проблемы маршрутизации.

Второй узел и обслуживание

Агент подключается к серверу по токену из /var/lib/rancher/k3s/server/node-token. На сервере должны быть открыты 6443/tcp и 8472/udp, между узлами — 10250/tcp. Не публикуйте API в интернет: для домашней лаборатории достаточно локальной сети.

sudo cat /var/lib/rancher/k3s/server/node-token
curl -sfL https://get.k3s.io | K3S_URL=https://192.168.1.50:6443 K3S_TOKEN=ТОКЕН sh -
kubectl get nodes
kubectl top nodes

Обновление выполняйте повторным запуском установочного скрипта с нужным каналом. Перед этим сохраните состояние: для SQLite остановите службу и скопируйте /var/lib/rancher/k3s/server/db, для etcd сделайте снимок командой k3s etcd-snapshot save.

sudo systemctl stop k3s
sudo cp -a /var/lib/rancher/k3s/server/db /var/backups/k3s-db-$(date +%F)
sudo systemctl start k3s
curl -sfL https://get.k3s.io | INSTALL_K3S_CHANNEL=stable sh -

Диагностика

Когда под не запускается, идите по цепочке: служба, события, описание пода, логи контейнера. K3s прячет kubectl за подкомандой, но можно пользоваться и обычным kubectl с корректным kubeconfig.

  • Pending — планировщику не хватает ресурсов или под не проходит по affinity.
  • ImagePullBackOff — неверный образ или недоступный registry.
  • CrashLoopBackOff — контейнер падает сразу после старта, смотрите kubectl logs.
  • ContainerCreating — проблема с CNI, томом или секретом.
sudo journalctl -u k3s -n 100 --no-pager
kubectl get events -A --sort-by=.lastTimestamp
kubectl describe pod POD_NAME -n NAMESPACE
sudo k3s crictl ps

Типичные причины: нехватка памяти, неверный образ, отсутствующий StorageClass, занятый порт. События показывают причину быстрее логов. Если не стартует сам сервер, смотрите journalctl -u k3s: там будут ошибки базы, сертификатов или занятого порта 6443.

Итог

K3s даёт полноценный Kubernetes без многочасовой настройки: один скрипт, один конфиг, понятные дополнения. Для дома достаточно одного узла с local-path и ingress, а второй узел добавляется токеном. Держите config.yaml в git, делайте резервную копию базы перед обновлением, не выставляйте API наружу и проверяйте состояние через события и journalctl. Этого набора хватает, чтобы лаборатория оставалась воспроизводимой, а не собиралась заново после каждой перезагрузки.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте