From 374f356435fb33fca402bc32e45ce0858cbc4d4c Mon Sep 17 00:00:00 2001 From: erjemin Date: Sun, 23 Feb 2025 15:09:12 +0300 Subject: [PATCH] add: k3s (1) --- raspberry-and-orange-pi/k3s.md | 126 ++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 24 deletions(-) diff --git a/raspberry-and-orange-pi/k3s.md b/raspberry-and-orange-pi/k3s.md index a427251..d92c117 100644 --- a/raspberry-and-orange-pi/k3s.md +++ b/raspberry-and-orange-pi/k3s.md @@ -10,25 +10,42 @@ IoT-устройства, edge-серверы и т.п.). Для кластер kube-controller-manager, kube-scheduler, kubelet на каждой ноде, kube-proxy, etcd и т.д. В K3s всё это упаковано в один бинарник. * Всё работает "из коробки" благодаря встроенному Flannel (CNI) и не надо вручную настраивать Calico, Weave, Cilium. +* В отличие от "классического" Kubernetes (например, kubeadm), где мастер-узлы по умолчанию изолированы от рабочих нагрузок с помощью taint'ов (например, NoSchedule), k3s не добавляет такие ограничения автоматически. Это значит: +* Для моего проекта особо важно, что из коробки мастер-узел(ы)) в k3s является "гибридным" и выполняет одновременно + функции управления (control-plane) и может запускать обычные поды, как воркер. Компоненты управления (API-сервер, + контроллеры, etcd) работают как системные сервисы, а для пользовательских подов используется тот же kubelet, + что и на воркерах. -Но, для конкретно моего случая у k3s есть один минус -- распределенная база **etcd**, в которой хранится состояния -кластера, нод и подов, в нем заменена SQLite . Это круто для маленьких компьютеров, экономно по памяти и ресурсам, и никак -не сказывается на производительности (пока узлов меньше 80-100), но означает, что в кластере k3s -может быть только одна мастер-нода. Если мастер-нода упадет, ее некому будет заменить и весь кластер умрет. -Я же хочу, чтобы все ноды были мастерами (с возможностью работать -с воркерами) и буду делать k3s-кластер с использованием etcd. Причем etcd будет внутри нод (!). +Но, есть у k3s и минус для конкретно моего случая -- распределенная база **etcd**, в которой хранится состояния +кластера, нод и подов, в нем заменена SQLite. Это круто для маленьких компьютеров: экономно по памяти и другим ресурсам, +и, что главное, никак не сказывается на производительности (пока узлов меньше 50-80), но означает, что в кластере k3s +может быть только одна мастер-нода. Если мастер-нода упадет, её некому будет заменить и весь кластер умрет. +Мне же надо, чтобы как миниум две (а лучше все) ноды могли быть мастерами, так что я буду делать k3s-кластер +с использованием *etcd*. ## Установка k3s на первом узле -На первой ноде запускаем. Пока без кластерного etcd (ока хранение идёт в SQLite) и без Traefik (Traefik -- это -ingress-контроллера в k3s, и в Kubernetes в целом, — это компонент, который управляет входящим сетевым трафиком -кластера и позволяет маршрутизировать HTTP/HTTPS-запросы к соответствующим подам, с динамической конфигурацией -и интеграцией с Let's Encrypt... но пока он нам не нужен). И так: +Некоторые требования к узлам: +* На всех Orange Pi установлена одинаковая версия Ubuntu (например, 22.04 или 24.04). +* Статические IP-адреса узлов (или зрезервированные под MAC-адреса IP в DHCP). +* На уздах открыты порты 6443 (для API), 2379-2380 (для etcd) и 10250 (для kubelet). + + +Установливаем первый мастер: ```bash -curl -sfL https://get.k3s.io | sh -s - --disable traefik +curl -sfL https://get.k3s.io | sh -s - server --cluster-init --tls-san=192.168.1.10 ``` -У нас один узел, состояние k3s хранится в SQLite. +Здесь: +* `server` -- значение по умолчанию, устанавливает узел k3s в режиме *мастер* (control-plane). В этом режиме узел + будет запускать все компоненты управления Kubernetes: API-сервер, контроллер-менеджер, планировщик (scheduler). + Такой узел отвечает за управление кластером и может также выполнять рабочие нагрузки (workloads), если + не настроены ограничения (taints). Если бы мы указали `agent` -- был бы установлен узел k3s в режиме *воркер*-узла. +* `--cluster-init` -- добавляет поддержку высокой доступности (HA -- High Availability) через встроенный `etcd`. Это + значит, что узел инициализирует новый кластер и готов к тому, чтобы другие мастер-узлы могли к нему подключиться + (для создания HA-конфигурации). +* `--tls-san=192.168.1.10` -- добавляет IP 192.168.1.10 в сертификаты API-сервера, чтобы другие узлы и клиенты + могли обращаться к нему по этому адресу. Проверим, что все k3s запущен: ```bash @@ -51,25 +68,86 @@ sudo kubectl get nodes И, та-да! Увидим одну ноду: ```text -NAME STATUS ROLES AGE VERSION -opi5plus-2 Ready control-plane,master 47m v1.31.5+k3s1 +NAME STATUS ROLES AGE VERSION +opi5plus-2 Ready control-plane,etcd,master 31m v1.31.5+k3s1 ``` +Как видим, узел `opi5plus-2` готов к работе и выполняет роли *control-plane*, *etcd* и *master*. + + А что там внутри? Посмотрим на поды: ```bash sudo kubectl get pods -A ``` -Целых три пода: +Целых семь подов (минималистичная установка k3s): ```text -NAMESPACE NAME READY STATUS RESTARTS AGE -kube-system coredns-ccb96694c-xnvwl 1/1 Running 0 47m -kube-system local-path-provisioner-5cf85fd84d-vpb5p 1/1 Running 0 47m -kube-system metrics-server-5985cbc9d7-ghmkh 1/1 Running 0 47m +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system coredns-ccb96694c-tfjwj 1/1 Running 0 13m +kube-system helm-install-traefik-crd-bdbgd 0/1 Completed 0 13m +kube-system helm-install-traefik-mlztm 0/1 Completed 1 13m +kube-system local-path-provisioner-5cf85fd84d-jwz5n 1/1 Running 0 13m +kube-system metrics-server-5985cbc9d7-n9dwz 1/1 Running 0 13m +kube-system svclb-traefik-4f8c2580-jddgz 2/2 Running 0 12m +kube-system traefik-5d45fc8cc9-t5d58 1/1 Running 0 12m ``` -* **coredns** -- DNS-сервер кластера, используется для разрешения имен сервисов и подов внутри k3s (и k8s тоже). -* **local-path-provisioner** -- организатор хранилища на дисках узлов, он автоматически создает Persistent Volumes (PV) - для хранения данных (например, базы). -* **metrics-server** -- агрегатор метрик, который собирает данные о нагрузке (CPU, память и все такое) на поды и узлы, - которые можно использовать для автоскейлинга (например, увеличивать количество подов при нагрузках). +Тут статус X/Y в выводе kubectl get pods показывает: +* Y — сколько контейнеров должно быть в поде (по спецификации). +* X — сколько из них сейчас работает (running). + +Представлены следующие поды: +1. `coredns` — это DNS-сервер для кластера. Он отвечает за разрешение имен внутри Kubernetes (например, чтобы поды + могли обращаться друг к другу по именам сервисов вроде my-service.default.svc.cluster.local). +2. `helm-install-traefik-crd` -- это временный под (Job), который устанавливает Custom Resource Definitions (CRD) + для *Traefik* — ingress-контроллера, встроенного в k3s. CRD нужны для управления ingress-ресурсами + (маршрутизацией HTTP/HTTPS). Этот под — одноразовая задача (Job), а не постоянный сервис. Он запустился, выполнил + работу (установил CRD) и завершился. Статус "*Completed*" значит, что он больше не работает. +3. `helm-install-traefik` -- ещё один Job, который устанавливает сам Traefik через Helm-чарт. Этот под развернул + основной Traefik-под и завершился. +4. `local-path-provisioner` -- компонент для автоматического создания локальных Persistent Volumes (PV) на узлах. Он + позволяет подам запрашивать хранилище (например, через PersistentVolumeClaim) без сложной настройки NFS или внешних + хранилищ. В k3s это встроено для простоты. +5. `metrics-server` -- собирает данные об использовании ресурсов (CPU, память) подов и узлов. Это нужно для команд + вроде `kubectl top` или для Horizontal Pod Autoscaler (HPA). Установку метрик можно отключить при запуске k3s + флагом `--disable=metrics-server`. +6. `svclb-traefik` - это под для балансировки нагрузки (Service Load Balancer) для Traefik. В k3s нет встроенного + облачного балансировщика (как в AWS/GCP), поэтому *svclb* эмулирует его на уровне узла, перенаправляя трафик + к сервисам типа LoadBalancer. У нас два таких контейнера: + * один для самой логики балансировки; + * другой для мониторинга или дополнительной функциональности (например, *keepalived* или аналога) и это зависит + от реализации в k3s. +7. `traefik` -- сам Traefik, ingress-контроллер, который обрабатывает HTTP/HTTPS трафик кластера и маршрутизирует + его к соответствующим подам (с динамической конфигурацией нашим) и сервисам по правилам Ingress. Traefik в k3s + установлен по умолчанию, но его можно отключить при запуске k3s флагом `--disable=traefik` (не будет ни *traefik*, + ни *svclb*, ни связанных *Helm Jobs*). + +Обратите внимание, что, например, под `coredns` получил имя `coredns-ccb96694c-tfjwj`. Имена подов (Pod Names) +в Kubernetes генерируются автоматически на основе правил, чтобы каждый под в кластере имел уникальное имя. +Структура имени -- `<имя-приложения>-<хеш-ревизии>-<случайный-суффикс>`. Впрочем, `<хеш-ревизии>` может отсутствовать, +если под не имеет контроллера репликации (например, Job или CronJob). + +Можно проверить, что API нашего узла (кластера) отвечает: +```bash +curl -k https://192.168.1.10 +``` + +Здесь ключ `-k` означает, что мы не проверяем сертификаты (нам важно только, что сервер отвечает). Должны получить +Unauthorized JSON-ответ от API. Что-то вроде: +```json +{ + "kind": "Status", + "apiVersion": "v1", + "metadata": {}, + "status": "Failure", + "message": "Unauthorized", + "reason": "Unauthorized", + "code": 401 +} +``` + + +---- +На первой ноде запускаем. Пока без кластерного etcd (ока хранение идёт в SQLite) и без Traefik (Traefik -- это +ingress-контроллера в k3s, и в Kubernetes в целом, — это компонент, который управляет входящим сетевым трафиком +кластера и позволяет маршрутизировать HTTP/HTTPS-запросы к соответствующим подам, с динамической конфигурацией \ No newline at end of file