Статья для тех, кто пытался поставить k3s на Arch Linux (и основанные на нём дистрибутивы) и столкнулся с зависающим установщиком, проблемами DNS и отсутствующими systemd юнитами. Полное руководство по ручной установке с реальными командами и решениями.

В мире контейнеризации есть негласное правило:

  • хочешь учить Kubernetes локально — ставь minikube;

  • хочешь что-то ближе к production — бери k3s.

Документация обещает установку «в одну команду» и поддержку «большинства современных Linux-дистрибутивов».
Я использую CachyOS (Arch-based), изучаю инфраструктуру под DevOps/SRE и хотел локальный Kubernetes, который:

  • лёгкий;

  • быстрее minikube;

  • и ведёт себя ближе к настоящему кластеру.

И, честно говоря, хотелось не просто «поиграться», а настроить что-то production-like.

После нескольких часов борьбы с зависающим установщиком, отсутствующими systemd-юнитами, конфликтами DNS и даже несовместимостью shell’а, кластер всё-таки встал.

«Попробую k3s — он ведь лёгкий и современный. Что может пойти не так?»

Спойлер: всё.

Если вы тоже на Arch или другом rolling-release дистрибутиве — этот разбор сэкономит вам время и нервы. Я уже прошёл через все грабли, чтобы вам не пришлось.


Почему именно k3s?

Для DevOps/SRE Kubernetes сегодня — стандарт. Но:

  • полноценный Kubernetes на ноутбук (особенно с 8 GB RAM) — слишком тяжело;

  • minikube — хороший вариант, но это скорее «песочница».

K3s — лёгкий, но production-ready Kubernetes. Отлично подходит для edge-систем и локальных экспериментов. K3s упакован в виде одного двоичного файла ( меньше, чем 70 МБ), что сокращает зависимости и количество шагов, необходимых для установки, запуска и автоматического обновления рабочего кластера Kubernetes.

«Лёгкий» — да.
«Работает везде» — не совсем. Rolling-release дистрибутивы вроде Arch — отдельная история.


Часть 1. Установка по документации: молчание ягнят

Официальный Quick-Start Guide уверяет, что установка простая:

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

Я запускаю команду. И… Ничего.

Абсолютно ничего. Ни вывода. Ни ошибки. Терминал зависает. Ctrl+C не помогает — только закрывать окно. Попытки ещё раз — тот же результат.

И проблема в документации в том, что в разделе Requirements написано, что k3s будет работать на большинстве современных систем Linux. Однако не было ничего про Arch и ему подобных дистрибутивов.


AUR? Не сегодня

Пошёл Arch-way вариантом (скачать через AUR):

paru -S k3s

И получил ошибку о том, что не удалось собрать пакет:

==> ERROR: Failed to build k3s

Пакет на тот момент, видимо, был просто сломан. Однако это у меня был такой случай, вам, может быть, повезёт больше.


Часть 2. Ручная установка и системные грабли

Скачиваем бинарник

Предупреждение: вообще, если у вас сработала ко��анда, которая предоставлена в Quick-Start Guide, то вам повезло в какой-то степени. Но в моём случае нет.

curl -L https://github.com/k3s-io/k3s/releases/download/v1.33.6%2Bk3s1/k3s -o k3s
chmod +x k3s
sudo mv k3s /usr/local/bin/

Файл на месте. Но…
Проблема: systemd unit отсутствует

Ни /etc/systemd/system/k3s.service, ни других юнитов не появилось. Без юнита — нет автозапуска, нет нормального управления. Пришлось писать вручную.


Рабочий systemd unit для k3s

создаём юнит в /etc/systemd/system/k3s.service:

sudo nano /etc/systemd/system/k3s.service

Пример минимального, но рабочего юнита:

[Unit]
Description=Lightweight Kubernetes
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/local/bin/k3s server
Restart=always
RestartSec=5s
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

Что здесь важно:

  • Type=notify — K3s сам сообщит systemd, когда действительно запустится

  • LimitNOFILE=1048576 — Kubernetes работает с тысячами файловых дескрипторов

  • After=network-online.target — без сети Kubernetes бесполезен

Запускаем daemon-reload и k3s:

sudo systemctl daemon-reload
sudo systemctl enable --now k3s

Часть 3. Кластер стартует, но не работает

Проверяем API с помощью curl:

curl -k https://127.0.0.1:6443/healthz

Ответ в формате JSON:

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401
}

401 Unauthorized — это хорошо! Значит, API сервер запущен и слушает порт 6443, требует аутентификацию (как и должно быть). Но при попытке использовать kubectl:

sleep 30  # Ждём полной инициализации
kubectl get nodes

В ответ получаем ошибку:

Error from server (NotFound): the server could not find the requested resource

Смотрим логи journalctl:

journalctl -u k3s -n 100 --no-pager

И находим такие строки:

дек 03 20:08:36 cachyos-x8664 k3s[194987]: E1203 20:08:36.951520 194987 dns.go:153] 
"Nameserver limits exceeded" err="Nameserver limits were exceeded, some nameservers have been omitted, 
the applied nameserver line is: 8.8.8.8 1.1.1.1 1.1.1.1"

Что говорит эта ошибка на человеческом:

«В /etc/resolv.conf слишком много DNS-серверов, пришлось некоторые проигнорировать. Оставил: 8.8.8.8, 1.1.1.1, 1.1.1.1»

Проблема: В Arch Linux одновременно работают NetworkManager и systemd-resolved. Оба пишут в /etc/resolv.conf, создавая дубликаты. K3s (точнее, его компонент CoreDNS) видит эти дубликаты, сходит с ума и отказывается работать.

K3s запущен, но DNS сломан. Без работающего DNS Kubernetes — просто красивая абстракция.


Часть 4. DNS в Arch — отдельный квест

Arch и CachyOS используют systemd-resolved + NetworkManager. K3s — ожидает статический /etc/resolv.conf.

В итоге CoreDNS получает:

  • дублирующиеся nameserver;

  • конфликты;

  • и просто отказывается работать.

Решение: сказать NetworkManager «не трогай DNS»

sudo nano /etc/NetworkManager/NetworkManager.conf

Добавить строки:

# В /etc/NetworkManager/NetworkManager.conf
[main]
dns=none # Фикс для Arch: останавливаем NetworkManager от управления DNS

И перезагрузить сервисы (NetworkManager и k3s):

sudo systemctl restart NetworkManager
sudo systemctl restart k3s

Почему в Arch нужно dns=none?

Arch Linux использует современный стек управления сетью: NetworkManager для удобства + systemd-resolved для DNS. Оба хотят управлять /etc/resolv.conf, создавая «войну DNS».

Когда NetworkManager и systemd-resolved пытаются править один файл, в /etc/resolv.conf появляются дублирующиеся nameserver'ы (типа 8.8.8.8 1.1.1.1 1.1.1.1, как в моём примере вышло).

K3s (а точнее — его CoreDNS) видит этот бардак, паникует и выдаёт Nameserver limits exceeded. Pod'ы перестают резолвить домены, кластер ломается.

Параметр dns=none говорит NetworkManager: «Не трогай DNS, пусть этим занимается systemd-resolved». Это останавливает войну и даёт k3s стабильный DNS.


Часть 5. Shell: Fish против Bash

Большинство туториалов используют Bash:

export KUBECONFIG=~/.kube/config

Но у меня установлен Fish shell — альтернатива Bash с другим синтаксисом. При попытке выполнить bash-команды Fish ругается:

~/.bashrc (line 10): Unsupported use of '='. In fish, please use 'set PS1 '[\u@\h \W]\$ ''

Что здесь происходит:

  1. Команда export VAR=value — это синтаксис Bash

  2. Fish использует другой синтаксис: set -x VAR value

  3. Когда Fish пытается «прочитать» bash-команды — он не понимает их

Поэтому:

mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER:$USER ~/.kube/config
set -Ux KUBECONFIG ~/.kube/config

Пояснение каждой команды:

  1. mkdir -p ~/.kube
    Создаём директорию для конфигов Kubernetes. Флаг -p означает: «создай родительские директории, если их нет;

  2. sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
    K3s при установке создаёт конфигурационный файл в /etc/rancher/k3s/k3s.yaml. Копируем его в домашнюю директорию, где у пользователя есть права на чтение;

  3. sudo chown $USER:$USER ~/.kube/config
    Файл скопирован от root, поэтому меняем владельца на текущего пользователя. Иначе kubectl не сможет его читать;

  4. set -Ux KUBECONFIG ~/.kube/config (команда Fish).

    set — команда установки переменной в Fish (аналог export в Bash).

    -U (universal) — переменная сохранится между перезапусками терминала.

    -x (export) — делает переменную доступной для дочерних процессов (включая kubectl).

    KUBECONFIG — переменная, в которой kubectl ищет путь к конфигурации кластера.

Почему это важно:
Без правильной переменной KUBECONFIG утилита kubectl не знает:

  • куда подключиться (адрес API-сервера);

  • какой сертификат использовать для аутентификации;

  • к какому кластеру обращаться.

Мы скопировали конфиг из системной директории в домашнюю, настроили права и сообщили Fish (а через него — kubectl), где искать настройки кластера.


Часть 6. Итог: кластер поднялся

Команда для вывода узлов (физических или виртуальных машин) в кластере:

kubectl get nodes

Вывод команды:

NAME            STATUS   ROLES                  AGE   VERSION
cachyos-x8664   Ready    control-plane,master   20m   v1.33.6+k3s1

Разбираем по колонкам:

Колонка

Значение

Что означает

NAME

cachyos-x8664

Имя ноды (берётся из hostname)

STATUS

Ready

Нода готова принимать Pod

ROLES

control-plane,master

Нода выполняет обе роли (в K3s они объединены)

AGE

20m

Кластер работает 20 минут

VERSION

v1.33.6+k3s1

Версия Kubernetes 1.33.6 с патчами K3s

Что это значит на практике:

  • Ready — нода прошла все health-чеки, сеть работает, kubelet отвечает;

  • control-plane,master — на этой же ноде работает и управляющая плоскость (API, scheduler, controller-manager);

  • 20m — кластер успел полностью инициализироваться;

  • k3s1 в версии — это именно K3s, а не ванильный Kubernetes.

Поды:

kubectl get pods -A

coredns                         Running
metrics-server                  Running
local-path-provisioner          Running
traefik                         Running

Кластер жив и готов к работе. Теперь можно делать свой HomeLab.


Часть 7. Быстрая инструкция (если вам не нужна история)

curl -L https://github.com/k3s-io/k3s/releases/download/v1.33.6%2Bk3s1/k3s -o k3s
chmod +x k3s
sudo mv k3s /usr/local/bin/
  • Создать systemd unit (см. выше)

  • Исправить DNS /etc/NetworkManager/NetworkManager.conf:

[main]
dns=none
  • Настроить kubectl

mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER:$USER ~/.kube/config
  • Если Fish, то для экспорта:

set -Ux KUBECONFIG ~/.kube/config
  • Запуск сервиса k3s:

sudo systemctl enable --now k3s
kubectl get nodes

Выводы

  1. Arch != «современный дистрибутив» в понимании документации. Rolling-release — это сила и боль одновременно;

  2. Разница между «установилось» и «работает» — огромная. Особенно в Kubernetes;

  3. Логи — главный инструмент диагностики, journalctl -u k3s спасал снова и снова;

  4. Shell имеет значение. Если вы не на Bash — готовьтесь к особенностям;

  5. Стоило ли это того?
    Для обучения — да.
    Для комфортной разработки — скорее нет. Minikube работает «из коробки».


Альтернатива: minikube на Arch

Если вам нужен просто обучающий кластер, то можно рассмотреть в сторону minikube, который имеет статью на ArchWiki:

paru -S minikube
minikube start --driver=docker

И всё.

Но если вам хочется именно лёгкий production-like Kubernetes — теперь вы знаете, как запустить k3s вручную.

Нашли ошибку в статье? Знаете более простой способ поставить k3s на Arch? Или прошли через такой же ад? Делитесь в комментариях — вместе сделаем мир Arch и Kubernetes менее болезненным.

Комментарии (4)


  1. dem0n3d
    09.12.2025 12:43

    Может стоило всё же разобраться почему первая команда не сработала? Там же просто sh скрипт, не так и сложно его отладить.


  1. DanLin Автор
    09.12.2025 12:43

    Well... Я не буду спорю, что можно было попробовать (и стоило бы) разобраться, почему curl -sfL https://get.k3s.io | sh - не сработала у меня. Однако у меня были попытки:
    - пробовал запустить curl с ключом -v и отдельный запуск sh -x, однако всё равно было "зависание" (то есть также - ни вывода, ни ошибки в виде [INFO] или [ERROR]);
    - смотрел что там по процессам (ps aux), но каких-то явных процессов, связанных с curl тоже не было (и я считаю довольно странно).

    Можно было подумать, что было проблема с сетью или столкнулся с какими-то блокировками, НО... самое интересное, что с какой-то попытки команда выполнилась (то есть был какой-то вывод с [INFO], а не просто какое-то молчание, с которым непонятно, как действовать), но однако после установки почему-то корректно не поднимался k3s и пришлось немного навести шен-шуя.

    Да, можно было это сделать расследования и сделать про это статью, но я на тот момент хотел просто сделать себе кластер, который будет состоять из одной ноды (мой ноутбук), с которым можно дальше как-то взаимодействовать.

    В любом случае, спасибо за замечание! Я думаю, что мне стоит подумать над этим.


    1. D4rQ
      09.12.2025 12:43

      Не знаю, в этом ли проблема, но у меня на ubuntu тоже ничего не ставилось, пока не попробовал с vpn

      Причем все ссылки из скрипта вроде как на гитхаб, то есть нет никаких заблокированных ресурсов, но без впн все равно не работало. Ровно так же - просто зависший скрипт, без логов про ошибки и тд


      1. DanLin Автор
        09.12.2025 12:43

        Хм, это интересно. Можно было бы попробовать через WireShark/tshark/tcpdump и посмотреть, что происходит без vpn и с vpn. Я, честно признаться, не хотел использовать бесплатные варианты, а денег, чтобы платить, нет. Хотя я мог попробовать через torsocks запустить команду и посмотреть, что будет.

        И самое интересное, я только что попробовал вставить ссылку в браузер https://get.k3s.io и без расширения VPN мне выдало "Не удается получить доступ к сайту". А ври с расширением - я вижу прям код скрипта на окне браузера. Тогда получается, что проблема с блокировками имеет право на существование?

        Хотя как тогда объяснить, что с какой-то попытки странным образом без манипуляций с сетью всё-таки сработала команда? Получается, что "раз в год и палка стреляет"? Или каком-то образом я получил скрипт удачным маршрутом...

        Возможно, есть прерывающиеся соединения к каким-то CDN или geolocation-based блокировки, которые срабатывают не всегда. Но в моём случае, даже если бы скрипт завершился успешно, я всё равно бы столкнулся с конфликтами nameserver'ов в Arch - поэтому ручная установка была неизбежна.